tcg/aarch64: Remove reloc_pc26_atomic
[qemu/ar7.git] / target / mips / translate.c
blobe9c23a594b12b8c4a232d70f1d191118ee2725e6
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
1414 * --------------------------------------------
1416 * Registers:
1418 * XRa, XRb, XRc, XRd - MXU registers
1419 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1421 * Subfields:
1423 * aptn1 - 1-bit accumulate add/subtract pattern
1424 * aptn2 - 2-bit accumulate add/subtract pattern
1425 * eptn2 - 2-bit execute add/subtract pattern
1426 * optn2 - 2-bit operand pattern
1427 * optn3 - 3-bit operand pattern
1428 * sft4 - 4-bit shift amount
1429 * strd2 - 2-bit stride amount
1431 * Prefixes:
1433 * <Operation parallel level><Operand size>
1434 * S 32
1435 * D 16
1436 * Q 8
1438 * Suffixes:
1440 * E - Expand results
1441 * F - Fixed point multiplication
1442 * L - Low part result
1443 * R - Doing rounding
1444 * V - Variable instead of immediate
1445 * W - Combine above L and V
1447 * Operations:
1449 * ADD - Add or subtract
1450 * ADDC - Add with carry-in
1451 * ACC - Accumulate
1452 * ASUM - Sum together then accumulate (add or subtract)
1453 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1454 * AVG - Average between 2 operands
1455 * ABD - Absolute difference
1456 * ALN - Align data
1457 * AND - Logical bitwise 'and' operation
1458 * CPS - Copy sign
1459 * EXTR - Extract bits
1460 * I2M - Move from GPR register to MXU register
1461 * LDD - Load data from memory to XRF
1462 * LDI - Load data from memory to XRF (and increase the address base)
1463 * LUI - Load unsigned immediate
1464 * MUL - Multiply
1465 * MULU - Unsigned multiply
1466 * MADD - 64-bit operand add 32x32 product
1467 * MSUB - 64-bit operand subtract 32x32 product
1468 * MAC - Multiply and accumulate (add or subtract)
1469 * MAD - Multiply and add or subtract
1470 * MAX - Maximum between 2 operands
1471 * MIN - Minimum between 2 operands
1472 * M2I - Move from MXU register to GPR register
1473 * MOVZ - Move if zero
1474 * MOVN - Move if non-zero
1475 * NOR - Logical bitwise 'nor' operation
1476 * OR - Logical bitwise 'or' operation
1477 * STD - Store data from XRF to memory
1478 * SDI - Store data from XRF to memory (and increase the address base)
1479 * SLT - Set of less than comparison
1480 * SAD - Sum of absolute differences
1481 * SLL - Logical shift left
1482 * SLR - Logical shift right
1483 * SAR - Arithmetic shift right
1484 * SAT - Saturation
1485 * SFL - Shuffle
1486 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1487 * XOR - Logical bitwise 'exclusive or' operation
1489 * Load/Store instructions Multiplication instructions
1490 * ----------------------- ---------------------------
1492 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1493 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1494 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1495 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1496 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1497 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1498 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1499 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1500 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1501 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1502 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1503 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1504 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1505 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1506 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1507 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1508 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1509 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1510 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1511 * S16SDI XRa, Rb, s10, eptn2
1512 * S8LDD XRa, Rb, s8, eptn3
1513 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1514 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1515 * S8SDI XRa, Rb, s8, eptn3
1516 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1517 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1518 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1519 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1520 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1521 * S32CPS XRa, XRb, XRc
1522 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1523 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1524 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1525 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1526 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1527 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1528 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1529 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1530 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1531 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1532 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1533 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1534 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1535 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1536 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1537 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1538 * Q8SLT XRa, XRb, XRc
1539 * Q8SLTU XRa, XRb, XRc
1540 * Q8MOVZ XRa, XRb, XRc Shift instructions
1541 * Q8MOVN XRa, XRb, XRc ------------------
1543 * D32SLL XRa, XRb, XRc, XRd, sft4
1544 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1545 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1546 * D32SARL XRa, XRb, XRc, sft4
1547 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1548 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1549 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1550 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1551 * Q16SLL XRa, XRb, XRc, XRd, sft4
1552 * Q16SLR XRa, XRb, XRc, XRd, sft4
1553 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1554 * ------------------------- Q16SLLV XRa, XRb, Rb
1555 * Q16SLRV XRa, XRb, Rb
1556 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1557 * S32ALN XRa, XRb, XRc, Rb
1558 * S32ALNI XRa, XRb, XRc, s3
1559 * S32LUI XRa, s8, optn3 Move instructions
1560 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1561 * S32EXTRV XRa, XRb, Rs, Rt
1562 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1563 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1566 * bits
1567 * 05..00
1569 * ┌─ 000000 ─ OPC_MXU_S32MADD
1570 * ├─ 000001 ─ OPC_MXU_S32MADDU
1571 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1572 * │
1573 * │ 20..18
1574 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1575 * │ ├─ 001 ─ OPC_MXU_S32MIN
1576 * │ ├─ 010 ─ OPC_MXU_D16MAX
1577 * │ ├─ 011 ─ OPC_MXU_D16MIN
1578 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1579 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1580 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1581 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1582 * ├─ 000100 ─ OPC_MXU_S32MSUB
1583 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1584 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1585 * │ ├─ 001 ─ OPC_MXU_D16SLT
1586 * │ ├─ 010 ─ OPC_MXU_D16AVG
1587 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1588 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1589 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1590 * │ └─ 111 ─ OPC_MXU_Q8ADD
1591 * │
1592 * │ 20..18
1593 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1594 * │ ├─ 010 ─ OPC_MXU_D16CPS
1595 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1596 * │ └─ 110 ─ OPC_MXU_Q16SAT
1597 * ├─ 001000 ─ OPC_MXU_D16MUL
1598 * │ 25..24
1599 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1600 * │ └─ 01 ─ OPC_MXU_D16MULE
1601 * ├─ 001010 ─ OPC_MXU_D16MAC
1602 * ├─ 001011 ─ OPC_MXU_D16MACF
1603 * ├─ 001100 ─ OPC_MXU_D16MADL
1604 * ├─ 001101 ─ OPC_MXU_S16MAD
1605 * ├─ 001110 ─ OPC_MXU_Q16ADD
1606 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1607 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1608 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1609 * │
1610 * │ 23
1611 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1612 * │ └─ 1 ─ OPC_MXU_S32STDR
1613 * │
1614 * │ 13..10
1615 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1616 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1617 * │
1618 * │ 13..10
1619 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1620 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1621 * │
1622 * │ 23
1623 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1624 * │ └─ 1 ─ OPC_MXU_S32LDIR
1625 * │
1626 * │ 23
1627 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1628 * │ └─ 1 ─ OPC_MXU_S32SDIR
1629 * │
1630 * │ 13..10
1631 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1632 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1633 * │
1634 * │ 13..10
1635 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1636 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1637 * ├─ 011000 ─ OPC_MXU_D32ADD
1638 * │ 23..22
1639 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1640 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1641 * │ └─ 10 ─ OPC_MXU_D32ASUM
1642 * ├─ 011010 ─ <not assigned>
1643 * │ 23..22
1644 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1645 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1646 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1647 * │
1648 * │ 23..22
1649 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1650 * │ ├─ 01 ─ OPC_MXU_D8SUM
1651 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1652 * ├─ 011110 ─ <not assigned>
1653 * ├─ 011111 ─ <not assigned>
1654 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1655 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1656 * ├─ 100010 ─ OPC_MXU_S8LDD
1657 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1658 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1659 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1660 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1661 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1662 * │
1663 * │ 20..18
1664 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1665 * │ ├─ 001 ─ OPC_MXU_S32ALN
1666 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1667 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1668 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1669 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1670 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1671 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1672 * ├─ 101110 ─ OPC_MXU_S32M2I
1673 * ├─ 101111 ─ OPC_MXU_S32I2M
1674 * ├─ 110000 ─ OPC_MXU_D32SLL
1675 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1676 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1677 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1678 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1679 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1680 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1681 * ├─ 110110 ─ OPC_MXU__POOL17 ─┴─ 101 ─ OPC_MXU_Q16SARV
1682 * │
1683 * ├─ 110111 ─ OPC_MXU_Q16SAR
1684 * │ 23..22
1685 * ├─ 111000 ─ OPC_MXU__POOL18 ─┬─ 00 ─ OPC_MXU_Q8MUL
1686 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1687 * │
1688 * │ 20..18
1689 * ├─ 111001 ─ OPC_MXU__POOL19 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1690 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1691 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1692 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1693 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1694 * │ └─ 101 ─ OPC_MXU_S32MOV
1695 * │
1696 * │ 23..22
1697 * ├─ 111010 ─ OPC_MXU__POOL20 ─┬─ 00 ─ OPC_MXU_Q8MAC
1698 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1699 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1700 * ├─ 111100 ─ OPC_MXU_Q8MADL
1701 * ├─ 111101 ─ OPC_MXU_S32SFL
1702 * ├─ 111110 ─ OPC_MXU_Q8SAD
1703 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1706 * Compiled after:
1708 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1709 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1712 enum {
1713 OPC_MXU_S32MADD = 0x00,
1714 OPC_MXU_S32MADDU = 0x01,
1715 OPC__MXU_MUL = 0x02,
1716 OPC_MXU__POOL00 = 0x03,
1717 OPC_MXU_S32MSUB = 0x04,
1718 OPC_MXU_S32MSUBU = 0x05,
1719 OPC_MXU__POOL01 = 0x06,
1720 OPC_MXU__POOL02 = 0x07,
1721 OPC_MXU_D16MUL = 0x08,
1722 OPC_MXU__POOL03 = 0x09,
1723 OPC_MXU_D16MAC = 0x0A,
1724 OPC_MXU_D16MACF = 0x0B,
1725 OPC_MXU_D16MADL = 0x0C,
1726 OPC_MXU_S16MAD = 0x0D,
1727 OPC_MXU_Q16ADD = 0x0E,
1728 OPC_MXU_D16MACE = 0x0F,
1729 OPC_MXU__POOL04 = 0x10,
1730 OPC_MXU__POOL05 = 0x11,
1731 OPC_MXU__POOL06 = 0x12,
1732 OPC_MXU__POOL07 = 0x13,
1733 OPC_MXU__POOL08 = 0x14,
1734 OPC_MXU__POOL09 = 0x15,
1735 OPC_MXU__POOL10 = 0x16,
1736 OPC_MXU__POOL11 = 0x17,
1737 OPC_MXU_D32ADD = 0x18,
1738 OPC_MXU__POOL12 = 0x19,
1739 /* not assigned 0x1A */
1740 OPC_MXU__POOL13 = 0x1B,
1741 OPC_MXU__POOL14 = 0x1C,
1742 OPC_MXU_Q8ACCE = 0x1D,
1743 /* not assigned 0x1E */
1744 /* not assigned 0x1F */
1745 /* not assigned 0x20 */
1746 /* not assigned 0x21 */
1747 OPC_MXU_S8LDD = 0x22,
1748 OPC_MXU_S8STD = 0x23,
1749 OPC_MXU_S8LDI = 0x24,
1750 OPC_MXU_S8SDI = 0x25,
1751 OPC_MXU__POOL15 = 0x26,
1752 OPC_MXU__POOL16 = 0x27,
1753 OPC_MXU_LXB = 0x28,
1754 /* not assigned 0x29 */
1755 OPC_MXU_S16LDD = 0x2A,
1756 OPC_MXU_S16STD = 0x2B,
1757 OPC_MXU_S16LDI = 0x2C,
1758 OPC_MXU_S16SDI = 0x2D,
1759 OPC_MXU_S32M2I = 0x2E,
1760 OPC_MXU_S32I2M = 0x2F,
1761 OPC_MXU_D32SLL = 0x30,
1762 OPC_MXU_D32SLR = 0x31,
1763 OPC_MXU_D32SARL = 0x32,
1764 OPC_MXU_D32SAR = 0x33,
1765 OPC_MXU_Q16SLL = 0x34,
1766 OPC_MXU_Q16SLR = 0x35,
1767 OPC_MXU__POOL17 = 0x36,
1768 OPC_MXU_Q16SAR = 0x37,
1769 OPC_MXU__POOL18 = 0x38,
1770 OPC_MXU__POOL19 = 0x39,
1771 OPC_MXU__POOL20 = 0x3A,
1772 OPC_MXU_Q16SCOP = 0x3B,
1773 OPC_MXU_Q8MADL = 0x3C,
1774 OPC_MXU_S32SFL = 0x3D,
1775 OPC_MXU_Q8SAD = 0x3E,
1776 /* not assigned 0x3F */
1781 * MXU pool 00
1783 enum {
1784 OPC_MXU_S32MAX = 0x00,
1785 OPC_MXU_S32MIN = 0x01,
1786 OPC_MXU_D16MAX = 0x02,
1787 OPC_MXU_D16MIN = 0x03,
1788 OPC_MXU_Q8MAX = 0x04,
1789 OPC_MXU_Q8MIN = 0x05,
1790 OPC_MXU_Q8SLT = 0x06,
1791 OPC_MXU_Q8SLTU = 0x07,
1795 * MXU pool 01
1797 enum {
1798 OPC_MXU_S32SLT = 0x00,
1799 OPC_MXU_D16SLT = 0x01,
1800 OPC_MXU_D16AVG = 0x02,
1801 OPC_MXU_D16AVGR = 0x03,
1802 OPC_MXU_Q8AVG = 0x04,
1803 OPC_MXU_Q8AVGR = 0x05,
1804 OPC_MXU_Q8ADD = 0x07,
1808 * MXU pool 02
1810 enum {
1811 OPC_MXU_S32CPS = 0x00,
1812 OPC_MXU_D16CPS = 0x02,
1813 OPC_MXU_Q8ABD = 0x04,
1814 OPC_MXU_Q16SAT = 0x06,
1818 * MXU pool 03
1820 enum {
1821 OPC_MXU_D16MULF = 0x00,
1822 OPC_MXU_D16MULE = 0x01,
1826 * MXU pool 04
1828 enum {
1829 OPC_MXU_S32LDD = 0x00,
1830 OPC_MXU_S32LDDR = 0x01,
1834 * MXU pool 05
1836 enum {
1837 OPC_MXU_S32STD = 0x00,
1838 OPC_MXU_S32STDR = 0x01,
1842 * MXU pool 06
1844 enum {
1845 OPC_MXU_S32LDDV = 0x00,
1846 OPC_MXU_S32LDDVR = 0x01,
1850 * MXU pool 07
1852 enum {
1853 OPC_MXU_S32STDV = 0x00,
1854 OPC_MXU_S32STDVR = 0x01,
1858 * MXU pool 08
1860 enum {
1861 OPC_MXU_S32LDI = 0x00,
1862 OPC_MXU_S32LDIR = 0x01,
1866 * MXU pool 09
1868 enum {
1869 OPC_MXU_S32SDI = 0x00,
1870 OPC_MXU_S32SDIR = 0x01,
1874 * MXU pool 10
1876 enum {
1877 OPC_MXU_S32LDIV = 0x00,
1878 OPC_MXU_S32LDIVR = 0x01,
1882 * MXU pool 11
1884 enum {
1885 OPC_MXU_S32SDIV = 0x00,
1886 OPC_MXU_S32SDIVR = 0x01,
1890 * MXU pool 12
1892 enum {
1893 OPC_MXU_D32ACC = 0x00,
1894 OPC_MXU_D32ACCM = 0x01,
1895 OPC_MXU_D32ASUM = 0x02,
1899 * MXU pool 13
1901 enum {
1902 OPC_MXU_Q16ACC = 0x00,
1903 OPC_MXU_Q16ACCM = 0x01,
1904 OPC_MXU_Q16ASUM = 0x02,
1908 * MXU pool 14
1910 enum {
1911 OPC_MXU_Q8ADDE = 0x00,
1912 OPC_MXU_D8SUM = 0x01,
1913 OPC_MXU_D8SUMC = 0x02,
1917 * MXU pool 15
1919 enum {
1920 OPC_MXU_S32MUL = 0x00,
1921 OPC_MXU_S32MULU = 0x01,
1922 OPC_MXU_S32EXTR = 0x02,
1923 OPC_MXU_S32EXTRV = 0x03,
1927 * MXU pool 16
1929 enum {
1930 OPC_MXU_D32SARW = 0x00,
1931 OPC_MXU_S32ALN = 0x01,
1932 OPC_MXU_S32ALNI = 0x02,
1933 OPC_MXU_S32NOR = 0x03,
1934 OPC_MXU_S32AND = 0x04,
1935 OPC_MXU_S32OR = 0x05,
1936 OPC_MXU_S32XOR = 0x06,
1937 OPC_MXU_S32LUI = 0x07,
1941 * MXU pool 17
1943 enum {
1944 OPC_MXU_D32SLLV = 0x00,
1945 OPC_MXU_D32SLRV = 0x01,
1946 OPC_MXU_D32SARV = 0x03,
1947 OPC_MXU_Q16SLLV = 0x04,
1948 OPC_MXU_Q16SLRV = 0x05,
1949 OPC_MXU_Q16SARV = 0x07,
1953 * MXU pool 18
1955 enum {
1956 OPC_MXU_Q8MUL = 0x00,
1957 OPC_MXU_Q8MULSU = 0x01,
1961 * MXU pool 19
1963 enum {
1964 OPC_MXU_Q8MOVZ = 0x00,
1965 OPC_MXU_Q8MOVN = 0x01,
1966 OPC_MXU_D16MOVZ = 0x02,
1967 OPC_MXU_D16MOVN = 0x03,
1968 OPC_MXU_S32MOVZ = 0x04,
1969 OPC_MXU_S32MOVN = 0x05,
1973 * MXU pool 20
1975 enum {
1976 OPC_MXU_Q8MAC = 0x00,
1977 OPC_MXU_Q8MACSU = 0x01,
1981 * Overview of the TX79-specific instruction set
1982 * =============================================
1984 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1985 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1986 * instructions and certain multimedia instructions (MMIs). These MMIs
1987 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1988 * or sixteen 8-bit paths.
1990 * Reference:
1992 * The Toshiba TX System RISC TX79 Core Architecture manual,
1993 * https://wiki.qemu.org/File:C790.pdf
1995 * Three-Operand Multiply and Multiply-Add (4 instructions)
1996 * --------------------------------------------------------
1997 * MADD [rd,] rs, rt Multiply/Add
1998 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1999 * MULT [rd,] rs, rt Multiply (3-operand)
2000 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2002 * Multiply Instructions for Pipeline 1 (10 instructions)
2003 * ------------------------------------------------------
2004 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2005 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2006 * DIV1 rs, rt Divide Pipeline 1
2007 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2008 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2009 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2010 * MFHI1 rd Move From HI1 Register
2011 * MFLO1 rd Move From LO1 Register
2012 * MTHI1 rs Move To HI1 Register
2013 * MTLO1 rs Move To LO1 Register
2015 * Arithmetic (19 instructions)
2016 * ----------------------------
2017 * PADDB rd, rs, rt Parallel Add Byte
2018 * PSUBB rd, rs, rt Parallel Subtract Byte
2019 * PADDH rd, rs, rt Parallel Add Halfword
2020 * PSUBH rd, rs, rt Parallel Subtract Halfword
2021 * PADDW rd, rs, rt Parallel Add Word
2022 * PSUBW rd, rs, rt Parallel Subtract Word
2023 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2024 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2025 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2026 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2027 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2028 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2029 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2030 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2031 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2032 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2033 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2034 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2035 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2037 * Min/Max (4 instructions)
2038 * ------------------------
2039 * PMAXH rd, rs, rt Parallel Maximum Halfword
2040 * PMINH rd, rs, rt Parallel Minimum Halfword
2041 * PMAXW rd, rs, rt Parallel Maximum Word
2042 * PMINW rd, rs, rt Parallel Minimum Word
2044 * Absolute (2 instructions)
2045 * -------------------------
2046 * PABSH rd, rt Parallel Absolute Halfword
2047 * PABSW rd, rt Parallel Absolute Word
2049 * Logical (4 instructions)
2050 * ------------------------
2051 * PAND rd, rs, rt Parallel AND
2052 * POR rd, rs, rt Parallel OR
2053 * PXOR rd, rs, rt Parallel XOR
2054 * PNOR rd, rs, rt Parallel NOR
2056 * Shift (9 instructions)
2057 * ----------------------
2058 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2059 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2060 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2061 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2062 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2063 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2064 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2065 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2066 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2068 * Compare (6 instructions)
2069 * ------------------------
2070 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2071 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2072 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2073 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2074 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2075 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2077 * LZC (1 instruction)
2078 * -------------------
2079 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2081 * Quadword Load and Store (2 instructions)
2082 * ----------------------------------------
2083 * LQ rt, offset(base) Load Quadword
2084 * SQ rt, offset(base) Store Quadword
2086 * Multiply and Divide (19 instructions)
2087 * -------------------------------------
2088 * PMULTW rd, rs, rt Parallel Multiply Word
2089 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2090 * PDIVW rs, rt Parallel Divide Word
2091 * PDIVUW rs, rt Parallel Divide Unsigned Word
2092 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2093 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2094 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2095 * PMULTH rd, rs, rt Parallel Multiply Halfword
2096 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2097 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2098 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2099 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2100 * PDIVBW rs, rt Parallel Divide Broadcast Word
2101 * PMFHI rd Parallel Move From HI Register
2102 * PMFLO rd Parallel Move From LO Register
2103 * PMTHI rs Parallel Move To HI Register
2104 * PMTLO rs Parallel Move To LO Register
2105 * PMFHL rd Parallel Move From HI/LO Register
2106 * PMTHL rs Parallel Move To HI/LO Register
2108 * Pack/Extend (11 instructions)
2109 * -----------------------------
2110 * PPAC5 rd, rt Parallel Pack to 5 bits
2111 * PPACB rd, rs, rt Parallel Pack to Byte
2112 * PPACH rd, rs, rt Parallel Pack to Halfword
2113 * PPACW rd, rs, rt Parallel Pack to Word
2114 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2115 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2116 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2117 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2118 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2119 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2120 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2122 * Others (16 instructions)
2123 * ------------------------
2124 * PCPYH rd, rt Parallel Copy Halfword
2125 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2126 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2127 * PREVH rd, rt Parallel Reverse Halfword
2128 * PINTH rd, rs, rt Parallel Interleave Halfword
2129 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2130 * PEXEH rd, rt Parallel Exchange Even Halfword
2131 * PEXCH rd, rt Parallel Exchange Center Halfword
2132 * PEXEW rd, rt Parallel Exchange Even Word
2133 * PEXCW rd, rt Parallel Exchange Center Word
2134 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2135 * MFSA rd Move from Shift Amount Register
2136 * MTSA rs Move to Shift Amount Register
2137 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2138 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2139 * PROT3W rd, rt Parallel Rotate 3 Words
2141 * MMI (MultiMedia Instruction) encodings
2142 * ======================================
2144 * MMI instructions encoding table keys:
2146 * * This code is reserved for future use. An attempt to execute it
2147 * causes a Reserved Instruction exception.
2148 * % This code indicates an instruction class. The instruction word
2149 * must be further decoded by examining additional tables that show
2150 * the values for other instruction fields.
2151 * # This code is reserved for the unsupported instructions DMULT,
2152 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2153 * to execute it causes a Reserved Instruction exception.
2155 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2157 * 31 26 0
2158 * +--------+----------------------------------------+
2159 * | opcode | |
2160 * +--------+----------------------------------------+
2162 * opcode bits 28..26
2163 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2164 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2165 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2166 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2167 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2168 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2169 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2170 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2171 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2172 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2173 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2176 enum {
2177 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2178 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2179 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2183 * MMI instructions with opcode field = MMI:
2185 * 31 26 5 0
2186 * +--------+-------------------------------+--------+
2187 * | MMI | |function|
2188 * +--------+-------------------------------+--------+
2190 * function bits 2..0
2191 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2192 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2193 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2194 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2195 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2196 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2197 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2198 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2199 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2200 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2201 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2204 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2205 enum {
2206 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2207 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2208 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2209 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2210 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2211 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2212 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2213 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2214 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2215 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2216 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2217 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2218 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2219 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2220 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2221 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2222 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2223 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2224 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2225 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2226 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2227 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2228 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2229 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2230 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2234 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2236 * 31 26 10 6 5 0
2237 * +--------+----------------------+--------+--------+
2238 * | MMI | |function| MMI0 |
2239 * +--------+----------------------+--------+--------+
2241 * function bits 7..6
2242 * bits | 0 | 1 | 2 | 3
2243 * 10..8 | 00 | 01 | 10 | 11
2244 * -------+-------+-------+-------+-------
2245 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2246 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2247 * 2 010 | PADDB | PSUBB | PCGTB | *
2248 * 3 011 | * | * | * | *
2249 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2250 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2251 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2252 * 7 111 | * | * | PEXT5 | PPAC5
2255 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2256 enum {
2257 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2258 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2259 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2260 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2261 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2262 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2263 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2264 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2265 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2266 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2267 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2268 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2269 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2270 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2271 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2272 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2273 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2274 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2275 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2276 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2277 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2278 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2279 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2280 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2281 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2285 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2287 * 31 26 10 6 5 0
2288 * +--------+----------------------+--------+--------+
2289 * | MMI | |function| MMI1 |
2290 * +--------+----------------------+--------+--------+
2292 * function bits 7..6
2293 * bits | 0 | 1 | 2 | 3
2294 * 10..8 | 00 | 01 | 10 | 11
2295 * -------+-------+-------+-------+-------
2296 * 0 000 | * | PABSW | PCEQW | PMINW
2297 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2298 * 2 010 | * | * | PCEQB | *
2299 * 3 011 | * | * | * | *
2300 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2301 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2302 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2303 * 7 111 | * | * | * | *
2306 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2307 enum {
2308 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2309 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2310 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2311 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2312 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2313 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2314 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2315 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2316 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2317 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2318 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2319 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2320 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2321 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2322 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2323 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2324 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2325 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2329 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2331 * 31 26 10 6 5 0
2332 * +--------+----------------------+--------+--------+
2333 * | MMI | |function| MMI2 |
2334 * +--------+----------------------+--------+--------+
2336 * function bits 7..6
2337 * bits | 0 | 1 | 2 | 3
2338 * 10..8 | 00 | 01 | 10 | 11
2339 * -------+-------+-------+-------+-------
2340 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2341 * 1 001 | PMSUBW| * | * | *
2342 * 2 010 | PMFHI | PMFLO | PINTH | *
2343 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2344 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2345 * 5 101 | PMSUBH| PHMSBH| * | *
2346 * 6 110 | * | * | PEXEH | PREVH
2347 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2350 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2351 enum {
2352 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2353 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2354 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2355 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2356 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2357 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2358 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2359 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2360 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2361 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2362 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2363 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2364 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2365 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2366 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2367 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2368 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2369 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2370 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2371 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2372 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2373 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2377 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2379 * 31 26 10 6 5 0
2380 * +--------+----------------------+--------+--------+
2381 * | MMI | |function| MMI3 |
2382 * +--------+----------------------+--------+--------+
2384 * function bits 7..6
2385 * bits | 0 | 1 | 2 | 3
2386 * 10..8 | 00 | 01 | 10 | 11
2387 * -------+-------+-------+-------+-------
2388 * 0 000 |PMADDUW| * | * | PSRAVW
2389 * 1 001 | * | * | * | *
2390 * 2 010 | PMTHI | PMTLO | PINTEH| *
2391 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2392 * 4 100 | * | * | POR | PNOR
2393 * 5 101 | * | * | * | *
2394 * 6 110 | * | * | PEXCH | PCPYH
2395 * 7 111 | * | * | PEXCW | *
2398 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2399 enum {
2400 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2401 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2402 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2403 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2404 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2405 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2406 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2407 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2408 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2409 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2410 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2411 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2412 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2415 /* global register indices */
2416 static TCGv cpu_gpr[32], cpu_PC;
2417 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2418 static TCGv cpu_dspctrl, btarget, bcond;
2419 static TCGv_i32 hflags;
2420 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2421 static TCGv_i64 fpu_f64[32];
2422 static TCGv_i64 msa_wr_d[64];
2424 /* MXU registers */
2425 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2426 static TCGv mxu_CR;
2428 #include "exec/gen-icount.h"
2430 #define gen_helper_0e0i(name, arg) do { \
2431 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2432 gen_helper_##name(cpu_env, helper_tmp); \
2433 tcg_temp_free_i32(helper_tmp); \
2434 } while(0)
2436 #define gen_helper_0e1i(name, arg1, arg2) do { \
2437 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2438 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2439 tcg_temp_free_i32(helper_tmp); \
2440 } while(0)
2442 #define gen_helper_1e0i(name, ret, arg1) do { \
2443 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2444 gen_helper_##name(ret, cpu_env, helper_tmp); \
2445 tcg_temp_free_i32(helper_tmp); \
2446 } while(0)
2448 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2449 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2450 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2451 tcg_temp_free_i32(helper_tmp); \
2452 } while(0)
2454 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2455 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2456 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2457 tcg_temp_free_i32(helper_tmp); \
2458 } while(0)
2460 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2461 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2462 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2463 tcg_temp_free_i32(helper_tmp); \
2464 } while(0)
2466 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2467 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2468 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2469 tcg_temp_free_i32(helper_tmp); \
2470 } while(0)
2472 typedef struct DisasContext {
2473 DisasContextBase base;
2474 target_ulong saved_pc;
2475 target_ulong page_start;
2476 uint32_t opcode;
2477 uint64_t insn_flags;
2478 int32_t CP0_Config1;
2479 int32_t CP0_Config2;
2480 int32_t CP0_Config3;
2481 int32_t CP0_Config5;
2482 /* Routine used to access memory */
2483 int mem_idx;
2484 TCGMemOp default_tcg_memop_mask;
2485 uint32_t hflags, saved_hflags;
2486 target_ulong btarget;
2487 bool ulri;
2488 int kscrexist;
2489 bool rxi;
2490 int ie;
2491 bool bi;
2492 bool bp;
2493 uint64_t PAMask;
2494 bool mvh;
2495 bool eva;
2496 bool sc;
2497 int CP0_LLAddr_shift;
2498 bool ps;
2499 bool vp;
2500 bool cmgcr;
2501 bool mrp;
2502 bool nan2008;
2503 bool abs2008;
2504 } DisasContext;
2506 #define DISAS_STOP DISAS_TARGET_0
2507 #define DISAS_EXIT DISAS_TARGET_1
2509 static const char * const regnames[] = {
2510 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2511 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2512 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2513 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2516 static const char * const regnames_HI[] = {
2517 "HI0", "HI1", "HI2", "HI3",
2520 static const char * const regnames_LO[] = {
2521 "LO0", "LO1", "LO2", "LO3",
2524 static const char * const fregnames[] = {
2525 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2526 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2527 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2528 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2531 static const char * const msaregnames[] = {
2532 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2533 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2534 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2535 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2536 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2537 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2538 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2539 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2540 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2541 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2542 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2543 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2544 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2545 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2546 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2547 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2550 static const char * const mxuregnames[] = {
2551 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2552 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2555 #define LOG_DISAS(...) \
2556 do { \
2557 if (MIPS_DEBUG_DISAS) { \
2558 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2560 } while (0)
2562 #define MIPS_INVAL(op) \
2563 do { \
2564 if (MIPS_DEBUG_DISAS) { \
2565 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2566 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2567 ctx->base.pc_next, ctx->opcode, op, \
2568 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2569 ((ctx->opcode >> 16) & 0x1F)); \
2571 } while (0)
2573 /* General purpose registers moves. */
2574 static inline void gen_load_gpr (TCGv t, int reg)
2576 if (reg == 0)
2577 tcg_gen_movi_tl(t, 0);
2578 else
2579 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2582 static inline void gen_store_gpr (TCGv t, int reg)
2584 if (reg != 0)
2585 tcg_gen_mov_tl(cpu_gpr[reg], t);
2588 /* Moves to/from shadow registers. */
2589 static inline void gen_load_srsgpr (int from, int to)
2591 TCGv t0 = tcg_temp_new();
2593 if (from == 0)
2594 tcg_gen_movi_tl(t0, 0);
2595 else {
2596 TCGv_i32 t2 = tcg_temp_new_i32();
2597 TCGv_ptr addr = tcg_temp_new_ptr();
2599 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2600 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2601 tcg_gen_andi_i32(t2, t2, 0xf);
2602 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2603 tcg_gen_ext_i32_ptr(addr, t2);
2604 tcg_gen_add_ptr(addr, cpu_env, addr);
2606 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2607 tcg_temp_free_ptr(addr);
2608 tcg_temp_free_i32(t2);
2610 gen_store_gpr(t0, to);
2611 tcg_temp_free(t0);
2614 static inline void gen_store_srsgpr (int from, int to)
2616 if (to != 0) {
2617 TCGv t0 = tcg_temp_new();
2618 TCGv_i32 t2 = tcg_temp_new_i32();
2619 TCGv_ptr addr = tcg_temp_new_ptr();
2621 gen_load_gpr(t0, from);
2622 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2623 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2624 tcg_gen_andi_i32(t2, t2, 0xf);
2625 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2626 tcg_gen_ext_i32_ptr(addr, t2);
2627 tcg_gen_add_ptr(addr, cpu_env, addr);
2629 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2630 tcg_temp_free_ptr(addr);
2631 tcg_temp_free_i32(t2);
2632 tcg_temp_free(t0);
2636 /* MXU General purpose registers moves. */
2637 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2639 if (reg == 0) {
2640 tcg_gen_movi_tl(t, 0);
2641 } else if (reg <= 15) {
2642 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2646 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2648 if (reg > 0 && reg <= 15) {
2649 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2653 /* MXU control register moves. */
2654 static inline void gen_load_mxu_cr(TCGv t)
2656 tcg_gen_mov_tl(t, mxu_CR);
2659 static inline void gen_store_mxu_cr(TCGv t)
2661 /* TODO: Add handling of RW rules for MXU_CR. */
2662 tcg_gen_mov_tl(mxu_CR, t);
2666 /* Tests */
2667 static inline void gen_save_pc(target_ulong pc)
2669 tcg_gen_movi_tl(cpu_PC, pc);
2672 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2674 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2675 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2676 gen_save_pc(ctx->base.pc_next);
2677 ctx->saved_pc = ctx->base.pc_next;
2679 if (ctx->hflags != ctx->saved_hflags) {
2680 tcg_gen_movi_i32(hflags, ctx->hflags);
2681 ctx->saved_hflags = ctx->hflags;
2682 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2683 case MIPS_HFLAG_BR:
2684 break;
2685 case MIPS_HFLAG_BC:
2686 case MIPS_HFLAG_BL:
2687 case MIPS_HFLAG_B:
2688 tcg_gen_movi_tl(btarget, ctx->btarget);
2689 break;
2694 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2696 ctx->saved_hflags = ctx->hflags;
2697 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2698 case MIPS_HFLAG_BR:
2699 break;
2700 case MIPS_HFLAG_BC:
2701 case MIPS_HFLAG_BL:
2702 case MIPS_HFLAG_B:
2703 ctx->btarget = env->btarget;
2704 break;
2708 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2710 TCGv_i32 texcp = tcg_const_i32(excp);
2711 TCGv_i32 terr = tcg_const_i32(err);
2712 save_cpu_state(ctx, 1);
2713 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2714 tcg_temp_free_i32(terr);
2715 tcg_temp_free_i32(texcp);
2716 ctx->base.is_jmp = DISAS_NORETURN;
2719 static inline void generate_exception(DisasContext *ctx, int excp)
2721 gen_helper_0e0i(raise_exception, excp);
2724 static inline void generate_exception_end(DisasContext *ctx, int excp)
2726 generate_exception_err(ctx, excp, 0);
2729 /* Floating point register moves. */
2730 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2732 if (ctx->hflags & MIPS_HFLAG_FRE) {
2733 generate_exception(ctx, EXCP_RI);
2735 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2738 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2740 TCGv_i64 t64;
2741 if (ctx->hflags & MIPS_HFLAG_FRE) {
2742 generate_exception(ctx, EXCP_RI);
2744 t64 = tcg_temp_new_i64();
2745 tcg_gen_extu_i32_i64(t64, t);
2746 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2747 tcg_temp_free_i64(t64);
2750 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2752 if (ctx->hflags & MIPS_HFLAG_F64) {
2753 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2754 } else {
2755 gen_load_fpr32(ctx, t, reg | 1);
2759 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2761 if (ctx->hflags & MIPS_HFLAG_F64) {
2762 TCGv_i64 t64 = tcg_temp_new_i64();
2763 tcg_gen_extu_i32_i64(t64, t);
2764 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2765 tcg_temp_free_i64(t64);
2766 } else {
2767 gen_store_fpr32(ctx, t, reg | 1);
2771 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2773 if (ctx->hflags & MIPS_HFLAG_F64) {
2774 tcg_gen_mov_i64(t, fpu_f64[reg]);
2775 } else {
2776 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2780 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2782 if (ctx->hflags & MIPS_HFLAG_F64) {
2783 tcg_gen_mov_i64(fpu_f64[reg], t);
2784 } else {
2785 TCGv_i64 t0;
2786 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2787 t0 = tcg_temp_new_i64();
2788 tcg_gen_shri_i64(t0, t, 32);
2789 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2790 tcg_temp_free_i64(t0);
2794 static inline int get_fp_bit (int cc)
2796 if (cc)
2797 return 24 + cc;
2798 else
2799 return 23;
2802 /* Addresses computation */
2803 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2805 tcg_gen_add_tl(ret, arg0, arg1);
2807 #if defined(TARGET_MIPS64)
2808 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2809 tcg_gen_ext32s_i64(ret, ret);
2811 #endif
2814 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2815 target_long ofs)
2817 tcg_gen_addi_tl(ret, base, ofs);
2819 #if defined(TARGET_MIPS64)
2820 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2821 tcg_gen_ext32s_i64(ret, ret);
2823 #endif
2826 /* Addresses computation (translation time) */
2827 static target_long addr_add(DisasContext *ctx, target_long base,
2828 target_long offset)
2830 target_long sum = base + offset;
2832 #if defined(TARGET_MIPS64)
2833 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2834 sum = (int32_t)sum;
2836 #endif
2837 return sum;
2840 /* Sign-extract the low 32-bits to a target_long. */
2841 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2843 #if defined(TARGET_MIPS64)
2844 tcg_gen_ext32s_i64(ret, arg);
2845 #else
2846 tcg_gen_extrl_i64_i32(ret, arg);
2847 #endif
2850 /* Sign-extract the high 32-bits to a target_long. */
2851 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2853 #if defined(TARGET_MIPS64)
2854 tcg_gen_sari_i64(ret, arg, 32);
2855 #else
2856 tcg_gen_extrh_i64_i32(ret, arg);
2857 #endif
2860 static inline void check_cp0_enabled(DisasContext *ctx)
2862 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2863 generate_exception_err(ctx, EXCP_CpU, 0);
2866 static inline void check_cp1_enabled(DisasContext *ctx)
2868 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2869 generate_exception_err(ctx, EXCP_CpU, 1);
2872 /* Verify that the processor is running with COP1X instructions enabled.
2873 This is associated with the nabla symbol in the MIPS32 and MIPS64
2874 opcode tables. */
2876 static inline void check_cop1x(DisasContext *ctx)
2878 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2879 generate_exception_end(ctx, EXCP_RI);
2882 /* Verify that the processor is running with 64-bit floating-point
2883 operations enabled. */
2885 static inline void check_cp1_64bitmode(DisasContext *ctx)
2887 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2888 generate_exception_end(ctx, EXCP_RI);
2892 * Verify if floating point register is valid; an operation is not defined
2893 * if bit 0 of any register specification is set and the FR bit in the
2894 * Status register equals zero, since the register numbers specify an
2895 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2896 * in the Status register equals one, both even and odd register numbers
2897 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2899 * Multiple 64 bit wide registers can be checked by calling
2900 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2902 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2904 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2905 generate_exception_end(ctx, EXCP_RI);
2908 /* Verify that the processor is running with DSP instructions enabled.
2909 This is enabled by CP0 Status register MX(24) bit.
2912 static inline void check_dsp(DisasContext *ctx)
2914 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2915 if (ctx->insn_flags & ASE_DSP) {
2916 generate_exception_end(ctx, EXCP_DSPDIS);
2917 } else {
2918 generate_exception_end(ctx, EXCP_RI);
2923 static inline void check_dsp_r2(DisasContext *ctx)
2925 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2926 if (ctx->insn_flags & ASE_DSP) {
2927 generate_exception_end(ctx, EXCP_DSPDIS);
2928 } else {
2929 generate_exception_end(ctx, EXCP_RI);
2934 static inline void check_dsp_r3(DisasContext *ctx)
2936 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2937 if (ctx->insn_flags & ASE_DSP) {
2938 generate_exception_end(ctx, EXCP_DSPDIS);
2939 } else {
2940 generate_exception_end(ctx, EXCP_RI);
2945 /* This code generates a "reserved instruction" exception if the
2946 CPU does not support the instruction set corresponding to flags. */
2947 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2949 if (unlikely(!(ctx->insn_flags & flags))) {
2950 generate_exception_end(ctx, EXCP_RI);
2954 /* This code generates a "reserved instruction" exception if the
2955 CPU has corresponding flag set which indicates that the instruction
2956 has been removed. */
2957 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2959 if (unlikely(ctx->insn_flags & flags)) {
2960 generate_exception_end(ctx, EXCP_RI);
2965 * The Linux kernel traps certain reserved instruction exceptions to
2966 * emulate the corresponding instructions. QEMU is the kernel in user
2967 * mode, so those traps are emulated by accepting the instructions.
2969 * A reserved instruction exception is generated for flagged CPUs if
2970 * QEMU runs in system mode.
2972 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2974 #ifndef CONFIG_USER_ONLY
2975 check_insn_opc_removed(ctx, flags);
2976 #endif
2979 /* This code generates a "reserved instruction" exception if the
2980 CPU does not support 64-bit paired-single (PS) floating point data type */
2981 static inline void check_ps(DisasContext *ctx)
2983 if (unlikely(!ctx->ps)) {
2984 generate_exception(ctx, EXCP_RI);
2986 check_cp1_64bitmode(ctx);
2989 #ifdef TARGET_MIPS64
2990 /* This code generates a "reserved instruction" exception if 64-bit
2991 instructions are not enabled. */
2992 static inline void check_mips_64(DisasContext *ctx)
2994 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2995 generate_exception_end(ctx, EXCP_RI);
2997 #endif
2999 #ifndef CONFIG_USER_ONLY
3000 static inline void check_mvh(DisasContext *ctx)
3002 if (unlikely(!ctx->mvh)) {
3003 generate_exception(ctx, EXCP_RI);
3006 #endif
3009 * This code generates a "reserved instruction" exception if the
3010 * Config5 XNP bit is set.
3012 static inline void check_xnp(DisasContext *ctx)
3014 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3015 generate_exception_end(ctx, EXCP_RI);
3019 #ifndef CONFIG_USER_ONLY
3021 * This code generates a "reserved instruction" exception if the
3022 * Config3 PW bit is NOT set.
3024 static inline void check_pw(DisasContext *ctx)
3026 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3027 generate_exception_end(ctx, EXCP_RI);
3030 #endif
3033 * This code generates a "reserved instruction" exception if the
3034 * Config3 MT bit is NOT set.
3036 static inline void check_mt(DisasContext *ctx)
3038 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3039 generate_exception_end(ctx, EXCP_RI);
3043 #ifndef CONFIG_USER_ONLY
3045 * This code generates a "coprocessor unusable" exception if CP0 is not
3046 * available, and, if that is not the case, generates a "reserved instruction"
3047 * exception if the Config5 MT bit is NOT set. This is needed for availability
3048 * control of some of MT ASE instructions.
3050 static inline void check_cp0_mt(DisasContext *ctx)
3052 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3053 generate_exception_err(ctx, EXCP_CpU, 0);
3054 } else {
3055 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3056 generate_exception_err(ctx, EXCP_RI, 0);
3060 #endif
3063 * This code generates a "reserved instruction" exception if the
3064 * Config5 NMS bit is set.
3066 static inline void check_nms(DisasContext *ctx)
3068 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3069 generate_exception_end(ctx, EXCP_RI);
3074 * This code generates a "reserved instruction" exception if the
3075 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3076 * Config2 TL, and Config5 L2C are unset.
3078 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3080 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3081 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3082 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3083 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3084 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3085 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))
3087 generate_exception_end(ctx, EXCP_RI);
3092 * This code generates a "reserved instruction" exception if the
3093 * Config5 EVA bit is NOT set.
3095 static inline void check_eva(DisasContext *ctx)
3097 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3098 generate_exception_end(ctx, EXCP_RI);
3103 /* Define small wrappers for gen_load_fpr* so that we have a uniform
3104 calling interface for 32 and 64-bit FPRs. No sense in changing
3105 all callers for gen_load_fpr32 when we need the CTX parameter for
3106 this one use. */
3107 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3108 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3109 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3110 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3111 int ft, int fs, int cc) \
3113 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3114 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3115 switch (ifmt) { \
3116 case FMT_PS: \
3117 check_ps(ctx); \
3118 break; \
3119 case FMT_D: \
3120 if (abs) { \
3121 check_cop1x(ctx); \
3123 check_cp1_registers(ctx, fs | ft); \
3124 break; \
3125 case FMT_S: \
3126 if (abs) { \
3127 check_cop1x(ctx); \
3129 break; \
3131 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3132 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3133 switch (n) { \
3134 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3135 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3136 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3137 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3138 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3139 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3140 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3141 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3142 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3143 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3144 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3145 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3146 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3147 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3148 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3149 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3150 default: abort(); \
3152 tcg_temp_free_i##bits (fp0); \
3153 tcg_temp_free_i##bits (fp1); \
3156 FOP_CONDS(, 0, d, FMT_D, 64)
3157 FOP_CONDS(abs, 1, d, FMT_D, 64)
3158 FOP_CONDS(, 0, s, FMT_S, 32)
3159 FOP_CONDS(abs, 1, s, FMT_S, 32)
3160 FOP_CONDS(, 0, ps, FMT_PS, 64)
3161 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3162 #undef FOP_CONDS
3164 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3165 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3166 int ft, int fs, int fd) \
3168 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3169 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3170 if (ifmt == FMT_D) { \
3171 check_cp1_registers(ctx, fs | ft | fd); \
3173 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3174 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3175 switch (n) { \
3176 case 0: \
3177 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3178 break; \
3179 case 1: \
3180 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3181 break; \
3182 case 2: \
3183 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3184 break; \
3185 case 3: \
3186 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3187 break; \
3188 case 4: \
3189 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3190 break; \
3191 case 5: \
3192 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3193 break; \
3194 case 6: \
3195 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3196 break; \
3197 case 7: \
3198 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3199 break; \
3200 case 8: \
3201 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3202 break; \
3203 case 9: \
3204 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3205 break; \
3206 case 10: \
3207 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3208 break; \
3209 case 11: \
3210 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3211 break; \
3212 case 12: \
3213 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3214 break; \
3215 case 13: \
3216 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3217 break; \
3218 case 14: \
3219 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3220 break; \
3221 case 15: \
3222 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3223 break; \
3224 case 17: \
3225 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3226 break; \
3227 case 18: \
3228 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3229 break; \
3230 case 19: \
3231 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3232 break; \
3233 case 25: \
3234 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3235 break; \
3236 case 26: \
3237 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3238 break; \
3239 case 27: \
3240 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3241 break; \
3242 default: \
3243 abort(); \
3245 STORE; \
3246 tcg_temp_free_i ## bits (fp0); \
3247 tcg_temp_free_i ## bits (fp1); \
3250 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3251 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3252 #undef FOP_CONDNS
3253 #undef gen_ldcmp_fpr32
3254 #undef gen_ldcmp_fpr64
3256 /* load/store instructions. */
3257 #ifdef CONFIG_USER_ONLY
3258 #define OP_LD_ATOMIC(insn,fname) \
3259 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3260 DisasContext *ctx) \
3262 TCGv t0 = tcg_temp_new(); \
3263 tcg_gen_mov_tl(t0, arg1); \
3264 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3265 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3266 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3267 tcg_temp_free(t0); \
3269 #else
3270 #define OP_LD_ATOMIC(insn,fname) \
3271 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3272 DisasContext *ctx) \
3274 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3276 #endif
3277 OP_LD_ATOMIC(ll,ld32s);
3278 #if defined(TARGET_MIPS64)
3279 OP_LD_ATOMIC(lld,ld64);
3280 #endif
3281 #undef OP_LD_ATOMIC
3283 #ifdef CONFIG_USER_ONLY
3284 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3285 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3286 DisasContext *ctx) \
3288 TCGv t0 = tcg_temp_new(); \
3289 TCGLabel *l1 = gen_new_label(); \
3290 TCGLabel *l2 = gen_new_label(); \
3292 tcg_gen_andi_tl(t0, arg2, almask); \
3293 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
3294 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
3295 generate_exception(ctx, EXCP_AdES); \
3296 gen_set_label(l1); \
3297 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3298 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3299 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
3300 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3301 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
3302 generate_exception_end(ctx, EXCP_SC); \
3303 gen_set_label(l2); \
3304 tcg_gen_movi_tl(t0, 0); \
3305 gen_store_gpr(t0, rt); \
3306 tcg_temp_free(t0); \
3308 #else
3309 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3310 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3311 DisasContext *ctx) \
3313 TCGv t0 = tcg_temp_new(); \
3314 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3315 gen_store_gpr(t0, rt); \
3316 tcg_temp_free(t0); \
3318 #endif
3319 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3320 #if defined(TARGET_MIPS64)
3321 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3322 #endif
3323 #undef OP_ST_ATOMIC
3325 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3326 int base, int offset)
3328 if (base == 0) {
3329 tcg_gen_movi_tl(addr, offset);
3330 } else if (offset == 0) {
3331 gen_load_gpr(addr, base);
3332 } else {
3333 tcg_gen_movi_tl(addr, offset);
3334 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3338 static target_ulong pc_relative_pc (DisasContext *ctx)
3340 target_ulong pc = ctx->base.pc_next;
3342 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3343 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3345 pc -= branch_bytes;
3348 pc &= ~(target_ulong)3;
3349 return pc;
3352 /* Load */
3353 static void gen_ld(DisasContext *ctx, uint32_t opc,
3354 int rt, int base, int offset)
3356 TCGv t0, t1, t2;
3357 int mem_idx = ctx->mem_idx;
3359 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3360 /* Loongson CPU uses a load to zero register for prefetch.
3361 We emulate it as a NOP. On other CPU we must perform the
3362 actual memory access. */
3363 return;
3366 t0 = tcg_temp_new();
3367 gen_base_offset_addr(ctx, t0, base, offset);
3369 switch (opc) {
3370 #if defined(TARGET_MIPS64)
3371 case OPC_LWU:
3372 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3373 ctx->default_tcg_memop_mask);
3374 gen_store_gpr(t0, rt);
3375 break;
3376 case OPC_LD:
3377 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3378 ctx->default_tcg_memop_mask);
3379 gen_store_gpr(t0, rt);
3380 break;
3381 case OPC_LLD:
3382 case R6_OPC_LLD:
3383 op_ld_lld(t0, t0, mem_idx, ctx);
3384 gen_store_gpr(t0, rt);
3385 break;
3386 case OPC_LDL:
3387 t1 = tcg_temp_new();
3388 /* Do a byte access to possibly trigger a page
3389 fault with the unaligned address. */
3390 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3391 tcg_gen_andi_tl(t1, t0, 7);
3392 #ifndef TARGET_WORDS_BIGENDIAN
3393 tcg_gen_xori_tl(t1, t1, 7);
3394 #endif
3395 tcg_gen_shli_tl(t1, t1, 3);
3396 tcg_gen_andi_tl(t0, t0, ~7);
3397 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3398 tcg_gen_shl_tl(t0, t0, t1);
3399 t2 = tcg_const_tl(-1);
3400 tcg_gen_shl_tl(t2, t2, t1);
3401 gen_load_gpr(t1, rt);
3402 tcg_gen_andc_tl(t1, t1, t2);
3403 tcg_temp_free(t2);
3404 tcg_gen_or_tl(t0, t0, t1);
3405 tcg_temp_free(t1);
3406 gen_store_gpr(t0, rt);
3407 break;
3408 case OPC_LDR:
3409 t1 = tcg_temp_new();
3410 /* Do a byte access to possibly trigger a page
3411 fault with the unaligned address. */
3412 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3413 tcg_gen_andi_tl(t1, t0, 7);
3414 #ifdef TARGET_WORDS_BIGENDIAN
3415 tcg_gen_xori_tl(t1, t1, 7);
3416 #endif
3417 tcg_gen_shli_tl(t1, t1, 3);
3418 tcg_gen_andi_tl(t0, t0, ~7);
3419 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3420 tcg_gen_shr_tl(t0, t0, t1);
3421 tcg_gen_xori_tl(t1, t1, 63);
3422 t2 = tcg_const_tl(0xfffffffffffffffeull);
3423 tcg_gen_shl_tl(t2, t2, t1);
3424 gen_load_gpr(t1, rt);
3425 tcg_gen_and_tl(t1, t1, t2);
3426 tcg_temp_free(t2);
3427 tcg_gen_or_tl(t0, t0, t1);
3428 tcg_temp_free(t1);
3429 gen_store_gpr(t0, rt);
3430 break;
3431 case OPC_LDPC:
3432 t1 = tcg_const_tl(pc_relative_pc(ctx));
3433 gen_op_addr_add(ctx, t0, t0, t1);
3434 tcg_temp_free(t1);
3435 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3436 gen_store_gpr(t0, rt);
3437 break;
3438 #endif
3439 case OPC_LWPC:
3440 t1 = tcg_const_tl(pc_relative_pc(ctx));
3441 gen_op_addr_add(ctx, t0, t0, t1);
3442 tcg_temp_free(t1);
3443 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3444 gen_store_gpr(t0, rt);
3445 break;
3446 case OPC_LWE:
3447 mem_idx = MIPS_HFLAG_UM;
3448 /* fall through */
3449 case OPC_LW:
3450 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3451 ctx->default_tcg_memop_mask);
3452 gen_store_gpr(t0, rt);
3453 break;
3454 case OPC_LHE:
3455 mem_idx = MIPS_HFLAG_UM;
3456 /* fall through */
3457 case OPC_LH:
3458 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3459 ctx->default_tcg_memop_mask);
3460 gen_store_gpr(t0, rt);
3461 break;
3462 case OPC_LHUE:
3463 mem_idx = MIPS_HFLAG_UM;
3464 /* fall through */
3465 case OPC_LHU:
3466 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3467 ctx->default_tcg_memop_mask);
3468 gen_store_gpr(t0, rt);
3469 break;
3470 case OPC_LBE:
3471 mem_idx = MIPS_HFLAG_UM;
3472 /* fall through */
3473 case OPC_LB:
3474 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3475 gen_store_gpr(t0, rt);
3476 break;
3477 case OPC_LBUE:
3478 mem_idx = MIPS_HFLAG_UM;
3479 /* fall through */
3480 case OPC_LBU:
3481 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3482 gen_store_gpr(t0, rt);
3483 break;
3484 case OPC_LWLE:
3485 mem_idx = MIPS_HFLAG_UM;
3486 /* fall through */
3487 case OPC_LWL:
3488 t1 = tcg_temp_new();
3489 /* Do a byte access to possibly trigger a page
3490 fault with the unaligned address. */
3491 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3492 tcg_gen_andi_tl(t1, t0, 3);
3493 #ifndef TARGET_WORDS_BIGENDIAN
3494 tcg_gen_xori_tl(t1, t1, 3);
3495 #endif
3496 tcg_gen_shli_tl(t1, t1, 3);
3497 tcg_gen_andi_tl(t0, t0, ~3);
3498 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3499 tcg_gen_shl_tl(t0, t0, t1);
3500 t2 = tcg_const_tl(-1);
3501 tcg_gen_shl_tl(t2, t2, t1);
3502 gen_load_gpr(t1, rt);
3503 tcg_gen_andc_tl(t1, t1, t2);
3504 tcg_temp_free(t2);
3505 tcg_gen_or_tl(t0, t0, t1);
3506 tcg_temp_free(t1);
3507 tcg_gen_ext32s_tl(t0, t0);
3508 gen_store_gpr(t0, rt);
3509 break;
3510 case OPC_LWRE:
3511 mem_idx = MIPS_HFLAG_UM;
3512 /* fall through */
3513 case OPC_LWR:
3514 t1 = tcg_temp_new();
3515 /* Do a byte access to possibly trigger a page
3516 fault with the unaligned address. */
3517 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3518 tcg_gen_andi_tl(t1, t0, 3);
3519 #ifdef TARGET_WORDS_BIGENDIAN
3520 tcg_gen_xori_tl(t1, t1, 3);
3521 #endif
3522 tcg_gen_shli_tl(t1, t1, 3);
3523 tcg_gen_andi_tl(t0, t0, ~3);
3524 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3525 tcg_gen_shr_tl(t0, t0, t1);
3526 tcg_gen_xori_tl(t1, t1, 31);
3527 t2 = tcg_const_tl(0xfffffffeull);
3528 tcg_gen_shl_tl(t2, t2, t1);
3529 gen_load_gpr(t1, rt);
3530 tcg_gen_and_tl(t1, t1, t2);
3531 tcg_temp_free(t2);
3532 tcg_gen_or_tl(t0, t0, t1);
3533 tcg_temp_free(t1);
3534 tcg_gen_ext32s_tl(t0, t0);
3535 gen_store_gpr(t0, rt);
3536 break;
3537 case OPC_LLE:
3538 mem_idx = MIPS_HFLAG_UM;
3539 /* fall through */
3540 case OPC_LL:
3541 case R6_OPC_LL:
3542 op_ld_ll(t0, t0, mem_idx, ctx);
3543 gen_store_gpr(t0, rt);
3544 break;
3546 tcg_temp_free(t0);
3549 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3550 uint32_t reg1, uint32_t reg2)
3552 TCGv taddr = tcg_temp_new();
3553 TCGv_i64 tval = tcg_temp_new_i64();
3554 TCGv tmp1 = tcg_temp_new();
3555 TCGv tmp2 = tcg_temp_new();
3557 gen_base_offset_addr(ctx, taddr, base, offset);
3558 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3559 #ifdef TARGET_WORDS_BIGENDIAN
3560 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3561 #else
3562 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3563 #endif
3564 gen_store_gpr(tmp1, reg1);
3565 tcg_temp_free(tmp1);
3566 gen_store_gpr(tmp2, reg2);
3567 tcg_temp_free(tmp2);
3568 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3569 tcg_temp_free_i64(tval);
3570 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3571 tcg_temp_free(taddr);
3574 /* Store */
3575 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3576 int base, int offset)
3578 TCGv t0 = tcg_temp_new();
3579 TCGv t1 = tcg_temp_new();
3580 int mem_idx = ctx->mem_idx;
3582 gen_base_offset_addr(ctx, t0, base, offset);
3583 gen_load_gpr(t1, rt);
3584 switch (opc) {
3585 #if defined(TARGET_MIPS64)
3586 case OPC_SD:
3587 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3588 ctx->default_tcg_memop_mask);
3589 break;
3590 case OPC_SDL:
3591 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3592 break;
3593 case OPC_SDR:
3594 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3595 break;
3596 #endif
3597 case OPC_SWE:
3598 mem_idx = MIPS_HFLAG_UM;
3599 /* fall through */
3600 case OPC_SW:
3601 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3602 ctx->default_tcg_memop_mask);
3603 break;
3604 case OPC_SHE:
3605 mem_idx = MIPS_HFLAG_UM;
3606 /* fall through */
3607 case OPC_SH:
3608 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3609 ctx->default_tcg_memop_mask);
3610 break;
3611 case OPC_SBE:
3612 mem_idx = MIPS_HFLAG_UM;
3613 /* fall through */
3614 case OPC_SB:
3615 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3616 break;
3617 case OPC_SWLE:
3618 mem_idx = MIPS_HFLAG_UM;
3619 /* fall through */
3620 case OPC_SWL:
3621 gen_helper_0e2i(swl, t1, t0, mem_idx);
3622 break;
3623 case OPC_SWRE:
3624 mem_idx = MIPS_HFLAG_UM;
3625 /* fall through */
3626 case OPC_SWR:
3627 gen_helper_0e2i(swr, t1, t0, mem_idx);
3628 break;
3630 tcg_temp_free(t0);
3631 tcg_temp_free(t1);
3635 /* Store conditional */
3636 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3637 int base, int16_t offset)
3639 TCGv t0, t1;
3640 int mem_idx = ctx->mem_idx;
3642 #ifdef CONFIG_USER_ONLY
3643 t0 = tcg_temp_local_new();
3644 t1 = tcg_temp_local_new();
3645 #else
3646 t0 = tcg_temp_new();
3647 t1 = tcg_temp_new();
3648 #endif
3649 gen_base_offset_addr(ctx, t0, base, offset);
3650 gen_load_gpr(t1, rt);
3651 switch (opc) {
3652 #if defined(TARGET_MIPS64)
3653 case OPC_SCD:
3654 case R6_OPC_SCD:
3655 op_st_scd(t1, t0, rt, mem_idx, ctx);
3656 break;
3657 #endif
3658 case OPC_SCE:
3659 mem_idx = MIPS_HFLAG_UM;
3660 /* fall through */
3661 case OPC_SC:
3662 case R6_OPC_SC:
3663 op_st_sc(t1, t0, rt, mem_idx, ctx);
3664 break;
3666 tcg_temp_free(t1);
3667 tcg_temp_free(t0);
3670 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3671 uint32_t reg1, uint32_t reg2)
3673 TCGv taddr = tcg_temp_local_new();
3674 TCGv lladdr = tcg_temp_local_new();
3675 TCGv_i64 tval = tcg_temp_new_i64();
3676 TCGv_i64 llval = tcg_temp_new_i64();
3677 TCGv_i64 val = tcg_temp_new_i64();
3678 TCGv tmp1 = tcg_temp_new();
3679 TCGv tmp2 = tcg_temp_new();
3680 TCGLabel *lab_fail = gen_new_label();
3681 TCGLabel *lab_done = gen_new_label();
3683 gen_base_offset_addr(ctx, taddr, base, offset);
3685 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3686 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3688 gen_load_gpr(tmp1, reg1);
3689 gen_load_gpr(tmp2, reg2);
3691 #ifdef TARGET_WORDS_BIGENDIAN
3692 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3693 #else
3694 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3695 #endif
3697 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3698 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3699 ctx->mem_idx, MO_64);
3700 if (reg1 != 0) {
3701 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3703 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3705 gen_set_label(lab_fail);
3707 if (reg1 != 0) {
3708 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3710 gen_set_label(lab_done);
3711 tcg_gen_movi_tl(lladdr, -1);
3712 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3715 /* Load and store */
3716 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3717 TCGv t0)
3719 /* Don't do NOP if destination is zero: we must perform the actual
3720 memory access. */
3721 switch (opc) {
3722 case OPC_LWC1:
3724 TCGv_i32 fp0 = tcg_temp_new_i32();
3725 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3726 ctx->default_tcg_memop_mask);
3727 gen_store_fpr32(ctx, fp0, ft);
3728 tcg_temp_free_i32(fp0);
3730 break;
3731 case OPC_SWC1:
3733 TCGv_i32 fp0 = tcg_temp_new_i32();
3734 gen_load_fpr32(ctx, fp0, ft);
3735 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3736 ctx->default_tcg_memop_mask);
3737 tcg_temp_free_i32(fp0);
3739 break;
3740 case OPC_LDC1:
3742 TCGv_i64 fp0 = tcg_temp_new_i64();
3743 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3744 ctx->default_tcg_memop_mask);
3745 gen_store_fpr64(ctx, fp0, ft);
3746 tcg_temp_free_i64(fp0);
3748 break;
3749 case OPC_SDC1:
3751 TCGv_i64 fp0 = tcg_temp_new_i64();
3752 gen_load_fpr64(ctx, fp0, ft);
3753 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3754 ctx->default_tcg_memop_mask);
3755 tcg_temp_free_i64(fp0);
3757 break;
3758 default:
3759 MIPS_INVAL("flt_ldst");
3760 generate_exception_end(ctx, EXCP_RI);
3761 break;
3765 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3766 int rs, int16_t imm)
3768 TCGv t0 = tcg_temp_new();
3770 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3771 check_cp1_enabled(ctx);
3772 switch (op) {
3773 case OPC_LDC1:
3774 case OPC_SDC1:
3775 check_insn(ctx, ISA_MIPS2);
3776 /* Fallthrough */
3777 default:
3778 gen_base_offset_addr(ctx, t0, rs, imm);
3779 gen_flt_ldst(ctx, op, rt, t0);
3781 } else {
3782 generate_exception_err(ctx, EXCP_CpU, 1);
3784 tcg_temp_free(t0);
3787 /* Arithmetic with immediate operand */
3788 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3789 int rt, int rs, int imm)
3791 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3793 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3794 /* If no destination, treat it as a NOP.
3795 For addi, we must generate the overflow exception when needed. */
3796 return;
3798 switch (opc) {
3799 case OPC_ADDI:
3801 TCGv t0 = tcg_temp_local_new();
3802 TCGv t1 = tcg_temp_new();
3803 TCGv t2 = tcg_temp_new();
3804 TCGLabel *l1 = gen_new_label();
3806 gen_load_gpr(t1, rs);
3807 tcg_gen_addi_tl(t0, t1, uimm);
3808 tcg_gen_ext32s_tl(t0, t0);
3810 tcg_gen_xori_tl(t1, t1, ~uimm);
3811 tcg_gen_xori_tl(t2, t0, uimm);
3812 tcg_gen_and_tl(t1, t1, t2);
3813 tcg_temp_free(t2);
3814 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3815 tcg_temp_free(t1);
3816 /* operands of same sign, result different sign */
3817 generate_exception(ctx, EXCP_OVERFLOW);
3818 gen_set_label(l1);
3819 tcg_gen_ext32s_tl(t0, t0);
3820 gen_store_gpr(t0, rt);
3821 tcg_temp_free(t0);
3823 break;
3824 case OPC_ADDIU:
3825 if (rs != 0) {
3826 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3827 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3828 } else {
3829 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3831 break;
3832 #if defined(TARGET_MIPS64)
3833 case OPC_DADDI:
3835 TCGv t0 = tcg_temp_local_new();
3836 TCGv t1 = tcg_temp_new();
3837 TCGv t2 = tcg_temp_new();
3838 TCGLabel *l1 = gen_new_label();
3840 gen_load_gpr(t1, rs);
3841 tcg_gen_addi_tl(t0, t1, uimm);
3843 tcg_gen_xori_tl(t1, t1, ~uimm);
3844 tcg_gen_xori_tl(t2, t0, uimm);
3845 tcg_gen_and_tl(t1, t1, t2);
3846 tcg_temp_free(t2);
3847 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3848 tcg_temp_free(t1);
3849 /* operands of same sign, result different sign */
3850 generate_exception(ctx, EXCP_OVERFLOW);
3851 gen_set_label(l1);
3852 gen_store_gpr(t0, rt);
3853 tcg_temp_free(t0);
3855 break;
3856 case OPC_DADDIU:
3857 if (rs != 0) {
3858 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3859 } else {
3860 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3862 break;
3863 #endif
3867 /* Logic with immediate operand */
3868 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3869 int rt, int rs, int16_t imm)
3871 target_ulong uimm;
3873 if (rt == 0) {
3874 /* If no destination, treat it as a NOP. */
3875 return;
3877 uimm = (uint16_t)imm;
3878 switch (opc) {
3879 case OPC_ANDI:
3880 if (likely(rs != 0))
3881 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3882 else
3883 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3884 break;
3885 case OPC_ORI:
3886 if (rs != 0)
3887 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3888 else
3889 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3890 break;
3891 case OPC_XORI:
3892 if (likely(rs != 0))
3893 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3894 else
3895 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3896 break;
3897 case OPC_LUI:
3898 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3899 /* OPC_AUI */
3900 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3901 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3902 } else {
3903 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3905 break;
3907 default:
3908 break;
3912 /* Set on less than with immediate operand */
3913 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3914 int rt, int rs, int16_t imm)
3916 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3917 TCGv t0;
3919 if (rt == 0) {
3920 /* If no destination, treat it as a NOP. */
3921 return;
3923 t0 = tcg_temp_new();
3924 gen_load_gpr(t0, rs);
3925 switch (opc) {
3926 case OPC_SLTI:
3927 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3928 break;
3929 case OPC_SLTIU:
3930 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3931 break;
3933 tcg_temp_free(t0);
3936 /* Shifts with immediate operand */
3937 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3938 int rt, int rs, int16_t imm)
3940 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3941 TCGv t0;
3943 if (rt == 0) {
3944 /* If no destination, treat it as a NOP. */
3945 return;
3948 t0 = tcg_temp_new();
3949 gen_load_gpr(t0, rs);
3950 switch (opc) {
3951 case OPC_SLL:
3952 tcg_gen_shli_tl(t0, t0, uimm);
3953 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3954 break;
3955 case OPC_SRA:
3956 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3957 break;
3958 case OPC_SRL:
3959 if (uimm != 0) {
3960 tcg_gen_ext32u_tl(t0, t0);
3961 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3962 } else {
3963 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3965 break;
3966 case OPC_ROTR:
3967 if (uimm != 0) {
3968 TCGv_i32 t1 = tcg_temp_new_i32();
3970 tcg_gen_trunc_tl_i32(t1, t0);
3971 tcg_gen_rotri_i32(t1, t1, uimm);
3972 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3973 tcg_temp_free_i32(t1);
3974 } else {
3975 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3977 break;
3978 #if defined(TARGET_MIPS64)
3979 case OPC_DSLL:
3980 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3981 break;
3982 case OPC_DSRA:
3983 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3984 break;
3985 case OPC_DSRL:
3986 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3987 break;
3988 case OPC_DROTR:
3989 if (uimm != 0) {
3990 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3991 } else {
3992 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3994 break;
3995 case OPC_DSLL32:
3996 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3997 break;
3998 case OPC_DSRA32:
3999 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4000 break;
4001 case OPC_DSRL32:
4002 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4003 break;
4004 case OPC_DROTR32:
4005 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4006 break;
4007 #endif
4009 tcg_temp_free(t0);
4012 /* Arithmetic */
4013 static void gen_arith(DisasContext *ctx, uint32_t opc,
4014 int rd, int rs, int rt)
4016 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4017 && opc != OPC_DADD && opc != OPC_DSUB) {
4018 /* If no destination, treat it as a NOP.
4019 For add & sub, we must generate the overflow exception when needed. */
4020 return;
4023 switch (opc) {
4024 case OPC_ADD:
4026 TCGv t0 = tcg_temp_local_new();
4027 TCGv t1 = tcg_temp_new();
4028 TCGv t2 = tcg_temp_new();
4029 TCGLabel *l1 = gen_new_label();
4031 gen_load_gpr(t1, rs);
4032 gen_load_gpr(t2, rt);
4033 tcg_gen_add_tl(t0, t1, t2);
4034 tcg_gen_ext32s_tl(t0, t0);
4035 tcg_gen_xor_tl(t1, t1, t2);
4036 tcg_gen_xor_tl(t2, t0, t2);
4037 tcg_gen_andc_tl(t1, t2, t1);
4038 tcg_temp_free(t2);
4039 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4040 tcg_temp_free(t1);
4041 /* operands of same sign, result different sign */
4042 generate_exception(ctx, EXCP_OVERFLOW);
4043 gen_set_label(l1);
4044 gen_store_gpr(t0, rd);
4045 tcg_temp_free(t0);
4047 break;
4048 case OPC_ADDU:
4049 if (rs != 0 && rt != 0) {
4050 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4051 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4052 } else if (rs == 0 && rt != 0) {
4053 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4054 } else if (rs != 0 && rt == 0) {
4055 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4056 } else {
4057 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4059 break;
4060 case OPC_SUB:
4062 TCGv t0 = tcg_temp_local_new();
4063 TCGv t1 = tcg_temp_new();
4064 TCGv t2 = tcg_temp_new();
4065 TCGLabel *l1 = gen_new_label();
4067 gen_load_gpr(t1, rs);
4068 gen_load_gpr(t2, rt);
4069 tcg_gen_sub_tl(t0, t1, t2);
4070 tcg_gen_ext32s_tl(t0, t0);
4071 tcg_gen_xor_tl(t2, t1, t2);
4072 tcg_gen_xor_tl(t1, t0, t1);
4073 tcg_gen_and_tl(t1, t1, t2);
4074 tcg_temp_free(t2);
4075 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4076 tcg_temp_free(t1);
4077 /* operands of different sign, first operand and result different sign */
4078 generate_exception(ctx, EXCP_OVERFLOW);
4079 gen_set_label(l1);
4080 gen_store_gpr(t0, rd);
4081 tcg_temp_free(t0);
4083 break;
4084 case OPC_SUBU:
4085 if (rs != 0 && rt != 0) {
4086 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4087 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4088 } else if (rs == 0 && rt != 0) {
4089 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4090 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4091 } else if (rs != 0 && rt == 0) {
4092 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4093 } else {
4094 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4096 break;
4097 #if defined(TARGET_MIPS64)
4098 case OPC_DADD:
4100 TCGv t0 = tcg_temp_local_new();
4101 TCGv t1 = tcg_temp_new();
4102 TCGv t2 = tcg_temp_new();
4103 TCGLabel *l1 = gen_new_label();
4105 gen_load_gpr(t1, rs);
4106 gen_load_gpr(t2, rt);
4107 tcg_gen_add_tl(t0, t1, t2);
4108 tcg_gen_xor_tl(t1, t1, t2);
4109 tcg_gen_xor_tl(t2, t0, t2);
4110 tcg_gen_andc_tl(t1, t2, t1);
4111 tcg_temp_free(t2);
4112 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4113 tcg_temp_free(t1);
4114 /* operands of same sign, result different sign */
4115 generate_exception(ctx, EXCP_OVERFLOW);
4116 gen_set_label(l1);
4117 gen_store_gpr(t0, rd);
4118 tcg_temp_free(t0);
4120 break;
4121 case OPC_DADDU:
4122 if (rs != 0 && rt != 0) {
4123 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4124 } else if (rs == 0 && rt != 0) {
4125 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4126 } else if (rs != 0 && rt == 0) {
4127 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4128 } else {
4129 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4131 break;
4132 case OPC_DSUB:
4134 TCGv t0 = tcg_temp_local_new();
4135 TCGv t1 = tcg_temp_new();
4136 TCGv t2 = tcg_temp_new();
4137 TCGLabel *l1 = gen_new_label();
4139 gen_load_gpr(t1, rs);
4140 gen_load_gpr(t2, rt);
4141 tcg_gen_sub_tl(t0, t1, t2);
4142 tcg_gen_xor_tl(t2, t1, t2);
4143 tcg_gen_xor_tl(t1, t0, t1);
4144 tcg_gen_and_tl(t1, t1, t2);
4145 tcg_temp_free(t2);
4146 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4147 tcg_temp_free(t1);
4148 /* operands of different sign, first operand and result different sign */
4149 generate_exception(ctx, EXCP_OVERFLOW);
4150 gen_set_label(l1);
4151 gen_store_gpr(t0, rd);
4152 tcg_temp_free(t0);
4154 break;
4155 case OPC_DSUBU:
4156 if (rs != 0 && rt != 0) {
4157 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4158 } else if (rs == 0 && rt != 0) {
4159 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4160 } else if (rs != 0 && rt == 0) {
4161 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4162 } else {
4163 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4165 break;
4166 #endif
4167 case OPC_MUL:
4168 if (likely(rs != 0 && rt != 0)) {
4169 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4170 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4171 } else {
4172 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4174 break;
4178 /* Conditional move */
4179 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4180 int rd, int rs, int rt)
4182 TCGv t0, t1, t2;
4184 if (rd == 0) {
4185 /* If no destination, treat it as a NOP. */
4186 return;
4189 t0 = tcg_temp_new();
4190 gen_load_gpr(t0, rt);
4191 t1 = tcg_const_tl(0);
4192 t2 = tcg_temp_new();
4193 gen_load_gpr(t2, rs);
4194 switch (opc) {
4195 case OPC_MOVN:
4196 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4197 break;
4198 case OPC_MOVZ:
4199 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4200 break;
4201 case OPC_SELNEZ:
4202 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4203 break;
4204 case OPC_SELEQZ:
4205 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4206 break;
4208 tcg_temp_free(t2);
4209 tcg_temp_free(t1);
4210 tcg_temp_free(t0);
4213 /* Logic */
4214 static void gen_logic(DisasContext *ctx, uint32_t opc,
4215 int rd, int rs, int rt)
4217 if (rd == 0) {
4218 /* If no destination, treat it as a NOP. */
4219 return;
4222 switch (opc) {
4223 case OPC_AND:
4224 if (likely(rs != 0 && rt != 0)) {
4225 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4226 } else {
4227 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4229 break;
4230 case OPC_NOR:
4231 if (rs != 0 && rt != 0) {
4232 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4233 } else if (rs == 0 && rt != 0) {
4234 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4235 } else if (rs != 0 && rt == 0) {
4236 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4237 } else {
4238 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4240 break;
4241 case OPC_OR:
4242 if (likely(rs != 0 && rt != 0)) {
4243 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4244 } else if (rs == 0 && rt != 0) {
4245 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4246 } else if (rs != 0 && rt == 0) {
4247 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4248 } else {
4249 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4251 break;
4252 case OPC_XOR:
4253 if (likely(rs != 0 && rt != 0)) {
4254 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4255 } else if (rs == 0 && rt != 0) {
4256 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4257 } else if (rs != 0 && rt == 0) {
4258 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4259 } else {
4260 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4262 break;
4266 /* Set on lower than */
4267 static void gen_slt(DisasContext *ctx, uint32_t opc,
4268 int rd, int rs, int rt)
4270 TCGv t0, t1;
4272 if (rd == 0) {
4273 /* If no destination, treat it as a NOP. */
4274 return;
4277 t0 = tcg_temp_new();
4278 t1 = tcg_temp_new();
4279 gen_load_gpr(t0, rs);
4280 gen_load_gpr(t1, rt);
4281 switch (opc) {
4282 case OPC_SLT:
4283 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4284 break;
4285 case OPC_SLTU:
4286 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4287 break;
4289 tcg_temp_free(t0);
4290 tcg_temp_free(t1);
4293 /* Shifts */
4294 static void gen_shift(DisasContext *ctx, uint32_t opc,
4295 int rd, int rs, int rt)
4297 TCGv t0, t1;
4299 if (rd == 0) {
4300 /* If no destination, treat it as a NOP.
4301 For add & sub, we must generate the overflow exception when needed. */
4302 return;
4305 t0 = tcg_temp_new();
4306 t1 = tcg_temp_new();
4307 gen_load_gpr(t0, rs);
4308 gen_load_gpr(t1, rt);
4309 switch (opc) {
4310 case OPC_SLLV:
4311 tcg_gen_andi_tl(t0, t0, 0x1f);
4312 tcg_gen_shl_tl(t0, t1, t0);
4313 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4314 break;
4315 case OPC_SRAV:
4316 tcg_gen_andi_tl(t0, t0, 0x1f);
4317 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4318 break;
4319 case OPC_SRLV:
4320 tcg_gen_ext32u_tl(t1, t1);
4321 tcg_gen_andi_tl(t0, t0, 0x1f);
4322 tcg_gen_shr_tl(t0, t1, t0);
4323 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4324 break;
4325 case OPC_ROTRV:
4327 TCGv_i32 t2 = tcg_temp_new_i32();
4328 TCGv_i32 t3 = tcg_temp_new_i32();
4330 tcg_gen_trunc_tl_i32(t2, t0);
4331 tcg_gen_trunc_tl_i32(t3, t1);
4332 tcg_gen_andi_i32(t2, t2, 0x1f);
4333 tcg_gen_rotr_i32(t2, t3, t2);
4334 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4335 tcg_temp_free_i32(t2);
4336 tcg_temp_free_i32(t3);
4338 break;
4339 #if defined(TARGET_MIPS64)
4340 case OPC_DSLLV:
4341 tcg_gen_andi_tl(t0, t0, 0x3f);
4342 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4343 break;
4344 case OPC_DSRAV:
4345 tcg_gen_andi_tl(t0, t0, 0x3f);
4346 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4347 break;
4348 case OPC_DSRLV:
4349 tcg_gen_andi_tl(t0, t0, 0x3f);
4350 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4351 break;
4352 case OPC_DROTRV:
4353 tcg_gen_andi_tl(t0, t0, 0x3f);
4354 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4355 break;
4356 #endif
4358 tcg_temp_free(t0);
4359 tcg_temp_free(t1);
4362 /* Copy GPR to and from TX79 HI1/LO1 register. */
4363 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4365 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4366 /* Treat as NOP. */
4367 return;
4370 switch (opc) {
4371 case MMI_OPC_MFHI1:
4372 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4373 break;
4374 case MMI_OPC_MFLO1:
4375 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4376 break;
4377 case MMI_OPC_MTHI1:
4378 if (reg != 0) {
4379 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4380 } else {
4381 tcg_gen_movi_tl(cpu_HI[1], 0);
4383 break;
4384 case MMI_OPC_MTLO1:
4385 if (reg != 0) {
4386 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4387 } else {
4388 tcg_gen_movi_tl(cpu_LO[1], 0);
4390 break;
4391 default:
4392 MIPS_INVAL("mfthilo1 TX79");
4393 generate_exception_end(ctx, EXCP_RI);
4394 break;
4398 /* Arithmetic on HI/LO registers */
4399 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4401 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4402 /* Treat as NOP. */
4403 return;
4406 if (acc != 0) {
4407 check_dsp(ctx);
4410 switch (opc) {
4411 case OPC_MFHI:
4412 #if defined(TARGET_MIPS64)
4413 if (acc != 0) {
4414 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4415 } else
4416 #endif
4418 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4420 break;
4421 case OPC_MFLO:
4422 #if defined(TARGET_MIPS64)
4423 if (acc != 0) {
4424 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4425 } else
4426 #endif
4428 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4430 break;
4431 case OPC_MTHI:
4432 if (reg != 0) {
4433 #if defined(TARGET_MIPS64)
4434 if (acc != 0) {
4435 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4436 } else
4437 #endif
4439 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4441 } else {
4442 tcg_gen_movi_tl(cpu_HI[acc], 0);
4444 break;
4445 case OPC_MTLO:
4446 if (reg != 0) {
4447 #if defined(TARGET_MIPS64)
4448 if (acc != 0) {
4449 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4450 } else
4451 #endif
4453 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4455 } else {
4456 tcg_gen_movi_tl(cpu_LO[acc], 0);
4458 break;
4462 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4463 TCGMemOp memop)
4465 TCGv t0 = tcg_const_tl(addr);
4466 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4467 gen_store_gpr(t0, reg);
4468 tcg_temp_free(t0);
4471 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4472 int rs)
4474 target_long offset;
4475 target_long addr;
4477 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4478 case OPC_ADDIUPC:
4479 if (rs != 0) {
4480 offset = sextract32(ctx->opcode << 2, 0, 21);
4481 addr = addr_add(ctx, pc, offset);
4482 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4484 break;
4485 case R6_OPC_LWPC:
4486 offset = sextract32(ctx->opcode << 2, 0, 21);
4487 addr = addr_add(ctx, pc, offset);
4488 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4489 break;
4490 #if defined(TARGET_MIPS64)
4491 case OPC_LWUPC:
4492 check_mips_64(ctx);
4493 offset = sextract32(ctx->opcode << 2, 0, 21);
4494 addr = addr_add(ctx, pc, offset);
4495 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4496 break;
4497 #endif
4498 default:
4499 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4500 case OPC_AUIPC:
4501 if (rs != 0) {
4502 offset = sextract32(ctx->opcode, 0, 16) << 16;
4503 addr = addr_add(ctx, pc, offset);
4504 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4506 break;
4507 case OPC_ALUIPC:
4508 if (rs != 0) {
4509 offset = sextract32(ctx->opcode, 0, 16) << 16;
4510 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4511 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4513 break;
4514 #if defined(TARGET_MIPS64)
4515 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4516 case R6_OPC_LDPC + (1 << 16):
4517 case R6_OPC_LDPC + (2 << 16):
4518 case R6_OPC_LDPC + (3 << 16):
4519 check_mips_64(ctx);
4520 offset = sextract32(ctx->opcode << 3, 0, 21);
4521 addr = addr_add(ctx, (pc & ~0x7), offset);
4522 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4523 break;
4524 #endif
4525 default:
4526 MIPS_INVAL("OPC_PCREL");
4527 generate_exception_end(ctx, EXCP_RI);
4528 break;
4530 break;
4534 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4536 TCGv t0, t1;
4538 if (rd == 0) {
4539 /* Treat as NOP. */
4540 return;
4543 t0 = tcg_temp_new();
4544 t1 = tcg_temp_new();
4546 gen_load_gpr(t0, rs);
4547 gen_load_gpr(t1, rt);
4549 switch (opc) {
4550 case R6_OPC_DIV:
4552 TCGv t2 = tcg_temp_new();
4553 TCGv t3 = tcg_temp_new();
4554 tcg_gen_ext32s_tl(t0, t0);
4555 tcg_gen_ext32s_tl(t1, t1);
4556 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4557 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4558 tcg_gen_and_tl(t2, t2, t3);
4559 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4560 tcg_gen_or_tl(t2, t2, t3);
4561 tcg_gen_movi_tl(t3, 0);
4562 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4563 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4564 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4565 tcg_temp_free(t3);
4566 tcg_temp_free(t2);
4568 break;
4569 case R6_OPC_MOD:
4571 TCGv t2 = tcg_temp_new();
4572 TCGv t3 = tcg_temp_new();
4573 tcg_gen_ext32s_tl(t0, t0);
4574 tcg_gen_ext32s_tl(t1, t1);
4575 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4576 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4577 tcg_gen_and_tl(t2, t2, t3);
4578 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4579 tcg_gen_or_tl(t2, t2, t3);
4580 tcg_gen_movi_tl(t3, 0);
4581 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4582 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4583 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4584 tcg_temp_free(t3);
4585 tcg_temp_free(t2);
4587 break;
4588 case R6_OPC_DIVU:
4590 TCGv t2 = tcg_const_tl(0);
4591 TCGv t3 = tcg_const_tl(1);
4592 tcg_gen_ext32u_tl(t0, t0);
4593 tcg_gen_ext32u_tl(t1, t1);
4594 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4595 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4596 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4597 tcg_temp_free(t3);
4598 tcg_temp_free(t2);
4600 break;
4601 case R6_OPC_MODU:
4603 TCGv t2 = tcg_const_tl(0);
4604 TCGv t3 = tcg_const_tl(1);
4605 tcg_gen_ext32u_tl(t0, t0);
4606 tcg_gen_ext32u_tl(t1, t1);
4607 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4608 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4609 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4610 tcg_temp_free(t3);
4611 tcg_temp_free(t2);
4613 break;
4614 case R6_OPC_MUL:
4616 TCGv_i32 t2 = tcg_temp_new_i32();
4617 TCGv_i32 t3 = tcg_temp_new_i32();
4618 tcg_gen_trunc_tl_i32(t2, t0);
4619 tcg_gen_trunc_tl_i32(t3, t1);
4620 tcg_gen_mul_i32(t2, t2, t3);
4621 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4622 tcg_temp_free_i32(t2);
4623 tcg_temp_free_i32(t3);
4625 break;
4626 case R6_OPC_MUH:
4628 TCGv_i32 t2 = tcg_temp_new_i32();
4629 TCGv_i32 t3 = tcg_temp_new_i32();
4630 tcg_gen_trunc_tl_i32(t2, t0);
4631 tcg_gen_trunc_tl_i32(t3, t1);
4632 tcg_gen_muls2_i32(t2, t3, t2, t3);
4633 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4634 tcg_temp_free_i32(t2);
4635 tcg_temp_free_i32(t3);
4637 break;
4638 case R6_OPC_MULU:
4640 TCGv_i32 t2 = tcg_temp_new_i32();
4641 TCGv_i32 t3 = tcg_temp_new_i32();
4642 tcg_gen_trunc_tl_i32(t2, t0);
4643 tcg_gen_trunc_tl_i32(t3, t1);
4644 tcg_gen_mul_i32(t2, t2, t3);
4645 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4646 tcg_temp_free_i32(t2);
4647 tcg_temp_free_i32(t3);
4649 break;
4650 case R6_OPC_MUHU:
4652 TCGv_i32 t2 = tcg_temp_new_i32();
4653 TCGv_i32 t3 = tcg_temp_new_i32();
4654 tcg_gen_trunc_tl_i32(t2, t0);
4655 tcg_gen_trunc_tl_i32(t3, t1);
4656 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4657 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4658 tcg_temp_free_i32(t2);
4659 tcg_temp_free_i32(t3);
4661 break;
4662 #if defined(TARGET_MIPS64)
4663 case R6_OPC_DDIV:
4665 TCGv t2 = tcg_temp_new();
4666 TCGv t3 = tcg_temp_new();
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4668 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4669 tcg_gen_and_tl(t2, t2, t3);
4670 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4671 tcg_gen_or_tl(t2, t2, t3);
4672 tcg_gen_movi_tl(t3, 0);
4673 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4674 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4675 tcg_temp_free(t3);
4676 tcg_temp_free(t2);
4678 break;
4679 case R6_OPC_DMOD:
4681 TCGv t2 = tcg_temp_new();
4682 TCGv t3 = tcg_temp_new();
4683 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4684 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4685 tcg_gen_and_tl(t2, t2, t3);
4686 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4687 tcg_gen_or_tl(t2, t2, t3);
4688 tcg_gen_movi_tl(t3, 0);
4689 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4690 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4691 tcg_temp_free(t3);
4692 tcg_temp_free(t2);
4694 break;
4695 case R6_OPC_DDIVU:
4697 TCGv t2 = tcg_const_tl(0);
4698 TCGv t3 = tcg_const_tl(1);
4699 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4700 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4701 tcg_temp_free(t3);
4702 tcg_temp_free(t2);
4704 break;
4705 case R6_OPC_DMODU:
4707 TCGv t2 = tcg_const_tl(0);
4708 TCGv t3 = tcg_const_tl(1);
4709 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4710 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4711 tcg_temp_free(t3);
4712 tcg_temp_free(t2);
4714 break;
4715 case R6_OPC_DMUL:
4716 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4717 break;
4718 case R6_OPC_DMUH:
4720 TCGv t2 = tcg_temp_new();
4721 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4722 tcg_temp_free(t2);
4724 break;
4725 case R6_OPC_DMULU:
4726 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4727 break;
4728 case R6_OPC_DMUHU:
4730 TCGv t2 = tcg_temp_new();
4731 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4732 tcg_temp_free(t2);
4734 break;
4735 #endif
4736 default:
4737 MIPS_INVAL("r6 mul/div");
4738 generate_exception_end(ctx, EXCP_RI);
4739 goto out;
4741 out:
4742 tcg_temp_free(t0);
4743 tcg_temp_free(t1);
4746 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4748 TCGv t0, t1;
4750 t0 = tcg_temp_new();
4751 t1 = tcg_temp_new();
4753 gen_load_gpr(t0, rs);
4754 gen_load_gpr(t1, rt);
4756 switch (opc) {
4757 case MMI_OPC_DIV1:
4759 TCGv t2 = tcg_temp_new();
4760 TCGv t3 = tcg_temp_new();
4761 tcg_gen_ext32s_tl(t0, t0);
4762 tcg_gen_ext32s_tl(t1, t1);
4763 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4764 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4765 tcg_gen_and_tl(t2, t2, t3);
4766 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4767 tcg_gen_or_tl(t2, t2, t3);
4768 tcg_gen_movi_tl(t3, 0);
4769 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4770 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4771 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4772 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4773 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4774 tcg_temp_free(t3);
4775 tcg_temp_free(t2);
4777 break;
4778 case MMI_OPC_DIVU1:
4780 TCGv t2 = tcg_const_tl(0);
4781 TCGv t3 = tcg_const_tl(1);
4782 tcg_gen_ext32u_tl(t0, t0);
4783 tcg_gen_ext32u_tl(t1, t1);
4784 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4785 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4786 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4787 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4788 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4789 tcg_temp_free(t3);
4790 tcg_temp_free(t2);
4792 break;
4793 default:
4794 MIPS_INVAL("div1 TX79");
4795 generate_exception_end(ctx, EXCP_RI);
4796 goto out;
4798 out:
4799 tcg_temp_free(t0);
4800 tcg_temp_free(t1);
4803 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4804 int acc, int rs, int rt)
4806 TCGv t0, t1;
4808 t0 = tcg_temp_new();
4809 t1 = tcg_temp_new();
4811 gen_load_gpr(t0, rs);
4812 gen_load_gpr(t1, rt);
4814 if (acc != 0) {
4815 check_dsp(ctx);
4818 switch (opc) {
4819 case OPC_DIV:
4821 TCGv t2 = tcg_temp_new();
4822 TCGv t3 = tcg_temp_new();
4823 tcg_gen_ext32s_tl(t0, t0);
4824 tcg_gen_ext32s_tl(t1, t1);
4825 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4826 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4827 tcg_gen_and_tl(t2, t2, t3);
4828 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4829 tcg_gen_or_tl(t2, t2, t3);
4830 tcg_gen_movi_tl(t3, 0);
4831 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4832 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4833 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4834 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4835 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4836 tcg_temp_free(t3);
4837 tcg_temp_free(t2);
4839 break;
4840 case OPC_DIVU:
4842 TCGv t2 = tcg_const_tl(0);
4843 TCGv t3 = tcg_const_tl(1);
4844 tcg_gen_ext32u_tl(t0, t0);
4845 tcg_gen_ext32u_tl(t1, t1);
4846 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4847 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4848 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4849 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4850 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4851 tcg_temp_free(t3);
4852 tcg_temp_free(t2);
4854 break;
4855 case OPC_MULT:
4857 TCGv_i32 t2 = tcg_temp_new_i32();
4858 TCGv_i32 t3 = tcg_temp_new_i32();
4859 tcg_gen_trunc_tl_i32(t2, t0);
4860 tcg_gen_trunc_tl_i32(t3, t1);
4861 tcg_gen_muls2_i32(t2, t3, t2, t3);
4862 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4863 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4864 tcg_temp_free_i32(t2);
4865 tcg_temp_free_i32(t3);
4867 break;
4868 case OPC_MULTU:
4870 TCGv_i32 t2 = tcg_temp_new_i32();
4871 TCGv_i32 t3 = tcg_temp_new_i32();
4872 tcg_gen_trunc_tl_i32(t2, t0);
4873 tcg_gen_trunc_tl_i32(t3, t1);
4874 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4875 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4876 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4877 tcg_temp_free_i32(t2);
4878 tcg_temp_free_i32(t3);
4880 break;
4881 #if defined(TARGET_MIPS64)
4882 case OPC_DDIV:
4884 TCGv t2 = tcg_temp_new();
4885 TCGv t3 = tcg_temp_new();
4886 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4887 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4888 tcg_gen_and_tl(t2, t2, t3);
4889 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4890 tcg_gen_or_tl(t2, t2, t3);
4891 tcg_gen_movi_tl(t3, 0);
4892 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4893 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4894 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4895 tcg_temp_free(t3);
4896 tcg_temp_free(t2);
4898 break;
4899 case OPC_DDIVU:
4901 TCGv t2 = tcg_const_tl(0);
4902 TCGv t3 = tcg_const_tl(1);
4903 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4904 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4905 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4906 tcg_temp_free(t3);
4907 tcg_temp_free(t2);
4909 break;
4910 case OPC_DMULT:
4911 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4912 break;
4913 case OPC_DMULTU:
4914 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4915 break;
4916 #endif
4917 case OPC_MADD:
4919 TCGv_i64 t2 = tcg_temp_new_i64();
4920 TCGv_i64 t3 = tcg_temp_new_i64();
4922 tcg_gen_ext_tl_i64(t2, t0);
4923 tcg_gen_ext_tl_i64(t3, t1);
4924 tcg_gen_mul_i64(t2, t2, t3);
4925 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4926 tcg_gen_add_i64(t2, t2, t3);
4927 tcg_temp_free_i64(t3);
4928 gen_move_low32(cpu_LO[acc], t2);
4929 gen_move_high32(cpu_HI[acc], t2);
4930 tcg_temp_free_i64(t2);
4932 break;
4933 case OPC_MADDU:
4935 TCGv_i64 t2 = tcg_temp_new_i64();
4936 TCGv_i64 t3 = tcg_temp_new_i64();
4938 tcg_gen_ext32u_tl(t0, t0);
4939 tcg_gen_ext32u_tl(t1, t1);
4940 tcg_gen_extu_tl_i64(t2, t0);
4941 tcg_gen_extu_tl_i64(t3, t1);
4942 tcg_gen_mul_i64(t2, t2, t3);
4943 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4944 tcg_gen_add_i64(t2, t2, t3);
4945 tcg_temp_free_i64(t3);
4946 gen_move_low32(cpu_LO[acc], t2);
4947 gen_move_high32(cpu_HI[acc], t2);
4948 tcg_temp_free_i64(t2);
4950 break;
4951 case OPC_MSUB:
4953 TCGv_i64 t2 = tcg_temp_new_i64();
4954 TCGv_i64 t3 = tcg_temp_new_i64();
4956 tcg_gen_ext_tl_i64(t2, t0);
4957 tcg_gen_ext_tl_i64(t3, t1);
4958 tcg_gen_mul_i64(t2, t2, t3);
4959 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4960 tcg_gen_sub_i64(t2, t3, t2);
4961 tcg_temp_free_i64(t3);
4962 gen_move_low32(cpu_LO[acc], t2);
4963 gen_move_high32(cpu_HI[acc], t2);
4964 tcg_temp_free_i64(t2);
4966 break;
4967 case OPC_MSUBU:
4969 TCGv_i64 t2 = tcg_temp_new_i64();
4970 TCGv_i64 t3 = tcg_temp_new_i64();
4972 tcg_gen_ext32u_tl(t0, t0);
4973 tcg_gen_ext32u_tl(t1, t1);
4974 tcg_gen_extu_tl_i64(t2, t0);
4975 tcg_gen_extu_tl_i64(t3, t1);
4976 tcg_gen_mul_i64(t2, t2, t3);
4977 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4978 tcg_gen_sub_i64(t2, t3, t2);
4979 tcg_temp_free_i64(t3);
4980 gen_move_low32(cpu_LO[acc], t2);
4981 gen_move_high32(cpu_HI[acc], t2);
4982 tcg_temp_free_i64(t2);
4984 break;
4985 default:
4986 MIPS_INVAL("mul/div");
4987 generate_exception_end(ctx, EXCP_RI);
4988 goto out;
4990 out:
4991 tcg_temp_free(t0);
4992 tcg_temp_free(t1);
4996 * These MULT and MULTU instructions implemented in for example the
4997 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4998 * architectures are special three-operand variants with the syntax
5000 * MULT[U][1] rd, rs, rt
5002 * such that
5004 * (rd, LO, HI) <- rs * rt
5006 * where the low-order 32-bits of the result is placed into both the
5007 * GPR rd and the special register LO. The high-order 32-bits of the
5008 * result is placed into the special register HI.
5010 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5011 * which is the zero register that always reads as 0.
5013 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5014 int rd, int rs, int rt)
5016 TCGv t0 = tcg_temp_new();
5017 TCGv t1 = tcg_temp_new();
5018 int acc = 0;
5020 gen_load_gpr(t0, rs);
5021 gen_load_gpr(t1, rt);
5023 switch (opc) {
5024 case MMI_OPC_MULT1:
5025 acc = 1;
5026 /* Fall through */
5027 case OPC_MULT:
5029 TCGv_i32 t2 = tcg_temp_new_i32();
5030 TCGv_i32 t3 = tcg_temp_new_i32();
5031 tcg_gen_trunc_tl_i32(t2, t0);
5032 tcg_gen_trunc_tl_i32(t3, t1);
5033 tcg_gen_muls2_i32(t2, t3, t2, t3);
5034 if (rd) {
5035 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5037 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5038 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5039 tcg_temp_free_i32(t2);
5040 tcg_temp_free_i32(t3);
5042 break;
5043 case MMI_OPC_MULTU1:
5044 acc = 1;
5045 /* Fall through */
5046 case OPC_MULTU:
5048 TCGv_i32 t2 = tcg_temp_new_i32();
5049 TCGv_i32 t3 = tcg_temp_new_i32();
5050 tcg_gen_trunc_tl_i32(t2, t0);
5051 tcg_gen_trunc_tl_i32(t3, t1);
5052 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5053 if (rd) {
5054 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5056 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5057 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5058 tcg_temp_free_i32(t2);
5059 tcg_temp_free_i32(t3);
5061 break;
5062 default:
5063 MIPS_INVAL("mul TXx9");
5064 generate_exception_end(ctx, EXCP_RI);
5065 goto out;
5068 out:
5069 tcg_temp_free(t0);
5070 tcg_temp_free(t1);
5073 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
5074 int rd, int rs, int rt)
5076 TCGv t0 = tcg_temp_new();
5077 TCGv t1 = tcg_temp_new();
5079 gen_load_gpr(t0, rs);
5080 gen_load_gpr(t1, rt);
5082 switch (opc) {
5083 case OPC_VR54XX_MULS:
5084 gen_helper_muls(t0, cpu_env, t0, t1);
5085 break;
5086 case OPC_VR54XX_MULSU:
5087 gen_helper_mulsu(t0, cpu_env, t0, t1);
5088 break;
5089 case OPC_VR54XX_MACC:
5090 gen_helper_macc(t0, cpu_env, t0, t1);
5091 break;
5092 case OPC_VR54XX_MACCU:
5093 gen_helper_maccu(t0, cpu_env, t0, t1);
5094 break;
5095 case OPC_VR54XX_MSAC:
5096 gen_helper_msac(t0, cpu_env, t0, t1);
5097 break;
5098 case OPC_VR54XX_MSACU:
5099 gen_helper_msacu(t0, cpu_env, t0, t1);
5100 break;
5101 case OPC_VR54XX_MULHI:
5102 gen_helper_mulhi(t0, cpu_env, t0, t1);
5103 break;
5104 case OPC_VR54XX_MULHIU:
5105 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5106 break;
5107 case OPC_VR54XX_MULSHI:
5108 gen_helper_mulshi(t0, cpu_env, t0, t1);
5109 break;
5110 case OPC_VR54XX_MULSHIU:
5111 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5112 break;
5113 case OPC_VR54XX_MACCHI:
5114 gen_helper_macchi(t0, cpu_env, t0, t1);
5115 break;
5116 case OPC_VR54XX_MACCHIU:
5117 gen_helper_macchiu(t0, cpu_env, t0, t1);
5118 break;
5119 case OPC_VR54XX_MSACHI:
5120 gen_helper_msachi(t0, cpu_env, t0, t1);
5121 break;
5122 case OPC_VR54XX_MSACHIU:
5123 gen_helper_msachiu(t0, cpu_env, t0, t1);
5124 break;
5125 default:
5126 MIPS_INVAL("mul vr54xx");
5127 generate_exception_end(ctx, EXCP_RI);
5128 goto out;
5130 gen_store_gpr(t0, rd);
5132 out:
5133 tcg_temp_free(t0);
5134 tcg_temp_free(t1);
5137 static void gen_cl (DisasContext *ctx, uint32_t opc,
5138 int rd, int rs)
5140 TCGv t0;
5142 if (rd == 0) {
5143 /* Treat as NOP. */
5144 return;
5146 t0 = cpu_gpr[rd];
5147 gen_load_gpr(t0, rs);
5149 switch (opc) {
5150 case OPC_CLO:
5151 case R6_OPC_CLO:
5152 #if defined(TARGET_MIPS64)
5153 case OPC_DCLO:
5154 case R6_OPC_DCLO:
5155 #endif
5156 tcg_gen_not_tl(t0, t0);
5157 break;
5160 switch (opc) {
5161 case OPC_CLO:
5162 case R6_OPC_CLO:
5163 case OPC_CLZ:
5164 case R6_OPC_CLZ:
5165 tcg_gen_ext32u_tl(t0, t0);
5166 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5167 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5168 break;
5169 #if defined(TARGET_MIPS64)
5170 case OPC_DCLO:
5171 case R6_OPC_DCLO:
5172 case OPC_DCLZ:
5173 case R6_OPC_DCLZ:
5174 tcg_gen_clzi_i64(t0, t0, 64);
5175 break;
5176 #endif
5180 /* Godson integer instructions */
5181 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5182 int rd, int rs, int rt)
5184 TCGv t0, t1;
5186 if (rd == 0) {
5187 /* Treat as NOP. */
5188 return;
5191 switch (opc) {
5192 case OPC_MULT_G_2E:
5193 case OPC_MULT_G_2F:
5194 case OPC_MULTU_G_2E:
5195 case OPC_MULTU_G_2F:
5196 #if defined(TARGET_MIPS64)
5197 case OPC_DMULT_G_2E:
5198 case OPC_DMULT_G_2F:
5199 case OPC_DMULTU_G_2E:
5200 case OPC_DMULTU_G_2F:
5201 #endif
5202 t0 = tcg_temp_new();
5203 t1 = tcg_temp_new();
5204 break;
5205 default:
5206 t0 = tcg_temp_local_new();
5207 t1 = tcg_temp_local_new();
5208 break;
5211 gen_load_gpr(t0, rs);
5212 gen_load_gpr(t1, rt);
5214 switch (opc) {
5215 case OPC_MULT_G_2E:
5216 case OPC_MULT_G_2F:
5217 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5218 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5219 break;
5220 case OPC_MULTU_G_2E:
5221 case OPC_MULTU_G_2F:
5222 tcg_gen_ext32u_tl(t0, t0);
5223 tcg_gen_ext32u_tl(t1, t1);
5224 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5225 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5226 break;
5227 case OPC_DIV_G_2E:
5228 case OPC_DIV_G_2F:
5230 TCGLabel *l1 = gen_new_label();
5231 TCGLabel *l2 = gen_new_label();
5232 TCGLabel *l3 = gen_new_label();
5233 tcg_gen_ext32s_tl(t0, t0);
5234 tcg_gen_ext32s_tl(t1, t1);
5235 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5236 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5237 tcg_gen_br(l3);
5238 gen_set_label(l1);
5239 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5240 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5241 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5242 tcg_gen_br(l3);
5243 gen_set_label(l2);
5244 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5245 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5246 gen_set_label(l3);
5248 break;
5249 case OPC_DIVU_G_2E:
5250 case OPC_DIVU_G_2F:
5252 TCGLabel *l1 = gen_new_label();
5253 TCGLabel *l2 = gen_new_label();
5254 tcg_gen_ext32u_tl(t0, t0);
5255 tcg_gen_ext32u_tl(t1, t1);
5256 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5257 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5258 tcg_gen_br(l2);
5259 gen_set_label(l1);
5260 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5261 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5262 gen_set_label(l2);
5264 break;
5265 case OPC_MOD_G_2E:
5266 case OPC_MOD_G_2F:
5268 TCGLabel *l1 = gen_new_label();
5269 TCGLabel *l2 = gen_new_label();
5270 TCGLabel *l3 = gen_new_label();
5271 tcg_gen_ext32u_tl(t0, t0);
5272 tcg_gen_ext32u_tl(t1, t1);
5273 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5274 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5275 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5276 gen_set_label(l1);
5277 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5278 tcg_gen_br(l3);
5279 gen_set_label(l2);
5280 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5281 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5282 gen_set_label(l3);
5284 break;
5285 case OPC_MODU_G_2E:
5286 case OPC_MODU_G_2F:
5288 TCGLabel *l1 = gen_new_label();
5289 TCGLabel *l2 = gen_new_label();
5290 tcg_gen_ext32u_tl(t0, t0);
5291 tcg_gen_ext32u_tl(t1, t1);
5292 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5293 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5294 tcg_gen_br(l2);
5295 gen_set_label(l1);
5296 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5297 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5298 gen_set_label(l2);
5300 break;
5301 #if defined(TARGET_MIPS64)
5302 case OPC_DMULT_G_2E:
5303 case OPC_DMULT_G_2F:
5304 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5305 break;
5306 case OPC_DMULTU_G_2E:
5307 case OPC_DMULTU_G_2F:
5308 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5309 break;
5310 case OPC_DDIV_G_2E:
5311 case OPC_DDIV_G_2F:
5313 TCGLabel *l1 = gen_new_label();
5314 TCGLabel *l2 = gen_new_label();
5315 TCGLabel *l3 = gen_new_label();
5316 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5317 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5318 tcg_gen_br(l3);
5319 gen_set_label(l1);
5320 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5321 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5322 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5323 tcg_gen_br(l3);
5324 gen_set_label(l2);
5325 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5326 gen_set_label(l3);
5328 break;
5329 case OPC_DDIVU_G_2E:
5330 case OPC_DDIVU_G_2F:
5332 TCGLabel *l1 = gen_new_label();
5333 TCGLabel *l2 = gen_new_label();
5334 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5335 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5336 tcg_gen_br(l2);
5337 gen_set_label(l1);
5338 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5339 gen_set_label(l2);
5341 break;
5342 case OPC_DMOD_G_2E:
5343 case OPC_DMOD_G_2F:
5345 TCGLabel *l1 = gen_new_label();
5346 TCGLabel *l2 = gen_new_label();
5347 TCGLabel *l3 = gen_new_label();
5348 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5349 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5350 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5351 gen_set_label(l1);
5352 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5353 tcg_gen_br(l3);
5354 gen_set_label(l2);
5355 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5356 gen_set_label(l3);
5358 break;
5359 case OPC_DMODU_G_2E:
5360 case OPC_DMODU_G_2F:
5362 TCGLabel *l1 = gen_new_label();
5363 TCGLabel *l2 = gen_new_label();
5364 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5365 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5366 tcg_gen_br(l2);
5367 gen_set_label(l1);
5368 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5369 gen_set_label(l2);
5371 break;
5372 #endif
5375 tcg_temp_free(t0);
5376 tcg_temp_free(t1);
5379 /* Loongson multimedia instructions */
5380 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5382 uint32_t opc, shift_max;
5383 TCGv_i64 t0, t1;
5385 opc = MASK_LMI(ctx->opcode);
5386 switch (opc) {
5387 case OPC_ADD_CP2:
5388 case OPC_SUB_CP2:
5389 case OPC_DADD_CP2:
5390 case OPC_DSUB_CP2:
5391 t0 = tcg_temp_local_new_i64();
5392 t1 = tcg_temp_local_new_i64();
5393 break;
5394 default:
5395 t0 = tcg_temp_new_i64();
5396 t1 = tcg_temp_new_i64();
5397 break;
5400 check_cp1_enabled(ctx);
5401 gen_load_fpr64(ctx, t0, rs);
5402 gen_load_fpr64(ctx, t1, rt);
5404 #define LMI_HELPER(UP, LO) \
5405 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5406 #define LMI_HELPER_1(UP, LO) \
5407 case OPC_##UP: gen_helper_##LO(t0, t0); break
5408 #define LMI_DIRECT(UP, LO, OP) \
5409 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5411 switch (opc) {
5412 LMI_HELPER(PADDSH, paddsh);
5413 LMI_HELPER(PADDUSH, paddush);
5414 LMI_HELPER(PADDH, paddh);
5415 LMI_HELPER(PADDW, paddw);
5416 LMI_HELPER(PADDSB, paddsb);
5417 LMI_HELPER(PADDUSB, paddusb);
5418 LMI_HELPER(PADDB, paddb);
5420 LMI_HELPER(PSUBSH, psubsh);
5421 LMI_HELPER(PSUBUSH, psubush);
5422 LMI_HELPER(PSUBH, psubh);
5423 LMI_HELPER(PSUBW, psubw);
5424 LMI_HELPER(PSUBSB, psubsb);
5425 LMI_HELPER(PSUBUSB, psubusb);
5426 LMI_HELPER(PSUBB, psubb);
5428 LMI_HELPER(PSHUFH, pshufh);
5429 LMI_HELPER(PACKSSWH, packsswh);
5430 LMI_HELPER(PACKSSHB, packsshb);
5431 LMI_HELPER(PACKUSHB, packushb);
5433 LMI_HELPER(PUNPCKLHW, punpcklhw);
5434 LMI_HELPER(PUNPCKHHW, punpckhhw);
5435 LMI_HELPER(PUNPCKLBH, punpcklbh);
5436 LMI_HELPER(PUNPCKHBH, punpckhbh);
5437 LMI_HELPER(PUNPCKLWD, punpcklwd);
5438 LMI_HELPER(PUNPCKHWD, punpckhwd);
5440 LMI_HELPER(PAVGH, pavgh);
5441 LMI_HELPER(PAVGB, pavgb);
5442 LMI_HELPER(PMAXSH, pmaxsh);
5443 LMI_HELPER(PMINSH, pminsh);
5444 LMI_HELPER(PMAXUB, pmaxub);
5445 LMI_HELPER(PMINUB, pminub);
5447 LMI_HELPER(PCMPEQW, pcmpeqw);
5448 LMI_HELPER(PCMPGTW, pcmpgtw);
5449 LMI_HELPER(PCMPEQH, pcmpeqh);
5450 LMI_HELPER(PCMPGTH, pcmpgth);
5451 LMI_HELPER(PCMPEQB, pcmpeqb);
5452 LMI_HELPER(PCMPGTB, pcmpgtb);
5454 LMI_HELPER(PSLLW, psllw);
5455 LMI_HELPER(PSLLH, psllh);
5456 LMI_HELPER(PSRLW, psrlw);
5457 LMI_HELPER(PSRLH, psrlh);
5458 LMI_HELPER(PSRAW, psraw);
5459 LMI_HELPER(PSRAH, psrah);
5461 LMI_HELPER(PMULLH, pmullh);
5462 LMI_HELPER(PMULHH, pmulhh);
5463 LMI_HELPER(PMULHUH, pmulhuh);
5464 LMI_HELPER(PMADDHW, pmaddhw);
5466 LMI_HELPER(PASUBUB, pasubub);
5467 LMI_HELPER_1(BIADD, biadd);
5468 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5470 LMI_DIRECT(PADDD, paddd, add);
5471 LMI_DIRECT(PSUBD, psubd, sub);
5472 LMI_DIRECT(XOR_CP2, xor, xor);
5473 LMI_DIRECT(NOR_CP2, nor, nor);
5474 LMI_DIRECT(AND_CP2, and, and);
5475 LMI_DIRECT(OR_CP2, or, or);
5477 case OPC_PANDN:
5478 tcg_gen_andc_i64(t0, t1, t0);
5479 break;
5481 case OPC_PINSRH_0:
5482 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5483 break;
5484 case OPC_PINSRH_1:
5485 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5486 break;
5487 case OPC_PINSRH_2:
5488 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5489 break;
5490 case OPC_PINSRH_3:
5491 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5492 break;
5494 case OPC_PEXTRH:
5495 tcg_gen_andi_i64(t1, t1, 3);
5496 tcg_gen_shli_i64(t1, t1, 4);
5497 tcg_gen_shr_i64(t0, t0, t1);
5498 tcg_gen_ext16u_i64(t0, t0);
5499 break;
5501 case OPC_ADDU_CP2:
5502 tcg_gen_add_i64(t0, t0, t1);
5503 tcg_gen_ext32s_i64(t0, t0);
5504 break;
5505 case OPC_SUBU_CP2:
5506 tcg_gen_sub_i64(t0, t0, t1);
5507 tcg_gen_ext32s_i64(t0, t0);
5508 break;
5510 case OPC_SLL_CP2:
5511 shift_max = 32;
5512 goto do_shift;
5513 case OPC_SRL_CP2:
5514 shift_max = 32;
5515 goto do_shift;
5516 case OPC_SRA_CP2:
5517 shift_max = 32;
5518 goto do_shift;
5519 case OPC_DSLL_CP2:
5520 shift_max = 64;
5521 goto do_shift;
5522 case OPC_DSRL_CP2:
5523 shift_max = 64;
5524 goto do_shift;
5525 case OPC_DSRA_CP2:
5526 shift_max = 64;
5527 goto do_shift;
5528 do_shift:
5529 /* Make sure shift count isn't TCG undefined behaviour. */
5530 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5532 switch (opc) {
5533 case OPC_SLL_CP2:
5534 case OPC_DSLL_CP2:
5535 tcg_gen_shl_i64(t0, t0, t1);
5536 break;
5537 case OPC_SRA_CP2:
5538 case OPC_DSRA_CP2:
5539 /* Since SRA is UndefinedResult without sign-extended inputs,
5540 we can treat SRA and DSRA the same. */
5541 tcg_gen_sar_i64(t0, t0, t1);
5542 break;
5543 case OPC_SRL_CP2:
5544 /* We want to shift in zeros for SRL; zero-extend first. */
5545 tcg_gen_ext32u_i64(t0, t0);
5546 /* FALLTHRU */
5547 case OPC_DSRL_CP2:
5548 tcg_gen_shr_i64(t0, t0, t1);
5549 break;
5552 if (shift_max == 32) {
5553 tcg_gen_ext32s_i64(t0, t0);
5556 /* Shifts larger than MAX produce zero. */
5557 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5558 tcg_gen_neg_i64(t1, t1);
5559 tcg_gen_and_i64(t0, t0, t1);
5560 break;
5562 case OPC_ADD_CP2:
5563 case OPC_DADD_CP2:
5565 TCGv_i64 t2 = tcg_temp_new_i64();
5566 TCGLabel *lab = gen_new_label();
5568 tcg_gen_mov_i64(t2, t0);
5569 tcg_gen_add_i64(t0, t1, t2);
5570 if (opc == OPC_ADD_CP2) {
5571 tcg_gen_ext32s_i64(t0, t0);
5573 tcg_gen_xor_i64(t1, t1, t2);
5574 tcg_gen_xor_i64(t2, t2, t0);
5575 tcg_gen_andc_i64(t1, t2, t1);
5576 tcg_temp_free_i64(t2);
5577 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5578 generate_exception(ctx, EXCP_OVERFLOW);
5579 gen_set_label(lab);
5580 break;
5583 case OPC_SUB_CP2:
5584 case OPC_DSUB_CP2:
5586 TCGv_i64 t2 = tcg_temp_new_i64();
5587 TCGLabel *lab = gen_new_label();
5589 tcg_gen_mov_i64(t2, t0);
5590 tcg_gen_sub_i64(t0, t1, t2);
5591 if (opc == OPC_SUB_CP2) {
5592 tcg_gen_ext32s_i64(t0, t0);
5594 tcg_gen_xor_i64(t1, t1, t2);
5595 tcg_gen_xor_i64(t2, t2, t0);
5596 tcg_gen_and_i64(t1, t1, t2);
5597 tcg_temp_free_i64(t2);
5598 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5599 generate_exception(ctx, EXCP_OVERFLOW);
5600 gen_set_label(lab);
5601 break;
5604 case OPC_PMULUW:
5605 tcg_gen_ext32u_i64(t0, t0);
5606 tcg_gen_ext32u_i64(t1, t1);
5607 tcg_gen_mul_i64(t0, t0, t1);
5608 break;
5610 case OPC_SEQU_CP2:
5611 case OPC_SEQ_CP2:
5612 case OPC_SLTU_CP2:
5613 case OPC_SLT_CP2:
5614 case OPC_SLEU_CP2:
5615 case OPC_SLE_CP2:
5616 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5617 FD field is the CC field? */
5618 default:
5619 MIPS_INVAL("loongson_cp2");
5620 generate_exception_end(ctx, EXCP_RI);
5621 return;
5624 #undef LMI_HELPER
5625 #undef LMI_DIRECT
5627 gen_store_fpr64(ctx, t0, rd);
5629 tcg_temp_free_i64(t0);
5630 tcg_temp_free_i64(t1);
5633 /* Traps */
5634 static void gen_trap (DisasContext *ctx, uint32_t opc,
5635 int rs, int rt, int16_t imm)
5637 int cond;
5638 TCGv t0 = tcg_temp_new();
5639 TCGv t1 = tcg_temp_new();
5641 cond = 0;
5642 /* Load needed operands */
5643 switch (opc) {
5644 case OPC_TEQ:
5645 case OPC_TGE:
5646 case OPC_TGEU:
5647 case OPC_TLT:
5648 case OPC_TLTU:
5649 case OPC_TNE:
5650 /* Compare two registers */
5651 if (rs != rt) {
5652 gen_load_gpr(t0, rs);
5653 gen_load_gpr(t1, rt);
5654 cond = 1;
5656 break;
5657 case OPC_TEQI:
5658 case OPC_TGEI:
5659 case OPC_TGEIU:
5660 case OPC_TLTI:
5661 case OPC_TLTIU:
5662 case OPC_TNEI:
5663 /* Compare register to immediate */
5664 if (rs != 0 || imm != 0) {
5665 gen_load_gpr(t0, rs);
5666 tcg_gen_movi_tl(t1, (int32_t)imm);
5667 cond = 1;
5669 break;
5671 if (cond == 0) {
5672 switch (opc) {
5673 case OPC_TEQ: /* rs == rs */
5674 case OPC_TEQI: /* r0 == 0 */
5675 case OPC_TGE: /* rs >= rs */
5676 case OPC_TGEI: /* r0 >= 0 */
5677 case OPC_TGEU: /* rs >= rs unsigned */
5678 case OPC_TGEIU: /* r0 >= 0 unsigned */
5679 /* Always trap */
5680 generate_exception_end(ctx, EXCP_TRAP);
5681 break;
5682 case OPC_TLT: /* rs < rs */
5683 case OPC_TLTI: /* r0 < 0 */
5684 case OPC_TLTU: /* rs < rs unsigned */
5685 case OPC_TLTIU: /* r0 < 0 unsigned */
5686 case OPC_TNE: /* rs != rs */
5687 case OPC_TNEI: /* r0 != 0 */
5688 /* Never trap: treat as NOP. */
5689 break;
5691 } else {
5692 TCGLabel *l1 = gen_new_label();
5694 switch (opc) {
5695 case OPC_TEQ:
5696 case OPC_TEQI:
5697 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5698 break;
5699 case OPC_TGE:
5700 case OPC_TGEI:
5701 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5702 break;
5703 case OPC_TGEU:
5704 case OPC_TGEIU:
5705 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5706 break;
5707 case OPC_TLT:
5708 case OPC_TLTI:
5709 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5710 break;
5711 case OPC_TLTU:
5712 case OPC_TLTIU:
5713 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5714 break;
5715 case OPC_TNE:
5716 case OPC_TNEI:
5717 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5718 break;
5720 generate_exception(ctx, EXCP_TRAP);
5721 gen_set_label(l1);
5723 tcg_temp_free(t0);
5724 tcg_temp_free(t1);
5727 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5729 if (unlikely(ctx->base.singlestep_enabled)) {
5730 return false;
5733 #ifndef CONFIG_USER_ONLY
5734 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5735 #else
5736 return true;
5737 #endif
5740 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5742 if (use_goto_tb(ctx, dest)) {
5743 tcg_gen_goto_tb(n);
5744 gen_save_pc(dest);
5745 tcg_gen_exit_tb(ctx->base.tb, n);
5746 } else {
5747 gen_save_pc(dest);
5748 if (ctx->base.singlestep_enabled) {
5749 save_cpu_state(ctx, 0);
5750 gen_helper_raise_exception_debug(cpu_env);
5752 tcg_gen_lookup_and_goto_ptr();
5756 /* Branches (before delay slot) */
5757 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5758 int insn_bytes,
5759 int rs, int rt, int32_t offset,
5760 int delayslot_size)
5762 target_ulong btgt = -1;
5763 int blink = 0;
5764 int bcond_compute = 0;
5765 TCGv t0 = tcg_temp_new();
5766 TCGv t1 = tcg_temp_new();
5768 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5769 #ifdef MIPS_DEBUG_DISAS
5770 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5771 TARGET_FMT_lx "\n", ctx->base.pc_next);
5772 #endif
5773 generate_exception_end(ctx, EXCP_RI);
5774 goto out;
5777 /* Load needed operands */
5778 switch (opc) {
5779 case OPC_BEQ:
5780 case OPC_BEQL:
5781 case OPC_BNE:
5782 case OPC_BNEL:
5783 /* Compare two registers */
5784 if (rs != rt) {
5785 gen_load_gpr(t0, rs);
5786 gen_load_gpr(t1, rt);
5787 bcond_compute = 1;
5789 btgt = ctx->base.pc_next + insn_bytes + offset;
5790 break;
5791 case OPC_BGEZ:
5792 case OPC_BGEZAL:
5793 case OPC_BGEZALL:
5794 case OPC_BGEZL:
5795 case OPC_BGTZ:
5796 case OPC_BGTZL:
5797 case OPC_BLEZ:
5798 case OPC_BLEZL:
5799 case OPC_BLTZ:
5800 case OPC_BLTZAL:
5801 case OPC_BLTZALL:
5802 case OPC_BLTZL:
5803 /* Compare to zero */
5804 if (rs != 0) {
5805 gen_load_gpr(t0, rs);
5806 bcond_compute = 1;
5808 btgt = ctx->base.pc_next + insn_bytes + offset;
5809 break;
5810 case OPC_BPOSGE32:
5811 #if defined(TARGET_MIPS64)
5812 case OPC_BPOSGE64:
5813 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5814 #else
5815 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5816 #endif
5817 bcond_compute = 1;
5818 btgt = ctx->base.pc_next + insn_bytes + offset;
5819 break;
5820 case OPC_J:
5821 case OPC_JAL:
5822 case OPC_JALX:
5823 /* Jump to immediate */
5824 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5825 (uint32_t)offset;
5826 break;
5827 case OPC_JR:
5828 case OPC_JALR:
5829 /* Jump to register */
5830 if (offset != 0 && offset != 16) {
5831 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5832 others are reserved. */
5833 MIPS_INVAL("jump hint");
5834 generate_exception_end(ctx, EXCP_RI);
5835 goto out;
5837 gen_load_gpr(btarget, rs);
5838 break;
5839 default:
5840 MIPS_INVAL("branch/jump");
5841 generate_exception_end(ctx, EXCP_RI);
5842 goto out;
5844 if (bcond_compute == 0) {
5845 /* No condition to be computed */
5846 switch (opc) {
5847 case OPC_BEQ: /* rx == rx */
5848 case OPC_BEQL: /* rx == rx likely */
5849 case OPC_BGEZ: /* 0 >= 0 */
5850 case OPC_BGEZL: /* 0 >= 0 likely */
5851 case OPC_BLEZ: /* 0 <= 0 */
5852 case OPC_BLEZL: /* 0 <= 0 likely */
5853 /* Always take */
5854 ctx->hflags |= MIPS_HFLAG_B;
5855 break;
5856 case OPC_BGEZAL: /* 0 >= 0 */
5857 case OPC_BGEZALL: /* 0 >= 0 likely */
5858 /* Always take and link */
5859 blink = 31;
5860 ctx->hflags |= MIPS_HFLAG_B;
5861 break;
5862 case OPC_BNE: /* rx != rx */
5863 case OPC_BGTZ: /* 0 > 0 */
5864 case OPC_BLTZ: /* 0 < 0 */
5865 /* Treat as NOP. */
5866 goto out;
5867 case OPC_BLTZAL: /* 0 < 0 */
5868 /* Handle as an unconditional branch to get correct delay
5869 slot checking. */
5870 blink = 31;
5871 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5872 ctx->hflags |= MIPS_HFLAG_B;
5873 break;
5874 case OPC_BLTZALL: /* 0 < 0 likely */
5875 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5876 /* Skip the instruction in the delay slot */
5877 ctx->base.pc_next += 4;
5878 goto out;
5879 case OPC_BNEL: /* rx != rx likely */
5880 case OPC_BGTZL: /* 0 > 0 likely */
5881 case OPC_BLTZL: /* 0 < 0 likely */
5882 /* Skip the instruction in the delay slot */
5883 ctx->base.pc_next += 4;
5884 goto out;
5885 case OPC_J:
5886 ctx->hflags |= MIPS_HFLAG_B;
5887 break;
5888 case OPC_JALX:
5889 ctx->hflags |= MIPS_HFLAG_BX;
5890 /* Fallthrough */
5891 case OPC_JAL:
5892 blink = 31;
5893 ctx->hflags |= MIPS_HFLAG_B;
5894 break;
5895 case OPC_JR:
5896 ctx->hflags |= MIPS_HFLAG_BR;
5897 break;
5898 case OPC_JALR:
5899 blink = rt;
5900 ctx->hflags |= MIPS_HFLAG_BR;
5901 break;
5902 default:
5903 MIPS_INVAL("branch/jump");
5904 generate_exception_end(ctx, EXCP_RI);
5905 goto out;
5907 } else {
5908 switch (opc) {
5909 case OPC_BEQ:
5910 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5911 goto not_likely;
5912 case OPC_BEQL:
5913 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5914 goto likely;
5915 case OPC_BNE:
5916 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5917 goto not_likely;
5918 case OPC_BNEL:
5919 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5920 goto likely;
5921 case OPC_BGEZ:
5922 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5923 goto not_likely;
5924 case OPC_BGEZL:
5925 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5926 goto likely;
5927 case OPC_BGEZAL:
5928 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5929 blink = 31;
5930 goto not_likely;
5931 case OPC_BGEZALL:
5932 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5933 blink = 31;
5934 goto likely;
5935 case OPC_BGTZ:
5936 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5937 goto not_likely;
5938 case OPC_BGTZL:
5939 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5940 goto likely;
5941 case OPC_BLEZ:
5942 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5943 goto not_likely;
5944 case OPC_BLEZL:
5945 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5946 goto likely;
5947 case OPC_BLTZ:
5948 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5949 goto not_likely;
5950 case OPC_BLTZL:
5951 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5952 goto likely;
5953 case OPC_BPOSGE32:
5954 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5955 goto not_likely;
5956 #if defined(TARGET_MIPS64)
5957 case OPC_BPOSGE64:
5958 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5959 goto not_likely;
5960 #endif
5961 case OPC_BLTZAL:
5962 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5963 blink = 31;
5964 not_likely:
5965 ctx->hflags |= MIPS_HFLAG_BC;
5966 break;
5967 case OPC_BLTZALL:
5968 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5969 blink = 31;
5970 likely:
5971 ctx->hflags |= MIPS_HFLAG_BL;
5972 break;
5973 default:
5974 MIPS_INVAL("conditional branch/jump");
5975 generate_exception_end(ctx, EXCP_RI);
5976 goto out;
5980 ctx->btarget = btgt;
5982 switch (delayslot_size) {
5983 case 2:
5984 ctx->hflags |= MIPS_HFLAG_BDS16;
5985 break;
5986 case 4:
5987 ctx->hflags |= MIPS_HFLAG_BDS32;
5988 break;
5991 if (blink > 0) {
5992 int post_delay = insn_bytes + delayslot_size;
5993 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5995 tcg_gen_movi_tl(cpu_gpr[blink],
5996 ctx->base.pc_next + post_delay + lowbit);
5999 out:
6000 if (insn_bytes == 2)
6001 ctx->hflags |= MIPS_HFLAG_B16;
6002 tcg_temp_free(t0);
6003 tcg_temp_free(t1);
6007 /* nanoMIPS Branches */
6008 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6009 int insn_bytes,
6010 int rs, int rt, int32_t offset)
6012 target_ulong btgt = -1;
6013 int bcond_compute = 0;
6014 TCGv t0 = tcg_temp_new();
6015 TCGv t1 = tcg_temp_new();
6017 /* Load needed operands */
6018 switch (opc) {
6019 case OPC_BEQ:
6020 case OPC_BNE:
6021 /* Compare two registers */
6022 if (rs != rt) {
6023 gen_load_gpr(t0, rs);
6024 gen_load_gpr(t1, rt);
6025 bcond_compute = 1;
6027 btgt = ctx->base.pc_next + insn_bytes + offset;
6028 break;
6029 case OPC_BGEZAL:
6030 /* Compare to zero */
6031 if (rs != 0) {
6032 gen_load_gpr(t0, rs);
6033 bcond_compute = 1;
6035 btgt = ctx->base.pc_next + insn_bytes + offset;
6036 break;
6037 case OPC_BPOSGE32:
6038 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6039 bcond_compute = 1;
6040 btgt = ctx->base.pc_next + insn_bytes + offset;
6041 break;
6042 case OPC_JR:
6043 case OPC_JALR:
6044 /* Jump to register */
6045 if (offset != 0 && offset != 16) {
6046 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6047 others are reserved. */
6048 MIPS_INVAL("jump hint");
6049 generate_exception_end(ctx, EXCP_RI);
6050 goto out;
6052 gen_load_gpr(btarget, rs);
6053 break;
6054 default:
6055 MIPS_INVAL("branch/jump");
6056 generate_exception_end(ctx, EXCP_RI);
6057 goto out;
6059 if (bcond_compute == 0) {
6060 /* No condition to be computed */
6061 switch (opc) {
6062 case OPC_BEQ: /* rx == rx */
6063 /* Always take */
6064 ctx->hflags |= MIPS_HFLAG_B;
6065 break;
6066 case OPC_BGEZAL: /* 0 >= 0 */
6067 /* Always take and link */
6068 tcg_gen_movi_tl(cpu_gpr[31],
6069 ctx->base.pc_next + insn_bytes);
6070 ctx->hflags |= MIPS_HFLAG_B;
6071 break;
6072 case OPC_BNE: /* rx != rx */
6073 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6074 /* Skip the instruction in the delay slot */
6075 ctx->base.pc_next += 4;
6076 goto out;
6077 case OPC_JR:
6078 ctx->hflags |= MIPS_HFLAG_BR;
6079 break;
6080 case OPC_JALR:
6081 if (rt > 0) {
6082 tcg_gen_movi_tl(cpu_gpr[rt],
6083 ctx->base.pc_next + insn_bytes);
6085 ctx->hflags |= MIPS_HFLAG_BR;
6086 break;
6087 default:
6088 MIPS_INVAL("branch/jump");
6089 generate_exception_end(ctx, EXCP_RI);
6090 goto out;
6092 } else {
6093 switch (opc) {
6094 case OPC_BEQ:
6095 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6096 goto not_likely;
6097 case OPC_BNE:
6098 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6099 goto not_likely;
6100 case OPC_BGEZAL:
6101 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6102 tcg_gen_movi_tl(cpu_gpr[31],
6103 ctx->base.pc_next + insn_bytes);
6104 goto not_likely;
6105 case OPC_BPOSGE32:
6106 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6107 not_likely:
6108 ctx->hflags |= MIPS_HFLAG_BC;
6109 break;
6110 default:
6111 MIPS_INVAL("conditional branch/jump");
6112 generate_exception_end(ctx, EXCP_RI);
6113 goto out;
6117 ctx->btarget = btgt;
6119 out:
6120 if (insn_bytes == 2) {
6121 ctx->hflags |= MIPS_HFLAG_B16;
6123 tcg_temp_free(t0);
6124 tcg_temp_free(t1);
6128 /* special3 bitfield operations */
6129 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
6130 int rs, int lsb, int msb)
6132 TCGv t0 = tcg_temp_new();
6133 TCGv t1 = tcg_temp_new();
6135 gen_load_gpr(t1, rs);
6136 switch (opc) {
6137 case OPC_EXT:
6138 if (lsb + msb > 31) {
6139 goto fail;
6141 if (msb != 31) {
6142 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6143 } else {
6144 /* The two checks together imply that lsb == 0,
6145 so this is a simple sign-extension. */
6146 tcg_gen_ext32s_tl(t0, t1);
6148 break;
6149 #if defined(TARGET_MIPS64)
6150 case OPC_DEXTU:
6151 lsb += 32;
6152 goto do_dext;
6153 case OPC_DEXTM:
6154 msb += 32;
6155 goto do_dext;
6156 case OPC_DEXT:
6157 do_dext:
6158 if (lsb + msb > 63) {
6159 goto fail;
6161 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6162 break;
6163 #endif
6164 case OPC_INS:
6165 if (lsb > msb) {
6166 goto fail;
6168 gen_load_gpr(t0, rt);
6169 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6170 tcg_gen_ext32s_tl(t0, t0);
6171 break;
6172 #if defined(TARGET_MIPS64)
6173 case OPC_DINSU:
6174 lsb += 32;
6175 /* FALLTHRU */
6176 case OPC_DINSM:
6177 msb += 32;
6178 /* FALLTHRU */
6179 case OPC_DINS:
6180 if (lsb > msb) {
6181 goto fail;
6183 gen_load_gpr(t0, rt);
6184 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6185 break;
6186 #endif
6187 default:
6188 fail:
6189 MIPS_INVAL("bitops");
6190 generate_exception_end(ctx, EXCP_RI);
6191 tcg_temp_free(t0);
6192 tcg_temp_free(t1);
6193 return;
6195 gen_store_gpr(t0, rt);
6196 tcg_temp_free(t0);
6197 tcg_temp_free(t1);
6200 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6202 TCGv t0;
6204 if (rd == 0) {
6205 /* If no destination, treat it as a NOP. */
6206 return;
6209 t0 = tcg_temp_new();
6210 gen_load_gpr(t0, rt);
6211 switch (op2) {
6212 case OPC_WSBH:
6214 TCGv t1 = tcg_temp_new();
6215 TCGv t2 = tcg_const_tl(0x00FF00FF);
6217 tcg_gen_shri_tl(t1, t0, 8);
6218 tcg_gen_and_tl(t1, t1, t2);
6219 tcg_gen_and_tl(t0, t0, t2);
6220 tcg_gen_shli_tl(t0, t0, 8);
6221 tcg_gen_or_tl(t0, t0, t1);
6222 tcg_temp_free(t2);
6223 tcg_temp_free(t1);
6224 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6226 break;
6227 case OPC_SEB:
6228 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6229 break;
6230 case OPC_SEH:
6231 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6232 break;
6233 #if defined(TARGET_MIPS64)
6234 case OPC_DSBH:
6236 TCGv t1 = tcg_temp_new();
6237 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6239 tcg_gen_shri_tl(t1, t0, 8);
6240 tcg_gen_and_tl(t1, t1, t2);
6241 tcg_gen_and_tl(t0, t0, t2);
6242 tcg_gen_shli_tl(t0, t0, 8);
6243 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6244 tcg_temp_free(t2);
6245 tcg_temp_free(t1);
6247 break;
6248 case OPC_DSHD:
6250 TCGv t1 = tcg_temp_new();
6251 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6253 tcg_gen_shri_tl(t1, t0, 16);
6254 tcg_gen_and_tl(t1, t1, t2);
6255 tcg_gen_and_tl(t0, t0, t2);
6256 tcg_gen_shli_tl(t0, t0, 16);
6257 tcg_gen_or_tl(t0, t0, t1);
6258 tcg_gen_shri_tl(t1, t0, 32);
6259 tcg_gen_shli_tl(t0, t0, 32);
6260 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6261 tcg_temp_free(t2);
6262 tcg_temp_free(t1);
6264 break;
6265 #endif
6266 default:
6267 MIPS_INVAL("bsfhl");
6268 generate_exception_end(ctx, EXCP_RI);
6269 tcg_temp_free(t0);
6270 return;
6272 tcg_temp_free(t0);
6275 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6276 int imm2)
6278 TCGv t0;
6279 TCGv t1;
6280 if (rd == 0) {
6281 /* Treat as NOP. */
6282 return;
6284 t0 = tcg_temp_new();
6285 t1 = tcg_temp_new();
6286 gen_load_gpr(t0, rs);
6287 gen_load_gpr(t1, rt);
6288 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6289 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6290 if (opc == OPC_LSA) {
6291 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6294 tcg_temp_free(t1);
6295 tcg_temp_free(t0);
6297 return;
6300 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6301 int rt, int bits)
6303 TCGv t0;
6304 if (rd == 0) {
6305 /* Treat as NOP. */
6306 return;
6308 t0 = tcg_temp_new();
6309 if (bits == 0 || bits == wordsz) {
6310 if (bits == 0) {
6311 gen_load_gpr(t0, rt);
6312 } else {
6313 gen_load_gpr(t0, rs);
6315 switch (wordsz) {
6316 case 32:
6317 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6318 break;
6319 #if defined(TARGET_MIPS64)
6320 case 64:
6321 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6322 break;
6323 #endif
6325 } else {
6326 TCGv t1 = tcg_temp_new();
6327 gen_load_gpr(t0, rt);
6328 gen_load_gpr(t1, rs);
6329 switch (wordsz) {
6330 case 32:
6332 TCGv_i64 t2 = tcg_temp_new_i64();
6333 tcg_gen_concat_tl_i64(t2, t1, t0);
6334 tcg_gen_shri_i64(t2, t2, 32 - bits);
6335 gen_move_low32(cpu_gpr[rd], t2);
6336 tcg_temp_free_i64(t2);
6338 break;
6339 #if defined(TARGET_MIPS64)
6340 case 64:
6341 tcg_gen_shli_tl(t0, t0, bits);
6342 tcg_gen_shri_tl(t1, t1, 64 - bits);
6343 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6344 break;
6345 #endif
6347 tcg_temp_free(t1);
6350 tcg_temp_free(t0);
6353 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6354 int bp)
6356 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6359 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6360 int shift)
6362 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6365 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6367 TCGv t0;
6368 if (rd == 0) {
6369 /* Treat as NOP. */
6370 return;
6372 t0 = tcg_temp_new();
6373 gen_load_gpr(t0, rt);
6374 switch (opc) {
6375 case OPC_BITSWAP:
6376 gen_helper_bitswap(cpu_gpr[rd], t0);
6377 break;
6378 #if defined(TARGET_MIPS64)
6379 case OPC_DBITSWAP:
6380 gen_helper_dbitswap(cpu_gpr[rd], t0);
6381 break;
6382 #endif
6384 tcg_temp_free(t0);
6387 #ifndef CONFIG_USER_ONLY
6388 /* CP0 (MMU and control) */
6389 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6391 TCGv_i64 t0 = tcg_temp_new_i64();
6392 TCGv_i64 t1 = tcg_temp_new_i64();
6394 tcg_gen_ext_tl_i64(t0, arg);
6395 tcg_gen_ld_i64(t1, cpu_env, off);
6396 #if defined(TARGET_MIPS64)
6397 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6398 #else
6399 tcg_gen_concat32_i64(t1, t1, t0);
6400 #endif
6401 tcg_gen_st_i64(t1, cpu_env, off);
6402 tcg_temp_free_i64(t1);
6403 tcg_temp_free_i64(t0);
6406 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6408 TCGv_i64 t0 = tcg_temp_new_i64();
6409 TCGv_i64 t1 = tcg_temp_new_i64();
6411 tcg_gen_ext_tl_i64(t0, arg);
6412 tcg_gen_ld_i64(t1, cpu_env, off);
6413 tcg_gen_concat32_i64(t1, t1, t0);
6414 tcg_gen_st_i64(t1, cpu_env, off);
6415 tcg_temp_free_i64(t1);
6416 tcg_temp_free_i64(t0);
6419 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6421 TCGv_i64 t0 = tcg_temp_new_i64();
6423 tcg_gen_ld_i64(t0, cpu_env, off);
6424 #if defined(TARGET_MIPS64)
6425 tcg_gen_shri_i64(t0, t0, 30);
6426 #else
6427 tcg_gen_shri_i64(t0, t0, 32);
6428 #endif
6429 gen_move_low32(arg, t0);
6430 tcg_temp_free_i64(t0);
6433 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6435 TCGv_i64 t0 = tcg_temp_new_i64();
6437 tcg_gen_ld_i64(t0, cpu_env, off);
6438 tcg_gen_shri_i64(t0, t0, 32 + shift);
6439 gen_move_low32(arg, t0);
6440 tcg_temp_free_i64(t0);
6443 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6445 TCGv_i32 t0 = tcg_temp_new_i32();
6447 tcg_gen_ld_i32(t0, cpu_env, off);
6448 tcg_gen_ext_i32_tl(arg, t0);
6449 tcg_temp_free_i32(t0);
6452 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6454 tcg_gen_ld_tl(arg, cpu_env, off);
6455 tcg_gen_ext32s_tl(arg, arg);
6458 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6460 TCGv_i32 t0 = tcg_temp_new_i32();
6462 tcg_gen_trunc_tl_i32(t0, arg);
6463 tcg_gen_st_i32(t0, cpu_env, off);
6464 tcg_temp_free_i32(t0);
6467 #define CP0_CHECK(c) \
6468 do { \
6469 if (!(c)) { \
6470 goto cp0_unimplemented; \
6472 } while (0)
6474 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6476 const char *rn = "invalid";
6478 switch (reg) {
6479 case 2:
6480 switch (sel) {
6481 case 0:
6482 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6483 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6484 rn = "EntryLo0";
6485 break;
6486 default:
6487 goto cp0_unimplemented;
6489 break;
6490 case 3:
6491 switch (sel) {
6492 case 0:
6493 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6494 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6495 rn = "EntryLo1";
6496 break;
6497 default:
6498 goto cp0_unimplemented;
6500 break;
6501 case 17:
6502 switch (sel) {
6503 case 0:
6504 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6505 ctx->CP0_LLAddr_shift);
6506 rn = "LLAddr";
6507 break;
6508 case 1:
6509 CP0_CHECK(ctx->mrp);
6510 gen_helper_mfhc0_maar(arg, cpu_env);
6511 rn = "MAAR";
6512 break;
6513 default:
6514 goto cp0_unimplemented;
6516 break;
6517 case 28:
6518 switch (sel) {
6519 case 0:
6520 case 2:
6521 case 4:
6522 case 6:
6523 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6524 rn = "TagLo";
6525 break;
6526 default:
6527 goto cp0_unimplemented;
6529 break;
6530 default:
6531 goto cp0_unimplemented;
6533 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6534 return;
6536 cp0_unimplemented:
6537 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6538 tcg_gen_movi_tl(arg, 0);
6541 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6543 const char *rn = "invalid";
6544 uint64_t mask = ctx->PAMask >> 36;
6546 switch (reg) {
6547 case 2:
6548 switch (sel) {
6549 case 0:
6550 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6551 tcg_gen_andi_tl(arg, arg, mask);
6552 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6553 rn = "EntryLo0";
6554 break;
6555 default:
6556 goto cp0_unimplemented;
6558 break;
6559 case 3:
6560 switch (sel) {
6561 case 0:
6562 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6563 tcg_gen_andi_tl(arg, arg, mask);
6564 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6565 rn = "EntryLo1";
6566 break;
6567 default:
6568 goto cp0_unimplemented;
6570 break;
6571 case 17:
6572 switch (sel) {
6573 case 0:
6574 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6575 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6576 relevant for modern MIPS cores supporting MTHC0, therefore
6577 treating MTHC0 to LLAddr as NOP. */
6578 rn = "LLAddr";
6579 break;
6580 case 1:
6581 CP0_CHECK(ctx->mrp);
6582 gen_helper_mthc0_maar(cpu_env, arg);
6583 rn = "MAAR";
6584 break;
6585 default:
6586 goto cp0_unimplemented;
6588 break;
6589 case 28:
6590 switch (sel) {
6591 case 0:
6592 case 2:
6593 case 4:
6594 case 6:
6595 tcg_gen_andi_tl(arg, arg, mask);
6596 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6597 rn = "TagLo";
6598 break;
6599 default:
6600 goto cp0_unimplemented;
6602 break;
6603 default:
6604 goto cp0_unimplemented;
6606 trace_mips_translate_c0("mthc0", rn, reg, sel);
6608 cp0_unimplemented:
6609 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6612 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6614 if (ctx->insn_flags & ISA_MIPS32R6) {
6615 tcg_gen_movi_tl(arg, 0);
6616 } else {
6617 tcg_gen_movi_tl(arg, ~0);
6621 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6623 const char *rn = "invalid";
6625 if (sel != 0)
6626 check_insn(ctx, ISA_MIPS32);
6628 switch (reg) {
6629 case 0:
6630 switch (sel) {
6631 case 0:
6632 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6633 rn = "Index";
6634 break;
6635 case 1:
6636 CP0_CHECK(ctx->insn_flags & ASE_MT);
6637 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6638 rn = "MVPControl";
6639 break;
6640 case 2:
6641 CP0_CHECK(ctx->insn_flags & ASE_MT);
6642 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6643 rn = "MVPConf0";
6644 break;
6645 case 3:
6646 CP0_CHECK(ctx->insn_flags & ASE_MT);
6647 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6648 rn = "MVPConf1";
6649 break;
6650 case 4:
6651 CP0_CHECK(ctx->vp);
6652 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6653 rn = "VPControl";
6654 break;
6655 default:
6656 goto cp0_unimplemented;
6658 break;
6659 case 1:
6660 switch (sel) {
6661 case 0:
6662 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6663 gen_helper_mfc0_random(arg, cpu_env);
6664 rn = "Random";
6665 break;
6666 case 1:
6667 CP0_CHECK(ctx->insn_flags & ASE_MT);
6668 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6669 rn = "VPEControl";
6670 break;
6671 case 2:
6672 CP0_CHECK(ctx->insn_flags & ASE_MT);
6673 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6674 rn = "VPEConf0";
6675 break;
6676 case 3:
6677 CP0_CHECK(ctx->insn_flags & ASE_MT);
6678 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6679 rn = "VPEConf1";
6680 break;
6681 case 4:
6682 CP0_CHECK(ctx->insn_flags & ASE_MT);
6683 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6684 rn = "YQMask";
6685 break;
6686 case 5:
6687 CP0_CHECK(ctx->insn_flags & ASE_MT);
6688 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6689 rn = "VPESchedule";
6690 break;
6691 case 6:
6692 CP0_CHECK(ctx->insn_flags & ASE_MT);
6693 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6694 rn = "VPEScheFBack";
6695 break;
6696 case 7:
6697 CP0_CHECK(ctx->insn_flags & ASE_MT);
6698 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6699 rn = "VPEOpt";
6700 break;
6701 default:
6702 goto cp0_unimplemented;
6704 break;
6705 case 2:
6706 switch (sel) {
6707 case 0:
6709 TCGv_i64 tmp = tcg_temp_new_i64();
6710 tcg_gen_ld_i64(tmp, cpu_env,
6711 offsetof(CPUMIPSState, CP0_EntryLo0));
6712 #if defined(TARGET_MIPS64)
6713 if (ctx->rxi) {
6714 /* Move RI/XI fields to bits 31:30 */
6715 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6716 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6718 #endif
6719 gen_move_low32(arg, tmp);
6720 tcg_temp_free_i64(tmp);
6722 rn = "EntryLo0";
6723 break;
6724 case 1:
6725 CP0_CHECK(ctx->insn_flags & ASE_MT);
6726 gen_helper_mfc0_tcstatus(arg, cpu_env);
6727 rn = "TCStatus";
6728 break;
6729 case 2:
6730 CP0_CHECK(ctx->insn_flags & ASE_MT);
6731 gen_helper_mfc0_tcbind(arg, cpu_env);
6732 rn = "TCBind";
6733 break;
6734 case 3:
6735 CP0_CHECK(ctx->insn_flags & ASE_MT);
6736 gen_helper_mfc0_tcrestart(arg, cpu_env);
6737 rn = "TCRestart";
6738 break;
6739 case 4:
6740 CP0_CHECK(ctx->insn_flags & ASE_MT);
6741 gen_helper_mfc0_tchalt(arg, cpu_env);
6742 rn = "TCHalt";
6743 break;
6744 case 5:
6745 CP0_CHECK(ctx->insn_flags & ASE_MT);
6746 gen_helper_mfc0_tccontext(arg, cpu_env);
6747 rn = "TCContext";
6748 break;
6749 case 6:
6750 CP0_CHECK(ctx->insn_flags & ASE_MT);
6751 gen_helper_mfc0_tcschedule(arg, cpu_env);
6752 rn = "TCSchedule";
6753 break;
6754 case 7:
6755 CP0_CHECK(ctx->insn_flags & ASE_MT);
6756 gen_helper_mfc0_tcschefback(arg, cpu_env);
6757 rn = "TCScheFBack";
6758 break;
6759 default:
6760 goto cp0_unimplemented;
6762 break;
6763 case 3:
6764 switch (sel) {
6765 case 0:
6767 TCGv_i64 tmp = tcg_temp_new_i64();
6768 tcg_gen_ld_i64(tmp, cpu_env,
6769 offsetof(CPUMIPSState, CP0_EntryLo1));
6770 #if defined(TARGET_MIPS64)
6771 if (ctx->rxi) {
6772 /* Move RI/XI fields to bits 31:30 */
6773 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6774 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6776 #endif
6777 gen_move_low32(arg, tmp);
6778 tcg_temp_free_i64(tmp);
6780 rn = "EntryLo1";
6781 break;
6782 case 1:
6783 CP0_CHECK(ctx->vp);
6784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6785 rn = "GlobalNumber";
6786 break;
6787 default:
6788 goto cp0_unimplemented;
6790 break;
6791 case 4:
6792 switch (sel) {
6793 case 0:
6794 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6795 tcg_gen_ext32s_tl(arg, arg);
6796 rn = "Context";
6797 break;
6798 case 1:
6799 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6800 rn = "ContextConfig";
6801 goto cp0_unimplemented;
6802 case 2:
6803 CP0_CHECK(ctx->ulri);
6804 tcg_gen_ld_tl(arg, cpu_env,
6805 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6806 tcg_gen_ext32s_tl(arg, arg);
6807 rn = "UserLocal";
6808 break;
6809 default:
6810 goto cp0_unimplemented;
6812 break;
6813 case 5:
6814 switch (sel) {
6815 case 0:
6816 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6817 rn = "PageMask";
6818 break;
6819 case 1:
6820 check_insn(ctx, ISA_MIPS32R2);
6821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6822 rn = "PageGrain";
6823 break;
6824 case 2:
6825 CP0_CHECK(ctx->sc);
6826 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6827 tcg_gen_ext32s_tl(arg, arg);
6828 rn = "SegCtl0";
6829 break;
6830 case 3:
6831 CP0_CHECK(ctx->sc);
6832 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6833 tcg_gen_ext32s_tl(arg, arg);
6834 rn = "SegCtl1";
6835 break;
6836 case 4:
6837 CP0_CHECK(ctx->sc);
6838 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6839 tcg_gen_ext32s_tl(arg, arg);
6840 rn = "SegCtl2";
6841 break;
6842 case 5:
6843 check_pw(ctx);
6844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6845 rn = "PWBase";
6846 break;
6847 case 6:
6848 check_pw(ctx);
6849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6850 rn = "PWField";
6851 break;
6852 case 7:
6853 check_pw(ctx);
6854 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6855 rn = "PWSize";
6856 break;
6857 default:
6858 goto cp0_unimplemented;
6860 break;
6861 case 6:
6862 switch (sel) {
6863 case 0:
6864 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6865 rn = "Wired";
6866 break;
6867 case 1:
6868 check_insn(ctx, ISA_MIPS32R2);
6869 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6870 rn = "SRSConf0";
6871 break;
6872 case 2:
6873 check_insn(ctx, ISA_MIPS32R2);
6874 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6875 rn = "SRSConf1";
6876 break;
6877 case 3:
6878 check_insn(ctx, ISA_MIPS32R2);
6879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6880 rn = "SRSConf2";
6881 break;
6882 case 4:
6883 check_insn(ctx, ISA_MIPS32R2);
6884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6885 rn = "SRSConf3";
6886 break;
6887 case 5:
6888 check_insn(ctx, ISA_MIPS32R2);
6889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6890 rn = "SRSConf4";
6891 break;
6892 case 6:
6893 check_pw(ctx);
6894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6895 rn = "PWCtl";
6896 break;
6897 default:
6898 goto cp0_unimplemented;
6900 break;
6901 case 7:
6902 switch (sel) {
6903 case 0:
6904 check_insn(ctx, ISA_MIPS32R2);
6905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6906 rn = "HWREna";
6907 break;
6908 default:
6909 goto cp0_unimplemented;
6911 break;
6912 case 8:
6913 switch (sel) {
6914 case 0:
6915 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6916 tcg_gen_ext32s_tl(arg, arg);
6917 rn = "BadVAddr";
6918 break;
6919 case 1:
6920 CP0_CHECK(ctx->bi);
6921 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6922 rn = "BadInstr";
6923 break;
6924 case 2:
6925 CP0_CHECK(ctx->bp);
6926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6927 rn = "BadInstrP";
6928 break;
6929 case 3:
6930 CP0_CHECK(ctx->bi);
6931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6932 tcg_gen_andi_tl(arg, arg, ~0xffff);
6933 rn = "BadInstrX";
6934 break;
6935 default:
6936 goto cp0_unimplemented;
6938 break;
6939 case 9:
6940 switch (sel) {
6941 case 0:
6942 /* Mark as an IO operation because we read the time. */
6943 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6944 gen_io_start();
6946 gen_helper_mfc0_count(arg, cpu_env);
6947 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6948 gen_io_end();
6950 /* Break the TB to be able to take timer interrupts immediately
6951 after reading count. DISAS_STOP isn't sufficient, we need to
6952 ensure we break completely out of translated code. */
6953 gen_save_pc(ctx->base.pc_next + 4);
6954 ctx->base.is_jmp = DISAS_EXIT;
6955 rn = "Count";
6956 break;
6957 /* 6,7 are implementation dependent */
6958 default:
6959 goto cp0_unimplemented;
6961 break;
6962 case 10:
6963 switch (sel) {
6964 case 0:
6965 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6966 tcg_gen_ext32s_tl(arg, arg);
6967 rn = "EntryHi";
6968 break;
6969 default:
6970 goto cp0_unimplemented;
6972 break;
6973 case 11:
6974 switch (sel) {
6975 case 0:
6976 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6977 rn = "Compare";
6978 break;
6979 /* 6,7 are implementation dependent */
6980 default:
6981 goto cp0_unimplemented;
6983 break;
6984 case 12:
6985 switch (sel) {
6986 case 0:
6987 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6988 rn = "Status";
6989 break;
6990 case 1:
6991 check_insn(ctx, ISA_MIPS32R2);
6992 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6993 rn = "IntCtl";
6994 break;
6995 case 2:
6996 check_insn(ctx, ISA_MIPS32R2);
6997 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6998 rn = "SRSCtl";
6999 break;
7000 case 3:
7001 check_insn(ctx, ISA_MIPS32R2);
7002 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7003 rn = "SRSMap";
7004 break;
7005 default:
7006 goto cp0_unimplemented;
7008 break;
7009 case 13:
7010 switch (sel) {
7011 case 0:
7012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7013 rn = "Cause";
7014 break;
7015 default:
7016 goto cp0_unimplemented;
7018 break;
7019 case 14:
7020 switch (sel) {
7021 case 0:
7022 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7023 tcg_gen_ext32s_tl(arg, arg);
7024 rn = "EPC";
7025 break;
7026 default:
7027 goto cp0_unimplemented;
7029 break;
7030 case 15:
7031 switch (sel) {
7032 case 0:
7033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7034 rn = "PRid";
7035 break;
7036 case 1:
7037 check_insn(ctx, ISA_MIPS32R2);
7038 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7039 tcg_gen_ext32s_tl(arg, arg);
7040 rn = "EBase";
7041 break;
7042 case 3:
7043 check_insn(ctx, ISA_MIPS32R2);
7044 CP0_CHECK(ctx->cmgcr);
7045 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7046 tcg_gen_ext32s_tl(arg, arg);
7047 rn = "CMGCRBase";
7048 break;
7049 default:
7050 goto cp0_unimplemented;
7052 break;
7053 case 16:
7054 switch (sel) {
7055 case 0:
7056 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7057 rn = "Config";
7058 break;
7059 case 1:
7060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7061 rn = "Config1";
7062 break;
7063 case 2:
7064 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7065 rn = "Config2";
7066 break;
7067 case 3:
7068 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7069 rn = "Config3";
7070 break;
7071 case 4:
7072 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7073 rn = "Config4";
7074 break;
7075 case 5:
7076 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7077 rn = "Config5";
7078 break;
7079 /* 6,7 are implementation dependent */
7080 case 6:
7081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7082 rn = "Config6";
7083 break;
7084 case 7:
7085 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7086 rn = "Config7";
7087 break;
7088 default:
7089 goto cp0_unimplemented;
7091 break;
7092 case 17:
7093 switch (sel) {
7094 case 0:
7095 gen_helper_mfc0_lladdr(arg, cpu_env);
7096 rn = "LLAddr";
7097 break;
7098 case 1:
7099 CP0_CHECK(ctx->mrp);
7100 gen_helper_mfc0_maar(arg, cpu_env);
7101 rn = "MAAR";
7102 break;
7103 case 2:
7104 CP0_CHECK(ctx->mrp);
7105 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7106 rn = "MAARI";
7107 break;
7108 default:
7109 goto cp0_unimplemented;
7111 break;
7112 case 18:
7113 switch (sel) {
7114 case 0:
7115 case 1:
7116 case 2:
7117 case 3:
7118 case 4:
7119 case 5:
7120 case 6:
7121 case 7:
7122 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7123 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7124 rn = "WatchLo";
7125 break;
7126 default:
7127 goto cp0_unimplemented;
7129 break;
7130 case 19:
7131 switch (sel) {
7132 case 0:
7133 case 1:
7134 case 2:
7135 case 3:
7136 case 4:
7137 case 5:
7138 case 6:
7139 case 7:
7140 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7141 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7142 rn = "WatchHi";
7143 break;
7144 default:
7145 goto cp0_unimplemented;
7147 break;
7148 case 20:
7149 switch (sel) {
7150 case 0:
7151 #if defined(TARGET_MIPS64)
7152 check_insn(ctx, ISA_MIPS3);
7153 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7154 tcg_gen_ext32s_tl(arg, arg);
7155 rn = "XContext";
7156 break;
7157 #endif
7158 default:
7159 goto cp0_unimplemented;
7161 break;
7162 case 21:
7163 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7164 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7165 switch (sel) {
7166 case 0:
7167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7168 rn = "Framemask";
7169 break;
7170 default:
7171 goto cp0_unimplemented;
7173 break;
7174 case 22:
7175 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7176 rn = "'Diagnostic"; /* implementation dependent */
7177 break;
7178 case 23:
7179 switch (sel) {
7180 case 0:
7181 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7182 rn = "Debug";
7183 break;
7184 case 1:
7185 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
7186 rn = "TraceControl";
7187 goto cp0_unimplemented;
7188 case 2:
7189 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
7190 rn = "TraceControl2";
7191 goto cp0_unimplemented;
7192 case 3:
7193 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7194 rn = "UserTraceData";
7195 goto cp0_unimplemented;
7196 case 4:
7197 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7198 rn = "TraceBPC";
7199 goto cp0_unimplemented;
7200 default:
7201 goto cp0_unimplemented;
7203 break;
7204 case 24:
7205 switch (sel) {
7206 case 0:
7207 /* EJTAG support */
7208 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7209 tcg_gen_ext32s_tl(arg, arg);
7210 rn = "DEPC";
7211 break;
7212 default:
7213 goto cp0_unimplemented;
7215 break;
7216 case 25:
7217 switch (sel) {
7218 case 0:
7219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7220 rn = "Performance0";
7221 break;
7222 case 1:
7223 // gen_helper_mfc0_performance1(arg);
7224 rn = "Performance1";
7225 goto cp0_unimplemented;
7226 case 2:
7227 // gen_helper_mfc0_performance2(arg);
7228 rn = "Performance2";
7229 goto cp0_unimplemented;
7230 case 3:
7231 // gen_helper_mfc0_performance3(arg);
7232 rn = "Performance3";
7233 goto cp0_unimplemented;
7234 case 4:
7235 // gen_helper_mfc0_performance4(arg);
7236 rn = "Performance4";
7237 goto cp0_unimplemented;
7238 case 5:
7239 // gen_helper_mfc0_performance5(arg);
7240 rn = "Performance5";
7241 goto cp0_unimplemented;
7242 case 6:
7243 // gen_helper_mfc0_performance6(arg);
7244 rn = "Performance6";
7245 goto cp0_unimplemented;
7246 case 7:
7247 // gen_helper_mfc0_performance7(arg);
7248 rn = "Performance7";
7249 goto cp0_unimplemented;
7250 default:
7251 goto cp0_unimplemented;
7253 break;
7254 case 26:
7255 switch (sel) {
7256 case 0:
7257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7258 rn = "ErrCtl";
7259 break;
7260 default:
7261 goto cp0_unimplemented;
7263 break;
7264 case 27:
7265 switch (sel) {
7266 case 0:
7267 case 1:
7268 case 2:
7269 case 3:
7270 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7271 rn = "CacheErr";
7272 break;
7273 default:
7274 goto cp0_unimplemented;
7276 break;
7277 case 28:
7278 switch (sel) {
7279 case 0:
7280 case 2:
7281 case 4:
7282 case 6:
7284 TCGv_i64 tmp = tcg_temp_new_i64();
7285 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7286 gen_move_low32(arg, tmp);
7287 tcg_temp_free_i64(tmp);
7289 rn = "TagLo";
7290 break;
7291 case 1:
7292 case 3:
7293 case 5:
7294 case 7:
7295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7296 rn = "DataLo";
7297 break;
7298 default:
7299 goto cp0_unimplemented;
7301 break;
7302 case 29:
7303 switch (sel) {
7304 case 0:
7305 case 2:
7306 case 4:
7307 case 6:
7308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7309 rn = "TagHi";
7310 break;
7311 case 1:
7312 case 3:
7313 case 5:
7314 case 7:
7315 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7316 rn = "DataHi";
7317 break;
7318 default:
7319 goto cp0_unimplemented;
7321 break;
7322 case 30:
7323 switch (sel) {
7324 case 0:
7325 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7326 tcg_gen_ext32s_tl(arg, arg);
7327 rn = "ErrorEPC";
7328 break;
7329 default:
7330 goto cp0_unimplemented;
7332 break;
7333 case 31:
7334 switch (sel) {
7335 case 0:
7336 /* EJTAG support */
7337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7338 rn = "DESAVE";
7339 break;
7340 case 2:
7341 case 3:
7342 case 4:
7343 case 5:
7344 case 6:
7345 case 7:
7346 CP0_CHECK(ctx->kscrexist & (1 << sel));
7347 tcg_gen_ld_tl(arg, cpu_env,
7348 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7349 tcg_gen_ext32s_tl(arg, arg);
7350 rn = "KScratch";
7351 break;
7352 default:
7353 goto cp0_unimplemented;
7355 break;
7356 default:
7357 goto cp0_unimplemented;
7359 trace_mips_translate_c0("mfc0", rn, reg, sel);
7360 return;
7362 cp0_unimplemented:
7363 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7364 gen_mfc0_unimplemented(ctx, arg);
7367 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7369 const char *rn = "invalid";
7371 if (sel != 0)
7372 check_insn(ctx, ISA_MIPS32);
7374 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7375 gen_io_start();
7378 switch (reg) {
7379 case 0:
7380 switch (sel) {
7381 case 0:
7382 gen_helper_mtc0_index(cpu_env, arg);
7383 rn = "Index";
7384 break;
7385 case 1:
7386 CP0_CHECK(ctx->insn_flags & ASE_MT);
7387 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7388 rn = "MVPControl";
7389 break;
7390 case 2:
7391 CP0_CHECK(ctx->insn_flags & ASE_MT);
7392 /* ignored */
7393 rn = "MVPConf0";
7394 break;
7395 case 3:
7396 CP0_CHECK(ctx->insn_flags & ASE_MT);
7397 /* ignored */
7398 rn = "MVPConf1";
7399 break;
7400 case 4:
7401 CP0_CHECK(ctx->vp);
7402 /* ignored */
7403 rn = "VPControl";
7404 break;
7405 default:
7406 goto cp0_unimplemented;
7408 break;
7409 case 1:
7410 switch (sel) {
7411 case 0:
7412 /* ignored */
7413 rn = "Random";
7414 break;
7415 case 1:
7416 CP0_CHECK(ctx->insn_flags & ASE_MT);
7417 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7418 rn = "VPEControl";
7419 break;
7420 case 2:
7421 CP0_CHECK(ctx->insn_flags & ASE_MT);
7422 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7423 rn = "VPEConf0";
7424 break;
7425 case 3:
7426 CP0_CHECK(ctx->insn_flags & ASE_MT);
7427 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7428 rn = "VPEConf1";
7429 break;
7430 case 4:
7431 CP0_CHECK(ctx->insn_flags & ASE_MT);
7432 gen_helper_mtc0_yqmask(cpu_env, arg);
7433 rn = "YQMask";
7434 break;
7435 case 5:
7436 CP0_CHECK(ctx->insn_flags & ASE_MT);
7437 tcg_gen_st_tl(arg, cpu_env,
7438 offsetof(CPUMIPSState, CP0_VPESchedule));
7439 rn = "VPESchedule";
7440 break;
7441 case 6:
7442 CP0_CHECK(ctx->insn_flags & ASE_MT);
7443 tcg_gen_st_tl(arg, cpu_env,
7444 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7445 rn = "VPEScheFBack";
7446 break;
7447 case 7:
7448 CP0_CHECK(ctx->insn_flags & ASE_MT);
7449 gen_helper_mtc0_vpeopt(cpu_env, arg);
7450 rn = "VPEOpt";
7451 break;
7452 default:
7453 goto cp0_unimplemented;
7455 break;
7456 case 2:
7457 switch (sel) {
7458 case 0:
7459 gen_helper_mtc0_entrylo0(cpu_env, arg);
7460 rn = "EntryLo0";
7461 break;
7462 case 1:
7463 CP0_CHECK(ctx->insn_flags & ASE_MT);
7464 gen_helper_mtc0_tcstatus(cpu_env, arg);
7465 rn = "TCStatus";
7466 break;
7467 case 2:
7468 CP0_CHECK(ctx->insn_flags & ASE_MT);
7469 gen_helper_mtc0_tcbind(cpu_env, arg);
7470 rn = "TCBind";
7471 break;
7472 case 3:
7473 CP0_CHECK(ctx->insn_flags & ASE_MT);
7474 gen_helper_mtc0_tcrestart(cpu_env, arg);
7475 rn = "TCRestart";
7476 break;
7477 case 4:
7478 CP0_CHECK(ctx->insn_flags & ASE_MT);
7479 gen_helper_mtc0_tchalt(cpu_env, arg);
7480 rn = "TCHalt";
7481 break;
7482 case 5:
7483 CP0_CHECK(ctx->insn_flags & ASE_MT);
7484 gen_helper_mtc0_tccontext(cpu_env, arg);
7485 rn = "TCContext";
7486 break;
7487 case 6:
7488 CP0_CHECK(ctx->insn_flags & ASE_MT);
7489 gen_helper_mtc0_tcschedule(cpu_env, arg);
7490 rn = "TCSchedule";
7491 break;
7492 case 7:
7493 CP0_CHECK(ctx->insn_flags & ASE_MT);
7494 gen_helper_mtc0_tcschefback(cpu_env, arg);
7495 rn = "TCScheFBack";
7496 break;
7497 default:
7498 goto cp0_unimplemented;
7500 break;
7501 case 3:
7502 switch (sel) {
7503 case 0:
7504 gen_helper_mtc0_entrylo1(cpu_env, arg);
7505 rn = "EntryLo1";
7506 break;
7507 case 1:
7508 CP0_CHECK(ctx->vp);
7509 /* ignored */
7510 rn = "GlobalNumber";
7511 break;
7512 default:
7513 goto cp0_unimplemented;
7515 break;
7516 case 4:
7517 switch (sel) {
7518 case 0:
7519 gen_helper_mtc0_context(cpu_env, arg);
7520 rn = "Context";
7521 break;
7522 case 1:
7523 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7524 rn = "ContextConfig";
7525 goto cp0_unimplemented;
7526 case 2:
7527 CP0_CHECK(ctx->ulri);
7528 tcg_gen_st_tl(arg, cpu_env,
7529 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7530 rn = "UserLocal";
7531 break;
7532 default:
7533 goto cp0_unimplemented;
7535 break;
7536 case 5:
7537 switch (sel) {
7538 case 0:
7539 gen_helper_mtc0_pagemask(cpu_env, arg);
7540 rn = "PageMask";
7541 break;
7542 case 1:
7543 check_insn(ctx, ISA_MIPS32R2);
7544 gen_helper_mtc0_pagegrain(cpu_env, arg);
7545 rn = "PageGrain";
7546 ctx->base.is_jmp = DISAS_STOP;
7547 break;
7548 case 2:
7549 CP0_CHECK(ctx->sc);
7550 gen_helper_mtc0_segctl0(cpu_env, arg);
7551 rn = "SegCtl0";
7552 break;
7553 case 3:
7554 CP0_CHECK(ctx->sc);
7555 gen_helper_mtc0_segctl1(cpu_env, arg);
7556 rn = "SegCtl1";
7557 break;
7558 case 4:
7559 CP0_CHECK(ctx->sc);
7560 gen_helper_mtc0_segctl2(cpu_env, arg);
7561 rn = "SegCtl2";
7562 break;
7563 case 5:
7564 check_pw(ctx);
7565 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7566 rn = "PWBase";
7567 break;
7568 case 6:
7569 check_pw(ctx);
7570 gen_helper_mtc0_pwfield(cpu_env, arg);
7571 rn = "PWField";
7572 break;
7573 case 7:
7574 check_pw(ctx);
7575 gen_helper_mtc0_pwsize(cpu_env, arg);
7576 rn = "PWSize";
7577 break;
7578 default:
7579 goto cp0_unimplemented;
7581 break;
7582 case 6:
7583 switch (sel) {
7584 case 0:
7585 gen_helper_mtc0_wired(cpu_env, arg);
7586 rn = "Wired";
7587 break;
7588 case 1:
7589 check_insn(ctx, ISA_MIPS32R2);
7590 gen_helper_mtc0_srsconf0(cpu_env, arg);
7591 rn = "SRSConf0";
7592 break;
7593 case 2:
7594 check_insn(ctx, ISA_MIPS32R2);
7595 gen_helper_mtc0_srsconf1(cpu_env, arg);
7596 rn = "SRSConf1";
7597 break;
7598 case 3:
7599 check_insn(ctx, ISA_MIPS32R2);
7600 gen_helper_mtc0_srsconf2(cpu_env, arg);
7601 rn = "SRSConf2";
7602 break;
7603 case 4:
7604 check_insn(ctx, ISA_MIPS32R2);
7605 gen_helper_mtc0_srsconf3(cpu_env, arg);
7606 rn = "SRSConf3";
7607 break;
7608 case 5:
7609 check_insn(ctx, ISA_MIPS32R2);
7610 gen_helper_mtc0_srsconf4(cpu_env, arg);
7611 rn = "SRSConf4";
7612 break;
7613 case 6:
7614 check_pw(ctx);
7615 gen_helper_mtc0_pwctl(cpu_env, arg);
7616 rn = "PWCtl";
7617 break;
7618 default:
7619 goto cp0_unimplemented;
7621 break;
7622 case 7:
7623 switch (sel) {
7624 case 0:
7625 check_insn(ctx, ISA_MIPS32R2);
7626 gen_helper_mtc0_hwrena(cpu_env, arg);
7627 ctx->base.is_jmp = DISAS_STOP;
7628 rn = "HWREna";
7629 break;
7630 default:
7631 goto cp0_unimplemented;
7633 break;
7634 case 8:
7635 switch (sel) {
7636 case 0:
7637 /* ignored */
7638 rn = "BadVAddr";
7639 break;
7640 case 1:
7641 /* ignored */
7642 rn = "BadInstr";
7643 break;
7644 case 2:
7645 /* ignored */
7646 rn = "BadInstrP";
7647 break;
7648 case 3:
7649 /* ignored */
7650 rn = "BadInstrX";
7651 break;
7652 default:
7653 goto cp0_unimplemented;
7655 break;
7656 case 9:
7657 switch (sel) {
7658 case 0:
7659 gen_helper_mtc0_count(cpu_env, arg);
7660 rn = "Count";
7661 break;
7662 /* 6,7 are implementation dependent */
7663 default:
7664 goto cp0_unimplemented;
7666 break;
7667 case 10:
7668 switch (sel) {
7669 case 0:
7670 gen_helper_mtc0_entryhi(cpu_env, arg);
7671 rn = "EntryHi";
7672 break;
7673 default:
7674 goto cp0_unimplemented;
7676 break;
7677 case 11:
7678 switch (sel) {
7679 case 0:
7680 gen_helper_mtc0_compare(cpu_env, arg);
7681 rn = "Compare";
7682 break;
7683 /* 6,7 are implementation dependent */
7684 default:
7685 goto cp0_unimplemented;
7687 break;
7688 case 12:
7689 switch (sel) {
7690 case 0:
7691 save_cpu_state(ctx, 1);
7692 gen_helper_mtc0_status(cpu_env, arg);
7693 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7694 gen_save_pc(ctx->base.pc_next + 4);
7695 ctx->base.is_jmp = DISAS_EXIT;
7696 rn = "Status";
7697 break;
7698 case 1:
7699 check_insn(ctx, ISA_MIPS32R2);
7700 gen_helper_mtc0_intctl(cpu_env, arg);
7701 /* Stop translation as we may have switched the execution mode */
7702 ctx->base.is_jmp = DISAS_STOP;
7703 rn = "IntCtl";
7704 break;
7705 case 2:
7706 check_insn(ctx, ISA_MIPS32R2);
7707 gen_helper_mtc0_srsctl(cpu_env, arg);
7708 /* Stop translation as we may have switched the execution mode */
7709 ctx->base.is_jmp = DISAS_STOP;
7710 rn = "SRSCtl";
7711 break;
7712 case 3:
7713 check_insn(ctx, ISA_MIPS32R2);
7714 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7715 /* Stop translation as we may have switched the execution mode */
7716 ctx->base.is_jmp = DISAS_STOP;
7717 rn = "SRSMap";
7718 break;
7719 default:
7720 goto cp0_unimplemented;
7722 break;
7723 case 13:
7724 switch (sel) {
7725 case 0:
7726 save_cpu_state(ctx, 1);
7727 gen_helper_mtc0_cause(cpu_env, arg);
7728 /* Stop translation as we may have triggered an interrupt.
7729 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7730 * translated code to check for pending interrupts. */
7731 gen_save_pc(ctx->base.pc_next + 4);
7732 ctx->base.is_jmp = DISAS_EXIT;
7733 rn = "Cause";
7734 break;
7735 default:
7736 goto cp0_unimplemented;
7738 break;
7739 case 14:
7740 switch (sel) {
7741 case 0:
7742 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7743 rn = "EPC";
7744 break;
7745 default:
7746 goto cp0_unimplemented;
7748 break;
7749 case 15:
7750 switch (sel) {
7751 case 0:
7752 /* ignored */
7753 rn = "PRid";
7754 break;
7755 case 1:
7756 check_insn(ctx, ISA_MIPS32R2);
7757 gen_helper_mtc0_ebase(cpu_env, arg);
7758 rn = "EBase";
7759 break;
7760 default:
7761 goto cp0_unimplemented;
7763 break;
7764 case 16:
7765 switch (sel) {
7766 case 0:
7767 gen_helper_mtc0_config0(cpu_env, arg);
7768 rn = "Config";
7769 /* Stop translation as we may have switched the execution mode */
7770 ctx->base.is_jmp = DISAS_STOP;
7771 break;
7772 case 1:
7773 /* ignored, read only */
7774 rn = "Config1";
7775 break;
7776 case 2:
7777 gen_helper_mtc0_config2(cpu_env, arg);
7778 rn = "Config2";
7779 /* Stop translation as we may have switched the execution mode */
7780 ctx->base.is_jmp = DISAS_STOP;
7781 break;
7782 case 3:
7783 gen_helper_mtc0_config3(cpu_env, arg);
7784 rn = "Config3";
7785 /* Stop translation as we may have switched the execution mode */
7786 ctx->base.is_jmp = DISAS_STOP;
7787 break;
7788 case 4:
7789 gen_helper_mtc0_config4(cpu_env, arg);
7790 rn = "Config4";
7791 ctx->base.is_jmp = DISAS_STOP;
7792 break;
7793 case 5:
7794 gen_helper_mtc0_config5(cpu_env, arg);
7795 rn = "Config5";
7796 /* Stop translation as we may have switched the execution mode */
7797 ctx->base.is_jmp = DISAS_STOP;
7798 break;
7799 /* 6,7 are implementation dependent */
7800 case 6:
7801 /* ignored */
7802 rn = "Config6";
7803 break;
7804 case 7:
7805 /* ignored */
7806 rn = "Config7";
7807 break;
7808 default:
7809 rn = "Invalid config selector";
7810 goto cp0_unimplemented;
7812 break;
7813 case 17:
7814 switch (sel) {
7815 case 0:
7816 gen_helper_mtc0_lladdr(cpu_env, arg);
7817 rn = "LLAddr";
7818 break;
7819 case 1:
7820 CP0_CHECK(ctx->mrp);
7821 gen_helper_mtc0_maar(cpu_env, arg);
7822 rn = "MAAR";
7823 break;
7824 case 2:
7825 CP0_CHECK(ctx->mrp);
7826 gen_helper_mtc0_maari(cpu_env, arg);
7827 rn = "MAARI";
7828 break;
7829 default:
7830 goto cp0_unimplemented;
7832 break;
7833 case 18:
7834 switch (sel) {
7835 case 0:
7836 case 1:
7837 case 2:
7838 case 3:
7839 case 4:
7840 case 5:
7841 case 6:
7842 case 7:
7843 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7844 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7845 rn = "WatchLo";
7846 break;
7847 default:
7848 goto cp0_unimplemented;
7850 break;
7851 case 19:
7852 switch (sel) {
7853 case 0:
7854 case 1:
7855 case 2:
7856 case 3:
7857 case 4:
7858 case 5:
7859 case 6:
7860 case 7:
7861 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7862 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7863 rn = "WatchHi";
7864 break;
7865 default:
7866 goto cp0_unimplemented;
7868 break;
7869 case 20:
7870 switch (sel) {
7871 case 0:
7872 #if defined(TARGET_MIPS64)
7873 check_insn(ctx, ISA_MIPS3);
7874 gen_helper_mtc0_xcontext(cpu_env, arg);
7875 rn = "XContext";
7876 break;
7877 #endif
7878 default:
7879 goto cp0_unimplemented;
7881 break;
7882 case 21:
7883 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7884 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7885 switch (sel) {
7886 case 0:
7887 gen_helper_mtc0_framemask(cpu_env, arg);
7888 rn = "Framemask";
7889 break;
7890 default:
7891 goto cp0_unimplemented;
7893 break;
7894 case 22:
7895 /* ignored */
7896 rn = "Diagnostic"; /* implementation dependent */
7897 break;
7898 case 23:
7899 switch (sel) {
7900 case 0:
7901 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7902 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7903 gen_save_pc(ctx->base.pc_next + 4);
7904 ctx->base.is_jmp = DISAS_EXIT;
7905 rn = "Debug";
7906 break;
7907 case 1:
7908 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7909 rn = "TraceControl";
7910 /* Stop translation as we may have switched the execution mode */
7911 ctx->base.is_jmp = DISAS_STOP;
7912 goto cp0_unimplemented;
7913 case 2:
7914 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7915 rn = "TraceControl2";
7916 /* Stop translation as we may have switched the execution mode */
7917 ctx->base.is_jmp = DISAS_STOP;
7918 goto cp0_unimplemented;
7919 case 3:
7920 /* Stop translation as we may have switched the execution mode */
7921 ctx->base.is_jmp = DISAS_STOP;
7922 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7923 rn = "UserTraceData";
7924 /* Stop translation as we may have switched the execution mode */
7925 ctx->base.is_jmp = DISAS_STOP;
7926 goto cp0_unimplemented;
7927 case 4:
7928 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7929 /* Stop translation as we may have switched the execution mode */
7930 ctx->base.is_jmp = DISAS_STOP;
7931 rn = "TraceBPC";
7932 goto cp0_unimplemented;
7933 default:
7934 goto cp0_unimplemented;
7936 break;
7937 case 24:
7938 switch (sel) {
7939 case 0:
7940 /* EJTAG support */
7941 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7942 rn = "DEPC";
7943 break;
7944 default:
7945 goto cp0_unimplemented;
7947 break;
7948 case 25:
7949 switch (sel) {
7950 case 0:
7951 gen_helper_mtc0_performance0(cpu_env, arg);
7952 rn = "Performance0";
7953 break;
7954 case 1:
7955 // gen_helper_mtc0_performance1(arg);
7956 rn = "Performance1";
7957 goto cp0_unimplemented;
7958 case 2:
7959 // gen_helper_mtc0_performance2(arg);
7960 rn = "Performance2";
7961 goto cp0_unimplemented;
7962 case 3:
7963 // gen_helper_mtc0_performance3(arg);
7964 rn = "Performance3";
7965 goto cp0_unimplemented;
7966 case 4:
7967 // gen_helper_mtc0_performance4(arg);
7968 rn = "Performance4";
7969 goto cp0_unimplemented;
7970 case 5:
7971 // gen_helper_mtc0_performance5(arg);
7972 rn = "Performance5";
7973 goto cp0_unimplemented;
7974 case 6:
7975 // gen_helper_mtc0_performance6(arg);
7976 rn = "Performance6";
7977 goto cp0_unimplemented;
7978 case 7:
7979 // gen_helper_mtc0_performance7(arg);
7980 rn = "Performance7";
7981 goto cp0_unimplemented;
7982 default:
7983 goto cp0_unimplemented;
7985 break;
7986 case 26:
7987 switch (sel) {
7988 case 0:
7989 gen_helper_mtc0_errctl(cpu_env, arg);
7990 ctx->base.is_jmp = DISAS_STOP;
7991 rn = "ErrCtl";
7992 break;
7993 default:
7994 goto cp0_unimplemented;
7996 break;
7997 case 27:
7998 switch (sel) {
7999 case 0:
8000 case 1:
8001 case 2:
8002 case 3:
8003 /* ignored */
8004 rn = "CacheErr";
8005 break;
8006 default:
8007 goto cp0_unimplemented;
8009 break;
8010 case 28:
8011 switch (sel) {
8012 case 0:
8013 case 2:
8014 case 4:
8015 case 6:
8016 gen_helper_mtc0_taglo(cpu_env, arg);
8017 rn = "TagLo";
8018 break;
8019 case 1:
8020 case 3:
8021 case 5:
8022 case 7:
8023 gen_helper_mtc0_datalo(cpu_env, arg);
8024 rn = "DataLo";
8025 break;
8026 default:
8027 goto cp0_unimplemented;
8029 break;
8030 case 29:
8031 switch (sel) {
8032 case 0:
8033 case 2:
8034 case 4:
8035 case 6:
8036 gen_helper_mtc0_taghi(cpu_env, arg);
8037 rn = "TagHi";
8038 break;
8039 case 1:
8040 case 3:
8041 case 5:
8042 case 7:
8043 gen_helper_mtc0_datahi(cpu_env, arg);
8044 rn = "DataHi";
8045 break;
8046 default:
8047 rn = "invalid sel";
8048 goto cp0_unimplemented;
8050 break;
8051 case 30:
8052 switch (sel) {
8053 case 0:
8054 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8055 rn = "ErrorEPC";
8056 break;
8057 default:
8058 goto cp0_unimplemented;
8060 break;
8061 case 31:
8062 switch (sel) {
8063 case 0:
8064 /* EJTAG support */
8065 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8066 rn = "DESAVE";
8067 break;
8068 case 2:
8069 case 3:
8070 case 4:
8071 case 5:
8072 case 6:
8073 case 7:
8074 CP0_CHECK(ctx->kscrexist & (1 << sel));
8075 tcg_gen_st_tl(arg, cpu_env,
8076 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8077 rn = "KScratch";
8078 break;
8079 default:
8080 goto cp0_unimplemented;
8082 break;
8083 default:
8084 goto cp0_unimplemented;
8086 trace_mips_translate_c0("mtc0", rn, reg, sel);
8088 /* For simplicity assume that all writes can cause interrupts. */
8089 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8090 gen_io_end();
8091 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
8092 * translated code to check for pending interrupts. */
8093 gen_save_pc(ctx->base.pc_next + 4);
8094 ctx->base.is_jmp = DISAS_EXIT;
8096 return;
8098 cp0_unimplemented:
8099 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8102 #if defined(TARGET_MIPS64)
8103 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8105 const char *rn = "invalid";
8107 if (sel != 0)
8108 check_insn(ctx, ISA_MIPS64);
8110 switch (reg) {
8111 case 0:
8112 switch (sel) {
8113 case 0:
8114 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8115 rn = "Index";
8116 break;
8117 case 1:
8118 CP0_CHECK(ctx->insn_flags & ASE_MT);
8119 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8120 rn = "MVPControl";
8121 break;
8122 case 2:
8123 CP0_CHECK(ctx->insn_flags & ASE_MT);
8124 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8125 rn = "MVPConf0";
8126 break;
8127 case 3:
8128 CP0_CHECK(ctx->insn_flags & ASE_MT);
8129 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8130 rn = "MVPConf1";
8131 break;
8132 case 4:
8133 CP0_CHECK(ctx->vp);
8134 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8135 rn = "VPControl";
8136 break;
8137 default:
8138 goto cp0_unimplemented;
8140 break;
8141 case 1:
8142 switch (sel) {
8143 case 0:
8144 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8145 gen_helper_mfc0_random(arg, cpu_env);
8146 rn = "Random";
8147 break;
8148 case 1:
8149 CP0_CHECK(ctx->insn_flags & ASE_MT);
8150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8151 rn = "VPEControl";
8152 break;
8153 case 2:
8154 CP0_CHECK(ctx->insn_flags & ASE_MT);
8155 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8156 rn = "VPEConf0";
8157 break;
8158 case 3:
8159 CP0_CHECK(ctx->insn_flags & ASE_MT);
8160 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8161 rn = "VPEConf1";
8162 break;
8163 case 4:
8164 CP0_CHECK(ctx->insn_flags & ASE_MT);
8165 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
8166 rn = "YQMask";
8167 break;
8168 case 5:
8169 CP0_CHECK(ctx->insn_flags & ASE_MT);
8170 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8171 rn = "VPESchedule";
8172 break;
8173 case 6:
8174 CP0_CHECK(ctx->insn_flags & ASE_MT);
8175 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8176 rn = "VPEScheFBack";
8177 break;
8178 case 7:
8179 CP0_CHECK(ctx->insn_flags & ASE_MT);
8180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8181 rn = "VPEOpt";
8182 break;
8183 default:
8184 goto cp0_unimplemented;
8186 break;
8187 case 2:
8188 switch (sel) {
8189 case 0:
8190 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
8191 rn = "EntryLo0";
8192 break;
8193 case 1:
8194 CP0_CHECK(ctx->insn_flags & ASE_MT);
8195 gen_helper_mfc0_tcstatus(arg, cpu_env);
8196 rn = "TCStatus";
8197 break;
8198 case 2:
8199 CP0_CHECK(ctx->insn_flags & ASE_MT);
8200 gen_helper_mfc0_tcbind(arg, cpu_env);
8201 rn = "TCBind";
8202 break;
8203 case 3:
8204 CP0_CHECK(ctx->insn_flags & ASE_MT);
8205 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8206 rn = "TCRestart";
8207 break;
8208 case 4:
8209 CP0_CHECK(ctx->insn_flags & ASE_MT);
8210 gen_helper_dmfc0_tchalt(arg, cpu_env);
8211 rn = "TCHalt";
8212 break;
8213 case 5:
8214 CP0_CHECK(ctx->insn_flags & ASE_MT);
8215 gen_helper_dmfc0_tccontext(arg, cpu_env);
8216 rn = "TCContext";
8217 break;
8218 case 6:
8219 CP0_CHECK(ctx->insn_flags & ASE_MT);
8220 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8221 rn = "TCSchedule";
8222 break;
8223 case 7:
8224 CP0_CHECK(ctx->insn_flags & ASE_MT);
8225 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8226 rn = "TCScheFBack";
8227 break;
8228 default:
8229 goto cp0_unimplemented;
8231 break;
8232 case 3:
8233 switch (sel) {
8234 case 0:
8235 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8236 rn = "EntryLo1";
8237 break;
8238 case 1:
8239 CP0_CHECK(ctx->vp);
8240 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8241 rn = "GlobalNumber";
8242 break;
8243 default:
8244 goto cp0_unimplemented;
8246 break;
8247 case 4:
8248 switch (sel) {
8249 case 0:
8250 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8251 rn = "Context";
8252 break;
8253 case 1:
8254 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8255 rn = "ContextConfig";
8256 goto cp0_unimplemented;
8257 case 2:
8258 CP0_CHECK(ctx->ulri);
8259 tcg_gen_ld_tl(arg, cpu_env,
8260 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8261 rn = "UserLocal";
8262 break;
8263 default:
8264 goto cp0_unimplemented;
8266 break;
8267 case 5:
8268 switch (sel) {
8269 case 0:
8270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8271 rn = "PageMask";
8272 break;
8273 case 1:
8274 check_insn(ctx, ISA_MIPS32R2);
8275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8276 rn = "PageGrain";
8277 break;
8278 case 2:
8279 CP0_CHECK(ctx->sc);
8280 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8281 rn = "SegCtl0";
8282 break;
8283 case 3:
8284 CP0_CHECK(ctx->sc);
8285 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8286 rn = "SegCtl1";
8287 break;
8288 case 4:
8289 CP0_CHECK(ctx->sc);
8290 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8291 rn = "SegCtl2";
8292 break;
8293 case 5:
8294 check_pw(ctx);
8295 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8296 rn = "PWBase";
8297 break;
8298 case 6:
8299 check_pw(ctx);
8300 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8301 rn = "PWField";
8302 break;
8303 case 7:
8304 check_pw(ctx);
8305 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8306 rn = "PWSize";
8307 break;
8308 default:
8309 goto cp0_unimplemented;
8311 break;
8312 case 6:
8313 switch (sel) {
8314 case 0:
8315 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8316 rn = "Wired";
8317 break;
8318 case 1:
8319 check_insn(ctx, ISA_MIPS32R2);
8320 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8321 rn = "SRSConf0";
8322 break;
8323 case 2:
8324 check_insn(ctx, ISA_MIPS32R2);
8325 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8326 rn = "SRSConf1";
8327 break;
8328 case 3:
8329 check_insn(ctx, ISA_MIPS32R2);
8330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8331 rn = "SRSConf2";
8332 break;
8333 case 4:
8334 check_insn(ctx, ISA_MIPS32R2);
8335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8336 rn = "SRSConf3";
8337 break;
8338 case 5:
8339 check_insn(ctx, ISA_MIPS32R2);
8340 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8341 rn = "SRSConf4";
8342 break;
8343 case 6:
8344 check_pw(ctx);
8345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8346 rn = "PWCtl";
8347 break;
8348 default:
8349 goto cp0_unimplemented;
8351 break;
8352 case 7:
8353 switch (sel) {
8354 case 0:
8355 check_insn(ctx, ISA_MIPS32R2);
8356 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8357 rn = "HWREna";
8358 break;
8359 default:
8360 goto cp0_unimplemented;
8362 break;
8363 case 8:
8364 switch (sel) {
8365 case 0:
8366 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8367 rn = "BadVAddr";
8368 break;
8369 case 1:
8370 CP0_CHECK(ctx->bi);
8371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8372 rn = "BadInstr";
8373 break;
8374 case 2:
8375 CP0_CHECK(ctx->bp);
8376 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8377 rn = "BadInstrP";
8378 break;
8379 case 3:
8380 CP0_CHECK(ctx->bi);
8381 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8382 tcg_gen_andi_tl(arg, arg, ~0xffff);
8383 rn = "BadInstrX";
8384 break;
8385 default:
8386 goto cp0_unimplemented;
8388 break;
8389 case 9:
8390 switch (sel) {
8391 case 0:
8392 /* Mark as an IO operation because we read the time. */
8393 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8394 gen_io_start();
8396 gen_helper_mfc0_count(arg, cpu_env);
8397 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8398 gen_io_end();
8400 /* Break the TB to be able to take timer interrupts immediately
8401 after reading count. DISAS_STOP isn't sufficient, we need to
8402 ensure we break completely out of translated code. */
8403 gen_save_pc(ctx->base.pc_next + 4);
8404 ctx->base.is_jmp = DISAS_EXIT;
8405 rn = "Count";
8406 break;
8407 /* 6,7 are implementation dependent */
8408 default:
8409 goto cp0_unimplemented;
8411 break;
8412 case 10:
8413 switch (sel) {
8414 case 0:
8415 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8416 rn = "EntryHi";
8417 break;
8418 default:
8419 goto cp0_unimplemented;
8421 break;
8422 case 11:
8423 switch (sel) {
8424 case 0:
8425 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8426 rn = "Compare";
8427 break;
8428 /* 6,7 are implementation dependent */
8429 default:
8430 goto cp0_unimplemented;
8432 break;
8433 case 12:
8434 switch (sel) {
8435 case 0:
8436 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8437 rn = "Status";
8438 break;
8439 case 1:
8440 check_insn(ctx, ISA_MIPS32R2);
8441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8442 rn = "IntCtl";
8443 break;
8444 case 2:
8445 check_insn(ctx, ISA_MIPS32R2);
8446 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8447 rn = "SRSCtl";
8448 break;
8449 case 3:
8450 check_insn(ctx, ISA_MIPS32R2);
8451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8452 rn = "SRSMap";
8453 break;
8454 default:
8455 goto cp0_unimplemented;
8457 break;
8458 case 13:
8459 switch (sel) {
8460 case 0:
8461 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8462 rn = "Cause";
8463 break;
8464 default:
8465 goto cp0_unimplemented;
8467 break;
8468 case 14:
8469 switch (sel) {
8470 case 0:
8471 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8472 rn = "EPC";
8473 break;
8474 default:
8475 goto cp0_unimplemented;
8477 break;
8478 case 15:
8479 switch (sel) {
8480 case 0:
8481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8482 rn = "PRid";
8483 break;
8484 case 1:
8485 check_insn(ctx, ISA_MIPS32R2);
8486 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8487 rn = "EBase";
8488 break;
8489 case 3:
8490 check_insn(ctx, ISA_MIPS32R2);
8491 CP0_CHECK(ctx->cmgcr);
8492 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8493 rn = "CMGCRBase";
8494 break;
8495 default:
8496 goto cp0_unimplemented;
8498 break;
8499 case 16:
8500 switch (sel) {
8501 case 0:
8502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8503 rn = "Config";
8504 break;
8505 case 1:
8506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8507 rn = "Config1";
8508 break;
8509 case 2:
8510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8511 rn = "Config2";
8512 break;
8513 case 3:
8514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8515 rn = "Config3";
8516 break;
8517 case 4:
8518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8519 rn = "Config4";
8520 break;
8521 case 5:
8522 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8523 rn = "Config5";
8524 break;
8525 /* 6,7 are implementation dependent */
8526 case 6:
8527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8528 rn = "Config6";
8529 break;
8530 case 7:
8531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8532 rn = "Config7";
8533 break;
8534 default:
8535 goto cp0_unimplemented;
8537 break;
8538 case 17:
8539 switch (sel) {
8540 case 0:
8541 gen_helper_dmfc0_lladdr(arg, cpu_env);
8542 rn = "LLAddr";
8543 break;
8544 case 1:
8545 CP0_CHECK(ctx->mrp);
8546 gen_helper_dmfc0_maar(arg, cpu_env);
8547 rn = "MAAR";
8548 break;
8549 case 2:
8550 CP0_CHECK(ctx->mrp);
8551 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8552 rn = "MAARI";
8553 break;
8554 default:
8555 goto cp0_unimplemented;
8557 break;
8558 case 18:
8559 switch (sel) {
8560 case 0:
8561 case 1:
8562 case 2:
8563 case 3:
8564 case 4:
8565 case 5:
8566 case 6:
8567 case 7:
8568 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8569 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8570 rn = "WatchLo";
8571 break;
8572 default:
8573 goto cp0_unimplemented;
8575 break;
8576 case 19:
8577 switch (sel) {
8578 case 0:
8579 case 1:
8580 case 2:
8581 case 3:
8582 case 4:
8583 case 5:
8584 case 6:
8585 case 7:
8586 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8587 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8588 rn = "WatchHi";
8589 break;
8590 default:
8591 goto cp0_unimplemented;
8593 break;
8594 case 20:
8595 switch (sel) {
8596 case 0:
8597 check_insn(ctx, ISA_MIPS3);
8598 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8599 rn = "XContext";
8600 break;
8601 default:
8602 goto cp0_unimplemented;
8604 break;
8605 case 21:
8606 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8607 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8608 switch (sel) {
8609 case 0:
8610 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8611 rn = "Framemask";
8612 break;
8613 default:
8614 goto cp0_unimplemented;
8616 break;
8617 case 22:
8618 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8619 rn = "'Diagnostic"; /* implementation dependent */
8620 break;
8621 case 23:
8622 switch (sel) {
8623 case 0:
8624 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8625 rn = "Debug";
8626 break;
8627 case 1:
8628 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8629 rn = "TraceControl";
8630 goto cp0_unimplemented;
8631 case 2:
8632 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8633 rn = "TraceControl2";
8634 goto cp0_unimplemented;
8635 case 3:
8636 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8637 rn = "UserTraceData";
8638 goto cp0_unimplemented;
8639 case 4:
8640 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8641 rn = "TraceBPC";
8642 goto cp0_unimplemented;
8643 default:
8644 goto cp0_unimplemented;
8646 break;
8647 case 24:
8648 switch (sel) {
8649 case 0:
8650 /* EJTAG support */
8651 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8652 rn = "DEPC";
8653 break;
8654 default:
8655 goto cp0_unimplemented;
8657 break;
8658 case 25:
8659 switch (sel) {
8660 case 0:
8661 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8662 rn = "Performance0";
8663 break;
8664 case 1:
8665 // gen_helper_dmfc0_performance1(arg);
8666 rn = "Performance1";
8667 goto cp0_unimplemented;
8668 case 2:
8669 // gen_helper_dmfc0_performance2(arg);
8670 rn = "Performance2";
8671 goto cp0_unimplemented;
8672 case 3:
8673 // gen_helper_dmfc0_performance3(arg);
8674 rn = "Performance3";
8675 goto cp0_unimplemented;
8676 case 4:
8677 // gen_helper_dmfc0_performance4(arg);
8678 rn = "Performance4";
8679 goto cp0_unimplemented;
8680 case 5:
8681 // gen_helper_dmfc0_performance5(arg);
8682 rn = "Performance5";
8683 goto cp0_unimplemented;
8684 case 6:
8685 // gen_helper_dmfc0_performance6(arg);
8686 rn = "Performance6";
8687 goto cp0_unimplemented;
8688 case 7:
8689 // gen_helper_dmfc0_performance7(arg);
8690 rn = "Performance7";
8691 goto cp0_unimplemented;
8692 default:
8693 goto cp0_unimplemented;
8695 break;
8696 case 26:
8697 switch (sel) {
8698 case 0:
8699 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8700 rn = "ErrCtl";
8701 break;
8702 default:
8703 goto cp0_unimplemented;
8705 break;
8706 case 27:
8707 switch (sel) {
8708 /* ignored */
8709 case 0:
8710 case 1:
8711 case 2:
8712 case 3:
8713 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8714 rn = "CacheErr";
8715 break;
8716 default:
8717 goto cp0_unimplemented;
8719 break;
8720 case 28:
8721 switch (sel) {
8722 case 0:
8723 case 2:
8724 case 4:
8725 case 6:
8726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8727 rn = "TagLo";
8728 break;
8729 case 1:
8730 case 3:
8731 case 5:
8732 case 7:
8733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8734 rn = "DataLo";
8735 break;
8736 default:
8737 goto cp0_unimplemented;
8739 break;
8740 case 29:
8741 switch (sel) {
8742 case 0:
8743 case 2:
8744 case 4:
8745 case 6:
8746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8747 rn = "TagHi";
8748 break;
8749 case 1:
8750 case 3:
8751 case 5:
8752 case 7:
8753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8754 rn = "DataHi";
8755 break;
8756 default:
8757 goto cp0_unimplemented;
8759 break;
8760 case 30:
8761 switch (sel) {
8762 case 0:
8763 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8764 rn = "ErrorEPC";
8765 break;
8766 default:
8767 goto cp0_unimplemented;
8769 break;
8770 case 31:
8771 switch (sel) {
8772 case 0:
8773 /* EJTAG support */
8774 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8775 rn = "DESAVE";
8776 break;
8777 case 2:
8778 case 3:
8779 case 4:
8780 case 5:
8781 case 6:
8782 case 7:
8783 CP0_CHECK(ctx->kscrexist & (1 << sel));
8784 tcg_gen_ld_tl(arg, cpu_env,
8785 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8786 rn = "KScratch";
8787 break;
8788 default:
8789 goto cp0_unimplemented;
8791 break;
8792 default:
8793 goto cp0_unimplemented;
8795 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8796 return;
8798 cp0_unimplemented:
8799 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8800 gen_mfc0_unimplemented(ctx, arg);
8803 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8805 const char *rn = "invalid";
8807 if (sel != 0)
8808 check_insn(ctx, ISA_MIPS64);
8810 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8811 gen_io_start();
8814 switch (reg) {
8815 case 0:
8816 switch (sel) {
8817 case 0:
8818 gen_helper_mtc0_index(cpu_env, arg);
8819 rn = "Index";
8820 break;
8821 case 1:
8822 CP0_CHECK(ctx->insn_flags & ASE_MT);
8823 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8824 rn = "MVPControl";
8825 break;
8826 case 2:
8827 CP0_CHECK(ctx->insn_flags & ASE_MT);
8828 /* ignored */
8829 rn = "MVPConf0";
8830 break;
8831 case 3:
8832 CP0_CHECK(ctx->insn_flags & ASE_MT);
8833 /* ignored */
8834 rn = "MVPConf1";
8835 break;
8836 case 4:
8837 CP0_CHECK(ctx->vp);
8838 /* ignored */
8839 rn = "VPControl";
8840 break;
8841 default:
8842 goto cp0_unimplemented;
8844 break;
8845 case 1:
8846 switch (sel) {
8847 case 0:
8848 /* ignored */
8849 rn = "Random";
8850 break;
8851 case 1:
8852 CP0_CHECK(ctx->insn_flags & ASE_MT);
8853 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8854 rn = "VPEControl";
8855 break;
8856 case 2:
8857 CP0_CHECK(ctx->insn_flags & ASE_MT);
8858 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8859 rn = "VPEConf0";
8860 break;
8861 case 3:
8862 CP0_CHECK(ctx->insn_flags & ASE_MT);
8863 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8864 rn = "VPEConf1";
8865 break;
8866 case 4:
8867 CP0_CHECK(ctx->insn_flags & ASE_MT);
8868 gen_helper_mtc0_yqmask(cpu_env, arg);
8869 rn = "YQMask";
8870 break;
8871 case 5:
8872 CP0_CHECK(ctx->insn_flags & ASE_MT);
8873 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8874 rn = "VPESchedule";
8875 break;
8876 case 6:
8877 CP0_CHECK(ctx->insn_flags & ASE_MT);
8878 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8879 rn = "VPEScheFBack";
8880 break;
8881 case 7:
8882 CP0_CHECK(ctx->insn_flags & ASE_MT);
8883 gen_helper_mtc0_vpeopt(cpu_env, arg);
8884 rn = "VPEOpt";
8885 break;
8886 default:
8887 goto cp0_unimplemented;
8889 break;
8890 case 2:
8891 switch (sel) {
8892 case 0:
8893 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8894 rn = "EntryLo0";
8895 break;
8896 case 1:
8897 CP0_CHECK(ctx->insn_flags & ASE_MT);
8898 gen_helper_mtc0_tcstatus(cpu_env, arg);
8899 rn = "TCStatus";
8900 break;
8901 case 2:
8902 CP0_CHECK(ctx->insn_flags & ASE_MT);
8903 gen_helper_mtc0_tcbind(cpu_env, arg);
8904 rn = "TCBind";
8905 break;
8906 case 3:
8907 CP0_CHECK(ctx->insn_flags & ASE_MT);
8908 gen_helper_mtc0_tcrestart(cpu_env, arg);
8909 rn = "TCRestart";
8910 break;
8911 case 4:
8912 CP0_CHECK(ctx->insn_flags & ASE_MT);
8913 gen_helper_mtc0_tchalt(cpu_env, arg);
8914 rn = "TCHalt";
8915 break;
8916 case 5:
8917 CP0_CHECK(ctx->insn_flags & ASE_MT);
8918 gen_helper_mtc0_tccontext(cpu_env, arg);
8919 rn = "TCContext";
8920 break;
8921 case 6:
8922 CP0_CHECK(ctx->insn_flags & ASE_MT);
8923 gen_helper_mtc0_tcschedule(cpu_env, arg);
8924 rn = "TCSchedule";
8925 break;
8926 case 7:
8927 CP0_CHECK(ctx->insn_flags & ASE_MT);
8928 gen_helper_mtc0_tcschefback(cpu_env, arg);
8929 rn = "TCScheFBack";
8930 break;
8931 default:
8932 goto cp0_unimplemented;
8934 break;
8935 case 3:
8936 switch (sel) {
8937 case 0:
8938 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8939 rn = "EntryLo1";
8940 break;
8941 case 1:
8942 CP0_CHECK(ctx->vp);
8943 /* ignored */
8944 rn = "GlobalNumber";
8945 break;
8946 default:
8947 goto cp0_unimplemented;
8949 break;
8950 case 4:
8951 switch (sel) {
8952 case 0:
8953 gen_helper_mtc0_context(cpu_env, arg);
8954 rn = "Context";
8955 break;
8956 case 1:
8957 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8958 rn = "ContextConfig";
8959 goto cp0_unimplemented;
8960 case 2:
8961 CP0_CHECK(ctx->ulri);
8962 tcg_gen_st_tl(arg, cpu_env,
8963 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8964 rn = "UserLocal";
8965 break;
8966 default:
8967 goto cp0_unimplemented;
8969 break;
8970 case 5:
8971 switch (sel) {
8972 case 0:
8973 gen_helper_mtc0_pagemask(cpu_env, arg);
8974 rn = "PageMask";
8975 break;
8976 case 1:
8977 check_insn(ctx, ISA_MIPS32R2);
8978 gen_helper_mtc0_pagegrain(cpu_env, arg);
8979 rn = "PageGrain";
8980 break;
8981 case 2:
8982 CP0_CHECK(ctx->sc);
8983 gen_helper_mtc0_segctl0(cpu_env, arg);
8984 rn = "SegCtl0";
8985 break;
8986 case 3:
8987 CP0_CHECK(ctx->sc);
8988 gen_helper_mtc0_segctl1(cpu_env, arg);
8989 rn = "SegCtl1";
8990 break;
8991 case 4:
8992 CP0_CHECK(ctx->sc);
8993 gen_helper_mtc0_segctl2(cpu_env, arg);
8994 rn = "SegCtl2";
8995 break;
8996 case 5:
8997 check_pw(ctx);
8998 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8999 rn = "PWBase";
9000 break;
9001 case 6:
9002 check_pw(ctx);
9003 gen_helper_mtc0_pwfield(cpu_env, arg);
9004 rn = "PWField";
9005 break;
9006 case 7:
9007 check_pw(ctx);
9008 gen_helper_mtc0_pwsize(cpu_env, arg);
9009 rn = "PWSize";
9010 break;
9011 default:
9012 goto cp0_unimplemented;
9014 break;
9015 case 6:
9016 switch (sel) {
9017 case 0:
9018 gen_helper_mtc0_wired(cpu_env, arg);
9019 rn = "Wired";
9020 break;
9021 case 1:
9022 check_insn(ctx, ISA_MIPS32R2);
9023 gen_helper_mtc0_srsconf0(cpu_env, arg);
9024 rn = "SRSConf0";
9025 break;
9026 case 2:
9027 check_insn(ctx, ISA_MIPS32R2);
9028 gen_helper_mtc0_srsconf1(cpu_env, arg);
9029 rn = "SRSConf1";
9030 break;
9031 case 3:
9032 check_insn(ctx, ISA_MIPS32R2);
9033 gen_helper_mtc0_srsconf2(cpu_env, arg);
9034 rn = "SRSConf2";
9035 break;
9036 case 4:
9037 check_insn(ctx, ISA_MIPS32R2);
9038 gen_helper_mtc0_srsconf3(cpu_env, arg);
9039 rn = "SRSConf3";
9040 break;
9041 case 5:
9042 check_insn(ctx, ISA_MIPS32R2);
9043 gen_helper_mtc0_srsconf4(cpu_env, arg);
9044 rn = "SRSConf4";
9045 break;
9046 case 6:
9047 check_pw(ctx);
9048 gen_helper_mtc0_pwctl(cpu_env, arg);
9049 rn = "PWCtl";
9050 break;
9051 default:
9052 goto cp0_unimplemented;
9054 break;
9055 case 7:
9056 switch (sel) {
9057 case 0:
9058 check_insn(ctx, ISA_MIPS32R2);
9059 gen_helper_mtc0_hwrena(cpu_env, arg);
9060 ctx->base.is_jmp = DISAS_STOP;
9061 rn = "HWREna";
9062 break;
9063 default:
9064 goto cp0_unimplemented;
9066 break;
9067 case 8:
9068 switch (sel) {
9069 case 0:
9070 /* ignored */
9071 rn = "BadVAddr";
9072 break;
9073 case 1:
9074 /* ignored */
9075 rn = "BadInstr";
9076 break;
9077 case 2:
9078 /* ignored */
9079 rn = "BadInstrP";
9080 break;
9081 case 3:
9082 /* ignored */
9083 rn = "BadInstrX";
9084 break;
9085 default:
9086 goto cp0_unimplemented;
9088 break;
9089 case 9:
9090 switch (sel) {
9091 case 0:
9092 gen_helper_mtc0_count(cpu_env, arg);
9093 rn = "Count";
9094 break;
9095 /* 6,7 are implementation dependent */
9096 default:
9097 goto cp0_unimplemented;
9099 /* Stop translation as we may have switched the execution mode */
9100 ctx->base.is_jmp = DISAS_STOP;
9101 break;
9102 case 10:
9103 switch (sel) {
9104 case 0:
9105 gen_helper_mtc0_entryhi(cpu_env, arg);
9106 rn = "EntryHi";
9107 break;
9108 default:
9109 goto cp0_unimplemented;
9111 break;
9112 case 11:
9113 switch (sel) {
9114 case 0:
9115 gen_helper_mtc0_compare(cpu_env, arg);
9116 rn = "Compare";
9117 break;
9118 /* 6,7 are implementation dependent */
9119 default:
9120 goto cp0_unimplemented;
9122 /* Stop translation as we may have switched the execution mode */
9123 ctx->base.is_jmp = DISAS_STOP;
9124 break;
9125 case 12:
9126 switch (sel) {
9127 case 0:
9128 save_cpu_state(ctx, 1);
9129 gen_helper_mtc0_status(cpu_env, arg);
9130 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9131 gen_save_pc(ctx->base.pc_next + 4);
9132 ctx->base.is_jmp = DISAS_EXIT;
9133 rn = "Status";
9134 break;
9135 case 1:
9136 check_insn(ctx, ISA_MIPS32R2);
9137 gen_helper_mtc0_intctl(cpu_env, arg);
9138 /* Stop translation as we may have switched the execution mode */
9139 ctx->base.is_jmp = DISAS_STOP;
9140 rn = "IntCtl";
9141 break;
9142 case 2:
9143 check_insn(ctx, ISA_MIPS32R2);
9144 gen_helper_mtc0_srsctl(cpu_env, arg);
9145 /* Stop translation as we may have switched the execution mode */
9146 ctx->base.is_jmp = DISAS_STOP;
9147 rn = "SRSCtl";
9148 break;
9149 case 3:
9150 check_insn(ctx, ISA_MIPS32R2);
9151 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9152 /* Stop translation as we may have switched the execution mode */
9153 ctx->base.is_jmp = DISAS_STOP;
9154 rn = "SRSMap";
9155 break;
9156 default:
9157 goto cp0_unimplemented;
9159 break;
9160 case 13:
9161 switch (sel) {
9162 case 0:
9163 save_cpu_state(ctx, 1);
9164 gen_helper_mtc0_cause(cpu_env, arg);
9165 /* Stop translation as we may have triggered an interrupt.
9166 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9167 * translated code to check for pending interrupts. */
9168 gen_save_pc(ctx->base.pc_next + 4);
9169 ctx->base.is_jmp = DISAS_EXIT;
9170 rn = "Cause";
9171 break;
9172 default:
9173 goto cp0_unimplemented;
9175 break;
9176 case 14:
9177 switch (sel) {
9178 case 0:
9179 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9180 rn = "EPC";
9181 break;
9182 default:
9183 goto cp0_unimplemented;
9185 break;
9186 case 15:
9187 switch (sel) {
9188 case 0:
9189 /* ignored */
9190 rn = "PRid";
9191 break;
9192 case 1:
9193 check_insn(ctx, ISA_MIPS32R2);
9194 gen_helper_mtc0_ebase(cpu_env, arg);
9195 rn = "EBase";
9196 break;
9197 default:
9198 goto cp0_unimplemented;
9200 break;
9201 case 16:
9202 switch (sel) {
9203 case 0:
9204 gen_helper_mtc0_config0(cpu_env, arg);
9205 rn = "Config";
9206 /* Stop translation as we may have switched the execution mode */
9207 ctx->base.is_jmp = DISAS_STOP;
9208 break;
9209 case 1:
9210 /* ignored, read only */
9211 rn = "Config1";
9212 break;
9213 case 2:
9214 gen_helper_mtc0_config2(cpu_env, arg);
9215 rn = "Config2";
9216 /* Stop translation as we may have switched the execution mode */
9217 ctx->base.is_jmp = DISAS_STOP;
9218 break;
9219 case 3:
9220 gen_helper_mtc0_config3(cpu_env, arg);
9221 rn = "Config3";
9222 /* Stop translation as we may have switched the execution mode */
9223 ctx->base.is_jmp = DISAS_STOP;
9224 break;
9225 case 4:
9226 /* currently ignored */
9227 rn = "Config4";
9228 break;
9229 case 5:
9230 gen_helper_mtc0_config5(cpu_env, arg);
9231 rn = "Config5";
9232 /* Stop translation as we may have switched the execution mode */
9233 ctx->base.is_jmp = DISAS_STOP;
9234 break;
9235 /* 6,7 are implementation dependent */
9236 default:
9237 rn = "Invalid config selector";
9238 goto cp0_unimplemented;
9240 break;
9241 case 17:
9242 switch (sel) {
9243 case 0:
9244 gen_helper_mtc0_lladdr(cpu_env, arg);
9245 rn = "LLAddr";
9246 break;
9247 case 1:
9248 CP0_CHECK(ctx->mrp);
9249 gen_helper_mtc0_maar(cpu_env, arg);
9250 rn = "MAAR";
9251 break;
9252 case 2:
9253 CP0_CHECK(ctx->mrp);
9254 gen_helper_mtc0_maari(cpu_env, arg);
9255 rn = "MAARI";
9256 break;
9257 default:
9258 goto cp0_unimplemented;
9260 break;
9261 case 18:
9262 switch (sel) {
9263 case 0:
9264 case 1:
9265 case 2:
9266 case 3:
9267 case 4:
9268 case 5:
9269 case 6:
9270 case 7:
9271 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9272 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9273 rn = "WatchLo";
9274 break;
9275 default:
9276 goto cp0_unimplemented;
9278 break;
9279 case 19:
9280 switch (sel) {
9281 case 0:
9282 case 1:
9283 case 2:
9284 case 3:
9285 case 4:
9286 case 5:
9287 case 6:
9288 case 7:
9289 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9290 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9291 rn = "WatchHi";
9292 break;
9293 default:
9294 goto cp0_unimplemented;
9296 break;
9297 case 20:
9298 switch (sel) {
9299 case 0:
9300 check_insn(ctx, ISA_MIPS3);
9301 gen_helper_mtc0_xcontext(cpu_env, arg);
9302 rn = "XContext";
9303 break;
9304 default:
9305 goto cp0_unimplemented;
9307 break;
9308 case 21:
9309 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9310 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9311 switch (sel) {
9312 case 0:
9313 gen_helper_mtc0_framemask(cpu_env, arg);
9314 rn = "Framemask";
9315 break;
9316 default:
9317 goto cp0_unimplemented;
9319 break;
9320 case 22:
9321 /* ignored */
9322 rn = "Diagnostic"; /* implementation dependent */
9323 break;
9324 case 23:
9325 switch (sel) {
9326 case 0:
9327 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9328 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9329 gen_save_pc(ctx->base.pc_next + 4);
9330 ctx->base.is_jmp = DISAS_EXIT;
9331 rn = "Debug";
9332 break;
9333 case 1:
9334 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9335 /* Stop translation as we may have switched the execution mode */
9336 ctx->base.is_jmp = DISAS_STOP;
9337 rn = "TraceControl";
9338 goto cp0_unimplemented;
9339 case 2:
9340 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9341 /* Stop translation as we may have switched the execution mode */
9342 ctx->base.is_jmp = DISAS_STOP;
9343 rn = "TraceControl2";
9344 goto cp0_unimplemented;
9345 case 3:
9346 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9347 /* Stop translation as we may have switched the execution mode */
9348 ctx->base.is_jmp = DISAS_STOP;
9349 rn = "UserTraceData";
9350 goto cp0_unimplemented;
9351 case 4:
9352 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9353 /* Stop translation as we may have switched the execution mode */
9354 ctx->base.is_jmp = DISAS_STOP;
9355 rn = "TraceBPC";
9356 goto cp0_unimplemented;
9357 default:
9358 goto cp0_unimplemented;
9360 break;
9361 case 24:
9362 switch (sel) {
9363 case 0:
9364 /* EJTAG support */
9365 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9366 rn = "DEPC";
9367 break;
9368 default:
9369 goto cp0_unimplemented;
9371 break;
9372 case 25:
9373 switch (sel) {
9374 case 0:
9375 gen_helper_mtc0_performance0(cpu_env, arg);
9376 rn = "Performance0";
9377 break;
9378 case 1:
9379 // gen_helper_mtc0_performance1(cpu_env, arg);
9380 rn = "Performance1";
9381 goto cp0_unimplemented;
9382 case 2:
9383 // gen_helper_mtc0_performance2(cpu_env, arg);
9384 rn = "Performance2";
9385 goto cp0_unimplemented;
9386 case 3:
9387 // gen_helper_mtc0_performance3(cpu_env, arg);
9388 rn = "Performance3";
9389 goto cp0_unimplemented;
9390 case 4:
9391 // gen_helper_mtc0_performance4(cpu_env, arg);
9392 rn = "Performance4";
9393 goto cp0_unimplemented;
9394 case 5:
9395 // gen_helper_mtc0_performance5(cpu_env, arg);
9396 rn = "Performance5";
9397 goto cp0_unimplemented;
9398 case 6:
9399 // gen_helper_mtc0_performance6(cpu_env, arg);
9400 rn = "Performance6";
9401 goto cp0_unimplemented;
9402 case 7:
9403 // gen_helper_mtc0_performance7(cpu_env, arg);
9404 rn = "Performance7";
9405 goto cp0_unimplemented;
9406 default:
9407 goto cp0_unimplemented;
9409 break;
9410 case 26:
9411 switch (sel) {
9412 case 0:
9413 gen_helper_mtc0_errctl(cpu_env, arg);
9414 ctx->base.is_jmp = DISAS_STOP;
9415 rn = "ErrCtl";
9416 break;
9417 default:
9418 goto cp0_unimplemented;
9420 break;
9421 case 27:
9422 switch (sel) {
9423 case 0:
9424 case 1:
9425 case 2:
9426 case 3:
9427 /* ignored */
9428 rn = "CacheErr";
9429 break;
9430 default:
9431 goto cp0_unimplemented;
9433 break;
9434 case 28:
9435 switch (sel) {
9436 case 0:
9437 case 2:
9438 case 4:
9439 case 6:
9440 gen_helper_mtc0_taglo(cpu_env, arg);
9441 rn = "TagLo";
9442 break;
9443 case 1:
9444 case 3:
9445 case 5:
9446 case 7:
9447 gen_helper_mtc0_datalo(cpu_env, arg);
9448 rn = "DataLo";
9449 break;
9450 default:
9451 goto cp0_unimplemented;
9453 break;
9454 case 29:
9455 switch (sel) {
9456 case 0:
9457 case 2:
9458 case 4:
9459 case 6:
9460 gen_helper_mtc0_taghi(cpu_env, arg);
9461 rn = "TagHi";
9462 break;
9463 case 1:
9464 case 3:
9465 case 5:
9466 case 7:
9467 gen_helper_mtc0_datahi(cpu_env, arg);
9468 rn = "DataHi";
9469 break;
9470 default:
9471 rn = "invalid sel";
9472 goto cp0_unimplemented;
9474 break;
9475 case 30:
9476 switch (sel) {
9477 case 0:
9478 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9479 rn = "ErrorEPC";
9480 break;
9481 default:
9482 goto cp0_unimplemented;
9484 break;
9485 case 31:
9486 switch (sel) {
9487 case 0:
9488 /* EJTAG support */
9489 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9490 rn = "DESAVE";
9491 break;
9492 case 2:
9493 case 3:
9494 case 4:
9495 case 5:
9496 case 6:
9497 case 7:
9498 CP0_CHECK(ctx->kscrexist & (1 << sel));
9499 tcg_gen_st_tl(arg, cpu_env,
9500 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9501 rn = "KScratch";
9502 break;
9503 default:
9504 goto cp0_unimplemented;
9506 break;
9507 default:
9508 goto cp0_unimplemented;
9510 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9512 /* For simplicity assume that all writes can cause interrupts. */
9513 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9514 gen_io_end();
9515 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9516 * translated code to check for pending interrupts. */
9517 gen_save_pc(ctx->base.pc_next + 4);
9518 ctx->base.is_jmp = DISAS_EXIT;
9520 return;
9522 cp0_unimplemented:
9523 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9525 #endif /* TARGET_MIPS64 */
9527 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9528 int u, int sel, int h)
9530 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9531 TCGv t0 = tcg_temp_local_new();
9533 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9534 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9535 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9536 tcg_gen_movi_tl(t0, -1);
9537 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9538 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9539 tcg_gen_movi_tl(t0, -1);
9540 else if (u == 0) {
9541 switch (rt) {
9542 case 1:
9543 switch (sel) {
9544 case 1:
9545 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9546 break;
9547 case 2:
9548 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9549 break;
9550 default:
9551 goto die;
9552 break;
9554 break;
9555 case 2:
9556 switch (sel) {
9557 case 1:
9558 gen_helper_mftc0_tcstatus(t0, cpu_env);
9559 break;
9560 case 2:
9561 gen_helper_mftc0_tcbind(t0, cpu_env);
9562 break;
9563 case 3:
9564 gen_helper_mftc0_tcrestart(t0, cpu_env);
9565 break;
9566 case 4:
9567 gen_helper_mftc0_tchalt(t0, cpu_env);
9568 break;
9569 case 5:
9570 gen_helper_mftc0_tccontext(t0, cpu_env);
9571 break;
9572 case 6:
9573 gen_helper_mftc0_tcschedule(t0, cpu_env);
9574 break;
9575 case 7:
9576 gen_helper_mftc0_tcschefback(t0, cpu_env);
9577 break;
9578 default:
9579 gen_mfc0(ctx, t0, rt, sel);
9580 break;
9582 break;
9583 case 10:
9584 switch (sel) {
9585 case 0:
9586 gen_helper_mftc0_entryhi(t0, cpu_env);
9587 break;
9588 default:
9589 gen_mfc0(ctx, t0, rt, sel);
9590 break;
9592 case 12:
9593 switch (sel) {
9594 case 0:
9595 gen_helper_mftc0_status(t0, cpu_env);
9596 break;
9597 default:
9598 gen_mfc0(ctx, t0, rt, sel);
9599 break;
9601 case 13:
9602 switch (sel) {
9603 case 0:
9604 gen_helper_mftc0_cause(t0, cpu_env);
9605 break;
9606 default:
9607 goto die;
9608 break;
9610 break;
9611 case 14:
9612 switch (sel) {
9613 case 0:
9614 gen_helper_mftc0_epc(t0, cpu_env);
9615 break;
9616 default:
9617 goto die;
9618 break;
9620 break;
9621 case 15:
9622 switch (sel) {
9623 case 1:
9624 gen_helper_mftc0_ebase(t0, cpu_env);
9625 break;
9626 default:
9627 goto die;
9628 break;
9630 break;
9631 case 16:
9632 switch (sel) {
9633 case 0:
9634 case 1:
9635 case 2:
9636 case 3:
9637 case 4:
9638 case 5:
9639 case 6:
9640 case 7:
9641 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9642 break;
9643 default:
9644 goto die;
9645 break;
9647 break;
9648 case 23:
9649 switch (sel) {
9650 case 0:
9651 gen_helper_mftc0_debug(t0, cpu_env);
9652 break;
9653 default:
9654 gen_mfc0(ctx, t0, rt, sel);
9655 break;
9657 break;
9658 default:
9659 gen_mfc0(ctx, t0, rt, sel);
9661 } else switch (sel) {
9662 /* GPR registers. */
9663 case 0:
9664 gen_helper_1e0i(mftgpr, t0, rt);
9665 break;
9666 /* Auxiliary CPU registers */
9667 case 1:
9668 switch (rt) {
9669 case 0:
9670 gen_helper_1e0i(mftlo, t0, 0);
9671 break;
9672 case 1:
9673 gen_helper_1e0i(mfthi, t0, 0);
9674 break;
9675 case 2:
9676 gen_helper_1e0i(mftacx, t0, 0);
9677 break;
9678 case 4:
9679 gen_helper_1e0i(mftlo, t0, 1);
9680 break;
9681 case 5:
9682 gen_helper_1e0i(mfthi, t0, 1);
9683 break;
9684 case 6:
9685 gen_helper_1e0i(mftacx, t0, 1);
9686 break;
9687 case 8:
9688 gen_helper_1e0i(mftlo, t0, 2);
9689 break;
9690 case 9:
9691 gen_helper_1e0i(mfthi, t0, 2);
9692 break;
9693 case 10:
9694 gen_helper_1e0i(mftacx, t0, 2);
9695 break;
9696 case 12:
9697 gen_helper_1e0i(mftlo, t0, 3);
9698 break;
9699 case 13:
9700 gen_helper_1e0i(mfthi, t0, 3);
9701 break;
9702 case 14:
9703 gen_helper_1e0i(mftacx, t0, 3);
9704 break;
9705 case 16:
9706 gen_helper_mftdsp(t0, cpu_env);
9707 break;
9708 default:
9709 goto die;
9711 break;
9712 /* Floating point (COP1). */
9713 case 2:
9714 /* XXX: For now we support only a single FPU context. */
9715 if (h == 0) {
9716 TCGv_i32 fp0 = tcg_temp_new_i32();
9718 gen_load_fpr32(ctx, fp0, rt);
9719 tcg_gen_ext_i32_tl(t0, fp0);
9720 tcg_temp_free_i32(fp0);
9721 } else {
9722 TCGv_i32 fp0 = tcg_temp_new_i32();
9724 gen_load_fpr32h(ctx, fp0, rt);
9725 tcg_gen_ext_i32_tl(t0, fp0);
9726 tcg_temp_free_i32(fp0);
9728 break;
9729 case 3:
9730 /* XXX: For now we support only a single FPU context. */
9731 gen_helper_1e0i(cfc1, t0, rt);
9732 break;
9733 /* COP2: Not implemented. */
9734 case 4:
9735 case 5:
9736 /* fall through */
9737 default:
9738 goto die;
9740 trace_mips_translate_tr("mftr", rt, u, sel, h);
9741 gen_store_gpr(t0, rd);
9742 tcg_temp_free(t0);
9743 return;
9745 die:
9746 tcg_temp_free(t0);
9747 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9748 generate_exception_end(ctx, EXCP_RI);
9751 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9752 int u, int sel, int h)
9754 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9755 TCGv t0 = tcg_temp_local_new();
9757 gen_load_gpr(t0, rt);
9758 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9759 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9760 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9761 /* NOP */ ;
9762 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9763 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9764 /* NOP */ ;
9765 else if (u == 0) {
9766 switch (rd) {
9767 case 1:
9768 switch (sel) {
9769 case 1:
9770 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9771 break;
9772 case 2:
9773 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9774 break;
9775 default:
9776 goto die;
9777 break;
9779 break;
9780 case 2:
9781 switch (sel) {
9782 case 1:
9783 gen_helper_mttc0_tcstatus(cpu_env, t0);
9784 break;
9785 case 2:
9786 gen_helper_mttc0_tcbind(cpu_env, t0);
9787 break;
9788 case 3:
9789 gen_helper_mttc0_tcrestart(cpu_env, t0);
9790 break;
9791 case 4:
9792 gen_helper_mttc0_tchalt(cpu_env, t0);
9793 break;
9794 case 5:
9795 gen_helper_mttc0_tccontext(cpu_env, t0);
9796 break;
9797 case 6:
9798 gen_helper_mttc0_tcschedule(cpu_env, t0);
9799 break;
9800 case 7:
9801 gen_helper_mttc0_tcschefback(cpu_env, t0);
9802 break;
9803 default:
9804 gen_mtc0(ctx, t0, rd, sel);
9805 break;
9807 break;
9808 case 10:
9809 switch (sel) {
9810 case 0:
9811 gen_helper_mttc0_entryhi(cpu_env, t0);
9812 break;
9813 default:
9814 gen_mtc0(ctx, t0, rd, sel);
9815 break;
9817 case 12:
9818 switch (sel) {
9819 case 0:
9820 gen_helper_mttc0_status(cpu_env, t0);
9821 break;
9822 default:
9823 gen_mtc0(ctx, t0, rd, sel);
9824 break;
9826 case 13:
9827 switch (sel) {
9828 case 0:
9829 gen_helper_mttc0_cause(cpu_env, t0);
9830 break;
9831 default:
9832 goto die;
9833 break;
9835 break;
9836 case 15:
9837 switch (sel) {
9838 case 1:
9839 gen_helper_mttc0_ebase(cpu_env, t0);
9840 break;
9841 default:
9842 goto die;
9843 break;
9845 break;
9846 case 23:
9847 switch (sel) {
9848 case 0:
9849 gen_helper_mttc0_debug(cpu_env, t0);
9850 break;
9851 default:
9852 gen_mtc0(ctx, t0, rd, sel);
9853 break;
9855 break;
9856 default:
9857 gen_mtc0(ctx, t0, rd, sel);
9859 } else switch (sel) {
9860 /* GPR registers. */
9861 case 0:
9862 gen_helper_0e1i(mttgpr, t0, rd);
9863 break;
9864 /* Auxiliary CPU registers */
9865 case 1:
9866 switch (rd) {
9867 case 0:
9868 gen_helper_0e1i(mttlo, t0, 0);
9869 break;
9870 case 1:
9871 gen_helper_0e1i(mtthi, t0, 0);
9872 break;
9873 case 2:
9874 gen_helper_0e1i(mttacx, t0, 0);
9875 break;
9876 case 4:
9877 gen_helper_0e1i(mttlo, t0, 1);
9878 break;
9879 case 5:
9880 gen_helper_0e1i(mtthi, t0, 1);
9881 break;
9882 case 6:
9883 gen_helper_0e1i(mttacx, t0, 1);
9884 break;
9885 case 8:
9886 gen_helper_0e1i(mttlo, t0, 2);
9887 break;
9888 case 9:
9889 gen_helper_0e1i(mtthi, t0, 2);
9890 break;
9891 case 10:
9892 gen_helper_0e1i(mttacx, t0, 2);
9893 break;
9894 case 12:
9895 gen_helper_0e1i(mttlo, t0, 3);
9896 break;
9897 case 13:
9898 gen_helper_0e1i(mtthi, t0, 3);
9899 break;
9900 case 14:
9901 gen_helper_0e1i(mttacx, t0, 3);
9902 break;
9903 case 16:
9904 gen_helper_mttdsp(cpu_env, t0);
9905 break;
9906 default:
9907 goto die;
9909 break;
9910 /* Floating point (COP1). */
9911 case 2:
9912 /* XXX: For now we support only a single FPU context. */
9913 if (h == 0) {
9914 TCGv_i32 fp0 = tcg_temp_new_i32();
9916 tcg_gen_trunc_tl_i32(fp0, t0);
9917 gen_store_fpr32(ctx, fp0, rd);
9918 tcg_temp_free_i32(fp0);
9919 } else {
9920 TCGv_i32 fp0 = tcg_temp_new_i32();
9922 tcg_gen_trunc_tl_i32(fp0, t0);
9923 gen_store_fpr32h(ctx, fp0, rd);
9924 tcg_temp_free_i32(fp0);
9926 break;
9927 case 3:
9928 /* XXX: For now we support only a single FPU context. */
9930 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9932 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9933 tcg_temp_free_i32(fs_tmp);
9935 /* Stop translation as we may have changed hflags */
9936 ctx->base.is_jmp = DISAS_STOP;
9937 break;
9938 /* COP2: Not implemented. */
9939 case 4:
9940 case 5:
9941 /* fall through */
9942 default:
9943 goto die;
9945 trace_mips_translate_tr("mttr", rd, u, sel, h);
9946 tcg_temp_free(t0);
9947 return;
9949 die:
9950 tcg_temp_free(t0);
9951 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9952 generate_exception_end(ctx, EXCP_RI);
9955 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9957 const char *opn = "ldst";
9959 check_cp0_enabled(ctx);
9960 switch (opc) {
9961 case OPC_MFC0:
9962 if (rt == 0) {
9963 /* Treat as NOP. */
9964 return;
9966 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9967 opn = "mfc0";
9968 break;
9969 case OPC_MTC0:
9971 TCGv t0 = tcg_temp_new();
9973 gen_load_gpr(t0, rt);
9974 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9975 tcg_temp_free(t0);
9977 opn = "mtc0";
9978 break;
9979 #if defined(TARGET_MIPS64)
9980 case OPC_DMFC0:
9981 check_insn(ctx, ISA_MIPS3);
9982 if (rt == 0) {
9983 /* Treat as NOP. */
9984 return;
9986 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9987 opn = "dmfc0";
9988 break;
9989 case OPC_DMTC0:
9990 check_insn(ctx, ISA_MIPS3);
9992 TCGv t0 = tcg_temp_new();
9994 gen_load_gpr(t0, rt);
9995 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9996 tcg_temp_free(t0);
9998 opn = "dmtc0";
9999 break;
10000 #endif
10001 case OPC_MFHC0:
10002 check_mvh(ctx);
10003 if (rt == 0) {
10004 /* Treat as NOP. */
10005 return;
10007 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10008 opn = "mfhc0";
10009 break;
10010 case OPC_MTHC0:
10011 check_mvh(ctx);
10013 TCGv t0 = tcg_temp_new();
10014 gen_load_gpr(t0, rt);
10015 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10016 tcg_temp_free(t0);
10018 opn = "mthc0";
10019 break;
10020 case OPC_MFTR:
10021 check_cp0_enabled(ctx);
10022 if (rd == 0) {
10023 /* Treat as NOP. */
10024 return;
10026 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10027 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10028 opn = "mftr";
10029 break;
10030 case OPC_MTTR:
10031 check_cp0_enabled(ctx);
10032 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10033 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10034 opn = "mttr";
10035 break;
10036 case OPC_TLBWI:
10037 opn = "tlbwi";
10038 if (!env->tlb->helper_tlbwi)
10039 goto die;
10040 gen_helper_tlbwi(cpu_env);
10041 break;
10042 case OPC_TLBINV:
10043 opn = "tlbinv";
10044 if (ctx->ie >= 2) {
10045 if (!env->tlb->helper_tlbinv) {
10046 goto die;
10048 gen_helper_tlbinv(cpu_env);
10049 } /* treat as nop if TLBINV not supported */
10050 break;
10051 case OPC_TLBINVF:
10052 opn = "tlbinvf";
10053 if (ctx->ie >= 2) {
10054 if (!env->tlb->helper_tlbinvf) {
10055 goto die;
10057 gen_helper_tlbinvf(cpu_env);
10058 } /* treat as nop if TLBINV not supported */
10059 break;
10060 case OPC_TLBWR:
10061 opn = "tlbwr";
10062 if (!env->tlb->helper_tlbwr)
10063 goto die;
10064 gen_helper_tlbwr(cpu_env);
10065 break;
10066 case OPC_TLBP:
10067 opn = "tlbp";
10068 if (!env->tlb->helper_tlbp)
10069 goto die;
10070 gen_helper_tlbp(cpu_env);
10071 break;
10072 case OPC_TLBR:
10073 opn = "tlbr";
10074 if (!env->tlb->helper_tlbr)
10075 goto die;
10076 gen_helper_tlbr(cpu_env);
10077 break;
10078 case OPC_ERET: /* OPC_ERETNC */
10079 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10080 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10081 goto die;
10082 } else {
10083 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10084 if (ctx->opcode & (1 << bit_shift)) {
10085 /* OPC_ERETNC */
10086 opn = "eretnc";
10087 check_insn(ctx, ISA_MIPS32R5);
10088 gen_helper_eretnc(cpu_env);
10089 } else {
10090 /* OPC_ERET */
10091 opn = "eret";
10092 check_insn(ctx, ISA_MIPS2);
10093 gen_helper_eret(cpu_env);
10095 ctx->base.is_jmp = DISAS_EXIT;
10097 break;
10098 case OPC_DERET:
10099 opn = "deret";
10100 check_insn(ctx, ISA_MIPS32);
10101 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10102 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10103 goto die;
10105 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10106 MIPS_INVAL(opn);
10107 generate_exception_end(ctx, EXCP_RI);
10108 } else {
10109 gen_helper_deret(cpu_env);
10110 ctx->base.is_jmp = DISAS_EXIT;
10112 break;
10113 case OPC_WAIT:
10114 opn = "wait";
10115 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10116 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10117 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10118 goto die;
10120 /* If we get an exception, we want to restart at next instruction */
10121 ctx->base.pc_next += 4;
10122 save_cpu_state(ctx, 1);
10123 ctx->base.pc_next -= 4;
10124 gen_helper_wait(cpu_env);
10125 ctx->base.is_jmp = DISAS_NORETURN;
10126 break;
10127 default:
10128 die:
10129 MIPS_INVAL(opn);
10130 generate_exception_end(ctx, EXCP_RI);
10131 return;
10133 (void)opn; /* avoid a compiler warning */
10135 #endif /* !CONFIG_USER_ONLY */
10137 /* CP1 Branches (before delay slot) */
10138 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10139 int32_t cc, int32_t offset)
10141 target_ulong btarget;
10142 TCGv_i32 t0 = tcg_temp_new_i32();
10144 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10145 generate_exception_end(ctx, EXCP_RI);
10146 goto out;
10149 if (cc != 0)
10150 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10152 btarget = ctx->base.pc_next + 4 + offset;
10154 switch (op) {
10155 case OPC_BC1F:
10156 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10157 tcg_gen_not_i32(t0, t0);
10158 tcg_gen_andi_i32(t0, t0, 1);
10159 tcg_gen_extu_i32_tl(bcond, t0);
10160 goto not_likely;
10161 case OPC_BC1FL:
10162 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10163 tcg_gen_not_i32(t0, t0);
10164 tcg_gen_andi_i32(t0, t0, 1);
10165 tcg_gen_extu_i32_tl(bcond, t0);
10166 goto likely;
10167 case OPC_BC1T:
10168 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10169 tcg_gen_andi_i32(t0, t0, 1);
10170 tcg_gen_extu_i32_tl(bcond, t0);
10171 goto not_likely;
10172 case OPC_BC1TL:
10173 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10174 tcg_gen_andi_i32(t0, t0, 1);
10175 tcg_gen_extu_i32_tl(bcond, t0);
10176 likely:
10177 ctx->hflags |= MIPS_HFLAG_BL;
10178 break;
10179 case OPC_BC1FANY2:
10181 TCGv_i32 t1 = tcg_temp_new_i32();
10182 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10183 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10184 tcg_gen_nand_i32(t0, t0, t1);
10185 tcg_temp_free_i32(t1);
10186 tcg_gen_andi_i32(t0, t0, 1);
10187 tcg_gen_extu_i32_tl(bcond, t0);
10189 goto not_likely;
10190 case OPC_BC1TANY2:
10192 TCGv_i32 t1 = tcg_temp_new_i32();
10193 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10194 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10195 tcg_gen_or_i32(t0, t0, t1);
10196 tcg_temp_free_i32(t1);
10197 tcg_gen_andi_i32(t0, t0, 1);
10198 tcg_gen_extu_i32_tl(bcond, t0);
10200 goto not_likely;
10201 case OPC_BC1FANY4:
10203 TCGv_i32 t1 = tcg_temp_new_i32();
10204 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10205 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10206 tcg_gen_and_i32(t0, t0, t1);
10207 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10208 tcg_gen_and_i32(t0, t0, t1);
10209 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10210 tcg_gen_nand_i32(t0, t0, t1);
10211 tcg_temp_free_i32(t1);
10212 tcg_gen_andi_i32(t0, t0, 1);
10213 tcg_gen_extu_i32_tl(bcond, t0);
10215 goto not_likely;
10216 case OPC_BC1TANY4:
10218 TCGv_i32 t1 = tcg_temp_new_i32();
10219 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10220 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10221 tcg_gen_or_i32(t0, t0, t1);
10222 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10223 tcg_gen_or_i32(t0, t0, t1);
10224 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10225 tcg_gen_or_i32(t0, t0, t1);
10226 tcg_temp_free_i32(t1);
10227 tcg_gen_andi_i32(t0, t0, 1);
10228 tcg_gen_extu_i32_tl(bcond, t0);
10230 not_likely:
10231 ctx->hflags |= MIPS_HFLAG_BC;
10232 break;
10233 default:
10234 MIPS_INVAL("cp1 cond branch");
10235 generate_exception_end(ctx, EXCP_RI);
10236 goto out;
10238 ctx->btarget = btarget;
10239 ctx->hflags |= MIPS_HFLAG_BDS32;
10240 out:
10241 tcg_temp_free_i32(t0);
10244 /* R6 CP1 Branches */
10245 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10246 int32_t ft, int32_t offset,
10247 int delayslot_size)
10249 target_ulong btarget;
10250 TCGv_i64 t0 = tcg_temp_new_i64();
10252 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10253 #ifdef MIPS_DEBUG_DISAS
10254 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10255 "\n", ctx->base.pc_next);
10256 #endif
10257 generate_exception_end(ctx, EXCP_RI);
10258 goto out;
10261 gen_load_fpr64(ctx, t0, ft);
10262 tcg_gen_andi_i64(t0, t0, 1);
10264 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10266 switch (op) {
10267 case OPC_BC1EQZ:
10268 tcg_gen_xori_i64(t0, t0, 1);
10269 ctx->hflags |= MIPS_HFLAG_BC;
10270 break;
10271 case OPC_BC1NEZ:
10272 /* t0 already set */
10273 ctx->hflags |= MIPS_HFLAG_BC;
10274 break;
10275 default:
10276 MIPS_INVAL("cp1 cond branch");
10277 generate_exception_end(ctx, EXCP_RI);
10278 goto out;
10281 tcg_gen_trunc_i64_tl(bcond, t0);
10283 ctx->btarget = btarget;
10285 switch (delayslot_size) {
10286 case 2:
10287 ctx->hflags |= MIPS_HFLAG_BDS16;
10288 break;
10289 case 4:
10290 ctx->hflags |= MIPS_HFLAG_BDS32;
10291 break;
10294 out:
10295 tcg_temp_free_i64(t0);
10298 /* Coprocessor 1 (FPU) */
10300 #define FOP(func, fmt) (((fmt) << 21) | (func))
10302 enum fopcode {
10303 OPC_ADD_S = FOP(0, FMT_S),
10304 OPC_SUB_S = FOP(1, FMT_S),
10305 OPC_MUL_S = FOP(2, FMT_S),
10306 OPC_DIV_S = FOP(3, FMT_S),
10307 OPC_SQRT_S = FOP(4, FMT_S),
10308 OPC_ABS_S = FOP(5, FMT_S),
10309 OPC_MOV_S = FOP(6, FMT_S),
10310 OPC_NEG_S = FOP(7, FMT_S),
10311 OPC_ROUND_L_S = FOP(8, FMT_S),
10312 OPC_TRUNC_L_S = FOP(9, FMT_S),
10313 OPC_CEIL_L_S = FOP(10, FMT_S),
10314 OPC_FLOOR_L_S = FOP(11, FMT_S),
10315 OPC_ROUND_W_S = FOP(12, FMT_S),
10316 OPC_TRUNC_W_S = FOP(13, FMT_S),
10317 OPC_CEIL_W_S = FOP(14, FMT_S),
10318 OPC_FLOOR_W_S = FOP(15, FMT_S),
10319 OPC_SEL_S = FOP(16, FMT_S),
10320 OPC_MOVCF_S = FOP(17, FMT_S),
10321 OPC_MOVZ_S = FOP(18, FMT_S),
10322 OPC_MOVN_S = FOP(19, FMT_S),
10323 OPC_SELEQZ_S = FOP(20, FMT_S),
10324 OPC_RECIP_S = FOP(21, FMT_S),
10325 OPC_RSQRT_S = FOP(22, FMT_S),
10326 OPC_SELNEZ_S = FOP(23, FMT_S),
10327 OPC_MADDF_S = FOP(24, FMT_S),
10328 OPC_MSUBF_S = FOP(25, FMT_S),
10329 OPC_RINT_S = FOP(26, FMT_S),
10330 OPC_CLASS_S = FOP(27, FMT_S),
10331 OPC_MIN_S = FOP(28, FMT_S),
10332 OPC_RECIP2_S = FOP(28, FMT_S),
10333 OPC_MINA_S = FOP(29, FMT_S),
10334 OPC_RECIP1_S = FOP(29, FMT_S),
10335 OPC_MAX_S = FOP(30, FMT_S),
10336 OPC_RSQRT1_S = FOP(30, FMT_S),
10337 OPC_MAXA_S = FOP(31, FMT_S),
10338 OPC_RSQRT2_S = FOP(31, FMT_S),
10339 OPC_CVT_D_S = FOP(33, FMT_S),
10340 OPC_CVT_W_S = FOP(36, FMT_S),
10341 OPC_CVT_L_S = FOP(37, FMT_S),
10342 OPC_CVT_PS_S = FOP(38, FMT_S),
10343 OPC_CMP_F_S = FOP (48, FMT_S),
10344 OPC_CMP_UN_S = FOP (49, FMT_S),
10345 OPC_CMP_EQ_S = FOP (50, FMT_S),
10346 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10347 OPC_CMP_OLT_S = FOP (52, FMT_S),
10348 OPC_CMP_ULT_S = FOP (53, FMT_S),
10349 OPC_CMP_OLE_S = FOP (54, FMT_S),
10350 OPC_CMP_ULE_S = FOP (55, FMT_S),
10351 OPC_CMP_SF_S = FOP (56, FMT_S),
10352 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10353 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10354 OPC_CMP_NGL_S = FOP (59, FMT_S),
10355 OPC_CMP_LT_S = FOP (60, FMT_S),
10356 OPC_CMP_NGE_S = FOP (61, FMT_S),
10357 OPC_CMP_LE_S = FOP (62, FMT_S),
10358 OPC_CMP_NGT_S = FOP (63, FMT_S),
10360 OPC_ADD_D = FOP(0, FMT_D),
10361 OPC_SUB_D = FOP(1, FMT_D),
10362 OPC_MUL_D = FOP(2, FMT_D),
10363 OPC_DIV_D = FOP(3, FMT_D),
10364 OPC_SQRT_D = FOP(4, FMT_D),
10365 OPC_ABS_D = FOP(5, FMT_D),
10366 OPC_MOV_D = FOP(6, FMT_D),
10367 OPC_NEG_D = FOP(7, FMT_D),
10368 OPC_ROUND_L_D = FOP(8, FMT_D),
10369 OPC_TRUNC_L_D = FOP(9, FMT_D),
10370 OPC_CEIL_L_D = FOP(10, FMT_D),
10371 OPC_FLOOR_L_D = FOP(11, FMT_D),
10372 OPC_ROUND_W_D = FOP(12, FMT_D),
10373 OPC_TRUNC_W_D = FOP(13, FMT_D),
10374 OPC_CEIL_W_D = FOP(14, FMT_D),
10375 OPC_FLOOR_W_D = FOP(15, FMT_D),
10376 OPC_SEL_D = FOP(16, FMT_D),
10377 OPC_MOVCF_D = FOP(17, FMT_D),
10378 OPC_MOVZ_D = FOP(18, FMT_D),
10379 OPC_MOVN_D = FOP(19, FMT_D),
10380 OPC_SELEQZ_D = FOP(20, FMT_D),
10381 OPC_RECIP_D = FOP(21, FMT_D),
10382 OPC_RSQRT_D = FOP(22, FMT_D),
10383 OPC_SELNEZ_D = FOP(23, FMT_D),
10384 OPC_MADDF_D = FOP(24, FMT_D),
10385 OPC_MSUBF_D = FOP(25, FMT_D),
10386 OPC_RINT_D = FOP(26, FMT_D),
10387 OPC_CLASS_D = FOP(27, FMT_D),
10388 OPC_MIN_D = FOP(28, FMT_D),
10389 OPC_RECIP2_D = FOP(28, FMT_D),
10390 OPC_MINA_D = FOP(29, FMT_D),
10391 OPC_RECIP1_D = FOP(29, FMT_D),
10392 OPC_MAX_D = FOP(30, FMT_D),
10393 OPC_RSQRT1_D = FOP(30, FMT_D),
10394 OPC_MAXA_D = FOP(31, FMT_D),
10395 OPC_RSQRT2_D = FOP(31, FMT_D),
10396 OPC_CVT_S_D = FOP(32, FMT_D),
10397 OPC_CVT_W_D = FOP(36, FMT_D),
10398 OPC_CVT_L_D = FOP(37, FMT_D),
10399 OPC_CMP_F_D = FOP (48, FMT_D),
10400 OPC_CMP_UN_D = FOP (49, FMT_D),
10401 OPC_CMP_EQ_D = FOP (50, FMT_D),
10402 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10403 OPC_CMP_OLT_D = FOP (52, FMT_D),
10404 OPC_CMP_ULT_D = FOP (53, FMT_D),
10405 OPC_CMP_OLE_D = FOP (54, FMT_D),
10406 OPC_CMP_ULE_D = FOP (55, FMT_D),
10407 OPC_CMP_SF_D = FOP (56, FMT_D),
10408 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10409 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10410 OPC_CMP_NGL_D = FOP (59, FMT_D),
10411 OPC_CMP_LT_D = FOP (60, FMT_D),
10412 OPC_CMP_NGE_D = FOP (61, FMT_D),
10413 OPC_CMP_LE_D = FOP (62, FMT_D),
10414 OPC_CMP_NGT_D = FOP (63, FMT_D),
10416 OPC_CVT_S_W = FOP(32, FMT_W),
10417 OPC_CVT_D_W = FOP(33, FMT_W),
10418 OPC_CVT_S_L = FOP(32, FMT_L),
10419 OPC_CVT_D_L = FOP(33, FMT_L),
10420 OPC_CVT_PS_PW = FOP(38, FMT_W),
10422 OPC_ADD_PS = FOP(0, FMT_PS),
10423 OPC_SUB_PS = FOP(1, FMT_PS),
10424 OPC_MUL_PS = FOP(2, FMT_PS),
10425 OPC_DIV_PS = FOP(3, FMT_PS),
10426 OPC_ABS_PS = FOP(5, FMT_PS),
10427 OPC_MOV_PS = FOP(6, FMT_PS),
10428 OPC_NEG_PS = FOP(7, FMT_PS),
10429 OPC_MOVCF_PS = FOP(17, FMT_PS),
10430 OPC_MOVZ_PS = FOP(18, FMT_PS),
10431 OPC_MOVN_PS = FOP(19, FMT_PS),
10432 OPC_ADDR_PS = FOP(24, FMT_PS),
10433 OPC_MULR_PS = FOP(26, FMT_PS),
10434 OPC_RECIP2_PS = FOP(28, FMT_PS),
10435 OPC_RECIP1_PS = FOP(29, FMT_PS),
10436 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10437 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10439 OPC_CVT_S_PU = FOP(32, FMT_PS),
10440 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10441 OPC_CVT_S_PL = FOP(40, FMT_PS),
10442 OPC_PLL_PS = FOP(44, FMT_PS),
10443 OPC_PLU_PS = FOP(45, FMT_PS),
10444 OPC_PUL_PS = FOP(46, FMT_PS),
10445 OPC_PUU_PS = FOP(47, FMT_PS),
10446 OPC_CMP_F_PS = FOP (48, FMT_PS),
10447 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10448 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10449 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10450 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10451 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10452 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10453 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10454 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10455 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10456 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10457 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10458 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10459 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10460 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10461 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10464 enum r6_f_cmp_op {
10465 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10466 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10467 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10468 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10469 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10470 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10471 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10472 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10473 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10474 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10475 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10476 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10477 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10478 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10479 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10480 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10481 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10482 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10483 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10484 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10485 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10486 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10488 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10489 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10490 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10491 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10492 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10493 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10494 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10495 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10496 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10497 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10498 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10499 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10500 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10501 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10502 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10503 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10504 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10505 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10506 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10507 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10508 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10509 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10511 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10513 TCGv t0 = tcg_temp_new();
10515 switch (opc) {
10516 case OPC_MFC1:
10518 TCGv_i32 fp0 = tcg_temp_new_i32();
10520 gen_load_fpr32(ctx, fp0, fs);
10521 tcg_gen_ext_i32_tl(t0, fp0);
10522 tcg_temp_free_i32(fp0);
10524 gen_store_gpr(t0, rt);
10525 break;
10526 case OPC_MTC1:
10527 gen_load_gpr(t0, rt);
10529 TCGv_i32 fp0 = tcg_temp_new_i32();
10531 tcg_gen_trunc_tl_i32(fp0, t0);
10532 gen_store_fpr32(ctx, fp0, fs);
10533 tcg_temp_free_i32(fp0);
10535 break;
10536 case OPC_CFC1:
10537 gen_helper_1e0i(cfc1, t0, fs);
10538 gen_store_gpr(t0, rt);
10539 break;
10540 case OPC_CTC1:
10541 gen_load_gpr(t0, rt);
10542 save_cpu_state(ctx, 0);
10544 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10546 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10547 tcg_temp_free_i32(fs_tmp);
10549 /* Stop translation as we may have changed hflags */
10550 ctx->base.is_jmp = DISAS_STOP;
10551 break;
10552 #if defined(TARGET_MIPS64)
10553 case OPC_DMFC1:
10554 gen_load_fpr64(ctx, t0, fs);
10555 gen_store_gpr(t0, rt);
10556 break;
10557 case OPC_DMTC1:
10558 gen_load_gpr(t0, rt);
10559 gen_store_fpr64(ctx, t0, fs);
10560 break;
10561 #endif
10562 case OPC_MFHC1:
10564 TCGv_i32 fp0 = tcg_temp_new_i32();
10566 gen_load_fpr32h(ctx, fp0, fs);
10567 tcg_gen_ext_i32_tl(t0, fp0);
10568 tcg_temp_free_i32(fp0);
10570 gen_store_gpr(t0, rt);
10571 break;
10572 case OPC_MTHC1:
10573 gen_load_gpr(t0, rt);
10575 TCGv_i32 fp0 = tcg_temp_new_i32();
10577 tcg_gen_trunc_tl_i32(fp0, t0);
10578 gen_store_fpr32h(ctx, fp0, fs);
10579 tcg_temp_free_i32(fp0);
10581 break;
10582 default:
10583 MIPS_INVAL("cp1 move");
10584 generate_exception_end(ctx, EXCP_RI);
10585 goto out;
10588 out:
10589 tcg_temp_free(t0);
10592 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10594 TCGLabel *l1;
10595 TCGCond cond;
10596 TCGv_i32 t0;
10598 if (rd == 0) {
10599 /* Treat as NOP. */
10600 return;
10603 if (tf)
10604 cond = TCG_COND_EQ;
10605 else
10606 cond = TCG_COND_NE;
10608 l1 = gen_new_label();
10609 t0 = tcg_temp_new_i32();
10610 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10611 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10612 tcg_temp_free_i32(t0);
10613 if (rs == 0) {
10614 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10615 } else {
10616 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10618 gen_set_label(l1);
10621 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10622 int tf)
10624 int cond;
10625 TCGv_i32 t0 = tcg_temp_new_i32();
10626 TCGLabel *l1 = gen_new_label();
10628 if (tf)
10629 cond = TCG_COND_EQ;
10630 else
10631 cond = TCG_COND_NE;
10633 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10634 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10635 gen_load_fpr32(ctx, t0, fs);
10636 gen_store_fpr32(ctx, t0, fd);
10637 gen_set_label(l1);
10638 tcg_temp_free_i32(t0);
10641 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10643 int cond;
10644 TCGv_i32 t0 = tcg_temp_new_i32();
10645 TCGv_i64 fp0;
10646 TCGLabel *l1 = gen_new_label();
10648 if (tf)
10649 cond = TCG_COND_EQ;
10650 else
10651 cond = TCG_COND_NE;
10653 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10654 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10655 tcg_temp_free_i32(t0);
10656 fp0 = tcg_temp_new_i64();
10657 gen_load_fpr64(ctx, fp0, fs);
10658 gen_store_fpr64(ctx, fp0, fd);
10659 tcg_temp_free_i64(fp0);
10660 gen_set_label(l1);
10663 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10664 int cc, int tf)
10666 int cond;
10667 TCGv_i32 t0 = tcg_temp_new_i32();
10668 TCGLabel *l1 = gen_new_label();
10669 TCGLabel *l2 = gen_new_label();
10671 if (tf)
10672 cond = TCG_COND_EQ;
10673 else
10674 cond = TCG_COND_NE;
10676 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10677 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10678 gen_load_fpr32(ctx, t0, fs);
10679 gen_store_fpr32(ctx, t0, fd);
10680 gen_set_label(l1);
10682 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10683 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10684 gen_load_fpr32h(ctx, t0, fs);
10685 gen_store_fpr32h(ctx, t0, fd);
10686 tcg_temp_free_i32(t0);
10687 gen_set_label(l2);
10690 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10691 int fs)
10693 TCGv_i32 t1 = tcg_const_i32(0);
10694 TCGv_i32 fp0 = tcg_temp_new_i32();
10695 TCGv_i32 fp1 = tcg_temp_new_i32();
10696 TCGv_i32 fp2 = tcg_temp_new_i32();
10697 gen_load_fpr32(ctx, fp0, fd);
10698 gen_load_fpr32(ctx, fp1, ft);
10699 gen_load_fpr32(ctx, fp2, fs);
10701 switch (op1) {
10702 case OPC_SEL_S:
10703 tcg_gen_andi_i32(fp0, fp0, 1);
10704 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10705 break;
10706 case OPC_SELEQZ_S:
10707 tcg_gen_andi_i32(fp1, fp1, 1);
10708 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10709 break;
10710 case OPC_SELNEZ_S:
10711 tcg_gen_andi_i32(fp1, fp1, 1);
10712 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10713 break;
10714 default:
10715 MIPS_INVAL("gen_sel_s");
10716 generate_exception_end(ctx, EXCP_RI);
10717 break;
10720 gen_store_fpr32(ctx, fp0, fd);
10721 tcg_temp_free_i32(fp2);
10722 tcg_temp_free_i32(fp1);
10723 tcg_temp_free_i32(fp0);
10724 tcg_temp_free_i32(t1);
10727 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10728 int fs)
10730 TCGv_i64 t1 = tcg_const_i64(0);
10731 TCGv_i64 fp0 = tcg_temp_new_i64();
10732 TCGv_i64 fp1 = tcg_temp_new_i64();
10733 TCGv_i64 fp2 = tcg_temp_new_i64();
10734 gen_load_fpr64(ctx, fp0, fd);
10735 gen_load_fpr64(ctx, fp1, ft);
10736 gen_load_fpr64(ctx, fp2, fs);
10738 switch (op1) {
10739 case OPC_SEL_D:
10740 tcg_gen_andi_i64(fp0, fp0, 1);
10741 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10742 break;
10743 case OPC_SELEQZ_D:
10744 tcg_gen_andi_i64(fp1, fp1, 1);
10745 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10746 break;
10747 case OPC_SELNEZ_D:
10748 tcg_gen_andi_i64(fp1, fp1, 1);
10749 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10750 break;
10751 default:
10752 MIPS_INVAL("gen_sel_d");
10753 generate_exception_end(ctx, EXCP_RI);
10754 break;
10757 gen_store_fpr64(ctx, fp0, fd);
10758 tcg_temp_free_i64(fp2);
10759 tcg_temp_free_i64(fp1);
10760 tcg_temp_free_i64(fp0);
10761 tcg_temp_free_i64(t1);
10764 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10765 int ft, int fs, int fd, int cc)
10767 uint32_t func = ctx->opcode & 0x3f;
10768 switch (op1) {
10769 case OPC_ADD_S:
10771 TCGv_i32 fp0 = tcg_temp_new_i32();
10772 TCGv_i32 fp1 = tcg_temp_new_i32();
10774 gen_load_fpr32(ctx, fp0, fs);
10775 gen_load_fpr32(ctx, fp1, ft);
10776 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10777 tcg_temp_free_i32(fp1);
10778 gen_store_fpr32(ctx, fp0, fd);
10779 tcg_temp_free_i32(fp0);
10781 break;
10782 case OPC_SUB_S:
10784 TCGv_i32 fp0 = tcg_temp_new_i32();
10785 TCGv_i32 fp1 = tcg_temp_new_i32();
10787 gen_load_fpr32(ctx, fp0, fs);
10788 gen_load_fpr32(ctx, fp1, ft);
10789 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10790 tcg_temp_free_i32(fp1);
10791 gen_store_fpr32(ctx, fp0, fd);
10792 tcg_temp_free_i32(fp0);
10794 break;
10795 case OPC_MUL_S:
10797 TCGv_i32 fp0 = tcg_temp_new_i32();
10798 TCGv_i32 fp1 = tcg_temp_new_i32();
10800 gen_load_fpr32(ctx, fp0, fs);
10801 gen_load_fpr32(ctx, fp1, ft);
10802 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10803 tcg_temp_free_i32(fp1);
10804 gen_store_fpr32(ctx, fp0, fd);
10805 tcg_temp_free_i32(fp0);
10807 break;
10808 case OPC_DIV_S:
10810 TCGv_i32 fp0 = tcg_temp_new_i32();
10811 TCGv_i32 fp1 = tcg_temp_new_i32();
10813 gen_load_fpr32(ctx, fp0, fs);
10814 gen_load_fpr32(ctx, fp1, ft);
10815 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10816 tcg_temp_free_i32(fp1);
10817 gen_store_fpr32(ctx, fp0, fd);
10818 tcg_temp_free_i32(fp0);
10820 break;
10821 case OPC_SQRT_S:
10823 TCGv_i32 fp0 = tcg_temp_new_i32();
10825 gen_load_fpr32(ctx, fp0, fs);
10826 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10827 gen_store_fpr32(ctx, fp0, fd);
10828 tcg_temp_free_i32(fp0);
10830 break;
10831 case OPC_ABS_S:
10833 TCGv_i32 fp0 = tcg_temp_new_i32();
10835 gen_load_fpr32(ctx, fp0, fs);
10836 if (ctx->abs2008) {
10837 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10838 } else {
10839 gen_helper_float_abs_s(fp0, fp0);
10841 gen_store_fpr32(ctx, fp0, fd);
10842 tcg_temp_free_i32(fp0);
10844 break;
10845 case OPC_MOV_S:
10847 TCGv_i32 fp0 = tcg_temp_new_i32();
10849 gen_load_fpr32(ctx, fp0, fs);
10850 gen_store_fpr32(ctx, fp0, fd);
10851 tcg_temp_free_i32(fp0);
10853 break;
10854 case OPC_NEG_S:
10856 TCGv_i32 fp0 = tcg_temp_new_i32();
10858 gen_load_fpr32(ctx, fp0, fs);
10859 if (ctx->abs2008) {
10860 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10861 } else {
10862 gen_helper_float_chs_s(fp0, fp0);
10864 gen_store_fpr32(ctx, fp0, fd);
10865 tcg_temp_free_i32(fp0);
10867 break;
10868 case OPC_ROUND_L_S:
10869 check_cp1_64bitmode(ctx);
10871 TCGv_i32 fp32 = tcg_temp_new_i32();
10872 TCGv_i64 fp64 = tcg_temp_new_i64();
10874 gen_load_fpr32(ctx, fp32, fs);
10875 if (ctx->nan2008) {
10876 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10877 } else {
10878 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10880 tcg_temp_free_i32(fp32);
10881 gen_store_fpr64(ctx, fp64, fd);
10882 tcg_temp_free_i64(fp64);
10884 break;
10885 case OPC_TRUNC_L_S:
10886 check_cp1_64bitmode(ctx);
10888 TCGv_i32 fp32 = tcg_temp_new_i32();
10889 TCGv_i64 fp64 = tcg_temp_new_i64();
10891 gen_load_fpr32(ctx, fp32, fs);
10892 if (ctx->nan2008) {
10893 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10894 } else {
10895 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10897 tcg_temp_free_i32(fp32);
10898 gen_store_fpr64(ctx, fp64, fd);
10899 tcg_temp_free_i64(fp64);
10901 break;
10902 case OPC_CEIL_L_S:
10903 check_cp1_64bitmode(ctx);
10905 TCGv_i32 fp32 = tcg_temp_new_i32();
10906 TCGv_i64 fp64 = tcg_temp_new_i64();
10908 gen_load_fpr32(ctx, fp32, fs);
10909 if (ctx->nan2008) {
10910 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10911 } else {
10912 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10914 tcg_temp_free_i32(fp32);
10915 gen_store_fpr64(ctx, fp64, fd);
10916 tcg_temp_free_i64(fp64);
10918 break;
10919 case OPC_FLOOR_L_S:
10920 check_cp1_64bitmode(ctx);
10922 TCGv_i32 fp32 = tcg_temp_new_i32();
10923 TCGv_i64 fp64 = tcg_temp_new_i64();
10925 gen_load_fpr32(ctx, fp32, fs);
10926 if (ctx->nan2008) {
10927 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10928 } else {
10929 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10931 tcg_temp_free_i32(fp32);
10932 gen_store_fpr64(ctx, fp64, fd);
10933 tcg_temp_free_i64(fp64);
10935 break;
10936 case OPC_ROUND_W_S:
10938 TCGv_i32 fp0 = tcg_temp_new_i32();
10940 gen_load_fpr32(ctx, fp0, fs);
10941 if (ctx->nan2008) {
10942 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10943 } else {
10944 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10946 gen_store_fpr32(ctx, fp0, fd);
10947 tcg_temp_free_i32(fp0);
10949 break;
10950 case OPC_TRUNC_W_S:
10952 TCGv_i32 fp0 = tcg_temp_new_i32();
10954 gen_load_fpr32(ctx, fp0, fs);
10955 if (ctx->nan2008) {
10956 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10957 } else {
10958 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10960 gen_store_fpr32(ctx, fp0, fd);
10961 tcg_temp_free_i32(fp0);
10963 break;
10964 case OPC_CEIL_W_S:
10966 TCGv_i32 fp0 = tcg_temp_new_i32();
10968 gen_load_fpr32(ctx, fp0, fs);
10969 if (ctx->nan2008) {
10970 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10971 } else {
10972 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10974 gen_store_fpr32(ctx, fp0, fd);
10975 tcg_temp_free_i32(fp0);
10977 break;
10978 case OPC_FLOOR_W_S:
10980 TCGv_i32 fp0 = tcg_temp_new_i32();
10982 gen_load_fpr32(ctx, fp0, fs);
10983 if (ctx->nan2008) {
10984 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10985 } else {
10986 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10988 gen_store_fpr32(ctx, fp0, fd);
10989 tcg_temp_free_i32(fp0);
10991 break;
10992 case OPC_SEL_S:
10993 check_insn(ctx, ISA_MIPS32R6);
10994 gen_sel_s(ctx, op1, fd, ft, fs);
10995 break;
10996 case OPC_SELEQZ_S:
10997 check_insn(ctx, ISA_MIPS32R6);
10998 gen_sel_s(ctx, op1, fd, ft, fs);
10999 break;
11000 case OPC_SELNEZ_S:
11001 check_insn(ctx, ISA_MIPS32R6);
11002 gen_sel_s(ctx, op1, fd, ft, fs);
11003 break;
11004 case OPC_MOVCF_S:
11005 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11006 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11007 break;
11008 case OPC_MOVZ_S:
11009 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11011 TCGLabel *l1 = gen_new_label();
11012 TCGv_i32 fp0;
11014 if (ft != 0) {
11015 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11017 fp0 = tcg_temp_new_i32();
11018 gen_load_fpr32(ctx, fp0, fs);
11019 gen_store_fpr32(ctx, fp0, fd);
11020 tcg_temp_free_i32(fp0);
11021 gen_set_label(l1);
11023 break;
11024 case OPC_MOVN_S:
11025 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11027 TCGLabel *l1 = gen_new_label();
11028 TCGv_i32 fp0;
11030 if (ft != 0) {
11031 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11032 fp0 = tcg_temp_new_i32();
11033 gen_load_fpr32(ctx, fp0, fs);
11034 gen_store_fpr32(ctx, fp0, fd);
11035 tcg_temp_free_i32(fp0);
11036 gen_set_label(l1);
11039 break;
11040 case OPC_RECIP_S:
11042 TCGv_i32 fp0 = tcg_temp_new_i32();
11044 gen_load_fpr32(ctx, fp0, fs);
11045 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11046 gen_store_fpr32(ctx, fp0, fd);
11047 tcg_temp_free_i32(fp0);
11049 break;
11050 case OPC_RSQRT_S:
11052 TCGv_i32 fp0 = tcg_temp_new_i32();
11054 gen_load_fpr32(ctx, fp0, fs);
11055 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11056 gen_store_fpr32(ctx, fp0, fd);
11057 tcg_temp_free_i32(fp0);
11059 break;
11060 case OPC_MADDF_S:
11061 check_insn(ctx, ISA_MIPS32R6);
11063 TCGv_i32 fp0 = tcg_temp_new_i32();
11064 TCGv_i32 fp1 = tcg_temp_new_i32();
11065 TCGv_i32 fp2 = tcg_temp_new_i32();
11066 gen_load_fpr32(ctx, fp0, fs);
11067 gen_load_fpr32(ctx, fp1, ft);
11068 gen_load_fpr32(ctx, fp2, fd);
11069 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11070 gen_store_fpr32(ctx, fp2, fd);
11071 tcg_temp_free_i32(fp2);
11072 tcg_temp_free_i32(fp1);
11073 tcg_temp_free_i32(fp0);
11075 break;
11076 case OPC_MSUBF_S:
11077 check_insn(ctx, ISA_MIPS32R6);
11079 TCGv_i32 fp0 = tcg_temp_new_i32();
11080 TCGv_i32 fp1 = tcg_temp_new_i32();
11081 TCGv_i32 fp2 = tcg_temp_new_i32();
11082 gen_load_fpr32(ctx, fp0, fs);
11083 gen_load_fpr32(ctx, fp1, ft);
11084 gen_load_fpr32(ctx, fp2, fd);
11085 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11086 gen_store_fpr32(ctx, fp2, fd);
11087 tcg_temp_free_i32(fp2);
11088 tcg_temp_free_i32(fp1);
11089 tcg_temp_free_i32(fp0);
11091 break;
11092 case OPC_RINT_S:
11093 check_insn(ctx, ISA_MIPS32R6);
11095 TCGv_i32 fp0 = tcg_temp_new_i32();
11096 gen_load_fpr32(ctx, fp0, fs);
11097 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11098 gen_store_fpr32(ctx, fp0, fd);
11099 tcg_temp_free_i32(fp0);
11101 break;
11102 case OPC_CLASS_S:
11103 check_insn(ctx, ISA_MIPS32R6);
11105 TCGv_i32 fp0 = tcg_temp_new_i32();
11106 gen_load_fpr32(ctx, fp0, fs);
11107 gen_helper_float_class_s(fp0, cpu_env, fp0);
11108 gen_store_fpr32(ctx, fp0, fd);
11109 tcg_temp_free_i32(fp0);
11111 break;
11112 case OPC_MIN_S: /* OPC_RECIP2_S */
11113 if (ctx->insn_flags & ISA_MIPS32R6) {
11114 /* OPC_MIN_S */
11115 TCGv_i32 fp0 = tcg_temp_new_i32();
11116 TCGv_i32 fp1 = tcg_temp_new_i32();
11117 TCGv_i32 fp2 = tcg_temp_new_i32();
11118 gen_load_fpr32(ctx, fp0, fs);
11119 gen_load_fpr32(ctx, fp1, ft);
11120 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11121 gen_store_fpr32(ctx, fp2, fd);
11122 tcg_temp_free_i32(fp2);
11123 tcg_temp_free_i32(fp1);
11124 tcg_temp_free_i32(fp0);
11125 } else {
11126 /* OPC_RECIP2_S */
11127 check_cp1_64bitmode(ctx);
11129 TCGv_i32 fp0 = tcg_temp_new_i32();
11130 TCGv_i32 fp1 = tcg_temp_new_i32();
11132 gen_load_fpr32(ctx, fp0, fs);
11133 gen_load_fpr32(ctx, fp1, ft);
11134 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11135 tcg_temp_free_i32(fp1);
11136 gen_store_fpr32(ctx, fp0, fd);
11137 tcg_temp_free_i32(fp0);
11140 break;
11141 case OPC_MINA_S: /* OPC_RECIP1_S */
11142 if (ctx->insn_flags & ISA_MIPS32R6) {
11143 /* OPC_MINA_S */
11144 TCGv_i32 fp0 = tcg_temp_new_i32();
11145 TCGv_i32 fp1 = tcg_temp_new_i32();
11146 TCGv_i32 fp2 = tcg_temp_new_i32();
11147 gen_load_fpr32(ctx, fp0, fs);
11148 gen_load_fpr32(ctx, fp1, ft);
11149 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11150 gen_store_fpr32(ctx, fp2, fd);
11151 tcg_temp_free_i32(fp2);
11152 tcg_temp_free_i32(fp1);
11153 tcg_temp_free_i32(fp0);
11154 } else {
11155 /* OPC_RECIP1_S */
11156 check_cp1_64bitmode(ctx);
11158 TCGv_i32 fp0 = tcg_temp_new_i32();
11160 gen_load_fpr32(ctx, fp0, fs);
11161 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11162 gen_store_fpr32(ctx, fp0, fd);
11163 tcg_temp_free_i32(fp0);
11166 break;
11167 case OPC_MAX_S: /* OPC_RSQRT1_S */
11168 if (ctx->insn_flags & ISA_MIPS32R6) {
11169 /* OPC_MAX_S */
11170 TCGv_i32 fp0 = tcg_temp_new_i32();
11171 TCGv_i32 fp1 = tcg_temp_new_i32();
11172 gen_load_fpr32(ctx, fp0, fs);
11173 gen_load_fpr32(ctx, fp1, ft);
11174 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11175 gen_store_fpr32(ctx, fp1, fd);
11176 tcg_temp_free_i32(fp1);
11177 tcg_temp_free_i32(fp0);
11178 } else {
11179 /* OPC_RSQRT1_S */
11180 check_cp1_64bitmode(ctx);
11182 TCGv_i32 fp0 = tcg_temp_new_i32();
11184 gen_load_fpr32(ctx, fp0, fs);
11185 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11186 gen_store_fpr32(ctx, fp0, fd);
11187 tcg_temp_free_i32(fp0);
11190 break;
11191 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11192 if (ctx->insn_flags & ISA_MIPS32R6) {
11193 /* OPC_MAXA_S */
11194 TCGv_i32 fp0 = tcg_temp_new_i32();
11195 TCGv_i32 fp1 = tcg_temp_new_i32();
11196 gen_load_fpr32(ctx, fp0, fs);
11197 gen_load_fpr32(ctx, fp1, ft);
11198 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11199 gen_store_fpr32(ctx, fp1, fd);
11200 tcg_temp_free_i32(fp1);
11201 tcg_temp_free_i32(fp0);
11202 } else {
11203 /* OPC_RSQRT2_S */
11204 check_cp1_64bitmode(ctx);
11206 TCGv_i32 fp0 = tcg_temp_new_i32();
11207 TCGv_i32 fp1 = tcg_temp_new_i32();
11209 gen_load_fpr32(ctx, fp0, fs);
11210 gen_load_fpr32(ctx, fp1, ft);
11211 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11212 tcg_temp_free_i32(fp1);
11213 gen_store_fpr32(ctx, fp0, fd);
11214 tcg_temp_free_i32(fp0);
11217 break;
11218 case OPC_CVT_D_S:
11219 check_cp1_registers(ctx, fd);
11221 TCGv_i32 fp32 = tcg_temp_new_i32();
11222 TCGv_i64 fp64 = tcg_temp_new_i64();
11224 gen_load_fpr32(ctx, fp32, fs);
11225 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11226 tcg_temp_free_i32(fp32);
11227 gen_store_fpr64(ctx, fp64, fd);
11228 tcg_temp_free_i64(fp64);
11230 break;
11231 case OPC_CVT_W_S:
11233 TCGv_i32 fp0 = tcg_temp_new_i32();
11235 gen_load_fpr32(ctx, fp0, fs);
11236 if (ctx->nan2008) {
11237 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11238 } else {
11239 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11241 gen_store_fpr32(ctx, fp0, fd);
11242 tcg_temp_free_i32(fp0);
11244 break;
11245 case OPC_CVT_L_S:
11246 check_cp1_64bitmode(ctx);
11248 TCGv_i32 fp32 = tcg_temp_new_i32();
11249 TCGv_i64 fp64 = tcg_temp_new_i64();
11251 gen_load_fpr32(ctx, fp32, fs);
11252 if (ctx->nan2008) {
11253 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11254 } else {
11255 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11257 tcg_temp_free_i32(fp32);
11258 gen_store_fpr64(ctx, fp64, fd);
11259 tcg_temp_free_i64(fp64);
11261 break;
11262 case OPC_CVT_PS_S:
11263 check_ps(ctx);
11265 TCGv_i64 fp64 = tcg_temp_new_i64();
11266 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11267 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11269 gen_load_fpr32(ctx, fp32_0, fs);
11270 gen_load_fpr32(ctx, fp32_1, ft);
11271 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11272 tcg_temp_free_i32(fp32_1);
11273 tcg_temp_free_i32(fp32_0);
11274 gen_store_fpr64(ctx, fp64, fd);
11275 tcg_temp_free_i64(fp64);
11277 break;
11278 case OPC_CMP_F_S:
11279 case OPC_CMP_UN_S:
11280 case OPC_CMP_EQ_S:
11281 case OPC_CMP_UEQ_S:
11282 case OPC_CMP_OLT_S:
11283 case OPC_CMP_ULT_S:
11284 case OPC_CMP_OLE_S:
11285 case OPC_CMP_ULE_S:
11286 case OPC_CMP_SF_S:
11287 case OPC_CMP_NGLE_S:
11288 case OPC_CMP_SEQ_S:
11289 case OPC_CMP_NGL_S:
11290 case OPC_CMP_LT_S:
11291 case OPC_CMP_NGE_S:
11292 case OPC_CMP_LE_S:
11293 case OPC_CMP_NGT_S:
11294 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11295 if (ctx->opcode & (1 << 6)) {
11296 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11297 } else {
11298 gen_cmp_s(ctx, func-48, ft, fs, cc);
11300 break;
11301 case OPC_ADD_D:
11302 check_cp1_registers(ctx, fs | ft | fd);
11304 TCGv_i64 fp0 = tcg_temp_new_i64();
11305 TCGv_i64 fp1 = tcg_temp_new_i64();
11307 gen_load_fpr64(ctx, fp0, fs);
11308 gen_load_fpr64(ctx, fp1, ft);
11309 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11310 tcg_temp_free_i64(fp1);
11311 gen_store_fpr64(ctx, fp0, fd);
11312 tcg_temp_free_i64(fp0);
11314 break;
11315 case OPC_SUB_D:
11316 check_cp1_registers(ctx, fs | ft | fd);
11318 TCGv_i64 fp0 = tcg_temp_new_i64();
11319 TCGv_i64 fp1 = tcg_temp_new_i64();
11321 gen_load_fpr64(ctx, fp0, fs);
11322 gen_load_fpr64(ctx, fp1, ft);
11323 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11324 tcg_temp_free_i64(fp1);
11325 gen_store_fpr64(ctx, fp0, fd);
11326 tcg_temp_free_i64(fp0);
11328 break;
11329 case OPC_MUL_D:
11330 check_cp1_registers(ctx, fs | ft | fd);
11332 TCGv_i64 fp0 = tcg_temp_new_i64();
11333 TCGv_i64 fp1 = tcg_temp_new_i64();
11335 gen_load_fpr64(ctx, fp0, fs);
11336 gen_load_fpr64(ctx, fp1, ft);
11337 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11338 tcg_temp_free_i64(fp1);
11339 gen_store_fpr64(ctx, fp0, fd);
11340 tcg_temp_free_i64(fp0);
11342 break;
11343 case OPC_DIV_D:
11344 check_cp1_registers(ctx, fs | ft | fd);
11346 TCGv_i64 fp0 = tcg_temp_new_i64();
11347 TCGv_i64 fp1 = tcg_temp_new_i64();
11349 gen_load_fpr64(ctx, fp0, fs);
11350 gen_load_fpr64(ctx, fp1, ft);
11351 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11352 tcg_temp_free_i64(fp1);
11353 gen_store_fpr64(ctx, fp0, fd);
11354 tcg_temp_free_i64(fp0);
11356 break;
11357 case OPC_SQRT_D:
11358 check_cp1_registers(ctx, fs | fd);
11360 TCGv_i64 fp0 = tcg_temp_new_i64();
11362 gen_load_fpr64(ctx, fp0, fs);
11363 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11364 gen_store_fpr64(ctx, fp0, fd);
11365 tcg_temp_free_i64(fp0);
11367 break;
11368 case OPC_ABS_D:
11369 check_cp1_registers(ctx, fs | fd);
11371 TCGv_i64 fp0 = tcg_temp_new_i64();
11373 gen_load_fpr64(ctx, fp0, fs);
11374 if (ctx->abs2008) {
11375 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11376 } else {
11377 gen_helper_float_abs_d(fp0, fp0);
11379 gen_store_fpr64(ctx, fp0, fd);
11380 tcg_temp_free_i64(fp0);
11382 break;
11383 case OPC_MOV_D:
11384 check_cp1_registers(ctx, fs | fd);
11386 TCGv_i64 fp0 = tcg_temp_new_i64();
11388 gen_load_fpr64(ctx, fp0, fs);
11389 gen_store_fpr64(ctx, fp0, fd);
11390 tcg_temp_free_i64(fp0);
11392 break;
11393 case OPC_NEG_D:
11394 check_cp1_registers(ctx, fs | fd);
11396 TCGv_i64 fp0 = tcg_temp_new_i64();
11398 gen_load_fpr64(ctx, fp0, fs);
11399 if (ctx->abs2008) {
11400 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11401 } else {
11402 gen_helper_float_chs_d(fp0, fp0);
11404 gen_store_fpr64(ctx, fp0, fd);
11405 tcg_temp_free_i64(fp0);
11407 break;
11408 case OPC_ROUND_L_D:
11409 check_cp1_64bitmode(ctx);
11411 TCGv_i64 fp0 = tcg_temp_new_i64();
11413 gen_load_fpr64(ctx, fp0, fs);
11414 if (ctx->nan2008) {
11415 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11416 } else {
11417 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11419 gen_store_fpr64(ctx, fp0, fd);
11420 tcg_temp_free_i64(fp0);
11422 break;
11423 case OPC_TRUNC_L_D:
11424 check_cp1_64bitmode(ctx);
11426 TCGv_i64 fp0 = tcg_temp_new_i64();
11428 gen_load_fpr64(ctx, fp0, fs);
11429 if (ctx->nan2008) {
11430 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11431 } else {
11432 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11434 gen_store_fpr64(ctx, fp0, fd);
11435 tcg_temp_free_i64(fp0);
11437 break;
11438 case OPC_CEIL_L_D:
11439 check_cp1_64bitmode(ctx);
11441 TCGv_i64 fp0 = tcg_temp_new_i64();
11443 gen_load_fpr64(ctx, fp0, fs);
11444 if (ctx->nan2008) {
11445 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11446 } else {
11447 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11449 gen_store_fpr64(ctx, fp0, fd);
11450 tcg_temp_free_i64(fp0);
11452 break;
11453 case OPC_FLOOR_L_D:
11454 check_cp1_64bitmode(ctx);
11456 TCGv_i64 fp0 = tcg_temp_new_i64();
11458 gen_load_fpr64(ctx, fp0, fs);
11459 if (ctx->nan2008) {
11460 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11461 } else {
11462 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11464 gen_store_fpr64(ctx, fp0, fd);
11465 tcg_temp_free_i64(fp0);
11467 break;
11468 case OPC_ROUND_W_D:
11469 check_cp1_registers(ctx, fs);
11471 TCGv_i32 fp32 = tcg_temp_new_i32();
11472 TCGv_i64 fp64 = tcg_temp_new_i64();
11474 gen_load_fpr64(ctx, fp64, fs);
11475 if (ctx->nan2008) {
11476 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11477 } else {
11478 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11480 tcg_temp_free_i64(fp64);
11481 gen_store_fpr32(ctx, fp32, fd);
11482 tcg_temp_free_i32(fp32);
11484 break;
11485 case OPC_TRUNC_W_D:
11486 check_cp1_registers(ctx, fs);
11488 TCGv_i32 fp32 = tcg_temp_new_i32();
11489 TCGv_i64 fp64 = tcg_temp_new_i64();
11491 gen_load_fpr64(ctx, fp64, fs);
11492 if (ctx->nan2008) {
11493 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11494 } else {
11495 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11497 tcg_temp_free_i64(fp64);
11498 gen_store_fpr32(ctx, fp32, fd);
11499 tcg_temp_free_i32(fp32);
11501 break;
11502 case OPC_CEIL_W_D:
11503 check_cp1_registers(ctx, fs);
11505 TCGv_i32 fp32 = tcg_temp_new_i32();
11506 TCGv_i64 fp64 = tcg_temp_new_i64();
11508 gen_load_fpr64(ctx, fp64, fs);
11509 if (ctx->nan2008) {
11510 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11511 } else {
11512 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11514 tcg_temp_free_i64(fp64);
11515 gen_store_fpr32(ctx, fp32, fd);
11516 tcg_temp_free_i32(fp32);
11518 break;
11519 case OPC_FLOOR_W_D:
11520 check_cp1_registers(ctx, fs);
11522 TCGv_i32 fp32 = tcg_temp_new_i32();
11523 TCGv_i64 fp64 = tcg_temp_new_i64();
11525 gen_load_fpr64(ctx, fp64, fs);
11526 if (ctx->nan2008) {
11527 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11528 } else {
11529 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11531 tcg_temp_free_i64(fp64);
11532 gen_store_fpr32(ctx, fp32, fd);
11533 tcg_temp_free_i32(fp32);
11535 break;
11536 case OPC_SEL_D:
11537 check_insn(ctx, ISA_MIPS32R6);
11538 gen_sel_d(ctx, op1, fd, ft, fs);
11539 break;
11540 case OPC_SELEQZ_D:
11541 check_insn(ctx, ISA_MIPS32R6);
11542 gen_sel_d(ctx, op1, fd, ft, fs);
11543 break;
11544 case OPC_SELNEZ_D:
11545 check_insn(ctx, ISA_MIPS32R6);
11546 gen_sel_d(ctx, op1, fd, ft, fs);
11547 break;
11548 case OPC_MOVCF_D:
11549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11550 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11551 break;
11552 case OPC_MOVZ_D:
11553 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11555 TCGLabel *l1 = gen_new_label();
11556 TCGv_i64 fp0;
11558 if (ft != 0) {
11559 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11561 fp0 = tcg_temp_new_i64();
11562 gen_load_fpr64(ctx, fp0, fs);
11563 gen_store_fpr64(ctx, fp0, fd);
11564 tcg_temp_free_i64(fp0);
11565 gen_set_label(l1);
11567 break;
11568 case OPC_MOVN_D:
11569 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11571 TCGLabel *l1 = gen_new_label();
11572 TCGv_i64 fp0;
11574 if (ft != 0) {
11575 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11576 fp0 = tcg_temp_new_i64();
11577 gen_load_fpr64(ctx, fp0, fs);
11578 gen_store_fpr64(ctx, fp0, fd);
11579 tcg_temp_free_i64(fp0);
11580 gen_set_label(l1);
11583 break;
11584 case OPC_RECIP_D:
11585 check_cp1_registers(ctx, fs | fd);
11587 TCGv_i64 fp0 = tcg_temp_new_i64();
11589 gen_load_fpr64(ctx, fp0, fs);
11590 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11591 gen_store_fpr64(ctx, fp0, fd);
11592 tcg_temp_free_i64(fp0);
11594 break;
11595 case OPC_RSQRT_D:
11596 check_cp1_registers(ctx, fs | fd);
11598 TCGv_i64 fp0 = tcg_temp_new_i64();
11600 gen_load_fpr64(ctx, fp0, fs);
11601 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11602 gen_store_fpr64(ctx, fp0, fd);
11603 tcg_temp_free_i64(fp0);
11605 break;
11606 case OPC_MADDF_D:
11607 check_insn(ctx, ISA_MIPS32R6);
11609 TCGv_i64 fp0 = tcg_temp_new_i64();
11610 TCGv_i64 fp1 = tcg_temp_new_i64();
11611 TCGv_i64 fp2 = tcg_temp_new_i64();
11612 gen_load_fpr64(ctx, fp0, fs);
11613 gen_load_fpr64(ctx, fp1, ft);
11614 gen_load_fpr64(ctx, fp2, fd);
11615 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11616 gen_store_fpr64(ctx, fp2, fd);
11617 tcg_temp_free_i64(fp2);
11618 tcg_temp_free_i64(fp1);
11619 tcg_temp_free_i64(fp0);
11621 break;
11622 case OPC_MSUBF_D:
11623 check_insn(ctx, ISA_MIPS32R6);
11625 TCGv_i64 fp0 = tcg_temp_new_i64();
11626 TCGv_i64 fp1 = tcg_temp_new_i64();
11627 TCGv_i64 fp2 = tcg_temp_new_i64();
11628 gen_load_fpr64(ctx, fp0, fs);
11629 gen_load_fpr64(ctx, fp1, ft);
11630 gen_load_fpr64(ctx, fp2, fd);
11631 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11632 gen_store_fpr64(ctx, fp2, fd);
11633 tcg_temp_free_i64(fp2);
11634 tcg_temp_free_i64(fp1);
11635 tcg_temp_free_i64(fp0);
11637 break;
11638 case OPC_RINT_D:
11639 check_insn(ctx, ISA_MIPS32R6);
11641 TCGv_i64 fp0 = tcg_temp_new_i64();
11642 gen_load_fpr64(ctx, fp0, fs);
11643 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11644 gen_store_fpr64(ctx, fp0, fd);
11645 tcg_temp_free_i64(fp0);
11647 break;
11648 case OPC_CLASS_D:
11649 check_insn(ctx, ISA_MIPS32R6);
11651 TCGv_i64 fp0 = tcg_temp_new_i64();
11652 gen_load_fpr64(ctx, fp0, fs);
11653 gen_helper_float_class_d(fp0, cpu_env, fp0);
11654 gen_store_fpr64(ctx, fp0, fd);
11655 tcg_temp_free_i64(fp0);
11657 break;
11658 case OPC_MIN_D: /* OPC_RECIP2_D */
11659 if (ctx->insn_flags & ISA_MIPS32R6) {
11660 /* OPC_MIN_D */
11661 TCGv_i64 fp0 = tcg_temp_new_i64();
11662 TCGv_i64 fp1 = tcg_temp_new_i64();
11663 gen_load_fpr64(ctx, fp0, fs);
11664 gen_load_fpr64(ctx, fp1, ft);
11665 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11666 gen_store_fpr64(ctx, fp1, fd);
11667 tcg_temp_free_i64(fp1);
11668 tcg_temp_free_i64(fp0);
11669 } else {
11670 /* OPC_RECIP2_D */
11671 check_cp1_64bitmode(ctx);
11673 TCGv_i64 fp0 = tcg_temp_new_i64();
11674 TCGv_i64 fp1 = tcg_temp_new_i64();
11676 gen_load_fpr64(ctx, fp0, fs);
11677 gen_load_fpr64(ctx, fp1, ft);
11678 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11679 tcg_temp_free_i64(fp1);
11680 gen_store_fpr64(ctx, fp0, fd);
11681 tcg_temp_free_i64(fp0);
11684 break;
11685 case OPC_MINA_D: /* OPC_RECIP1_D */
11686 if (ctx->insn_flags & ISA_MIPS32R6) {
11687 /* OPC_MINA_D */
11688 TCGv_i64 fp0 = tcg_temp_new_i64();
11689 TCGv_i64 fp1 = tcg_temp_new_i64();
11690 gen_load_fpr64(ctx, fp0, fs);
11691 gen_load_fpr64(ctx, fp1, ft);
11692 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11693 gen_store_fpr64(ctx, fp1, fd);
11694 tcg_temp_free_i64(fp1);
11695 tcg_temp_free_i64(fp0);
11696 } else {
11697 /* OPC_RECIP1_D */
11698 check_cp1_64bitmode(ctx);
11700 TCGv_i64 fp0 = tcg_temp_new_i64();
11702 gen_load_fpr64(ctx, fp0, fs);
11703 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11704 gen_store_fpr64(ctx, fp0, fd);
11705 tcg_temp_free_i64(fp0);
11708 break;
11709 case OPC_MAX_D: /* OPC_RSQRT1_D */
11710 if (ctx->insn_flags & ISA_MIPS32R6) {
11711 /* OPC_MAX_D */
11712 TCGv_i64 fp0 = tcg_temp_new_i64();
11713 TCGv_i64 fp1 = tcg_temp_new_i64();
11714 gen_load_fpr64(ctx, fp0, fs);
11715 gen_load_fpr64(ctx, fp1, ft);
11716 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11717 gen_store_fpr64(ctx, fp1, fd);
11718 tcg_temp_free_i64(fp1);
11719 tcg_temp_free_i64(fp0);
11720 } else {
11721 /* OPC_RSQRT1_D */
11722 check_cp1_64bitmode(ctx);
11724 TCGv_i64 fp0 = tcg_temp_new_i64();
11726 gen_load_fpr64(ctx, fp0, fs);
11727 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11728 gen_store_fpr64(ctx, fp0, fd);
11729 tcg_temp_free_i64(fp0);
11732 break;
11733 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11734 if (ctx->insn_flags & ISA_MIPS32R6) {
11735 /* OPC_MAXA_D */
11736 TCGv_i64 fp0 = tcg_temp_new_i64();
11737 TCGv_i64 fp1 = tcg_temp_new_i64();
11738 gen_load_fpr64(ctx, fp0, fs);
11739 gen_load_fpr64(ctx, fp1, ft);
11740 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11741 gen_store_fpr64(ctx, fp1, fd);
11742 tcg_temp_free_i64(fp1);
11743 tcg_temp_free_i64(fp0);
11744 } else {
11745 /* OPC_RSQRT2_D */
11746 check_cp1_64bitmode(ctx);
11748 TCGv_i64 fp0 = tcg_temp_new_i64();
11749 TCGv_i64 fp1 = tcg_temp_new_i64();
11751 gen_load_fpr64(ctx, fp0, fs);
11752 gen_load_fpr64(ctx, fp1, ft);
11753 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11754 tcg_temp_free_i64(fp1);
11755 gen_store_fpr64(ctx, fp0, fd);
11756 tcg_temp_free_i64(fp0);
11759 break;
11760 case OPC_CMP_F_D:
11761 case OPC_CMP_UN_D:
11762 case OPC_CMP_EQ_D:
11763 case OPC_CMP_UEQ_D:
11764 case OPC_CMP_OLT_D:
11765 case OPC_CMP_ULT_D:
11766 case OPC_CMP_OLE_D:
11767 case OPC_CMP_ULE_D:
11768 case OPC_CMP_SF_D:
11769 case OPC_CMP_NGLE_D:
11770 case OPC_CMP_SEQ_D:
11771 case OPC_CMP_NGL_D:
11772 case OPC_CMP_LT_D:
11773 case OPC_CMP_NGE_D:
11774 case OPC_CMP_LE_D:
11775 case OPC_CMP_NGT_D:
11776 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11777 if (ctx->opcode & (1 << 6)) {
11778 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11779 } else {
11780 gen_cmp_d(ctx, func-48, ft, fs, cc);
11782 break;
11783 case OPC_CVT_S_D:
11784 check_cp1_registers(ctx, fs);
11786 TCGv_i32 fp32 = tcg_temp_new_i32();
11787 TCGv_i64 fp64 = tcg_temp_new_i64();
11789 gen_load_fpr64(ctx, fp64, fs);
11790 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11791 tcg_temp_free_i64(fp64);
11792 gen_store_fpr32(ctx, fp32, fd);
11793 tcg_temp_free_i32(fp32);
11795 break;
11796 case OPC_CVT_W_D:
11797 check_cp1_registers(ctx, fs);
11799 TCGv_i32 fp32 = tcg_temp_new_i32();
11800 TCGv_i64 fp64 = tcg_temp_new_i64();
11802 gen_load_fpr64(ctx, fp64, fs);
11803 if (ctx->nan2008) {
11804 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11805 } else {
11806 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11808 tcg_temp_free_i64(fp64);
11809 gen_store_fpr32(ctx, fp32, fd);
11810 tcg_temp_free_i32(fp32);
11812 break;
11813 case OPC_CVT_L_D:
11814 check_cp1_64bitmode(ctx);
11816 TCGv_i64 fp0 = tcg_temp_new_i64();
11818 gen_load_fpr64(ctx, fp0, fs);
11819 if (ctx->nan2008) {
11820 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11821 } else {
11822 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11824 gen_store_fpr64(ctx, fp0, fd);
11825 tcg_temp_free_i64(fp0);
11827 break;
11828 case OPC_CVT_S_W:
11830 TCGv_i32 fp0 = tcg_temp_new_i32();
11832 gen_load_fpr32(ctx, fp0, fs);
11833 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11834 gen_store_fpr32(ctx, fp0, fd);
11835 tcg_temp_free_i32(fp0);
11837 break;
11838 case OPC_CVT_D_W:
11839 check_cp1_registers(ctx, fd);
11841 TCGv_i32 fp32 = tcg_temp_new_i32();
11842 TCGv_i64 fp64 = tcg_temp_new_i64();
11844 gen_load_fpr32(ctx, fp32, fs);
11845 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11846 tcg_temp_free_i32(fp32);
11847 gen_store_fpr64(ctx, fp64, fd);
11848 tcg_temp_free_i64(fp64);
11850 break;
11851 case OPC_CVT_S_L:
11852 check_cp1_64bitmode(ctx);
11854 TCGv_i32 fp32 = tcg_temp_new_i32();
11855 TCGv_i64 fp64 = tcg_temp_new_i64();
11857 gen_load_fpr64(ctx, fp64, fs);
11858 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11859 tcg_temp_free_i64(fp64);
11860 gen_store_fpr32(ctx, fp32, fd);
11861 tcg_temp_free_i32(fp32);
11863 break;
11864 case OPC_CVT_D_L:
11865 check_cp1_64bitmode(ctx);
11867 TCGv_i64 fp0 = tcg_temp_new_i64();
11869 gen_load_fpr64(ctx, fp0, fs);
11870 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11871 gen_store_fpr64(ctx, fp0, fd);
11872 tcg_temp_free_i64(fp0);
11874 break;
11875 case OPC_CVT_PS_PW:
11876 check_ps(ctx);
11878 TCGv_i64 fp0 = tcg_temp_new_i64();
11880 gen_load_fpr64(ctx, fp0, fs);
11881 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11882 gen_store_fpr64(ctx, fp0, fd);
11883 tcg_temp_free_i64(fp0);
11885 break;
11886 case OPC_ADD_PS:
11887 check_ps(ctx);
11889 TCGv_i64 fp0 = tcg_temp_new_i64();
11890 TCGv_i64 fp1 = tcg_temp_new_i64();
11892 gen_load_fpr64(ctx, fp0, fs);
11893 gen_load_fpr64(ctx, fp1, ft);
11894 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11895 tcg_temp_free_i64(fp1);
11896 gen_store_fpr64(ctx, fp0, fd);
11897 tcg_temp_free_i64(fp0);
11899 break;
11900 case OPC_SUB_PS:
11901 check_ps(ctx);
11903 TCGv_i64 fp0 = tcg_temp_new_i64();
11904 TCGv_i64 fp1 = tcg_temp_new_i64();
11906 gen_load_fpr64(ctx, fp0, fs);
11907 gen_load_fpr64(ctx, fp1, ft);
11908 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11909 tcg_temp_free_i64(fp1);
11910 gen_store_fpr64(ctx, fp0, fd);
11911 tcg_temp_free_i64(fp0);
11913 break;
11914 case OPC_MUL_PS:
11915 check_ps(ctx);
11917 TCGv_i64 fp0 = tcg_temp_new_i64();
11918 TCGv_i64 fp1 = tcg_temp_new_i64();
11920 gen_load_fpr64(ctx, fp0, fs);
11921 gen_load_fpr64(ctx, fp1, ft);
11922 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11923 tcg_temp_free_i64(fp1);
11924 gen_store_fpr64(ctx, fp0, fd);
11925 tcg_temp_free_i64(fp0);
11927 break;
11928 case OPC_ABS_PS:
11929 check_ps(ctx);
11931 TCGv_i64 fp0 = tcg_temp_new_i64();
11933 gen_load_fpr64(ctx, fp0, fs);
11934 gen_helper_float_abs_ps(fp0, fp0);
11935 gen_store_fpr64(ctx, fp0, fd);
11936 tcg_temp_free_i64(fp0);
11938 break;
11939 case OPC_MOV_PS:
11940 check_ps(ctx);
11942 TCGv_i64 fp0 = tcg_temp_new_i64();
11944 gen_load_fpr64(ctx, fp0, fs);
11945 gen_store_fpr64(ctx, fp0, fd);
11946 tcg_temp_free_i64(fp0);
11948 break;
11949 case OPC_NEG_PS:
11950 check_ps(ctx);
11952 TCGv_i64 fp0 = tcg_temp_new_i64();
11954 gen_load_fpr64(ctx, fp0, fs);
11955 gen_helper_float_chs_ps(fp0, fp0);
11956 gen_store_fpr64(ctx, fp0, fd);
11957 tcg_temp_free_i64(fp0);
11959 break;
11960 case OPC_MOVCF_PS:
11961 check_ps(ctx);
11962 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11963 break;
11964 case OPC_MOVZ_PS:
11965 check_ps(ctx);
11967 TCGLabel *l1 = gen_new_label();
11968 TCGv_i64 fp0;
11970 if (ft != 0)
11971 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11972 fp0 = tcg_temp_new_i64();
11973 gen_load_fpr64(ctx, fp0, fs);
11974 gen_store_fpr64(ctx, fp0, fd);
11975 tcg_temp_free_i64(fp0);
11976 gen_set_label(l1);
11978 break;
11979 case OPC_MOVN_PS:
11980 check_ps(ctx);
11982 TCGLabel *l1 = gen_new_label();
11983 TCGv_i64 fp0;
11985 if (ft != 0) {
11986 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11987 fp0 = tcg_temp_new_i64();
11988 gen_load_fpr64(ctx, fp0, fs);
11989 gen_store_fpr64(ctx, fp0, fd);
11990 tcg_temp_free_i64(fp0);
11991 gen_set_label(l1);
11994 break;
11995 case OPC_ADDR_PS:
11996 check_ps(ctx);
11998 TCGv_i64 fp0 = tcg_temp_new_i64();
11999 TCGv_i64 fp1 = tcg_temp_new_i64();
12001 gen_load_fpr64(ctx, fp0, ft);
12002 gen_load_fpr64(ctx, fp1, fs);
12003 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12004 tcg_temp_free_i64(fp1);
12005 gen_store_fpr64(ctx, fp0, fd);
12006 tcg_temp_free_i64(fp0);
12008 break;
12009 case OPC_MULR_PS:
12010 check_ps(ctx);
12012 TCGv_i64 fp0 = tcg_temp_new_i64();
12013 TCGv_i64 fp1 = tcg_temp_new_i64();
12015 gen_load_fpr64(ctx, fp0, ft);
12016 gen_load_fpr64(ctx, fp1, fs);
12017 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12018 tcg_temp_free_i64(fp1);
12019 gen_store_fpr64(ctx, fp0, fd);
12020 tcg_temp_free_i64(fp0);
12022 break;
12023 case OPC_RECIP2_PS:
12024 check_ps(ctx);
12026 TCGv_i64 fp0 = tcg_temp_new_i64();
12027 TCGv_i64 fp1 = tcg_temp_new_i64();
12029 gen_load_fpr64(ctx, fp0, fs);
12030 gen_load_fpr64(ctx, fp1, ft);
12031 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12032 tcg_temp_free_i64(fp1);
12033 gen_store_fpr64(ctx, fp0, fd);
12034 tcg_temp_free_i64(fp0);
12036 break;
12037 case OPC_RECIP1_PS:
12038 check_ps(ctx);
12040 TCGv_i64 fp0 = tcg_temp_new_i64();
12042 gen_load_fpr64(ctx, fp0, fs);
12043 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12044 gen_store_fpr64(ctx, fp0, fd);
12045 tcg_temp_free_i64(fp0);
12047 break;
12048 case OPC_RSQRT1_PS:
12049 check_ps(ctx);
12051 TCGv_i64 fp0 = tcg_temp_new_i64();
12053 gen_load_fpr64(ctx, fp0, fs);
12054 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12055 gen_store_fpr64(ctx, fp0, fd);
12056 tcg_temp_free_i64(fp0);
12058 break;
12059 case OPC_RSQRT2_PS:
12060 check_ps(ctx);
12062 TCGv_i64 fp0 = tcg_temp_new_i64();
12063 TCGv_i64 fp1 = tcg_temp_new_i64();
12065 gen_load_fpr64(ctx, fp0, fs);
12066 gen_load_fpr64(ctx, fp1, ft);
12067 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12068 tcg_temp_free_i64(fp1);
12069 gen_store_fpr64(ctx, fp0, fd);
12070 tcg_temp_free_i64(fp0);
12072 break;
12073 case OPC_CVT_S_PU:
12074 check_cp1_64bitmode(ctx);
12076 TCGv_i32 fp0 = tcg_temp_new_i32();
12078 gen_load_fpr32h(ctx, fp0, fs);
12079 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12080 gen_store_fpr32(ctx, fp0, fd);
12081 tcg_temp_free_i32(fp0);
12083 break;
12084 case OPC_CVT_PW_PS:
12085 check_ps(ctx);
12087 TCGv_i64 fp0 = tcg_temp_new_i64();
12089 gen_load_fpr64(ctx, fp0, fs);
12090 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12091 gen_store_fpr64(ctx, fp0, fd);
12092 tcg_temp_free_i64(fp0);
12094 break;
12095 case OPC_CVT_S_PL:
12096 check_cp1_64bitmode(ctx);
12098 TCGv_i32 fp0 = tcg_temp_new_i32();
12100 gen_load_fpr32(ctx, fp0, fs);
12101 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12102 gen_store_fpr32(ctx, fp0, fd);
12103 tcg_temp_free_i32(fp0);
12105 break;
12106 case OPC_PLL_PS:
12107 check_ps(ctx);
12109 TCGv_i32 fp0 = tcg_temp_new_i32();
12110 TCGv_i32 fp1 = tcg_temp_new_i32();
12112 gen_load_fpr32(ctx, fp0, fs);
12113 gen_load_fpr32(ctx, fp1, ft);
12114 gen_store_fpr32h(ctx, fp0, fd);
12115 gen_store_fpr32(ctx, fp1, fd);
12116 tcg_temp_free_i32(fp0);
12117 tcg_temp_free_i32(fp1);
12119 break;
12120 case OPC_PLU_PS:
12121 check_ps(ctx);
12123 TCGv_i32 fp0 = tcg_temp_new_i32();
12124 TCGv_i32 fp1 = tcg_temp_new_i32();
12126 gen_load_fpr32(ctx, fp0, fs);
12127 gen_load_fpr32h(ctx, fp1, ft);
12128 gen_store_fpr32(ctx, fp1, fd);
12129 gen_store_fpr32h(ctx, fp0, fd);
12130 tcg_temp_free_i32(fp0);
12131 tcg_temp_free_i32(fp1);
12133 break;
12134 case OPC_PUL_PS:
12135 check_ps(ctx);
12137 TCGv_i32 fp0 = tcg_temp_new_i32();
12138 TCGv_i32 fp1 = tcg_temp_new_i32();
12140 gen_load_fpr32h(ctx, fp0, fs);
12141 gen_load_fpr32(ctx, fp1, ft);
12142 gen_store_fpr32(ctx, fp1, fd);
12143 gen_store_fpr32h(ctx, fp0, fd);
12144 tcg_temp_free_i32(fp0);
12145 tcg_temp_free_i32(fp1);
12147 break;
12148 case OPC_PUU_PS:
12149 check_ps(ctx);
12151 TCGv_i32 fp0 = tcg_temp_new_i32();
12152 TCGv_i32 fp1 = tcg_temp_new_i32();
12154 gen_load_fpr32h(ctx, fp0, fs);
12155 gen_load_fpr32h(ctx, fp1, ft);
12156 gen_store_fpr32(ctx, fp1, fd);
12157 gen_store_fpr32h(ctx, fp0, fd);
12158 tcg_temp_free_i32(fp0);
12159 tcg_temp_free_i32(fp1);
12161 break;
12162 case OPC_CMP_F_PS:
12163 case OPC_CMP_UN_PS:
12164 case OPC_CMP_EQ_PS:
12165 case OPC_CMP_UEQ_PS:
12166 case OPC_CMP_OLT_PS:
12167 case OPC_CMP_ULT_PS:
12168 case OPC_CMP_OLE_PS:
12169 case OPC_CMP_ULE_PS:
12170 case OPC_CMP_SF_PS:
12171 case OPC_CMP_NGLE_PS:
12172 case OPC_CMP_SEQ_PS:
12173 case OPC_CMP_NGL_PS:
12174 case OPC_CMP_LT_PS:
12175 case OPC_CMP_NGE_PS:
12176 case OPC_CMP_LE_PS:
12177 case OPC_CMP_NGT_PS:
12178 if (ctx->opcode & (1 << 6)) {
12179 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
12180 } else {
12181 gen_cmp_ps(ctx, func-48, ft, fs, cc);
12183 break;
12184 default:
12185 MIPS_INVAL("farith");
12186 generate_exception_end(ctx, EXCP_RI);
12187 return;
12191 /* Coprocessor 3 (FPU) */
12192 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12193 int fd, int fs, int base, int index)
12195 TCGv t0 = tcg_temp_new();
12197 if (base == 0) {
12198 gen_load_gpr(t0, index);
12199 } else if (index == 0) {
12200 gen_load_gpr(t0, base);
12201 } else {
12202 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12204 /* Don't do NOP if destination is zero: we must perform the actual
12205 memory access. */
12206 switch (opc) {
12207 case OPC_LWXC1:
12208 check_cop1x(ctx);
12210 TCGv_i32 fp0 = tcg_temp_new_i32();
12212 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12213 tcg_gen_trunc_tl_i32(fp0, t0);
12214 gen_store_fpr32(ctx, fp0, fd);
12215 tcg_temp_free_i32(fp0);
12217 break;
12218 case OPC_LDXC1:
12219 check_cop1x(ctx);
12220 check_cp1_registers(ctx, fd);
12222 TCGv_i64 fp0 = tcg_temp_new_i64();
12223 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12224 gen_store_fpr64(ctx, fp0, fd);
12225 tcg_temp_free_i64(fp0);
12227 break;
12228 case OPC_LUXC1:
12229 check_cp1_64bitmode(ctx);
12230 tcg_gen_andi_tl(t0, t0, ~0x7);
12232 TCGv_i64 fp0 = tcg_temp_new_i64();
12234 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12235 gen_store_fpr64(ctx, fp0, fd);
12236 tcg_temp_free_i64(fp0);
12238 break;
12239 case OPC_SWXC1:
12240 check_cop1x(ctx);
12242 TCGv_i32 fp0 = tcg_temp_new_i32();
12243 gen_load_fpr32(ctx, fp0, fs);
12244 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12245 tcg_temp_free_i32(fp0);
12247 break;
12248 case OPC_SDXC1:
12249 check_cop1x(ctx);
12250 check_cp1_registers(ctx, fs);
12252 TCGv_i64 fp0 = tcg_temp_new_i64();
12253 gen_load_fpr64(ctx, fp0, fs);
12254 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12255 tcg_temp_free_i64(fp0);
12257 break;
12258 case OPC_SUXC1:
12259 check_cp1_64bitmode(ctx);
12260 tcg_gen_andi_tl(t0, t0, ~0x7);
12262 TCGv_i64 fp0 = tcg_temp_new_i64();
12263 gen_load_fpr64(ctx, fp0, fs);
12264 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12265 tcg_temp_free_i64(fp0);
12267 break;
12269 tcg_temp_free(t0);
12272 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12273 int fd, int fr, int fs, int ft)
12275 switch (opc) {
12276 case OPC_ALNV_PS:
12277 check_ps(ctx);
12279 TCGv t0 = tcg_temp_local_new();
12280 TCGv_i32 fp = tcg_temp_new_i32();
12281 TCGv_i32 fph = tcg_temp_new_i32();
12282 TCGLabel *l1 = gen_new_label();
12283 TCGLabel *l2 = gen_new_label();
12285 gen_load_gpr(t0, fr);
12286 tcg_gen_andi_tl(t0, t0, 0x7);
12288 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12289 gen_load_fpr32(ctx, fp, fs);
12290 gen_load_fpr32h(ctx, fph, fs);
12291 gen_store_fpr32(ctx, fp, fd);
12292 gen_store_fpr32h(ctx, fph, fd);
12293 tcg_gen_br(l2);
12294 gen_set_label(l1);
12295 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12296 tcg_temp_free(t0);
12297 #ifdef TARGET_WORDS_BIGENDIAN
12298 gen_load_fpr32(ctx, fp, fs);
12299 gen_load_fpr32h(ctx, fph, ft);
12300 gen_store_fpr32h(ctx, fp, fd);
12301 gen_store_fpr32(ctx, fph, fd);
12302 #else
12303 gen_load_fpr32h(ctx, fph, fs);
12304 gen_load_fpr32(ctx, fp, ft);
12305 gen_store_fpr32(ctx, fph, fd);
12306 gen_store_fpr32h(ctx, fp, fd);
12307 #endif
12308 gen_set_label(l2);
12309 tcg_temp_free_i32(fp);
12310 tcg_temp_free_i32(fph);
12312 break;
12313 case OPC_MADD_S:
12314 check_cop1x(ctx);
12316 TCGv_i32 fp0 = tcg_temp_new_i32();
12317 TCGv_i32 fp1 = tcg_temp_new_i32();
12318 TCGv_i32 fp2 = tcg_temp_new_i32();
12320 gen_load_fpr32(ctx, fp0, fs);
12321 gen_load_fpr32(ctx, fp1, ft);
12322 gen_load_fpr32(ctx, fp2, fr);
12323 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12324 tcg_temp_free_i32(fp0);
12325 tcg_temp_free_i32(fp1);
12326 gen_store_fpr32(ctx, fp2, fd);
12327 tcg_temp_free_i32(fp2);
12329 break;
12330 case OPC_MADD_D:
12331 check_cop1x(ctx);
12332 check_cp1_registers(ctx, fd | fs | ft | fr);
12334 TCGv_i64 fp0 = tcg_temp_new_i64();
12335 TCGv_i64 fp1 = tcg_temp_new_i64();
12336 TCGv_i64 fp2 = tcg_temp_new_i64();
12338 gen_load_fpr64(ctx, fp0, fs);
12339 gen_load_fpr64(ctx, fp1, ft);
12340 gen_load_fpr64(ctx, fp2, fr);
12341 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12342 tcg_temp_free_i64(fp0);
12343 tcg_temp_free_i64(fp1);
12344 gen_store_fpr64(ctx, fp2, fd);
12345 tcg_temp_free_i64(fp2);
12347 break;
12348 case OPC_MADD_PS:
12349 check_ps(ctx);
12351 TCGv_i64 fp0 = tcg_temp_new_i64();
12352 TCGv_i64 fp1 = tcg_temp_new_i64();
12353 TCGv_i64 fp2 = tcg_temp_new_i64();
12355 gen_load_fpr64(ctx, fp0, fs);
12356 gen_load_fpr64(ctx, fp1, ft);
12357 gen_load_fpr64(ctx, fp2, fr);
12358 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12359 tcg_temp_free_i64(fp0);
12360 tcg_temp_free_i64(fp1);
12361 gen_store_fpr64(ctx, fp2, fd);
12362 tcg_temp_free_i64(fp2);
12364 break;
12365 case OPC_MSUB_S:
12366 check_cop1x(ctx);
12368 TCGv_i32 fp0 = tcg_temp_new_i32();
12369 TCGv_i32 fp1 = tcg_temp_new_i32();
12370 TCGv_i32 fp2 = tcg_temp_new_i32();
12372 gen_load_fpr32(ctx, fp0, fs);
12373 gen_load_fpr32(ctx, fp1, ft);
12374 gen_load_fpr32(ctx, fp2, fr);
12375 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12376 tcg_temp_free_i32(fp0);
12377 tcg_temp_free_i32(fp1);
12378 gen_store_fpr32(ctx, fp2, fd);
12379 tcg_temp_free_i32(fp2);
12381 break;
12382 case OPC_MSUB_D:
12383 check_cop1x(ctx);
12384 check_cp1_registers(ctx, fd | fs | ft | fr);
12386 TCGv_i64 fp0 = tcg_temp_new_i64();
12387 TCGv_i64 fp1 = tcg_temp_new_i64();
12388 TCGv_i64 fp2 = tcg_temp_new_i64();
12390 gen_load_fpr64(ctx, fp0, fs);
12391 gen_load_fpr64(ctx, fp1, ft);
12392 gen_load_fpr64(ctx, fp2, fr);
12393 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12394 tcg_temp_free_i64(fp0);
12395 tcg_temp_free_i64(fp1);
12396 gen_store_fpr64(ctx, fp2, fd);
12397 tcg_temp_free_i64(fp2);
12399 break;
12400 case OPC_MSUB_PS:
12401 check_ps(ctx);
12403 TCGv_i64 fp0 = tcg_temp_new_i64();
12404 TCGv_i64 fp1 = tcg_temp_new_i64();
12405 TCGv_i64 fp2 = tcg_temp_new_i64();
12407 gen_load_fpr64(ctx, fp0, fs);
12408 gen_load_fpr64(ctx, fp1, ft);
12409 gen_load_fpr64(ctx, fp2, fr);
12410 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12411 tcg_temp_free_i64(fp0);
12412 tcg_temp_free_i64(fp1);
12413 gen_store_fpr64(ctx, fp2, fd);
12414 tcg_temp_free_i64(fp2);
12416 break;
12417 case OPC_NMADD_S:
12418 check_cop1x(ctx);
12420 TCGv_i32 fp0 = tcg_temp_new_i32();
12421 TCGv_i32 fp1 = tcg_temp_new_i32();
12422 TCGv_i32 fp2 = tcg_temp_new_i32();
12424 gen_load_fpr32(ctx, fp0, fs);
12425 gen_load_fpr32(ctx, fp1, ft);
12426 gen_load_fpr32(ctx, fp2, fr);
12427 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12428 tcg_temp_free_i32(fp0);
12429 tcg_temp_free_i32(fp1);
12430 gen_store_fpr32(ctx, fp2, fd);
12431 tcg_temp_free_i32(fp2);
12433 break;
12434 case OPC_NMADD_D:
12435 check_cop1x(ctx);
12436 check_cp1_registers(ctx, fd | fs | ft | fr);
12438 TCGv_i64 fp0 = tcg_temp_new_i64();
12439 TCGv_i64 fp1 = tcg_temp_new_i64();
12440 TCGv_i64 fp2 = tcg_temp_new_i64();
12442 gen_load_fpr64(ctx, fp0, fs);
12443 gen_load_fpr64(ctx, fp1, ft);
12444 gen_load_fpr64(ctx, fp2, fr);
12445 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12446 tcg_temp_free_i64(fp0);
12447 tcg_temp_free_i64(fp1);
12448 gen_store_fpr64(ctx, fp2, fd);
12449 tcg_temp_free_i64(fp2);
12451 break;
12452 case OPC_NMADD_PS:
12453 check_ps(ctx);
12455 TCGv_i64 fp0 = tcg_temp_new_i64();
12456 TCGv_i64 fp1 = tcg_temp_new_i64();
12457 TCGv_i64 fp2 = tcg_temp_new_i64();
12459 gen_load_fpr64(ctx, fp0, fs);
12460 gen_load_fpr64(ctx, fp1, ft);
12461 gen_load_fpr64(ctx, fp2, fr);
12462 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12463 tcg_temp_free_i64(fp0);
12464 tcg_temp_free_i64(fp1);
12465 gen_store_fpr64(ctx, fp2, fd);
12466 tcg_temp_free_i64(fp2);
12468 break;
12469 case OPC_NMSUB_S:
12470 check_cop1x(ctx);
12472 TCGv_i32 fp0 = tcg_temp_new_i32();
12473 TCGv_i32 fp1 = tcg_temp_new_i32();
12474 TCGv_i32 fp2 = tcg_temp_new_i32();
12476 gen_load_fpr32(ctx, fp0, fs);
12477 gen_load_fpr32(ctx, fp1, ft);
12478 gen_load_fpr32(ctx, fp2, fr);
12479 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12480 tcg_temp_free_i32(fp0);
12481 tcg_temp_free_i32(fp1);
12482 gen_store_fpr32(ctx, fp2, fd);
12483 tcg_temp_free_i32(fp2);
12485 break;
12486 case OPC_NMSUB_D:
12487 check_cop1x(ctx);
12488 check_cp1_registers(ctx, fd | fs | ft | fr);
12490 TCGv_i64 fp0 = tcg_temp_new_i64();
12491 TCGv_i64 fp1 = tcg_temp_new_i64();
12492 TCGv_i64 fp2 = tcg_temp_new_i64();
12494 gen_load_fpr64(ctx, fp0, fs);
12495 gen_load_fpr64(ctx, fp1, ft);
12496 gen_load_fpr64(ctx, fp2, fr);
12497 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12498 tcg_temp_free_i64(fp0);
12499 tcg_temp_free_i64(fp1);
12500 gen_store_fpr64(ctx, fp2, fd);
12501 tcg_temp_free_i64(fp2);
12503 break;
12504 case OPC_NMSUB_PS:
12505 check_ps(ctx);
12507 TCGv_i64 fp0 = tcg_temp_new_i64();
12508 TCGv_i64 fp1 = tcg_temp_new_i64();
12509 TCGv_i64 fp2 = tcg_temp_new_i64();
12511 gen_load_fpr64(ctx, fp0, fs);
12512 gen_load_fpr64(ctx, fp1, ft);
12513 gen_load_fpr64(ctx, fp2, fr);
12514 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12515 tcg_temp_free_i64(fp0);
12516 tcg_temp_free_i64(fp1);
12517 gen_store_fpr64(ctx, fp2, fd);
12518 tcg_temp_free_i64(fp2);
12520 break;
12521 default:
12522 MIPS_INVAL("flt3_arith");
12523 generate_exception_end(ctx, EXCP_RI);
12524 return;
12528 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12530 TCGv t0;
12532 #if !defined(CONFIG_USER_ONLY)
12533 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12534 Therefore only check the ISA in system mode. */
12535 check_insn(ctx, ISA_MIPS32R2);
12536 #endif
12537 t0 = tcg_temp_new();
12539 switch (rd) {
12540 case 0:
12541 gen_helper_rdhwr_cpunum(t0, cpu_env);
12542 gen_store_gpr(t0, rt);
12543 break;
12544 case 1:
12545 gen_helper_rdhwr_synci_step(t0, cpu_env);
12546 gen_store_gpr(t0, rt);
12547 break;
12548 case 2:
12549 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12550 gen_io_start();
12552 gen_helper_rdhwr_cc(t0, cpu_env);
12553 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12554 gen_io_end();
12556 gen_store_gpr(t0, rt);
12557 /* Break the TB to be able to take timer interrupts immediately
12558 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12559 we break completely out of translated code. */
12560 gen_save_pc(ctx->base.pc_next + 4);
12561 ctx->base.is_jmp = DISAS_EXIT;
12562 break;
12563 case 3:
12564 gen_helper_rdhwr_ccres(t0, cpu_env);
12565 gen_store_gpr(t0, rt);
12566 break;
12567 case 4:
12568 check_insn(ctx, ISA_MIPS32R6);
12569 if (sel != 0) {
12570 /* Performance counter registers are not implemented other than
12571 * control register 0.
12573 generate_exception(ctx, EXCP_RI);
12575 gen_helper_rdhwr_performance(t0, cpu_env);
12576 gen_store_gpr(t0, rt);
12577 break;
12578 case 5:
12579 check_insn(ctx, ISA_MIPS32R6);
12580 gen_helper_rdhwr_xnp(t0, cpu_env);
12581 gen_store_gpr(t0, rt);
12582 break;
12583 case 29:
12584 #if defined(CONFIG_USER_ONLY)
12585 tcg_gen_ld_tl(t0, cpu_env,
12586 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12587 gen_store_gpr(t0, rt);
12588 break;
12589 #else
12590 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12591 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12592 tcg_gen_ld_tl(t0, cpu_env,
12593 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12594 gen_store_gpr(t0, rt);
12595 } else {
12596 generate_exception_end(ctx, EXCP_RI);
12598 break;
12599 #endif
12600 default: /* Invalid */
12601 MIPS_INVAL("rdhwr");
12602 generate_exception_end(ctx, EXCP_RI);
12603 break;
12605 tcg_temp_free(t0);
12608 static inline void clear_branch_hflags(DisasContext *ctx)
12610 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12611 if (ctx->base.is_jmp == DISAS_NEXT) {
12612 save_cpu_state(ctx, 0);
12613 } else {
12614 /* it is not safe to save ctx->hflags as hflags may be changed
12615 in execution time by the instruction in delay / forbidden slot. */
12616 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12620 static void gen_branch(DisasContext *ctx, int insn_bytes)
12622 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12623 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12624 /* Branches completion */
12625 clear_branch_hflags(ctx);
12626 ctx->base.is_jmp = DISAS_NORETURN;
12627 /* FIXME: Need to clear can_do_io. */
12628 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12629 case MIPS_HFLAG_FBNSLOT:
12630 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12631 break;
12632 case MIPS_HFLAG_B:
12633 /* unconditional branch */
12634 if (proc_hflags & MIPS_HFLAG_BX) {
12635 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12637 gen_goto_tb(ctx, 0, ctx->btarget);
12638 break;
12639 case MIPS_HFLAG_BL:
12640 /* blikely taken case */
12641 gen_goto_tb(ctx, 0, ctx->btarget);
12642 break;
12643 case MIPS_HFLAG_BC:
12644 /* Conditional branch */
12646 TCGLabel *l1 = gen_new_label();
12648 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12649 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12650 gen_set_label(l1);
12651 gen_goto_tb(ctx, 0, ctx->btarget);
12653 break;
12654 case MIPS_HFLAG_BR:
12655 /* unconditional branch to register */
12656 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12657 TCGv t0 = tcg_temp_new();
12658 TCGv_i32 t1 = tcg_temp_new_i32();
12660 tcg_gen_andi_tl(t0, btarget, 0x1);
12661 tcg_gen_trunc_tl_i32(t1, t0);
12662 tcg_temp_free(t0);
12663 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12664 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12665 tcg_gen_or_i32(hflags, hflags, t1);
12666 tcg_temp_free_i32(t1);
12668 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12669 } else {
12670 tcg_gen_mov_tl(cpu_PC, btarget);
12672 if (ctx->base.singlestep_enabled) {
12673 save_cpu_state(ctx, 0);
12674 gen_helper_raise_exception_debug(cpu_env);
12676 tcg_gen_lookup_and_goto_ptr();
12677 break;
12678 default:
12679 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12680 abort();
12685 /* Compact Branches */
12686 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12687 int rs, int rt, int32_t offset)
12689 int bcond_compute = 0;
12690 TCGv t0 = tcg_temp_new();
12691 TCGv t1 = tcg_temp_new();
12692 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12694 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12695 #ifdef MIPS_DEBUG_DISAS
12696 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12697 "\n", ctx->base.pc_next);
12698 #endif
12699 generate_exception_end(ctx, EXCP_RI);
12700 goto out;
12703 /* Load needed operands and calculate btarget */
12704 switch (opc) {
12705 /* compact branch */
12706 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12707 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12708 gen_load_gpr(t0, rs);
12709 gen_load_gpr(t1, rt);
12710 bcond_compute = 1;
12711 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12712 if (rs <= rt && rs == 0) {
12713 /* OPC_BEQZALC, OPC_BNEZALC */
12714 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12716 break;
12717 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12718 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12719 gen_load_gpr(t0, rs);
12720 gen_load_gpr(t1, rt);
12721 bcond_compute = 1;
12722 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12723 break;
12724 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12725 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12726 if (rs == 0 || rs == rt) {
12727 /* OPC_BLEZALC, OPC_BGEZALC */
12728 /* OPC_BGTZALC, OPC_BLTZALC */
12729 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12731 gen_load_gpr(t0, rs);
12732 gen_load_gpr(t1, rt);
12733 bcond_compute = 1;
12734 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12735 break;
12736 case OPC_BC:
12737 case OPC_BALC:
12738 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12739 break;
12740 case OPC_BEQZC:
12741 case OPC_BNEZC:
12742 if (rs != 0) {
12743 /* OPC_BEQZC, OPC_BNEZC */
12744 gen_load_gpr(t0, rs);
12745 bcond_compute = 1;
12746 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12747 } else {
12748 /* OPC_JIC, OPC_JIALC */
12749 TCGv tbase = tcg_temp_new();
12750 TCGv toffset = tcg_temp_new();
12752 gen_load_gpr(tbase, rt);
12753 tcg_gen_movi_tl(toffset, offset);
12754 gen_op_addr_add(ctx, btarget, tbase, toffset);
12755 tcg_temp_free(tbase);
12756 tcg_temp_free(toffset);
12758 break;
12759 default:
12760 MIPS_INVAL("Compact branch/jump");
12761 generate_exception_end(ctx, EXCP_RI);
12762 goto out;
12765 if (bcond_compute == 0) {
12766 /* Uncoditional compact branch */
12767 switch (opc) {
12768 case OPC_JIALC:
12769 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12770 /* Fallthrough */
12771 case OPC_JIC:
12772 ctx->hflags |= MIPS_HFLAG_BR;
12773 break;
12774 case OPC_BALC:
12775 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12776 /* Fallthrough */
12777 case OPC_BC:
12778 ctx->hflags |= MIPS_HFLAG_B;
12779 break;
12780 default:
12781 MIPS_INVAL("Compact branch/jump");
12782 generate_exception_end(ctx, EXCP_RI);
12783 goto out;
12786 /* Generating branch here as compact branches don't have delay slot */
12787 gen_branch(ctx, 4);
12788 } else {
12789 /* Conditional compact branch */
12790 TCGLabel *fs = gen_new_label();
12791 save_cpu_state(ctx, 0);
12793 switch (opc) {
12794 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12795 if (rs == 0 && rt != 0) {
12796 /* OPC_BLEZALC */
12797 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12798 } else if (rs != 0 && rt != 0 && rs == rt) {
12799 /* OPC_BGEZALC */
12800 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12801 } else {
12802 /* OPC_BGEUC */
12803 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12805 break;
12806 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12807 if (rs == 0 && rt != 0) {
12808 /* OPC_BGTZALC */
12809 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12810 } else if (rs != 0 && rt != 0 && rs == rt) {
12811 /* OPC_BLTZALC */
12812 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12813 } else {
12814 /* OPC_BLTUC */
12815 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12817 break;
12818 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12819 if (rs == 0 && rt != 0) {
12820 /* OPC_BLEZC */
12821 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12822 } else if (rs != 0 && rt != 0 && rs == rt) {
12823 /* OPC_BGEZC */
12824 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12825 } else {
12826 /* OPC_BGEC */
12827 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12829 break;
12830 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12831 if (rs == 0 && rt != 0) {
12832 /* OPC_BGTZC */
12833 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12834 } else if (rs != 0 && rt != 0 && rs == rt) {
12835 /* OPC_BLTZC */
12836 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12837 } else {
12838 /* OPC_BLTC */
12839 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12841 break;
12842 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12843 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12844 if (rs >= rt) {
12845 /* OPC_BOVC, OPC_BNVC */
12846 TCGv t2 = tcg_temp_new();
12847 TCGv t3 = tcg_temp_new();
12848 TCGv t4 = tcg_temp_new();
12849 TCGv input_overflow = tcg_temp_new();
12851 gen_load_gpr(t0, rs);
12852 gen_load_gpr(t1, rt);
12853 tcg_gen_ext32s_tl(t2, t0);
12854 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12855 tcg_gen_ext32s_tl(t3, t1);
12856 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12857 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12859 tcg_gen_add_tl(t4, t2, t3);
12860 tcg_gen_ext32s_tl(t4, t4);
12861 tcg_gen_xor_tl(t2, t2, t3);
12862 tcg_gen_xor_tl(t3, t4, t3);
12863 tcg_gen_andc_tl(t2, t3, t2);
12864 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12865 tcg_gen_or_tl(t4, t4, input_overflow);
12866 if (opc == OPC_BOVC) {
12867 /* OPC_BOVC */
12868 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12869 } else {
12870 /* OPC_BNVC */
12871 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12873 tcg_temp_free(input_overflow);
12874 tcg_temp_free(t4);
12875 tcg_temp_free(t3);
12876 tcg_temp_free(t2);
12877 } else if (rs < rt && rs == 0) {
12878 /* OPC_BEQZALC, OPC_BNEZALC */
12879 if (opc == OPC_BEQZALC) {
12880 /* OPC_BEQZALC */
12881 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12882 } else {
12883 /* OPC_BNEZALC */
12884 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12886 } else {
12887 /* OPC_BEQC, OPC_BNEC */
12888 if (opc == OPC_BEQC) {
12889 /* OPC_BEQC */
12890 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12891 } else {
12892 /* OPC_BNEC */
12893 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12896 break;
12897 case OPC_BEQZC:
12898 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12899 break;
12900 case OPC_BNEZC:
12901 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12902 break;
12903 default:
12904 MIPS_INVAL("Compact conditional branch/jump");
12905 generate_exception_end(ctx, EXCP_RI);
12906 goto out;
12909 /* Generating branch here as compact branches don't have delay slot */
12910 gen_goto_tb(ctx, 1, ctx->btarget);
12911 gen_set_label(fs);
12913 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12916 out:
12917 tcg_temp_free(t0);
12918 tcg_temp_free(t1);
12921 /* ISA extensions (ASEs) */
12922 /* MIPS16 extension to MIPS32 */
12924 /* MIPS16 major opcodes */
12925 enum {
12926 M16_OPC_ADDIUSP = 0x00,
12927 M16_OPC_ADDIUPC = 0x01,
12928 M16_OPC_B = 0x02,
12929 M16_OPC_JAL = 0x03,
12930 M16_OPC_BEQZ = 0x04,
12931 M16_OPC_BNEQZ = 0x05,
12932 M16_OPC_SHIFT = 0x06,
12933 M16_OPC_LD = 0x07,
12934 M16_OPC_RRIA = 0x08,
12935 M16_OPC_ADDIU8 = 0x09,
12936 M16_OPC_SLTI = 0x0a,
12937 M16_OPC_SLTIU = 0x0b,
12938 M16_OPC_I8 = 0x0c,
12939 M16_OPC_LI = 0x0d,
12940 M16_OPC_CMPI = 0x0e,
12941 M16_OPC_SD = 0x0f,
12942 M16_OPC_LB = 0x10,
12943 M16_OPC_LH = 0x11,
12944 M16_OPC_LWSP = 0x12,
12945 M16_OPC_LW = 0x13,
12946 M16_OPC_LBU = 0x14,
12947 M16_OPC_LHU = 0x15,
12948 M16_OPC_LWPC = 0x16,
12949 M16_OPC_LWU = 0x17,
12950 M16_OPC_SB = 0x18,
12951 M16_OPC_SH = 0x19,
12952 M16_OPC_SWSP = 0x1a,
12953 M16_OPC_SW = 0x1b,
12954 M16_OPC_RRR = 0x1c,
12955 M16_OPC_RR = 0x1d,
12956 M16_OPC_EXTEND = 0x1e,
12957 M16_OPC_I64 = 0x1f
12960 /* I8 funct field */
12961 enum {
12962 I8_BTEQZ = 0x0,
12963 I8_BTNEZ = 0x1,
12964 I8_SWRASP = 0x2,
12965 I8_ADJSP = 0x3,
12966 I8_SVRS = 0x4,
12967 I8_MOV32R = 0x5,
12968 I8_MOVR32 = 0x7
12971 /* RRR f field */
12972 enum {
12973 RRR_DADDU = 0x0,
12974 RRR_ADDU = 0x1,
12975 RRR_DSUBU = 0x2,
12976 RRR_SUBU = 0x3
12979 /* RR funct field */
12980 enum {
12981 RR_JR = 0x00,
12982 RR_SDBBP = 0x01,
12983 RR_SLT = 0x02,
12984 RR_SLTU = 0x03,
12985 RR_SLLV = 0x04,
12986 RR_BREAK = 0x05,
12987 RR_SRLV = 0x06,
12988 RR_SRAV = 0x07,
12989 RR_DSRL = 0x08,
12990 RR_CMP = 0x0a,
12991 RR_NEG = 0x0b,
12992 RR_AND = 0x0c,
12993 RR_OR = 0x0d,
12994 RR_XOR = 0x0e,
12995 RR_NOT = 0x0f,
12996 RR_MFHI = 0x10,
12997 RR_CNVT = 0x11,
12998 RR_MFLO = 0x12,
12999 RR_DSRA = 0x13,
13000 RR_DSLLV = 0x14,
13001 RR_DSRLV = 0x16,
13002 RR_DSRAV = 0x17,
13003 RR_MULT = 0x18,
13004 RR_MULTU = 0x19,
13005 RR_DIV = 0x1a,
13006 RR_DIVU = 0x1b,
13007 RR_DMULT = 0x1c,
13008 RR_DMULTU = 0x1d,
13009 RR_DDIV = 0x1e,
13010 RR_DDIVU = 0x1f
13013 /* I64 funct field */
13014 enum {
13015 I64_LDSP = 0x0,
13016 I64_SDSP = 0x1,
13017 I64_SDRASP = 0x2,
13018 I64_DADJSP = 0x3,
13019 I64_LDPC = 0x4,
13020 I64_DADDIU5 = 0x5,
13021 I64_DADDIUPC = 0x6,
13022 I64_DADDIUSP = 0x7
13025 /* RR ry field for CNVT */
13026 enum {
13027 RR_RY_CNVT_ZEB = 0x0,
13028 RR_RY_CNVT_ZEH = 0x1,
13029 RR_RY_CNVT_ZEW = 0x2,
13030 RR_RY_CNVT_SEB = 0x4,
13031 RR_RY_CNVT_SEH = 0x5,
13032 RR_RY_CNVT_SEW = 0x6,
13035 static int xlat (int r)
13037 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13039 return map[r];
13042 static void gen_mips16_save (DisasContext *ctx,
13043 int xsregs, int aregs,
13044 int do_ra, int do_s0, int do_s1,
13045 int framesize)
13047 TCGv t0 = tcg_temp_new();
13048 TCGv t1 = tcg_temp_new();
13049 TCGv t2 = tcg_temp_new();
13050 int args, astatic;
13052 switch (aregs) {
13053 case 0:
13054 case 1:
13055 case 2:
13056 case 3:
13057 case 11:
13058 args = 0;
13059 break;
13060 case 4:
13061 case 5:
13062 case 6:
13063 case 7:
13064 args = 1;
13065 break;
13066 case 8:
13067 case 9:
13068 case 10:
13069 args = 2;
13070 break;
13071 case 12:
13072 case 13:
13073 args = 3;
13074 break;
13075 case 14:
13076 args = 4;
13077 break;
13078 default:
13079 generate_exception_end(ctx, EXCP_RI);
13080 return;
13083 switch (args) {
13084 case 4:
13085 gen_base_offset_addr(ctx, t0, 29, 12);
13086 gen_load_gpr(t1, 7);
13087 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13088 /* Fall through */
13089 case 3:
13090 gen_base_offset_addr(ctx, t0, 29, 8);
13091 gen_load_gpr(t1, 6);
13092 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13093 /* Fall through */
13094 case 2:
13095 gen_base_offset_addr(ctx, t0, 29, 4);
13096 gen_load_gpr(t1, 5);
13097 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13098 /* Fall through */
13099 case 1:
13100 gen_base_offset_addr(ctx, t0, 29, 0);
13101 gen_load_gpr(t1, 4);
13102 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13105 gen_load_gpr(t0, 29);
13107 #define DECR_AND_STORE(reg) do { \
13108 tcg_gen_movi_tl(t2, -4); \
13109 gen_op_addr_add(ctx, t0, t0, t2); \
13110 gen_load_gpr(t1, reg); \
13111 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13112 } while (0)
13114 if (do_ra) {
13115 DECR_AND_STORE(31);
13118 switch (xsregs) {
13119 case 7:
13120 DECR_AND_STORE(30);
13121 /* Fall through */
13122 case 6:
13123 DECR_AND_STORE(23);
13124 /* Fall through */
13125 case 5:
13126 DECR_AND_STORE(22);
13127 /* Fall through */
13128 case 4:
13129 DECR_AND_STORE(21);
13130 /* Fall through */
13131 case 3:
13132 DECR_AND_STORE(20);
13133 /* Fall through */
13134 case 2:
13135 DECR_AND_STORE(19);
13136 /* Fall through */
13137 case 1:
13138 DECR_AND_STORE(18);
13141 if (do_s1) {
13142 DECR_AND_STORE(17);
13144 if (do_s0) {
13145 DECR_AND_STORE(16);
13148 switch (aregs) {
13149 case 0:
13150 case 4:
13151 case 8:
13152 case 12:
13153 case 14:
13154 astatic = 0;
13155 break;
13156 case 1:
13157 case 5:
13158 case 9:
13159 case 13:
13160 astatic = 1;
13161 break;
13162 case 2:
13163 case 6:
13164 case 10:
13165 astatic = 2;
13166 break;
13167 case 3:
13168 case 7:
13169 astatic = 3;
13170 break;
13171 case 11:
13172 astatic = 4;
13173 break;
13174 default:
13175 generate_exception_end(ctx, EXCP_RI);
13176 return;
13179 if (astatic > 0) {
13180 DECR_AND_STORE(7);
13181 if (astatic > 1) {
13182 DECR_AND_STORE(6);
13183 if (astatic > 2) {
13184 DECR_AND_STORE(5);
13185 if (astatic > 3) {
13186 DECR_AND_STORE(4);
13191 #undef DECR_AND_STORE
13193 tcg_gen_movi_tl(t2, -framesize);
13194 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13195 tcg_temp_free(t0);
13196 tcg_temp_free(t1);
13197 tcg_temp_free(t2);
13200 static void gen_mips16_restore (DisasContext *ctx,
13201 int xsregs, int aregs,
13202 int do_ra, int do_s0, int do_s1,
13203 int framesize)
13205 int astatic;
13206 TCGv t0 = tcg_temp_new();
13207 TCGv t1 = tcg_temp_new();
13208 TCGv t2 = tcg_temp_new();
13210 tcg_gen_movi_tl(t2, framesize);
13211 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13213 #define DECR_AND_LOAD(reg) do { \
13214 tcg_gen_movi_tl(t2, -4); \
13215 gen_op_addr_add(ctx, t0, t0, t2); \
13216 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13217 gen_store_gpr(t1, reg); \
13218 } while (0)
13220 if (do_ra) {
13221 DECR_AND_LOAD(31);
13224 switch (xsregs) {
13225 case 7:
13226 DECR_AND_LOAD(30);
13227 /* Fall through */
13228 case 6:
13229 DECR_AND_LOAD(23);
13230 /* Fall through */
13231 case 5:
13232 DECR_AND_LOAD(22);
13233 /* Fall through */
13234 case 4:
13235 DECR_AND_LOAD(21);
13236 /* Fall through */
13237 case 3:
13238 DECR_AND_LOAD(20);
13239 /* Fall through */
13240 case 2:
13241 DECR_AND_LOAD(19);
13242 /* Fall through */
13243 case 1:
13244 DECR_AND_LOAD(18);
13247 if (do_s1) {
13248 DECR_AND_LOAD(17);
13250 if (do_s0) {
13251 DECR_AND_LOAD(16);
13254 switch (aregs) {
13255 case 0:
13256 case 4:
13257 case 8:
13258 case 12:
13259 case 14:
13260 astatic = 0;
13261 break;
13262 case 1:
13263 case 5:
13264 case 9:
13265 case 13:
13266 astatic = 1;
13267 break;
13268 case 2:
13269 case 6:
13270 case 10:
13271 astatic = 2;
13272 break;
13273 case 3:
13274 case 7:
13275 astatic = 3;
13276 break;
13277 case 11:
13278 astatic = 4;
13279 break;
13280 default:
13281 generate_exception_end(ctx, EXCP_RI);
13282 return;
13285 if (astatic > 0) {
13286 DECR_AND_LOAD(7);
13287 if (astatic > 1) {
13288 DECR_AND_LOAD(6);
13289 if (astatic > 2) {
13290 DECR_AND_LOAD(5);
13291 if (astatic > 3) {
13292 DECR_AND_LOAD(4);
13297 #undef DECR_AND_LOAD
13299 tcg_gen_movi_tl(t2, framesize);
13300 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13301 tcg_temp_free(t0);
13302 tcg_temp_free(t1);
13303 tcg_temp_free(t2);
13306 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13307 int is_64_bit, int extended)
13309 TCGv t0;
13311 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13312 generate_exception_end(ctx, EXCP_RI);
13313 return;
13316 t0 = tcg_temp_new();
13318 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13319 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13320 if (!is_64_bit) {
13321 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13324 tcg_temp_free(t0);
13327 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13328 int16_t offset)
13330 TCGv_i32 t0 = tcg_const_i32(op);
13331 TCGv t1 = tcg_temp_new();
13332 gen_base_offset_addr(ctx, t1, base, offset);
13333 gen_helper_cache(cpu_env, t1, t0);
13336 #if defined(TARGET_MIPS64)
13337 static void decode_i64_mips16 (DisasContext *ctx,
13338 int ry, int funct, int16_t offset,
13339 int extended)
13341 switch (funct) {
13342 case I64_LDSP:
13343 check_insn(ctx, ISA_MIPS3);
13344 check_mips_64(ctx);
13345 offset = extended ? offset : offset << 3;
13346 gen_ld(ctx, OPC_LD, ry, 29, offset);
13347 break;
13348 case I64_SDSP:
13349 check_insn(ctx, ISA_MIPS3);
13350 check_mips_64(ctx);
13351 offset = extended ? offset : offset << 3;
13352 gen_st(ctx, OPC_SD, ry, 29, offset);
13353 break;
13354 case I64_SDRASP:
13355 check_insn(ctx, ISA_MIPS3);
13356 check_mips_64(ctx);
13357 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13358 gen_st(ctx, OPC_SD, 31, 29, offset);
13359 break;
13360 case I64_DADJSP:
13361 check_insn(ctx, ISA_MIPS3);
13362 check_mips_64(ctx);
13363 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13364 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13365 break;
13366 case I64_LDPC:
13367 check_insn(ctx, ISA_MIPS3);
13368 check_mips_64(ctx);
13369 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13370 generate_exception_end(ctx, EXCP_RI);
13371 } else {
13372 offset = extended ? offset : offset << 3;
13373 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13375 break;
13376 case I64_DADDIU5:
13377 check_insn(ctx, ISA_MIPS3);
13378 check_mips_64(ctx);
13379 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13380 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13381 break;
13382 case I64_DADDIUPC:
13383 check_insn(ctx, ISA_MIPS3);
13384 check_mips_64(ctx);
13385 offset = extended ? offset : offset << 2;
13386 gen_addiupc(ctx, ry, offset, 1, extended);
13387 break;
13388 case I64_DADDIUSP:
13389 check_insn(ctx, ISA_MIPS3);
13390 check_mips_64(ctx);
13391 offset = extended ? offset : offset << 2;
13392 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13393 break;
13396 #endif
13398 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13400 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13401 int op, rx, ry, funct, sa;
13402 int16_t imm, offset;
13404 ctx->opcode = (ctx->opcode << 16) | extend;
13405 op = (ctx->opcode >> 11) & 0x1f;
13406 sa = (ctx->opcode >> 22) & 0x1f;
13407 funct = (ctx->opcode >> 8) & 0x7;
13408 rx = xlat((ctx->opcode >> 8) & 0x7);
13409 ry = xlat((ctx->opcode >> 5) & 0x7);
13410 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13411 | ((ctx->opcode >> 21) & 0x3f) << 5
13412 | (ctx->opcode & 0x1f));
13414 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13415 counterparts. */
13416 switch (op) {
13417 case M16_OPC_ADDIUSP:
13418 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13419 break;
13420 case M16_OPC_ADDIUPC:
13421 gen_addiupc(ctx, rx, imm, 0, 1);
13422 break;
13423 case M16_OPC_B:
13424 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13425 /* No delay slot, so just process as a normal instruction */
13426 break;
13427 case M16_OPC_BEQZ:
13428 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13429 /* No delay slot, so just process as a normal instruction */
13430 break;
13431 case M16_OPC_BNEQZ:
13432 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13433 /* No delay slot, so just process as a normal instruction */
13434 break;
13435 case M16_OPC_SHIFT:
13436 switch (ctx->opcode & 0x3) {
13437 case 0x0:
13438 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13439 break;
13440 case 0x1:
13441 #if defined(TARGET_MIPS64)
13442 check_mips_64(ctx);
13443 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13444 #else
13445 generate_exception_end(ctx, EXCP_RI);
13446 #endif
13447 break;
13448 case 0x2:
13449 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13450 break;
13451 case 0x3:
13452 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13453 break;
13455 break;
13456 #if defined(TARGET_MIPS64)
13457 case M16_OPC_LD:
13458 check_insn(ctx, ISA_MIPS3);
13459 check_mips_64(ctx);
13460 gen_ld(ctx, OPC_LD, ry, rx, offset);
13461 break;
13462 #endif
13463 case M16_OPC_RRIA:
13464 imm = ctx->opcode & 0xf;
13465 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13466 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13467 imm = (int16_t) (imm << 1) >> 1;
13468 if ((ctx->opcode >> 4) & 0x1) {
13469 #if defined(TARGET_MIPS64)
13470 check_mips_64(ctx);
13471 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13472 #else
13473 generate_exception_end(ctx, EXCP_RI);
13474 #endif
13475 } else {
13476 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13478 break;
13479 case M16_OPC_ADDIU8:
13480 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13481 break;
13482 case M16_OPC_SLTI:
13483 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13484 break;
13485 case M16_OPC_SLTIU:
13486 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13487 break;
13488 case M16_OPC_I8:
13489 switch (funct) {
13490 case I8_BTEQZ:
13491 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13492 break;
13493 case I8_BTNEZ:
13494 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13495 break;
13496 case I8_SWRASP:
13497 gen_st(ctx, OPC_SW, 31, 29, imm);
13498 break;
13499 case I8_ADJSP:
13500 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13501 break;
13502 case I8_SVRS:
13503 check_insn(ctx, ISA_MIPS32);
13505 int xsregs = (ctx->opcode >> 24) & 0x7;
13506 int aregs = (ctx->opcode >> 16) & 0xf;
13507 int do_ra = (ctx->opcode >> 6) & 0x1;
13508 int do_s0 = (ctx->opcode >> 5) & 0x1;
13509 int do_s1 = (ctx->opcode >> 4) & 0x1;
13510 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13511 | (ctx->opcode & 0xf)) << 3;
13513 if (ctx->opcode & (1 << 7)) {
13514 gen_mips16_save(ctx, xsregs, aregs,
13515 do_ra, do_s0, do_s1,
13516 framesize);
13517 } else {
13518 gen_mips16_restore(ctx, xsregs, aregs,
13519 do_ra, do_s0, do_s1,
13520 framesize);
13523 break;
13524 default:
13525 generate_exception_end(ctx, EXCP_RI);
13526 break;
13528 break;
13529 case M16_OPC_LI:
13530 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13531 break;
13532 case M16_OPC_CMPI:
13533 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13534 break;
13535 #if defined(TARGET_MIPS64)
13536 case M16_OPC_SD:
13537 check_insn(ctx, ISA_MIPS3);
13538 check_mips_64(ctx);
13539 gen_st(ctx, OPC_SD, ry, rx, offset);
13540 break;
13541 #endif
13542 case M16_OPC_LB:
13543 gen_ld(ctx, OPC_LB, ry, rx, offset);
13544 break;
13545 case M16_OPC_LH:
13546 gen_ld(ctx, OPC_LH, ry, rx, offset);
13547 break;
13548 case M16_OPC_LWSP:
13549 gen_ld(ctx, OPC_LW, rx, 29, offset);
13550 break;
13551 case M16_OPC_LW:
13552 gen_ld(ctx, OPC_LW, ry, rx, offset);
13553 break;
13554 case M16_OPC_LBU:
13555 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13556 break;
13557 case M16_OPC_LHU:
13558 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13559 break;
13560 case M16_OPC_LWPC:
13561 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13562 break;
13563 #if defined(TARGET_MIPS64)
13564 case M16_OPC_LWU:
13565 check_insn(ctx, ISA_MIPS3);
13566 check_mips_64(ctx);
13567 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13568 break;
13569 #endif
13570 case M16_OPC_SB:
13571 gen_st(ctx, OPC_SB, ry, rx, offset);
13572 break;
13573 case M16_OPC_SH:
13574 gen_st(ctx, OPC_SH, ry, rx, offset);
13575 break;
13576 case M16_OPC_SWSP:
13577 gen_st(ctx, OPC_SW, rx, 29, offset);
13578 break;
13579 case M16_OPC_SW:
13580 gen_st(ctx, OPC_SW, ry, rx, offset);
13581 break;
13582 #if defined(TARGET_MIPS64)
13583 case M16_OPC_I64:
13584 decode_i64_mips16(ctx, ry, funct, offset, 1);
13585 break;
13586 #endif
13587 default:
13588 generate_exception_end(ctx, EXCP_RI);
13589 break;
13592 return 4;
13595 static inline bool is_uhi(int sdbbp_code)
13597 #ifdef CONFIG_USER_ONLY
13598 return false;
13599 #else
13600 return semihosting_enabled() && sdbbp_code == 1;
13601 #endif
13604 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13606 int rx, ry;
13607 int sa;
13608 int op, cnvt_op, op1, offset;
13609 int funct;
13610 int n_bytes;
13612 op = (ctx->opcode >> 11) & 0x1f;
13613 sa = (ctx->opcode >> 2) & 0x7;
13614 sa = sa == 0 ? 8 : sa;
13615 rx = xlat((ctx->opcode >> 8) & 0x7);
13616 cnvt_op = (ctx->opcode >> 5) & 0x7;
13617 ry = xlat((ctx->opcode >> 5) & 0x7);
13618 op1 = offset = ctx->opcode & 0x1f;
13620 n_bytes = 2;
13622 switch (op) {
13623 case M16_OPC_ADDIUSP:
13625 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13627 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13629 break;
13630 case M16_OPC_ADDIUPC:
13631 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13632 break;
13633 case M16_OPC_B:
13634 offset = (ctx->opcode & 0x7ff) << 1;
13635 offset = (int16_t)(offset << 4) >> 4;
13636 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13637 /* No delay slot, so just process as a normal instruction */
13638 break;
13639 case M16_OPC_JAL:
13640 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13641 offset = (((ctx->opcode & 0x1f) << 21)
13642 | ((ctx->opcode >> 5) & 0x1f) << 16
13643 | offset) << 2;
13644 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13645 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13646 n_bytes = 4;
13647 break;
13648 case M16_OPC_BEQZ:
13649 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13650 ((int8_t)ctx->opcode) << 1, 0);
13651 /* No delay slot, so just process as a normal instruction */
13652 break;
13653 case M16_OPC_BNEQZ:
13654 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13655 ((int8_t)ctx->opcode) << 1, 0);
13656 /* No delay slot, so just process as a normal instruction */
13657 break;
13658 case M16_OPC_SHIFT:
13659 switch (ctx->opcode & 0x3) {
13660 case 0x0:
13661 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13662 break;
13663 case 0x1:
13664 #if defined(TARGET_MIPS64)
13665 check_insn(ctx, ISA_MIPS3);
13666 check_mips_64(ctx);
13667 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13668 #else
13669 generate_exception_end(ctx, EXCP_RI);
13670 #endif
13671 break;
13672 case 0x2:
13673 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13674 break;
13675 case 0x3:
13676 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13677 break;
13679 break;
13680 #if defined(TARGET_MIPS64)
13681 case M16_OPC_LD:
13682 check_insn(ctx, ISA_MIPS3);
13683 check_mips_64(ctx);
13684 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13685 break;
13686 #endif
13687 case M16_OPC_RRIA:
13689 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13691 if ((ctx->opcode >> 4) & 1) {
13692 #if defined(TARGET_MIPS64)
13693 check_insn(ctx, ISA_MIPS3);
13694 check_mips_64(ctx);
13695 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13696 #else
13697 generate_exception_end(ctx, EXCP_RI);
13698 #endif
13699 } else {
13700 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13703 break;
13704 case M16_OPC_ADDIU8:
13706 int16_t imm = (int8_t) ctx->opcode;
13708 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13710 break;
13711 case M16_OPC_SLTI:
13713 int16_t imm = (uint8_t) ctx->opcode;
13714 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13716 break;
13717 case M16_OPC_SLTIU:
13719 int16_t imm = (uint8_t) ctx->opcode;
13720 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13722 break;
13723 case M16_OPC_I8:
13725 int reg32;
13727 funct = (ctx->opcode >> 8) & 0x7;
13728 switch (funct) {
13729 case I8_BTEQZ:
13730 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13731 ((int8_t)ctx->opcode) << 1, 0);
13732 break;
13733 case I8_BTNEZ:
13734 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13735 ((int8_t)ctx->opcode) << 1, 0);
13736 break;
13737 case I8_SWRASP:
13738 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13739 break;
13740 case I8_ADJSP:
13741 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13742 ((int8_t)ctx->opcode) << 3);
13743 break;
13744 case I8_SVRS:
13745 check_insn(ctx, ISA_MIPS32);
13747 int do_ra = ctx->opcode & (1 << 6);
13748 int do_s0 = ctx->opcode & (1 << 5);
13749 int do_s1 = ctx->opcode & (1 << 4);
13750 int framesize = ctx->opcode & 0xf;
13752 if (framesize == 0) {
13753 framesize = 128;
13754 } else {
13755 framesize = framesize << 3;
13758 if (ctx->opcode & (1 << 7)) {
13759 gen_mips16_save(ctx, 0, 0,
13760 do_ra, do_s0, do_s1, framesize);
13761 } else {
13762 gen_mips16_restore(ctx, 0, 0,
13763 do_ra, do_s0, do_s1, framesize);
13766 break;
13767 case I8_MOV32R:
13769 int rz = xlat(ctx->opcode & 0x7);
13771 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13772 ((ctx->opcode >> 5) & 0x7);
13773 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13775 break;
13776 case I8_MOVR32:
13777 reg32 = ctx->opcode & 0x1f;
13778 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13779 break;
13780 default:
13781 generate_exception_end(ctx, EXCP_RI);
13782 break;
13785 break;
13786 case M16_OPC_LI:
13788 int16_t imm = (uint8_t) ctx->opcode;
13790 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13792 break;
13793 case M16_OPC_CMPI:
13795 int16_t imm = (uint8_t) ctx->opcode;
13796 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13798 break;
13799 #if defined(TARGET_MIPS64)
13800 case M16_OPC_SD:
13801 check_insn(ctx, ISA_MIPS3);
13802 check_mips_64(ctx);
13803 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13804 break;
13805 #endif
13806 case M16_OPC_LB:
13807 gen_ld(ctx, OPC_LB, ry, rx, offset);
13808 break;
13809 case M16_OPC_LH:
13810 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13811 break;
13812 case M16_OPC_LWSP:
13813 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13814 break;
13815 case M16_OPC_LW:
13816 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13817 break;
13818 case M16_OPC_LBU:
13819 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13820 break;
13821 case M16_OPC_LHU:
13822 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13823 break;
13824 case M16_OPC_LWPC:
13825 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13826 break;
13827 #if defined (TARGET_MIPS64)
13828 case M16_OPC_LWU:
13829 check_insn(ctx, ISA_MIPS3);
13830 check_mips_64(ctx);
13831 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13832 break;
13833 #endif
13834 case M16_OPC_SB:
13835 gen_st(ctx, OPC_SB, ry, rx, offset);
13836 break;
13837 case M16_OPC_SH:
13838 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13839 break;
13840 case M16_OPC_SWSP:
13841 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13842 break;
13843 case M16_OPC_SW:
13844 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13845 break;
13846 case M16_OPC_RRR:
13848 int rz = xlat((ctx->opcode >> 2) & 0x7);
13849 int mips32_op;
13851 switch (ctx->opcode & 0x3) {
13852 case RRR_ADDU:
13853 mips32_op = OPC_ADDU;
13854 break;
13855 case RRR_SUBU:
13856 mips32_op = OPC_SUBU;
13857 break;
13858 #if defined(TARGET_MIPS64)
13859 case RRR_DADDU:
13860 mips32_op = OPC_DADDU;
13861 check_insn(ctx, ISA_MIPS3);
13862 check_mips_64(ctx);
13863 break;
13864 case RRR_DSUBU:
13865 mips32_op = OPC_DSUBU;
13866 check_insn(ctx, ISA_MIPS3);
13867 check_mips_64(ctx);
13868 break;
13869 #endif
13870 default:
13871 generate_exception_end(ctx, EXCP_RI);
13872 goto done;
13875 gen_arith(ctx, mips32_op, rz, rx, ry);
13876 done:
13879 break;
13880 case M16_OPC_RR:
13881 switch (op1) {
13882 case RR_JR:
13884 int nd = (ctx->opcode >> 7) & 0x1;
13885 int link = (ctx->opcode >> 6) & 0x1;
13886 int ra = (ctx->opcode >> 5) & 0x1;
13888 if (nd) {
13889 check_insn(ctx, ISA_MIPS32);
13892 if (link) {
13893 op = OPC_JALR;
13894 } else {
13895 op = OPC_JR;
13898 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13899 (nd ? 0 : 2));
13901 break;
13902 case RR_SDBBP:
13903 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13904 gen_helper_do_semihosting(cpu_env);
13905 } else {
13906 /* XXX: not clear which exception should be raised
13907 * when in debug mode...
13909 check_insn(ctx, ISA_MIPS32);
13910 generate_exception_end(ctx, EXCP_DBp);
13912 break;
13913 case RR_SLT:
13914 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13915 break;
13916 case RR_SLTU:
13917 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13918 break;
13919 case RR_BREAK:
13920 generate_exception_end(ctx, EXCP_BREAK);
13921 break;
13922 case RR_SLLV:
13923 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13924 break;
13925 case RR_SRLV:
13926 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13927 break;
13928 case RR_SRAV:
13929 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13930 break;
13931 #if defined (TARGET_MIPS64)
13932 case RR_DSRL:
13933 check_insn(ctx, ISA_MIPS3);
13934 check_mips_64(ctx);
13935 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13936 break;
13937 #endif
13938 case RR_CMP:
13939 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13940 break;
13941 case RR_NEG:
13942 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13943 break;
13944 case RR_AND:
13945 gen_logic(ctx, OPC_AND, rx, rx, ry);
13946 break;
13947 case RR_OR:
13948 gen_logic(ctx, OPC_OR, rx, rx, ry);
13949 break;
13950 case RR_XOR:
13951 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13952 break;
13953 case RR_NOT:
13954 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13955 break;
13956 case RR_MFHI:
13957 gen_HILO(ctx, OPC_MFHI, 0, rx);
13958 break;
13959 case RR_CNVT:
13960 check_insn(ctx, ISA_MIPS32);
13961 switch (cnvt_op) {
13962 case RR_RY_CNVT_ZEB:
13963 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13964 break;
13965 case RR_RY_CNVT_ZEH:
13966 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13967 break;
13968 case RR_RY_CNVT_SEB:
13969 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13970 break;
13971 case RR_RY_CNVT_SEH:
13972 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13973 break;
13974 #if defined (TARGET_MIPS64)
13975 case RR_RY_CNVT_ZEW:
13976 check_insn(ctx, ISA_MIPS64);
13977 check_mips_64(ctx);
13978 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13979 break;
13980 case RR_RY_CNVT_SEW:
13981 check_insn(ctx, ISA_MIPS64);
13982 check_mips_64(ctx);
13983 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13984 break;
13985 #endif
13986 default:
13987 generate_exception_end(ctx, EXCP_RI);
13988 break;
13990 break;
13991 case RR_MFLO:
13992 gen_HILO(ctx, OPC_MFLO, 0, rx);
13993 break;
13994 #if defined (TARGET_MIPS64)
13995 case RR_DSRA:
13996 check_insn(ctx, ISA_MIPS3);
13997 check_mips_64(ctx);
13998 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13999 break;
14000 case RR_DSLLV:
14001 check_insn(ctx, ISA_MIPS3);
14002 check_mips_64(ctx);
14003 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14004 break;
14005 case RR_DSRLV:
14006 check_insn(ctx, ISA_MIPS3);
14007 check_mips_64(ctx);
14008 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14009 break;
14010 case RR_DSRAV:
14011 check_insn(ctx, ISA_MIPS3);
14012 check_mips_64(ctx);
14013 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14014 break;
14015 #endif
14016 case RR_MULT:
14017 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14018 break;
14019 case RR_MULTU:
14020 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14021 break;
14022 case RR_DIV:
14023 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14024 break;
14025 case RR_DIVU:
14026 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14027 break;
14028 #if defined (TARGET_MIPS64)
14029 case RR_DMULT:
14030 check_insn(ctx, ISA_MIPS3);
14031 check_mips_64(ctx);
14032 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14033 break;
14034 case RR_DMULTU:
14035 check_insn(ctx, ISA_MIPS3);
14036 check_mips_64(ctx);
14037 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14038 break;
14039 case RR_DDIV:
14040 check_insn(ctx, ISA_MIPS3);
14041 check_mips_64(ctx);
14042 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14043 break;
14044 case RR_DDIVU:
14045 check_insn(ctx, ISA_MIPS3);
14046 check_mips_64(ctx);
14047 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14048 break;
14049 #endif
14050 default:
14051 generate_exception_end(ctx, EXCP_RI);
14052 break;
14054 break;
14055 case M16_OPC_EXTEND:
14056 decode_extended_mips16_opc(env, ctx);
14057 n_bytes = 4;
14058 break;
14059 #if defined(TARGET_MIPS64)
14060 case M16_OPC_I64:
14061 funct = (ctx->opcode >> 8) & 0x7;
14062 decode_i64_mips16(ctx, ry, funct, offset, 0);
14063 break;
14064 #endif
14065 default:
14066 generate_exception_end(ctx, EXCP_RI);
14067 break;
14070 return n_bytes;
14073 /* microMIPS extension to MIPS32/MIPS64 */
14076 * microMIPS32/microMIPS64 major opcodes
14078 * 1. MIPS Architecture for Programmers Volume II-B:
14079 * The microMIPS32 Instruction Set (Revision 3.05)
14081 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14083 * 2. MIPS Architecture For Programmers Volume II-A:
14084 * The MIPS64 Instruction Set (Revision 3.51)
14087 enum {
14088 POOL32A = 0x00,
14089 POOL16A = 0x01,
14090 LBU16 = 0x02,
14091 MOVE16 = 0x03,
14092 ADDI32 = 0x04,
14093 R6_LUI = 0x04,
14094 AUI = 0x04,
14095 LBU32 = 0x05,
14096 SB32 = 0x06,
14097 LB32 = 0x07,
14099 POOL32B = 0x08,
14100 POOL16B = 0x09,
14101 LHU16 = 0x0a,
14102 ANDI16 = 0x0b,
14103 ADDIU32 = 0x0c,
14104 LHU32 = 0x0d,
14105 SH32 = 0x0e,
14106 LH32 = 0x0f,
14108 POOL32I = 0x10,
14109 POOL16C = 0x11,
14110 LWSP16 = 0x12,
14111 POOL16D = 0x13,
14112 ORI32 = 0x14,
14113 POOL32F = 0x15,
14114 POOL32S = 0x16, /* MIPS64 */
14115 DADDIU32 = 0x17, /* MIPS64 */
14117 POOL32C = 0x18,
14118 LWGP16 = 0x19,
14119 LW16 = 0x1a,
14120 POOL16E = 0x1b,
14121 XORI32 = 0x1c,
14122 JALS32 = 0x1d,
14123 BOVC = 0x1d,
14124 BEQC = 0x1d,
14125 BEQZALC = 0x1d,
14126 ADDIUPC = 0x1e,
14127 PCREL = 0x1e,
14128 BNVC = 0x1f,
14129 BNEC = 0x1f,
14130 BNEZALC = 0x1f,
14132 R6_BEQZC = 0x20,
14133 JIC = 0x20,
14134 POOL16F = 0x21,
14135 SB16 = 0x22,
14136 BEQZ16 = 0x23,
14137 BEQZC16 = 0x23,
14138 SLTI32 = 0x24,
14139 BEQ32 = 0x25,
14140 BC = 0x25,
14141 SWC132 = 0x26,
14142 LWC132 = 0x27,
14144 /* 0x29 is reserved */
14145 RES_29 = 0x29,
14146 R6_BNEZC = 0x28,
14147 JIALC = 0x28,
14148 SH16 = 0x2a,
14149 BNEZ16 = 0x2b,
14150 BNEZC16 = 0x2b,
14151 SLTIU32 = 0x2c,
14152 BNE32 = 0x2d,
14153 BALC = 0x2d,
14154 SDC132 = 0x2e,
14155 LDC132 = 0x2f,
14157 /* 0x31 is reserved */
14158 RES_31 = 0x31,
14159 BLEZALC = 0x30,
14160 BGEZALC = 0x30,
14161 BGEUC = 0x30,
14162 SWSP16 = 0x32,
14163 B16 = 0x33,
14164 BC16 = 0x33,
14165 ANDI32 = 0x34,
14166 J32 = 0x35,
14167 BGTZC = 0x35,
14168 BLTZC = 0x35,
14169 BLTC = 0x35,
14170 SD32 = 0x36, /* MIPS64 */
14171 LD32 = 0x37, /* MIPS64 */
14173 /* 0x39 is reserved */
14174 RES_39 = 0x39,
14175 BGTZALC = 0x38,
14176 BLTZALC = 0x38,
14177 BLTUC = 0x38,
14178 SW16 = 0x3a,
14179 LI16 = 0x3b,
14180 JALX32 = 0x3c,
14181 JAL32 = 0x3d,
14182 BLEZC = 0x3d,
14183 BGEZC = 0x3d,
14184 BGEC = 0x3d,
14185 SW32 = 0x3e,
14186 LW32 = 0x3f
14189 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14190 enum {
14191 ADDIUPC_00 = 0x00,
14192 ADDIUPC_01 = 0x01,
14193 ADDIUPC_02 = 0x02,
14194 ADDIUPC_03 = 0x03,
14195 ADDIUPC_04 = 0x04,
14196 ADDIUPC_05 = 0x05,
14197 ADDIUPC_06 = 0x06,
14198 ADDIUPC_07 = 0x07,
14199 AUIPC = 0x1e,
14200 ALUIPC = 0x1f,
14201 LWPC_08 = 0x08,
14202 LWPC_09 = 0x09,
14203 LWPC_0A = 0x0A,
14204 LWPC_0B = 0x0B,
14205 LWPC_0C = 0x0C,
14206 LWPC_0D = 0x0D,
14207 LWPC_0E = 0x0E,
14208 LWPC_0F = 0x0F,
14211 /* POOL32A encoding of minor opcode field */
14213 enum {
14214 /* These opcodes are distinguished only by bits 9..6; those bits are
14215 * what are recorded below. */
14216 SLL32 = 0x0,
14217 SRL32 = 0x1,
14218 SRA = 0x2,
14219 ROTR = 0x3,
14220 SELEQZ = 0x5,
14221 SELNEZ = 0x6,
14222 R6_RDHWR = 0x7,
14224 SLLV = 0x0,
14225 SRLV = 0x1,
14226 SRAV = 0x2,
14227 ROTRV = 0x3,
14228 ADD = 0x4,
14229 ADDU32 = 0x5,
14230 SUB = 0x6,
14231 SUBU32 = 0x7,
14232 MUL = 0x8,
14233 AND = 0x9,
14234 OR32 = 0xa,
14235 NOR = 0xb,
14236 XOR32 = 0xc,
14237 SLT = 0xd,
14238 SLTU = 0xe,
14240 MOVN = 0x0,
14241 R6_MUL = 0x0,
14242 MOVZ = 0x1,
14243 MUH = 0x1,
14244 MULU = 0x2,
14245 MUHU = 0x3,
14246 LWXS = 0x4,
14247 R6_DIV = 0x4,
14248 MOD = 0x5,
14249 R6_DIVU = 0x6,
14250 MODU = 0x7,
14252 /* The following can be distinguished by their lower 6 bits. */
14253 BREAK32 = 0x07,
14254 INS = 0x0c,
14255 LSA = 0x0f,
14256 ALIGN = 0x1f,
14257 EXT = 0x2c,
14258 POOL32AXF = 0x3c,
14259 SIGRIE = 0x3f
14262 /* POOL32AXF encoding of minor opcode field extension */
14265 * 1. MIPS Architecture for Programmers Volume II-B:
14266 * The microMIPS32 Instruction Set (Revision 3.05)
14268 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14270 * 2. MIPS Architecture for Programmers VolumeIV-e:
14271 * The MIPS DSP Application-Specific Extension
14272 * to the microMIPS32 Architecture (Revision 2.34)
14274 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14277 enum {
14278 /* bits 11..6 */
14279 TEQ = 0x00,
14280 TGE = 0x08,
14281 TGEU = 0x10,
14282 TLT = 0x20,
14283 TLTU = 0x28,
14284 TNE = 0x30,
14286 MFC0 = 0x03,
14287 MTC0 = 0x0b,
14289 /* begin of microMIPS32 DSP */
14291 /* bits 13..12 for 0x01 */
14292 MFHI_ACC = 0x0,
14293 MFLO_ACC = 0x1,
14294 MTHI_ACC = 0x2,
14295 MTLO_ACC = 0x3,
14297 /* bits 13..12 for 0x2a */
14298 MADD_ACC = 0x0,
14299 MADDU_ACC = 0x1,
14300 MSUB_ACC = 0x2,
14301 MSUBU_ACC = 0x3,
14303 /* bits 13..12 for 0x32 */
14304 MULT_ACC = 0x0,
14305 MULTU_ACC = 0x1,
14307 /* end of microMIPS32 DSP */
14309 /* bits 15..12 for 0x2c */
14310 BITSWAP = 0x0,
14311 SEB = 0x2,
14312 SEH = 0x3,
14313 CLO = 0x4,
14314 CLZ = 0x5,
14315 RDHWR = 0x6,
14316 WSBH = 0x7,
14317 MULT = 0x8,
14318 MULTU = 0x9,
14319 DIV = 0xa,
14320 DIVU = 0xb,
14321 MADD = 0xc,
14322 MADDU = 0xd,
14323 MSUB = 0xe,
14324 MSUBU = 0xf,
14326 /* bits 15..12 for 0x34 */
14327 MFC2 = 0x4,
14328 MTC2 = 0x5,
14329 MFHC2 = 0x8,
14330 MTHC2 = 0x9,
14331 CFC2 = 0xc,
14332 CTC2 = 0xd,
14334 /* bits 15..12 for 0x3c */
14335 JALR = 0x0,
14336 JR = 0x0, /* alias */
14337 JALRC = 0x0,
14338 JRC = 0x0,
14339 JALR_HB = 0x1,
14340 JALRC_HB = 0x1,
14341 JALRS = 0x4,
14342 JALRS_HB = 0x5,
14344 /* bits 15..12 for 0x05 */
14345 RDPGPR = 0xe,
14346 WRPGPR = 0xf,
14348 /* bits 15..12 for 0x0d */
14349 TLBP = 0x0,
14350 TLBR = 0x1,
14351 TLBWI = 0x2,
14352 TLBWR = 0x3,
14353 TLBINV = 0x4,
14354 TLBINVF = 0x5,
14355 WAIT = 0x9,
14356 IRET = 0xd,
14357 DERET = 0xe,
14358 ERET = 0xf,
14360 /* bits 15..12 for 0x15 */
14361 DMT = 0x0,
14362 DVPE = 0x1,
14363 EMT = 0x2,
14364 EVPE = 0x3,
14366 /* bits 15..12 for 0x1d */
14367 DI = 0x4,
14368 EI = 0x5,
14370 /* bits 15..12 for 0x2d */
14371 SYNC = 0x6,
14372 SYSCALL = 0x8,
14373 SDBBP = 0xd,
14375 /* bits 15..12 for 0x35 */
14376 MFHI32 = 0x0,
14377 MFLO32 = 0x1,
14378 MTHI32 = 0x2,
14379 MTLO32 = 0x3,
14382 /* POOL32B encoding of minor opcode field (bits 15..12) */
14384 enum {
14385 LWC2 = 0x0,
14386 LWP = 0x1,
14387 LDP = 0x4,
14388 LWM32 = 0x5,
14389 CACHE = 0x6,
14390 LDM = 0x7,
14391 SWC2 = 0x8,
14392 SWP = 0x9,
14393 SDP = 0xc,
14394 SWM32 = 0xd,
14395 SDM = 0xf
14398 /* POOL32C encoding of minor opcode field (bits 15..12) */
14400 enum {
14401 LWL = 0x0,
14402 SWL = 0x8,
14403 LWR = 0x1,
14404 SWR = 0x9,
14405 PREF = 0x2,
14406 ST_EVA = 0xa,
14407 LL = 0x3,
14408 SC = 0xb,
14409 LDL = 0x4,
14410 SDL = 0xc,
14411 LDR = 0x5,
14412 SDR = 0xd,
14413 LD_EVA = 0x6,
14414 LWU = 0xe,
14415 LLD = 0x7,
14416 SCD = 0xf
14419 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14421 enum {
14422 LBUE = 0x0,
14423 LHUE = 0x1,
14424 LWLE = 0x2,
14425 LWRE = 0x3,
14426 LBE = 0x4,
14427 LHE = 0x5,
14428 LLE = 0x6,
14429 LWE = 0x7,
14432 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14434 enum {
14435 SWLE = 0x0,
14436 SWRE = 0x1,
14437 PREFE = 0x2,
14438 CACHEE = 0x3,
14439 SBE = 0x4,
14440 SHE = 0x5,
14441 SCE = 0x6,
14442 SWE = 0x7,
14445 /* POOL32F encoding of minor opcode field (bits 5..0) */
14447 enum {
14448 /* These are the bit 7..6 values */
14449 ADD_FMT = 0x0,
14451 SUB_FMT = 0x1,
14453 MUL_FMT = 0x2,
14455 DIV_FMT = 0x3,
14457 /* These are the bit 8..6 values */
14458 MOVN_FMT = 0x0,
14459 RSQRT2_FMT = 0x0,
14460 MOVF_FMT = 0x0,
14461 RINT_FMT = 0x0,
14462 SELNEZ_FMT = 0x0,
14464 MOVZ_FMT = 0x1,
14465 LWXC1 = 0x1,
14466 MOVT_FMT = 0x1,
14467 CLASS_FMT = 0x1,
14468 SELEQZ_FMT = 0x1,
14470 PLL_PS = 0x2,
14471 SWXC1 = 0x2,
14472 SEL_FMT = 0x2,
14474 PLU_PS = 0x3,
14475 LDXC1 = 0x3,
14477 MOVN_FMT_04 = 0x4,
14478 PUL_PS = 0x4,
14479 SDXC1 = 0x4,
14480 RECIP2_FMT = 0x4,
14482 MOVZ_FMT_05 = 0x05,
14483 PUU_PS = 0x5,
14484 LUXC1 = 0x5,
14486 CVT_PS_S = 0x6,
14487 SUXC1 = 0x6,
14488 ADDR_PS = 0x6,
14489 PREFX = 0x6,
14490 MADDF_FMT = 0x6,
14492 MULR_PS = 0x7,
14493 MSUBF_FMT = 0x7,
14495 MADD_S = 0x01,
14496 MADD_D = 0x09,
14497 MADD_PS = 0x11,
14498 ALNV_PS = 0x19,
14499 MSUB_S = 0x21,
14500 MSUB_D = 0x29,
14501 MSUB_PS = 0x31,
14503 NMADD_S = 0x02,
14504 NMADD_D = 0x0a,
14505 NMADD_PS = 0x12,
14506 NMSUB_S = 0x22,
14507 NMSUB_D = 0x2a,
14508 NMSUB_PS = 0x32,
14510 MIN_FMT = 0x3,
14511 MAX_FMT = 0xb,
14512 MINA_FMT = 0x23,
14513 MAXA_FMT = 0x2b,
14514 POOL32FXF = 0x3b,
14516 CABS_COND_FMT = 0x1c, /* MIPS3D */
14517 C_COND_FMT = 0x3c,
14519 CMP_CONDN_S = 0x5,
14520 CMP_CONDN_D = 0x15
14523 /* POOL32Fxf encoding of minor opcode extension field */
14525 enum {
14526 CVT_L = 0x04,
14527 RSQRT_FMT = 0x08,
14528 FLOOR_L = 0x0c,
14529 CVT_PW_PS = 0x1c,
14530 CVT_W = 0x24,
14531 SQRT_FMT = 0x28,
14532 FLOOR_W = 0x2c,
14533 CVT_PS_PW = 0x3c,
14534 CFC1 = 0x40,
14535 RECIP_FMT = 0x48,
14536 CEIL_L = 0x4c,
14537 CTC1 = 0x60,
14538 CEIL_W = 0x6c,
14539 MFC1 = 0x80,
14540 CVT_S_PL = 0x84,
14541 TRUNC_L = 0x8c,
14542 MTC1 = 0xa0,
14543 CVT_S_PU = 0xa4,
14544 TRUNC_W = 0xac,
14545 MFHC1 = 0xc0,
14546 ROUND_L = 0xcc,
14547 MTHC1 = 0xe0,
14548 ROUND_W = 0xec,
14550 MOV_FMT = 0x01,
14551 MOVF = 0x05,
14552 ABS_FMT = 0x0d,
14553 RSQRT1_FMT = 0x1d,
14554 MOVT = 0x25,
14555 NEG_FMT = 0x2d,
14556 CVT_D = 0x4d,
14557 RECIP1_FMT = 0x5d,
14558 CVT_S = 0x6d
14561 /* POOL32I encoding of minor opcode field (bits 25..21) */
14563 enum {
14564 BLTZ = 0x00,
14565 BLTZAL = 0x01,
14566 BGEZ = 0x02,
14567 BGEZAL = 0x03,
14568 BLEZ = 0x04,
14569 BNEZC = 0x05,
14570 BGTZ = 0x06,
14571 BEQZC = 0x07,
14572 TLTI = 0x08,
14573 BC1EQZC = 0x08,
14574 TGEI = 0x09,
14575 BC1NEZC = 0x09,
14576 TLTIU = 0x0a,
14577 BC2EQZC = 0x0a,
14578 TGEIU = 0x0b,
14579 BC2NEZC = 0x0a,
14580 TNEI = 0x0c,
14581 R6_SYNCI = 0x0c,
14582 LUI = 0x0d,
14583 TEQI = 0x0e,
14584 SYNCI = 0x10,
14585 BLTZALS = 0x11,
14586 BGEZALS = 0x13,
14587 BC2F = 0x14,
14588 BC2T = 0x15,
14589 BPOSGE64 = 0x1a,
14590 BPOSGE32 = 0x1b,
14591 /* These overlap and are distinguished by bit16 of the instruction */
14592 BC1F = 0x1c,
14593 BC1T = 0x1d,
14594 BC1ANY2F = 0x1c,
14595 BC1ANY2T = 0x1d,
14596 BC1ANY4F = 0x1e,
14597 BC1ANY4T = 0x1f
14600 /* POOL16A encoding of minor opcode field */
14602 enum {
14603 ADDU16 = 0x0,
14604 SUBU16 = 0x1
14607 /* POOL16B encoding of minor opcode field */
14609 enum {
14610 SLL16 = 0x0,
14611 SRL16 = 0x1
14614 /* POOL16C encoding of minor opcode field */
14616 enum {
14617 NOT16 = 0x00,
14618 XOR16 = 0x04,
14619 AND16 = 0x08,
14620 OR16 = 0x0c,
14621 LWM16 = 0x10,
14622 SWM16 = 0x14,
14623 JR16 = 0x18,
14624 JRC16 = 0x1a,
14625 JALR16 = 0x1c,
14626 JALR16S = 0x1e,
14627 MFHI16 = 0x20,
14628 MFLO16 = 0x24,
14629 BREAK16 = 0x28,
14630 SDBBP16 = 0x2c,
14631 JRADDIUSP = 0x30
14634 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14636 enum {
14637 R6_NOT16 = 0x00,
14638 R6_AND16 = 0x01,
14639 R6_LWM16 = 0x02,
14640 R6_JRC16 = 0x03,
14641 MOVEP = 0x04,
14642 MOVEP_05 = 0x05,
14643 MOVEP_06 = 0x06,
14644 MOVEP_07 = 0x07,
14645 R6_XOR16 = 0x08,
14646 R6_OR16 = 0x09,
14647 R6_SWM16 = 0x0a,
14648 JALRC16 = 0x0b,
14649 MOVEP_0C = 0x0c,
14650 MOVEP_0D = 0x0d,
14651 MOVEP_0E = 0x0e,
14652 MOVEP_0F = 0x0f,
14653 JRCADDIUSP = 0x13,
14654 R6_BREAK16 = 0x1b,
14655 R6_SDBBP16 = 0x3b
14658 /* POOL16D encoding of minor opcode field */
14660 enum {
14661 ADDIUS5 = 0x0,
14662 ADDIUSP = 0x1
14665 /* POOL16E encoding of minor opcode field */
14667 enum {
14668 ADDIUR2 = 0x0,
14669 ADDIUR1SP = 0x1
14672 static int mmreg (int r)
14674 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14676 return map[r];
14679 /* Used for 16-bit store instructions. */
14680 static int mmreg2 (int r)
14682 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14684 return map[r];
14687 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14688 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14689 #define uMIPS_RS2(op) uMIPS_RS(op)
14690 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14691 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14692 #define uMIPS_RS5(op) (op & 0x1f)
14694 /* Signed immediate */
14695 #define SIMM(op, start, width) \
14696 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14697 << (32-width)) \
14698 >> (32-width))
14699 /* Zero-extended immediate */
14700 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14702 static void gen_addiur1sp(DisasContext *ctx)
14704 int rd = mmreg(uMIPS_RD(ctx->opcode));
14706 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14709 static void gen_addiur2(DisasContext *ctx)
14711 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14712 int rd = mmreg(uMIPS_RD(ctx->opcode));
14713 int rs = mmreg(uMIPS_RS(ctx->opcode));
14715 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14718 static void gen_addiusp(DisasContext *ctx)
14720 int encoded = ZIMM(ctx->opcode, 1, 9);
14721 int decoded;
14723 if (encoded <= 1) {
14724 decoded = 256 + encoded;
14725 } else if (encoded <= 255) {
14726 decoded = encoded;
14727 } else if (encoded <= 509) {
14728 decoded = encoded - 512;
14729 } else {
14730 decoded = encoded - 768;
14733 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14736 static void gen_addius5(DisasContext *ctx)
14738 int imm = SIMM(ctx->opcode, 1, 4);
14739 int rd = (ctx->opcode >> 5) & 0x1f;
14741 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14744 static void gen_andi16(DisasContext *ctx)
14746 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14747 31, 32, 63, 64, 255, 32768, 65535 };
14748 int rd = mmreg(uMIPS_RD(ctx->opcode));
14749 int rs = mmreg(uMIPS_RS(ctx->opcode));
14750 int encoded = ZIMM(ctx->opcode, 0, 4);
14752 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14755 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14756 int base, int16_t offset)
14758 TCGv t0, t1;
14759 TCGv_i32 t2;
14761 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14762 generate_exception_end(ctx, EXCP_RI);
14763 return;
14766 t0 = tcg_temp_new();
14768 gen_base_offset_addr(ctx, t0, base, offset);
14770 t1 = tcg_const_tl(reglist);
14771 t2 = tcg_const_i32(ctx->mem_idx);
14773 save_cpu_state(ctx, 1);
14774 switch (opc) {
14775 case LWM32:
14776 gen_helper_lwm(cpu_env, t0, t1, t2);
14777 break;
14778 case SWM32:
14779 gen_helper_swm(cpu_env, t0, t1, t2);
14780 break;
14781 #ifdef TARGET_MIPS64
14782 case LDM:
14783 gen_helper_ldm(cpu_env, t0, t1, t2);
14784 break;
14785 case SDM:
14786 gen_helper_sdm(cpu_env, t0, t1, t2);
14787 break;
14788 #endif
14790 tcg_temp_free(t0);
14791 tcg_temp_free(t1);
14792 tcg_temp_free_i32(t2);
14796 static void gen_pool16c_insn(DisasContext *ctx)
14798 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14799 int rs = mmreg(ctx->opcode & 0x7);
14801 switch (((ctx->opcode) >> 4) & 0x3f) {
14802 case NOT16 + 0:
14803 case NOT16 + 1:
14804 case NOT16 + 2:
14805 case NOT16 + 3:
14806 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14807 break;
14808 case XOR16 + 0:
14809 case XOR16 + 1:
14810 case XOR16 + 2:
14811 case XOR16 + 3:
14812 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14813 break;
14814 case AND16 + 0:
14815 case AND16 + 1:
14816 case AND16 + 2:
14817 case AND16 + 3:
14818 gen_logic(ctx, OPC_AND, rd, rd, rs);
14819 break;
14820 case OR16 + 0:
14821 case OR16 + 1:
14822 case OR16 + 2:
14823 case OR16 + 3:
14824 gen_logic(ctx, OPC_OR, rd, rd, rs);
14825 break;
14826 case LWM16 + 0:
14827 case LWM16 + 1:
14828 case LWM16 + 2:
14829 case LWM16 + 3:
14831 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14832 int offset = ZIMM(ctx->opcode, 0, 4);
14834 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14835 29, offset << 2);
14837 break;
14838 case SWM16 + 0:
14839 case SWM16 + 1:
14840 case SWM16 + 2:
14841 case SWM16 + 3:
14843 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14844 int offset = ZIMM(ctx->opcode, 0, 4);
14846 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14847 29, offset << 2);
14849 break;
14850 case JR16 + 0:
14851 case JR16 + 1:
14853 int reg = ctx->opcode & 0x1f;
14855 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14857 break;
14858 case JRC16 + 0:
14859 case JRC16 + 1:
14861 int reg = ctx->opcode & 0x1f;
14862 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14863 /* Let normal delay slot handling in our caller take us
14864 to the branch target. */
14866 break;
14867 case JALR16 + 0:
14868 case JALR16 + 1:
14869 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14870 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14871 break;
14872 case JALR16S + 0:
14873 case JALR16S + 1:
14874 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14875 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14876 break;
14877 case MFHI16 + 0:
14878 case MFHI16 + 1:
14879 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14880 break;
14881 case MFLO16 + 0:
14882 case MFLO16 + 1:
14883 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14884 break;
14885 case BREAK16:
14886 generate_exception_end(ctx, EXCP_BREAK);
14887 break;
14888 case SDBBP16:
14889 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14890 gen_helper_do_semihosting(cpu_env);
14891 } else {
14892 /* XXX: not clear which exception should be raised
14893 * when in debug mode...
14895 check_insn(ctx, ISA_MIPS32);
14896 generate_exception_end(ctx, EXCP_DBp);
14898 break;
14899 case JRADDIUSP + 0:
14900 case JRADDIUSP + 1:
14902 int imm = ZIMM(ctx->opcode, 0, 5);
14903 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14904 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14905 /* Let normal delay slot handling in our caller take us
14906 to the branch target. */
14908 break;
14909 default:
14910 generate_exception_end(ctx, EXCP_RI);
14911 break;
14915 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14916 int enc_rs)
14918 int rd, rs, re, rt;
14919 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14920 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14921 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14922 rd = rd_enc[enc_dest];
14923 re = re_enc[enc_dest];
14924 rs = rs_rt_enc[enc_rs];
14925 rt = rs_rt_enc[enc_rt];
14926 if (rs) {
14927 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14928 } else {
14929 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14931 if (rt) {
14932 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14933 } else {
14934 tcg_gen_movi_tl(cpu_gpr[re], 0);
14938 static void gen_pool16c_r6_insn(DisasContext *ctx)
14940 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14941 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14943 switch (ctx->opcode & 0xf) {
14944 case R6_NOT16:
14945 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14946 break;
14947 case R6_AND16:
14948 gen_logic(ctx, OPC_AND, rt, rt, rs);
14949 break;
14950 case R6_LWM16:
14952 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14953 int offset = extract32(ctx->opcode, 4, 4);
14954 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14956 break;
14957 case R6_JRC16: /* JRCADDIUSP */
14958 if ((ctx->opcode >> 4) & 1) {
14959 /* JRCADDIUSP */
14960 int imm = extract32(ctx->opcode, 5, 5);
14961 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14962 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14963 } else {
14964 /* JRC16 */
14965 rs = extract32(ctx->opcode, 5, 5);
14966 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14968 break;
14969 case MOVEP:
14970 case MOVEP_05:
14971 case MOVEP_06:
14972 case MOVEP_07:
14973 case MOVEP_0C:
14974 case MOVEP_0D:
14975 case MOVEP_0E:
14976 case MOVEP_0F:
14978 int enc_dest = uMIPS_RD(ctx->opcode);
14979 int enc_rt = uMIPS_RS2(ctx->opcode);
14980 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14981 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14983 break;
14984 case R6_XOR16:
14985 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14986 break;
14987 case R6_OR16:
14988 gen_logic(ctx, OPC_OR, rt, rt, rs);
14989 break;
14990 case R6_SWM16:
14992 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14993 int offset = extract32(ctx->opcode, 4, 4);
14994 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14996 break;
14997 case JALRC16: /* BREAK16, SDBBP16 */
14998 switch (ctx->opcode & 0x3f) {
14999 case JALRC16:
15000 case JALRC16 + 0x20:
15001 /* JALRC16 */
15002 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15003 31, 0, 0);
15004 break;
15005 case R6_BREAK16:
15006 /* BREAK16 */
15007 generate_exception(ctx, EXCP_BREAK);
15008 break;
15009 case R6_SDBBP16:
15010 /* SDBBP16 */
15011 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15012 gen_helper_do_semihosting(cpu_env);
15013 } else {
15014 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15015 generate_exception(ctx, EXCP_RI);
15016 } else {
15017 generate_exception(ctx, EXCP_DBp);
15020 break;
15022 break;
15023 default:
15024 generate_exception(ctx, EXCP_RI);
15025 break;
15029 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
15031 TCGv t0 = tcg_temp_new();
15032 TCGv t1 = tcg_temp_new();
15034 gen_load_gpr(t0, base);
15036 if (index != 0) {
15037 gen_load_gpr(t1, index);
15038 tcg_gen_shli_tl(t1, t1, 2);
15039 gen_op_addr_add(ctx, t0, t1, t0);
15042 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15043 gen_store_gpr(t1, rd);
15045 tcg_temp_free(t0);
15046 tcg_temp_free(t1);
15049 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
15050 int base, int16_t offset)
15052 TCGv t0, t1;
15054 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15055 generate_exception_end(ctx, EXCP_RI);
15056 return;
15059 t0 = tcg_temp_new();
15060 t1 = tcg_temp_new();
15062 gen_base_offset_addr(ctx, t0, base, offset);
15064 switch (opc) {
15065 case LWP:
15066 if (rd == base) {
15067 generate_exception_end(ctx, EXCP_RI);
15068 return;
15070 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15071 gen_store_gpr(t1, rd);
15072 tcg_gen_movi_tl(t1, 4);
15073 gen_op_addr_add(ctx, t0, t0, t1);
15074 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15075 gen_store_gpr(t1, rd+1);
15076 break;
15077 case SWP:
15078 gen_load_gpr(t1, rd);
15079 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15080 tcg_gen_movi_tl(t1, 4);
15081 gen_op_addr_add(ctx, t0, t0, t1);
15082 gen_load_gpr(t1, rd+1);
15083 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15084 break;
15085 #ifdef TARGET_MIPS64
15086 case LDP:
15087 if (rd == base) {
15088 generate_exception_end(ctx, EXCP_RI);
15089 return;
15091 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15092 gen_store_gpr(t1, rd);
15093 tcg_gen_movi_tl(t1, 8);
15094 gen_op_addr_add(ctx, t0, t0, t1);
15095 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15096 gen_store_gpr(t1, rd+1);
15097 break;
15098 case SDP:
15099 gen_load_gpr(t1, rd);
15100 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15101 tcg_gen_movi_tl(t1, 8);
15102 gen_op_addr_add(ctx, t0, t0, t1);
15103 gen_load_gpr(t1, rd+1);
15104 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15105 break;
15106 #endif
15108 tcg_temp_free(t0);
15109 tcg_temp_free(t1);
15112 static void gen_sync(int stype)
15114 TCGBar tcg_mo = TCG_BAR_SC;
15116 switch (stype) {
15117 case 0x4: /* SYNC_WMB */
15118 tcg_mo |= TCG_MO_ST_ST;
15119 break;
15120 case 0x10: /* SYNC_MB */
15121 tcg_mo |= TCG_MO_ALL;
15122 break;
15123 case 0x11: /* SYNC_ACQUIRE */
15124 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15125 break;
15126 case 0x12: /* SYNC_RELEASE */
15127 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15128 break;
15129 case 0x13: /* SYNC_RMB */
15130 tcg_mo |= TCG_MO_LD_LD;
15131 break;
15132 default:
15133 tcg_mo |= TCG_MO_ALL;
15134 break;
15137 tcg_gen_mb(tcg_mo);
15140 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15142 int extension = (ctx->opcode >> 6) & 0x3f;
15143 int minor = (ctx->opcode >> 12) & 0xf;
15144 uint32_t mips32_op;
15146 switch (extension) {
15147 case TEQ:
15148 mips32_op = OPC_TEQ;
15149 goto do_trap;
15150 case TGE:
15151 mips32_op = OPC_TGE;
15152 goto do_trap;
15153 case TGEU:
15154 mips32_op = OPC_TGEU;
15155 goto do_trap;
15156 case TLT:
15157 mips32_op = OPC_TLT;
15158 goto do_trap;
15159 case TLTU:
15160 mips32_op = OPC_TLTU;
15161 goto do_trap;
15162 case TNE:
15163 mips32_op = OPC_TNE;
15164 do_trap:
15165 gen_trap(ctx, mips32_op, rs, rt, -1);
15166 break;
15167 #ifndef CONFIG_USER_ONLY
15168 case MFC0:
15169 case MFC0 + 32:
15170 check_cp0_enabled(ctx);
15171 if (rt == 0) {
15172 /* Treat as NOP. */
15173 break;
15175 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15176 break;
15177 case MTC0:
15178 case MTC0 + 32:
15179 check_cp0_enabled(ctx);
15181 TCGv t0 = tcg_temp_new();
15183 gen_load_gpr(t0, rt);
15184 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15185 tcg_temp_free(t0);
15187 break;
15188 #endif
15189 case 0x2a:
15190 switch (minor & 3) {
15191 case MADD_ACC:
15192 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15193 break;
15194 case MADDU_ACC:
15195 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15196 break;
15197 case MSUB_ACC:
15198 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15199 break;
15200 case MSUBU_ACC:
15201 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15202 break;
15203 default:
15204 goto pool32axf_invalid;
15206 break;
15207 case 0x32:
15208 switch (minor & 3) {
15209 case MULT_ACC:
15210 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15211 break;
15212 case MULTU_ACC:
15213 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15214 break;
15215 default:
15216 goto pool32axf_invalid;
15218 break;
15219 case 0x2c:
15220 switch (minor) {
15221 case BITSWAP:
15222 check_insn(ctx, ISA_MIPS32R6);
15223 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15224 break;
15225 case SEB:
15226 gen_bshfl(ctx, OPC_SEB, rs, rt);
15227 break;
15228 case SEH:
15229 gen_bshfl(ctx, OPC_SEH, rs, rt);
15230 break;
15231 case CLO:
15232 mips32_op = OPC_CLO;
15233 goto do_cl;
15234 case CLZ:
15235 mips32_op = OPC_CLZ;
15236 do_cl:
15237 check_insn(ctx, ISA_MIPS32);
15238 gen_cl(ctx, mips32_op, rt, rs);
15239 break;
15240 case RDHWR:
15241 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15242 gen_rdhwr(ctx, rt, rs, 0);
15243 break;
15244 case WSBH:
15245 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15246 break;
15247 case MULT:
15248 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15249 mips32_op = OPC_MULT;
15250 goto do_mul;
15251 case MULTU:
15252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15253 mips32_op = OPC_MULTU;
15254 goto do_mul;
15255 case DIV:
15256 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15257 mips32_op = OPC_DIV;
15258 goto do_div;
15259 case DIVU:
15260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15261 mips32_op = OPC_DIVU;
15262 goto do_div;
15263 do_div:
15264 check_insn(ctx, ISA_MIPS32);
15265 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15266 break;
15267 case MADD:
15268 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15269 mips32_op = OPC_MADD;
15270 goto do_mul;
15271 case MADDU:
15272 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15273 mips32_op = OPC_MADDU;
15274 goto do_mul;
15275 case MSUB:
15276 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15277 mips32_op = OPC_MSUB;
15278 goto do_mul;
15279 case MSUBU:
15280 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15281 mips32_op = OPC_MSUBU;
15282 do_mul:
15283 check_insn(ctx, ISA_MIPS32);
15284 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15285 break;
15286 default:
15287 goto pool32axf_invalid;
15289 break;
15290 case 0x34:
15291 switch (minor) {
15292 case MFC2:
15293 case MTC2:
15294 case MFHC2:
15295 case MTHC2:
15296 case CFC2:
15297 case CTC2:
15298 generate_exception_err(ctx, EXCP_CpU, 2);
15299 break;
15300 default:
15301 goto pool32axf_invalid;
15303 break;
15304 case 0x3c:
15305 switch (minor) {
15306 case JALR: /* JALRC */
15307 case JALR_HB: /* JALRC_HB */
15308 if (ctx->insn_flags & ISA_MIPS32R6) {
15309 /* JALRC, JALRC_HB */
15310 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15311 } else {
15312 /* JALR, JALR_HB */
15313 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15314 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15316 break;
15317 case JALRS:
15318 case JALRS_HB:
15319 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15320 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15321 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15322 break;
15323 default:
15324 goto pool32axf_invalid;
15326 break;
15327 case 0x05:
15328 switch (minor) {
15329 case RDPGPR:
15330 check_cp0_enabled(ctx);
15331 check_insn(ctx, ISA_MIPS32R2);
15332 gen_load_srsgpr(rs, rt);
15333 break;
15334 case WRPGPR:
15335 check_cp0_enabled(ctx);
15336 check_insn(ctx, ISA_MIPS32R2);
15337 gen_store_srsgpr(rs, rt);
15338 break;
15339 default:
15340 goto pool32axf_invalid;
15342 break;
15343 #ifndef CONFIG_USER_ONLY
15344 case 0x0d:
15345 switch (minor) {
15346 case TLBP:
15347 mips32_op = OPC_TLBP;
15348 goto do_cp0;
15349 case TLBR:
15350 mips32_op = OPC_TLBR;
15351 goto do_cp0;
15352 case TLBWI:
15353 mips32_op = OPC_TLBWI;
15354 goto do_cp0;
15355 case TLBWR:
15356 mips32_op = OPC_TLBWR;
15357 goto do_cp0;
15358 case TLBINV:
15359 mips32_op = OPC_TLBINV;
15360 goto do_cp0;
15361 case TLBINVF:
15362 mips32_op = OPC_TLBINVF;
15363 goto do_cp0;
15364 case WAIT:
15365 mips32_op = OPC_WAIT;
15366 goto do_cp0;
15367 case DERET:
15368 mips32_op = OPC_DERET;
15369 goto do_cp0;
15370 case ERET:
15371 mips32_op = OPC_ERET;
15372 do_cp0:
15373 gen_cp0(env, ctx, mips32_op, rt, rs);
15374 break;
15375 default:
15376 goto pool32axf_invalid;
15378 break;
15379 case 0x1d:
15380 switch (minor) {
15381 case DI:
15382 check_cp0_enabled(ctx);
15384 TCGv t0 = tcg_temp_new();
15386 save_cpu_state(ctx, 1);
15387 gen_helper_di(t0, cpu_env);
15388 gen_store_gpr(t0, rs);
15389 /* Stop translation as we may have switched the execution mode */
15390 ctx->base.is_jmp = DISAS_STOP;
15391 tcg_temp_free(t0);
15393 break;
15394 case EI:
15395 check_cp0_enabled(ctx);
15397 TCGv t0 = tcg_temp_new();
15399 save_cpu_state(ctx, 1);
15400 gen_helper_ei(t0, cpu_env);
15401 gen_store_gpr(t0, rs);
15402 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15403 of translated code to check for pending interrupts. */
15404 gen_save_pc(ctx->base.pc_next + 4);
15405 ctx->base.is_jmp = DISAS_EXIT;
15406 tcg_temp_free(t0);
15408 break;
15409 default:
15410 goto pool32axf_invalid;
15412 break;
15413 #endif
15414 case 0x2d:
15415 switch (minor) {
15416 case SYNC:
15417 gen_sync(extract32(ctx->opcode, 16, 5));
15418 break;
15419 case SYSCALL:
15420 generate_exception_end(ctx, EXCP_SYSCALL);
15421 break;
15422 case SDBBP:
15423 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15424 gen_helper_do_semihosting(cpu_env);
15425 } else {
15426 check_insn(ctx, ISA_MIPS32);
15427 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15428 generate_exception_end(ctx, EXCP_RI);
15429 } else {
15430 generate_exception_end(ctx, EXCP_DBp);
15433 break;
15434 default:
15435 goto pool32axf_invalid;
15437 break;
15438 case 0x01:
15439 switch (minor & 3) {
15440 case MFHI_ACC:
15441 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15442 break;
15443 case MFLO_ACC:
15444 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15445 break;
15446 case MTHI_ACC:
15447 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15448 break;
15449 case MTLO_ACC:
15450 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15451 break;
15452 default:
15453 goto pool32axf_invalid;
15455 break;
15456 case 0x35:
15457 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15458 switch (minor) {
15459 case MFHI32:
15460 gen_HILO(ctx, OPC_MFHI, 0, rs);
15461 break;
15462 case MFLO32:
15463 gen_HILO(ctx, OPC_MFLO, 0, rs);
15464 break;
15465 case MTHI32:
15466 gen_HILO(ctx, OPC_MTHI, 0, rs);
15467 break;
15468 case MTLO32:
15469 gen_HILO(ctx, OPC_MTLO, 0, rs);
15470 break;
15471 default:
15472 goto pool32axf_invalid;
15474 break;
15475 default:
15476 pool32axf_invalid:
15477 MIPS_INVAL("pool32axf");
15478 generate_exception_end(ctx, EXCP_RI);
15479 break;
15483 /* Values for microMIPS fmt field. Variable-width, depending on which
15484 formats the instruction supports. */
15486 enum {
15487 FMT_SD_S = 0,
15488 FMT_SD_D = 1,
15490 FMT_SDPS_S = 0,
15491 FMT_SDPS_D = 1,
15492 FMT_SDPS_PS = 2,
15494 FMT_SWL_S = 0,
15495 FMT_SWL_W = 1,
15496 FMT_SWL_L = 2,
15498 FMT_DWL_D = 0,
15499 FMT_DWL_W = 1,
15500 FMT_DWL_L = 2
15503 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15505 int extension = (ctx->opcode >> 6) & 0x3ff;
15506 uint32_t mips32_op;
15508 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15509 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15510 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15512 switch (extension) {
15513 case FLOAT_1BIT_FMT(CFC1, 0):
15514 mips32_op = OPC_CFC1;
15515 goto do_cp1;
15516 case FLOAT_1BIT_FMT(CTC1, 0):
15517 mips32_op = OPC_CTC1;
15518 goto do_cp1;
15519 case FLOAT_1BIT_FMT(MFC1, 0):
15520 mips32_op = OPC_MFC1;
15521 goto do_cp1;
15522 case FLOAT_1BIT_FMT(MTC1, 0):
15523 mips32_op = OPC_MTC1;
15524 goto do_cp1;
15525 case FLOAT_1BIT_FMT(MFHC1, 0):
15526 mips32_op = OPC_MFHC1;
15527 goto do_cp1;
15528 case FLOAT_1BIT_FMT(MTHC1, 0):
15529 mips32_op = OPC_MTHC1;
15530 do_cp1:
15531 gen_cp1(ctx, mips32_op, rt, rs);
15532 break;
15534 /* Reciprocal square root */
15535 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15536 mips32_op = OPC_RSQRT_S;
15537 goto do_unaryfp;
15538 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15539 mips32_op = OPC_RSQRT_D;
15540 goto do_unaryfp;
15542 /* Square root */
15543 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15544 mips32_op = OPC_SQRT_S;
15545 goto do_unaryfp;
15546 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15547 mips32_op = OPC_SQRT_D;
15548 goto do_unaryfp;
15550 /* Reciprocal */
15551 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15552 mips32_op = OPC_RECIP_S;
15553 goto do_unaryfp;
15554 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15555 mips32_op = OPC_RECIP_D;
15556 goto do_unaryfp;
15558 /* Floor */
15559 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15560 mips32_op = OPC_FLOOR_L_S;
15561 goto do_unaryfp;
15562 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15563 mips32_op = OPC_FLOOR_L_D;
15564 goto do_unaryfp;
15565 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15566 mips32_op = OPC_FLOOR_W_S;
15567 goto do_unaryfp;
15568 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15569 mips32_op = OPC_FLOOR_W_D;
15570 goto do_unaryfp;
15572 /* Ceiling */
15573 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15574 mips32_op = OPC_CEIL_L_S;
15575 goto do_unaryfp;
15576 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15577 mips32_op = OPC_CEIL_L_D;
15578 goto do_unaryfp;
15579 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15580 mips32_op = OPC_CEIL_W_S;
15581 goto do_unaryfp;
15582 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15583 mips32_op = OPC_CEIL_W_D;
15584 goto do_unaryfp;
15586 /* Truncation */
15587 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15588 mips32_op = OPC_TRUNC_L_S;
15589 goto do_unaryfp;
15590 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15591 mips32_op = OPC_TRUNC_L_D;
15592 goto do_unaryfp;
15593 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15594 mips32_op = OPC_TRUNC_W_S;
15595 goto do_unaryfp;
15596 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15597 mips32_op = OPC_TRUNC_W_D;
15598 goto do_unaryfp;
15600 /* Round */
15601 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15602 mips32_op = OPC_ROUND_L_S;
15603 goto do_unaryfp;
15604 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15605 mips32_op = OPC_ROUND_L_D;
15606 goto do_unaryfp;
15607 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15608 mips32_op = OPC_ROUND_W_S;
15609 goto do_unaryfp;
15610 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15611 mips32_op = OPC_ROUND_W_D;
15612 goto do_unaryfp;
15614 /* Integer to floating-point conversion */
15615 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15616 mips32_op = OPC_CVT_L_S;
15617 goto do_unaryfp;
15618 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15619 mips32_op = OPC_CVT_L_D;
15620 goto do_unaryfp;
15621 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15622 mips32_op = OPC_CVT_W_S;
15623 goto do_unaryfp;
15624 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15625 mips32_op = OPC_CVT_W_D;
15626 goto do_unaryfp;
15628 /* Paired-foo conversions */
15629 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15630 mips32_op = OPC_CVT_S_PL;
15631 goto do_unaryfp;
15632 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15633 mips32_op = OPC_CVT_S_PU;
15634 goto do_unaryfp;
15635 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15636 mips32_op = OPC_CVT_PW_PS;
15637 goto do_unaryfp;
15638 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15639 mips32_op = OPC_CVT_PS_PW;
15640 goto do_unaryfp;
15642 /* Floating-point moves */
15643 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15644 mips32_op = OPC_MOV_S;
15645 goto do_unaryfp;
15646 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15647 mips32_op = OPC_MOV_D;
15648 goto do_unaryfp;
15649 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15650 mips32_op = OPC_MOV_PS;
15651 goto do_unaryfp;
15653 /* Absolute value */
15654 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15655 mips32_op = OPC_ABS_S;
15656 goto do_unaryfp;
15657 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15658 mips32_op = OPC_ABS_D;
15659 goto do_unaryfp;
15660 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15661 mips32_op = OPC_ABS_PS;
15662 goto do_unaryfp;
15664 /* Negation */
15665 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15666 mips32_op = OPC_NEG_S;
15667 goto do_unaryfp;
15668 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15669 mips32_op = OPC_NEG_D;
15670 goto do_unaryfp;
15671 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15672 mips32_op = OPC_NEG_PS;
15673 goto do_unaryfp;
15675 /* Reciprocal square root step */
15676 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15677 mips32_op = OPC_RSQRT1_S;
15678 goto do_unaryfp;
15679 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15680 mips32_op = OPC_RSQRT1_D;
15681 goto do_unaryfp;
15682 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15683 mips32_op = OPC_RSQRT1_PS;
15684 goto do_unaryfp;
15686 /* Reciprocal step */
15687 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15688 mips32_op = OPC_RECIP1_S;
15689 goto do_unaryfp;
15690 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15691 mips32_op = OPC_RECIP1_S;
15692 goto do_unaryfp;
15693 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15694 mips32_op = OPC_RECIP1_PS;
15695 goto do_unaryfp;
15697 /* Conversions from double */
15698 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15699 mips32_op = OPC_CVT_D_S;
15700 goto do_unaryfp;
15701 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15702 mips32_op = OPC_CVT_D_W;
15703 goto do_unaryfp;
15704 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15705 mips32_op = OPC_CVT_D_L;
15706 goto do_unaryfp;
15708 /* Conversions from single */
15709 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15710 mips32_op = OPC_CVT_S_D;
15711 goto do_unaryfp;
15712 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15713 mips32_op = OPC_CVT_S_W;
15714 goto do_unaryfp;
15715 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15716 mips32_op = OPC_CVT_S_L;
15717 do_unaryfp:
15718 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15719 break;
15721 /* Conditional moves on floating-point codes */
15722 case COND_FLOAT_MOV(MOVT, 0):
15723 case COND_FLOAT_MOV(MOVT, 1):
15724 case COND_FLOAT_MOV(MOVT, 2):
15725 case COND_FLOAT_MOV(MOVT, 3):
15726 case COND_FLOAT_MOV(MOVT, 4):
15727 case COND_FLOAT_MOV(MOVT, 5):
15728 case COND_FLOAT_MOV(MOVT, 6):
15729 case COND_FLOAT_MOV(MOVT, 7):
15730 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15731 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15732 break;
15733 case COND_FLOAT_MOV(MOVF, 0):
15734 case COND_FLOAT_MOV(MOVF, 1):
15735 case COND_FLOAT_MOV(MOVF, 2):
15736 case COND_FLOAT_MOV(MOVF, 3):
15737 case COND_FLOAT_MOV(MOVF, 4):
15738 case COND_FLOAT_MOV(MOVF, 5):
15739 case COND_FLOAT_MOV(MOVF, 6):
15740 case COND_FLOAT_MOV(MOVF, 7):
15741 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15742 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15743 break;
15744 default:
15745 MIPS_INVAL("pool32fxf");
15746 generate_exception_end(ctx, EXCP_RI);
15747 break;
15751 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15753 int32_t offset;
15754 uint16_t insn;
15755 int rt, rs, rd, rr;
15756 int16_t imm;
15757 uint32_t op, minor, minor2, mips32_op;
15758 uint32_t cond, fmt, cc;
15760 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15761 ctx->opcode = (ctx->opcode << 16) | insn;
15763 rt = (ctx->opcode >> 21) & 0x1f;
15764 rs = (ctx->opcode >> 16) & 0x1f;
15765 rd = (ctx->opcode >> 11) & 0x1f;
15766 rr = (ctx->opcode >> 6) & 0x1f;
15767 imm = (int16_t) ctx->opcode;
15769 op = (ctx->opcode >> 26) & 0x3f;
15770 switch (op) {
15771 case POOL32A:
15772 minor = ctx->opcode & 0x3f;
15773 switch (minor) {
15774 case 0x00:
15775 minor = (ctx->opcode >> 6) & 0xf;
15776 switch (minor) {
15777 case SLL32:
15778 mips32_op = OPC_SLL;
15779 goto do_shifti;
15780 case SRA:
15781 mips32_op = OPC_SRA;
15782 goto do_shifti;
15783 case SRL32:
15784 mips32_op = OPC_SRL;
15785 goto do_shifti;
15786 case ROTR:
15787 mips32_op = OPC_ROTR;
15788 do_shifti:
15789 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15790 break;
15791 case SELEQZ:
15792 check_insn(ctx, ISA_MIPS32R6);
15793 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15794 break;
15795 case SELNEZ:
15796 check_insn(ctx, ISA_MIPS32R6);
15797 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15798 break;
15799 case R6_RDHWR:
15800 check_insn(ctx, ISA_MIPS32R6);
15801 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15802 break;
15803 default:
15804 goto pool32a_invalid;
15806 break;
15807 case 0x10:
15808 minor = (ctx->opcode >> 6) & 0xf;
15809 switch (minor) {
15810 /* Arithmetic */
15811 case ADD:
15812 mips32_op = OPC_ADD;
15813 goto do_arith;
15814 case ADDU32:
15815 mips32_op = OPC_ADDU;
15816 goto do_arith;
15817 case SUB:
15818 mips32_op = OPC_SUB;
15819 goto do_arith;
15820 case SUBU32:
15821 mips32_op = OPC_SUBU;
15822 goto do_arith;
15823 case MUL:
15824 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15825 mips32_op = OPC_MUL;
15826 do_arith:
15827 gen_arith(ctx, mips32_op, rd, rs, rt);
15828 break;
15829 /* Shifts */
15830 case SLLV:
15831 mips32_op = OPC_SLLV;
15832 goto do_shift;
15833 case SRLV:
15834 mips32_op = OPC_SRLV;
15835 goto do_shift;
15836 case SRAV:
15837 mips32_op = OPC_SRAV;
15838 goto do_shift;
15839 case ROTRV:
15840 mips32_op = OPC_ROTRV;
15841 do_shift:
15842 gen_shift(ctx, mips32_op, rd, rs, rt);
15843 break;
15844 /* Logical operations */
15845 case AND:
15846 mips32_op = OPC_AND;
15847 goto do_logic;
15848 case OR32:
15849 mips32_op = OPC_OR;
15850 goto do_logic;
15851 case NOR:
15852 mips32_op = OPC_NOR;
15853 goto do_logic;
15854 case XOR32:
15855 mips32_op = OPC_XOR;
15856 do_logic:
15857 gen_logic(ctx, mips32_op, rd, rs, rt);
15858 break;
15859 /* Set less than */
15860 case SLT:
15861 mips32_op = OPC_SLT;
15862 goto do_slt;
15863 case SLTU:
15864 mips32_op = OPC_SLTU;
15865 do_slt:
15866 gen_slt(ctx, mips32_op, rd, rs, rt);
15867 break;
15868 default:
15869 goto pool32a_invalid;
15871 break;
15872 case 0x18:
15873 minor = (ctx->opcode >> 6) & 0xf;
15874 switch (minor) {
15875 /* Conditional moves */
15876 case MOVN: /* MUL */
15877 if (ctx->insn_flags & ISA_MIPS32R6) {
15878 /* MUL */
15879 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15880 } else {
15881 /* MOVN */
15882 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15884 break;
15885 case MOVZ: /* MUH */
15886 if (ctx->insn_flags & ISA_MIPS32R6) {
15887 /* MUH */
15888 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15889 } else {
15890 /* MOVZ */
15891 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15893 break;
15894 case MULU:
15895 check_insn(ctx, ISA_MIPS32R6);
15896 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15897 break;
15898 case MUHU:
15899 check_insn(ctx, ISA_MIPS32R6);
15900 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15901 break;
15902 case LWXS: /* DIV */
15903 if (ctx->insn_flags & ISA_MIPS32R6) {
15904 /* DIV */
15905 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15906 } else {
15907 /* LWXS */
15908 gen_ldxs(ctx, rs, rt, rd);
15910 break;
15911 case MOD:
15912 check_insn(ctx, ISA_MIPS32R6);
15913 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15914 break;
15915 case R6_DIVU:
15916 check_insn(ctx, ISA_MIPS32R6);
15917 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15918 break;
15919 case MODU:
15920 check_insn(ctx, ISA_MIPS32R6);
15921 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15922 break;
15923 default:
15924 goto pool32a_invalid;
15926 break;
15927 case INS:
15928 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15929 return;
15930 case LSA:
15931 check_insn(ctx, ISA_MIPS32R6);
15932 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15933 extract32(ctx->opcode, 9, 2));
15934 break;
15935 case ALIGN:
15936 check_insn(ctx, ISA_MIPS32R6);
15937 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15938 break;
15939 case EXT:
15940 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15941 return;
15942 case POOL32AXF:
15943 gen_pool32axf(env, ctx, rt, rs);
15944 break;
15945 case BREAK32:
15946 generate_exception_end(ctx, EXCP_BREAK);
15947 break;
15948 case SIGRIE:
15949 check_insn(ctx, ISA_MIPS32R6);
15950 generate_exception_end(ctx, EXCP_RI);
15951 break;
15952 default:
15953 pool32a_invalid:
15954 MIPS_INVAL("pool32a");
15955 generate_exception_end(ctx, EXCP_RI);
15956 break;
15958 break;
15959 case POOL32B:
15960 minor = (ctx->opcode >> 12) & 0xf;
15961 switch (minor) {
15962 case CACHE:
15963 check_cp0_enabled(ctx);
15964 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15965 gen_cache_operation(ctx, rt, rs, imm);
15967 break;
15968 case LWC2:
15969 case SWC2:
15970 /* COP2: Not implemented. */
15971 generate_exception_err(ctx, EXCP_CpU, 2);
15972 break;
15973 #ifdef TARGET_MIPS64
15974 case LDP:
15975 case SDP:
15976 check_insn(ctx, ISA_MIPS3);
15977 check_mips_64(ctx);
15978 #endif
15979 /* fall through */
15980 case LWP:
15981 case SWP:
15982 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15983 break;
15984 #ifdef TARGET_MIPS64
15985 case LDM:
15986 case SDM:
15987 check_insn(ctx, ISA_MIPS3);
15988 check_mips_64(ctx);
15989 #endif
15990 /* fall through */
15991 case LWM32:
15992 case SWM32:
15993 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15994 break;
15995 default:
15996 MIPS_INVAL("pool32b");
15997 generate_exception_end(ctx, EXCP_RI);
15998 break;
16000 break;
16001 case POOL32F:
16002 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16003 minor = ctx->opcode & 0x3f;
16004 check_cp1_enabled(ctx);
16005 switch (minor) {
16006 case ALNV_PS:
16007 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16008 mips32_op = OPC_ALNV_PS;
16009 goto do_madd;
16010 case MADD_S:
16011 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16012 mips32_op = OPC_MADD_S;
16013 goto do_madd;
16014 case MADD_D:
16015 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16016 mips32_op = OPC_MADD_D;
16017 goto do_madd;
16018 case MADD_PS:
16019 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16020 mips32_op = OPC_MADD_PS;
16021 goto do_madd;
16022 case MSUB_S:
16023 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16024 mips32_op = OPC_MSUB_S;
16025 goto do_madd;
16026 case MSUB_D:
16027 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16028 mips32_op = OPC_MSUB_D;
16029 goto do_madd;
16030 case MSUB_PS:
16031 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16032 mips32_op = OPC_MSUB_PS;
16033 goto do_madd;
16034 case NMADD_S:
16035 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16036 mips32_op = OPC_NMADD_S;
16037 goto do_madd;
16038 case NMADD_D:
16039 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16040 mips32_op = OPC_NMADD_D;
16041 goto do_madd;
16042 case NMADD_PS:
16043 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16044 mips32_op = OPC_NMADD_PS;
16045 goto do_madd;
16046 case NMSUB_S:
16047 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16048 mips32_op = OPC_NMSUB_S;
16049 goto do_madd;
16050 case NMSUB_D:
16051 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16052 mips32_op = OPC_NMSUB_D;
16053 goto do_madd;
16054 case NMSUB_PS:
16055 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16056 mips32_op = OPC_NMSUB_PS;
16057 do_madd:
16058 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16059 break;
16060 case CABS_COND_FMT:
16061 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16062 cond = (ctx->opcode >> 6) & 0xf;
16063 cc = (ctx->opcode >> 13) & 0x7;
16064 fmt = (ctx->opcode >> 10) & 0x3;
16065 switch (fmt) {
16066 case 0x0:
16067 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16068 break;
16069 case 0x1:
16070 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16071 break;
16072 case 0x2:
16073 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16074 break;
16075 default:
16076 goto pool32f_invalid;
16078 break;
16079 case C_COND_FMT:
16080 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16081 cond = (ctx->opcode >> 6) & 0xf;
16082 cc = (ctx->opcode >> 13) & 0x7;
16083 fmt = (ctx->opcode >> 10) & 0x3;
16084 switch (fmt) {
16085 case 0x0:
16086 gen_cmp_s(ctx, cond, rt, rs, cc);
16087 break;
16088 case 0x1:
16089 gen_cmp_d(ctx, cond, rt, rs, cc);
16090 break;
16091 case 0x2:
16092 gen_cmp_ps(ctx, cond, rt, rs, cc);
16093 break;
16094 default:
16095 goto pool32f_invalid;
16097 break;
16098 case CMP_CONDN_S:
16099 check_insn(ctx, ISA_MIPS32R6);
16100 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16101 break;
16102 case CMP_CONDN_D:
16103 check_insn(ctx, ISA_MIPS32R6);
16104 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16105 break;
16106 case POOL32FXF:
16107 gen_pool32fxf(ctx, rt, rs);
16108 break;
16109 case 0x00:
16110 /* PLL foo */
16111 switch ((ctx->opcode >> 6) & 0x7) {
16112 case PLL_PS:
16113 mips32_op = OPC_PLL_PS;
16114 goto do_ps;
16115 case PLU_PS:
16116 mips32_op = OPC_PLU_PS;
16117 goto do_ps;
16118 case PUL_PS:
16119 mips32_op = OPC_PUL_PS;
16120 goto do_ps;
16121 case PUU_PS:
16122 mips32_op = OPC_PUU_PS;
16123 goto do_ps;
16124 case CVT_PS_S:
16125 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16126 mips32_op = OPC_CVT_PS_S;
16127 do_ps:
16128 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16129 break;
16130 default:
16131 goto pool32f_invalid;
16133 break;
16134 case MIN_FMT:
16135 check_insn(ctx, ISA_MIPS32R6);
16136 switch ((ctx->opcode >> 9) & 0x3) {
16137 case FMT_SDPS_S:
16138 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16139 break;
16140 case FMT_SDPS_D:
16141 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16142 break;
16143 default:
16144 goto pool32f_invalid;
16146 break;
16147 case 0x08:
16148 /* [LS][WDU]XC1 */
16149 switch ((ctx->opcode >> 6) & 0x7) {
16150 case LWXC1:
16151 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16152 mips32_op = OPC_LWXC1;
16153 goto do_ldst_cp1;
16154 case SWXC1:
16155 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16156 mips32_op = OPC_SWXC1;
16157 goto do_ldst_cp1;
16158 case LDXC1:
16159 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16160 mips32_op = OPC_LDXC1;
16161 goto do_ldst_cp1;
16162 case SDXC1:
16163 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16164 mips32_op = OPC_SDXC1;
16165 goto do_ldst_cp1;
16166 case LUXC1:
16167 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16168 mips32_op = OPC_LUXC1;
16169 goto do_ldst_cp1;
16170 case SUXC1:
16171 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16172 mips32_op = OPC_SUXC1;
16173 do_ldst_cp1:
16174 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16175 break;
16176 default:
16177 goto pool32f_invalid;
16179 break;
16180 case MAX_FMT:
16181 check_insn(ctx, ISA_MIPS32R6);
16182 switch ((ctx->opcode >> 9) & 0x3) {
16183 case FMT_SDPS_S:
16184 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16185 break;
16186 case FMT_SDPS_D:
16187 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16188 break;
16189 default:
16190 goto pool32f_invalid;
16192 break;
16193 case 0x18:
16194 /* 3D insns */
16195 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16196 fmt = (ctx->opcode >> 9) & 0x3;
16197 switch ((ctx->opcode >> 6) & 0x7) {
16198 case RSQRT2_FMT:
16199 switch (fmt) {
16200 case FMT_SDPS_S:
16201 mips32_op = OPC_RSQRT2_S;
16202 goto do_3d;
16203 case FMT_SDPS_D:
16204 mips32_op = OPC_RSQRT2_D;
16205 goto do_3d;
16206 case FMT_SDPS_PS:
16207 mips32_op = OPC_RSQRT2_PS;
16208 goto do_3d;
16209 default:
16210 goto pool32f_invalid;
16212 break;
16213 case RECIP2_FMT:
16214 switch (fmt) {
16215 case FMT_SDPS_S:
16216 mips32_op = OPC_RECIP2_S;
16217 goto do_3d;
16218 case FMT_SDPS_D:
16219 mips32_op = OPC_RECIP2_D;
16220 goto do_3d;
16221 case FMT_SDPS_PS:
16222 mips32_op = OPC_RECIP2_PS;
16223 goto do_3d;
16224 default:
16225 goto pool32f_invalid;
16227 break;
16228 case ADDR_PS:
16229 mips32_op = OPC_ADDR_PS;
16230 goto do_3d;
16231 case MULR_PS:
16232 mips32_op = OPC_MULR_PS;
16233 do_3d:
16234 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16235 break;
16236 default:
16237 goto pool32f_invalid;
16239 break;
16240 case 0x20:
16241 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16242 cc = (ctx->opcode >> 13) & 0x7;
16243 fmt = (ctx->opcode >> 9) & 0x3;
16244 switch ((ctx->opcode >> 6) & 0x7) {
16245 case MOVF_FMT: /* RINT_FMT */
16246 if (ctx->insn_flags & ISA_MIPS32R6) {
16247 /* RINT_FMT */
16248 switch (fmt) {
16249 case FMT_SDPS_S:
16250 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16251 break;
16252 case FMT_SDPS_D:
16253 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16254 break;
16255 default:
16256 goto pool32f_invalid;
16258 } else {
16259 /* MOVF_FMT */
16260 switch (fmt) {
16261 case FMT_SDPS_S:
16262 gen_movcf_s(ctx, rs, rt, cc, 0);
16263 break;
16264 case FMT_SDPS_D:
16265 gen_movcf_d(ctx, rs, rt, cc, 0);
16266 break;
16267 case FMT_SDPS_PS:
16268 check_ps(ctx);
16269 gen_movcf_ps(ctx, rs, rt, cc, 0);
16270 break;
16271 default:
16272 goto pool32f_invalid;
16275 break;
16276 case MOVT_FMT: /* CLASS_FMT */
16277 if (ctx->insn_flags & ISA_MIPS32R6) {
16278 /* CLASS_FMT */
16279 switch (fmt) {
16280 case FMT_SDPS_S:
16281 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16282 break;
16283 case FMT_SDPS_D:
16284 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16285 break;
16286 default:
16287 goto pool32f_invalid;
16289 } else {
16290 /* MOVT_FMT */
16291 switch (fmt) {
16292 case FMT_SDPS_S:
16293 gen_movcf_s(ctx, rs, rt, cc, 1);
16294 break;
16295 case FMT_SDPS_D:
16296 gen_movcf_d(ctx, rs, rt, cc, 1);
16297 break;
16298 case FMT_SDPS_PS:
16299 check_ps(ctx);
16300 gen_movcf_ps(ctx, rs, rt, cc, 1);
16301 break;
16302 default:
16303 goto pool32f_invalid;
16306 break;
16307 case PREFX:
16308 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16309 break;
16310 default:
16311 goto pool32f_invalid;
16313 break;
16314 #define FINSN_3ARG_SDPS(prfx) \
16315 switch ((ctx->opcode >> 8) & 0x3) { \
16316 case FMT_SDPS_S: \
16317 mips32_op = OPC_##prfx##_S; \
16318 goto do_fpop; \
16319 case FMT_SDPS_D: \
16320 mips32_op = OPC_##prfx##_D; \
16321 goto do_fpop; \
16322 case FMT_SDPS_PS: \
16323 check_ps(ctx); \
16324 mips32_op = OPC_##prfx##_PS; \
16325 goto do_fpop; \
16326 default: \
16327 goto pool32f_invalid; \
16329 case MINA_FMT:
16330 check_insn(ctx, ISA_MIPS32R6);
16331 switch ((ctx->opcode >> 9) & 0x3) {
16332 case FMT_SDPS_S:
16333 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16334 break;
16335 case FMT_SDPS_D:
16336 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16337 break;
16338 default:
16339 goto pool32f_invalid;
16341 break;
16342 case MAXA_FMT:
16343 check_insn(ctx, ISA_MIPS32R6);
16344 switch ((ctx->opcode >> 9) & 0x3) {
16345 case FMT_SDPS_S:
16346 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16347 break;
16348 case FMT_SDPS_D:
16349 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16350 break;
16351 default:
16352 goto pool32f_invalid;
16354 break;
16355 case 0x30:
16356 /* regular FP ops */
16357 switch ((ctx->opcode >> 6) & 0x3) {
16358 case ADD_FMT:
16359 FINSN_3ARG_SDPS(ADD);
16360 break;
16361 case SUB_FMT:
16362 FINSN_3ARG_SDPS(SUB);
16363 break;
16364 case MUL_FMT:
16365 FINSN_3ARG_SDPS(MUL);
16366 break;
16367 case DIV_FMT:
16368 fmt = (ctx->opcode >> 8) & 0x3;
16369 if (fmt == 1) {
16370 mips32_op = OPC_DIV_D;
16371 } else if (fmt == 0) {
16372 mips32_op = OPC_DIV_S;
16373 } else {
16374 goto pool32f_invalid;
16376 goto do_fpop;
16377 default:
16378 goto pool32f_invalid;
16380 break;
16381 case 0x38:
16382 /* cmovs */
16383 switch ((ctx->opcode >> 6) & 0x7) {
16384 case MOVN_FMT: /* SELEQZ_FMT */
16385 if (ctx->insn_flags & ISA_MIPS32R6) {
16386 /* SELEQZ_FMT */
16387 switch ((ctx->opcode >> 9) & 0x3) {
16388 case FMT_SDPS_S:
16389 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16390 break;
16391 case FMT_SDPS_D:
16392 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16393 break;
16394 default:
16395 goto pool32f_invalid;
16397 } else {
16398 /* MOVN_FMT */
16399 FINSN_3ARG_SDPS(MOVN);
16401 break;
16402 case MOVN_FMT_04:
16403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16404 FINSN_3ARG_SDPS(MOVN);
16405 break;
16406 case MOVZ_FMT: /* SELNEZ_FMT */
16407 if (ctx->insn_flags & ISA_MIPS32R6) {
16408 /* SELNEZ_FMT */
16409 switch ((ctx->opcode >> 9) & 0x3) {
16410 case FMT_SDPS_S:
16411 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16412 break;
16413 case FMT_SDPS_D:
16414 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16415 break;
16416 default:
16417 goto pool32f_invalid;
16419 } else {
16420 /* MOVZ_FMT */
16421 FINSN_3ARG_SDPS(MOVZ);
16423 break;
16424 case MOVZ_FMT_05:
16425 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16426 FINSN_3ARG_SDPS(MOVZ);
16427 break;
16428 case SEL_FMT:
16429 check_insn(ctx, ISA_MIPS32R6);
16430 switch ((ctx->opcode >> 9) & 0x3) {
16431 case FMT_SDPS_S:
16432 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16433 break;
16434 case FMT_SDPS_D:
16435 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16436 break;
16437 default:
16438 goto pool32f_invalid;
16440 break;
16441 case MADDF_FMT:
16442 check_insn(ctx, ISA_MIPS32R6);
16443 switch ((ctx->opcode >> 9) & 0x3) {
16444 case FMT_SDPS_S:
16445 mips32_op = OPC_MADDF_S;
16446 goto do_fpop;
16447 case FMT_SDPS_D:
16448 mips32_op = OPC_MADDF_D;
16449 goto do_fpop;
16450 default:
16451 goto pool32f_invalid;
16453 break;
16454 case MSUBF_FMT:
16455 check_insn(ctx, ISA_MIPS32R6);
16456 switch ((ctx->opcode >> 9) & 0x3) {
16457 case FMT_SDPS_S:
16458 mips32_op = OPC_MSUBF_S;
16459 goto do_fpop;
16460 case FMT_SDPS_D:
16461 mips32_op = OPC_MSUBF_D;
16462 goto do_fpop;
16463 default:
16464 goto pool32f_invalid;
16466 break;
16467 default:
16468 goto pool32f_invalid;
16470 break;
16471 do_fpop:
16472 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16473 break;
16474 default:
16475 pool32f_invalid:
16476 MIPS_INVAL("pool32f");
16477 generate_exception_end(ctx, EXCP_RI);
16478 break;
16480 } else {
16481 generate_exception_err(ctx, EXCP_CpU, 1);
16483 break;
16484 case POOL32I:
16485 minor = (ctx->opcode >> 21) & 0x1f;
16486 switch (minor) {
16487 case BLTZ:
16488 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16489 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16490 break;
16491 case BLTZAL:
16492 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16493 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16494 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16495 break;
16496 case BLTZALS:
16497 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16498 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16499 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16500 break;
16501 case BGEZ:
16502 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16503 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16504 break;
16505 case BGEZAL:
16506 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16507 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16508 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16509 break;
16510 case BGEZALS:
16511 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16512 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16513 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16514 break;
16515 case BLEZ:
16516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16517 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16518 break;
16519 case BGTZ:
16520 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16521 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16522 break;
16524 /* Traps */
16525 case TLTI: /* BC1EQZC */
16526 if (ctx->insn_flags & ISA_MIPS32R6) {
16527 /* BC1EQZC */
16528 check_cp1_enabled(ctx);
16529 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16530 } else {
16531 /* TLTI */
16532 mips32_op = OPC_TLTI;
16533 goto do_trapi;
16535 break;
16536 case TGEI: /* BC1NEZC */
16537 if (ctx->insn_flags & ISA_MIPS32R6) {
16538 /* BC1NEZC */
16539 check_cp1_enabled(ctx);
16540 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16541 } else {
16542 /* TGEI */
16543 mips32_op = OPC_TGEI;
16544 goto do_trapi;
16546 break;
16547 case TLTIU:
16548 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16549 mips32_op = OPC_TLTIU;
16550 goto do_trapi;
16551 case TGEIU:
16552 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16553 mips32_op = OPC_TGEIU;
16554 goto do_trapi;
16555 case TNEI: /* SYNCI */
16556 if (ctx->insn_flags & ISA_MIPS32R6) {
16557 /* SYNCI */
16558 /* Break the TB to be able to sync copied instructions
16559 immediately */
16560 ctx->base.is_jmp = DISAS_STOP;
16561 } else {
16562 /* TNEI */
16563 mips32_op = OPC_TNEI;
16564 goto do_trapi;
16566 break;
16567 case TEQI:
16568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16569 mips32_op = OPC_TEQI;
16570 do_trapi:
16571 gen_trap(ctx, mips32_op, rs, -1, imm);
16572 break;
16574 case BNEZC:
16575 case BEQZC:
16576 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16577 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16578 4, rs, 0, imm << 1, 0);
16579 /* Compact branches don't have a delay slot, so just let
16580 the normal delay slot handling take us to the branch
16581 target. */
16582 break;
16583 case LUI:
16584 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16585 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16586 break;
16587 case SYNCI:
16588 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16589 /* Break the TB to be able to sync copied instructions
16590 immediately */
16591 ctx->base.is_jmp = DISAS_STOP;
16592 break;
16593 case BC2F:
16594 case BC2T:
16595 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16596 /* COP2: Not implemented. */
16597 generate_exception_err(ctx, EXCP_CpU, 2);
16598 break;
16599 case BC1F:
16600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16601 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16602 goto do_cp1branch;
16603 case BC1T:
16604 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16605 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16606 goto do_cp1branch;
16607 case BC1ANY4F:
16608 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16609 mips32_op = OPC_BC1FANY4;
16610 goto do_cp1mips3d;
16611 case BC1ANY4T:
16612 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16613 mips32_op = OPC_BC1TANY4;
16614 do_cp1mips3d:
16615 check_cop1x(ctx);
16616 check_insn(ctx, ASE_MIPS3D);
16617 /* Fall through */
16618 do_cp1branch:
16619 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16620 check_cp1_enabled(ctx);
16621 gen_compute_branch1(ctx, mips32_op,
16622 (ctx->opcode >> 18) & 0x7, imm << 1);
16623 } else {
16624 generate_exception_err(ctx, EXCP_CpU, 1);
16626 break;
16627 case BPOSGE64:
16628 case BPOSGE32:
16629 /* MIPS DSP: not implemented */
16630 /* Fall through */
16631 default:
16632 MIPS_INVAL("pool32i");
16633 generate_exception_end(ctx, EXCP_RI);
16634 break;
16636 break;
16637 case POOL32C:
16638 minor = (ctx->opcode >> 12) & 0xf;
16639 offset = sextract32(ctx->opcode, 0,
16640 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16641 switch (minor) {
16642 case LWL:
16643 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16644 mips32_op = OPC_LWL;
16645 goto do_ld_lr;
16646 case SWL:
16647 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16648 mips32_op = OPC_SWL;
16649 goto do_st_lr;
16650 case LWR:
16651 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16652 mips32_op = OPC_LWR;
16653 goto do_ld_lr;
16654 case SWR:
16655 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16656 mips32_op = OPC_SWR;
16657 goto do_st_lr;
16658 #if defined(TARGET_MIPS64)
16659 case LDL:
16660 check_insn(ctx, ISA_MIPS3);
16661 check_mips_64(ctx);
16662 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16663 mips32_op = OPC_LDL;
16664 goto do_ld_lr;
16665 case SDL:
16666 check_insn(ctx, ISA_MIPS3);
16667 check_mips_64(ctx);
16668 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16669 mips32_op = OPC_SDL;
16670 goto do_st_lr;
16671 case LDR:
16672 check_insn(ctx, ISA_MIPS3);
16673 check_mips_64(ctx);
16674 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16675 mips32_op = OPC_LDR;
16676 goto do_ld_lr;
16677 case SDR:
16678 check_insn(ctx, ISA_MIPS3);
16679 check_mips_64(ctx);
16680 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16681 mips32_op = OPC_SDR;
16682 goto do_st_lr;
16683 case LWU:
16684 check_insn(ctx, ISA_MIPS3);
16685 check_mips_64(ctx);
16686 mips32_op = OPC_LWU;
16687 goto do_ld_lr;
16688 case LLD:
16689 check_insn(ctx, ISA_MIPS3);
16690 check_mips_64(ctx);
16691 mips32_op = OPC_LLD;
16692 goto do_ld_lr;
16693 #endif
16694 case LL:
16695 mips32_op = OPC_LL;
16696 goto do_ld_lr;
16697 do_ld_lr:
16698 gen_ld(ctx, mips32_op, rt, rs, offset);
16699 break;
16700 do_st_lr:
16701 gen_st(ctx, mips32_op, rt, rs, offset);
16702 break;
16703 case SC:
16704 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16705 break;
16706 #if defined(TARGET_MIPS64)
16707 case SCD:
16708 check_insn(ctx, ISA_MIPS3);
16709 check_mips_64(ctx);
16710 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16711 break;
16712 #endif
16713 case LD_EVA:
16714 if (!ctx->eva) {
16715 MIPS_INVAL("pool32c ld-eva");
16716 generate_exception_end(ctx, EXCP_RI);
16717 break;
16719 check_cp0_enabled(ctx);
16721 minor2 = (ctx->opcode >> 9) & 0x7;
16722 offset = sextract32(ctx->opcode, 0, 9);
16723 switch (minor2) {
16724 case LBUE:
16725 mips32_op = OPC_LBUE;
16726 goto do_ld_lr;
16727 case LHUE:
16728 mips32_op = OPC_LHUE;
16729 goto do_ld_lr;
16730 case LWLE:
16731 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16732 mips32_op = OPC_LWLE;
16733 goto do_ld_lr;
16734 case LWRE:
16735 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16736 mips32_op = OPC_LWRE;
16737 goto do_ld_lr;
16738 case LBE:
16739 mips32_op = OPC_LBE;
16740 goto do_ld_lr;
16741 case LHE:
16742 mips32_op = OPC_LHE;
16743 goto do_ld_lr;
16744 case LLE:
16745 mips32_op = OPC_LLE;
16746 goto do_ld_lr;
16747 case LWE:
16748 mips32_op = OPC_LWE;
16749 goto do_ld_lr;
16751 break;
16752 case ST_EVA:
16753 if (!ctx->eva) {
16754 MIPS_INVAL("pool32c st-eva");
16755 generate_exception_end(ctx, EXCP_RI);
16756 break;
16758 check_cp0_enabled(ctx);
16760 minor2 = (ctx->opcode >> 9) & 0x7;
16761 offset = sextract32(ctx->opcode, 0, 9);
16762 switch (minor2) {
16763 case SWLE:
16764 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16765 mips32_op = OPC_SWLE;
16766 goto do_st_lr;
16767 case SWRE:
16768 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16769 mips32_op = OPC_SWRE;
16770 goto do_st_lr;
16771 case PREFE:
16772 /* Treat as no-op */
16773 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16774 /* hint codes 24-31 are reserved and signal RI */
16775 generate_exception(ctx, EXCP_RI);
16777 break;
16778 case CACHEE:
16779 /* Treat as no-op */
16780 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16781 gen_cache_operation(ctx, rt, rs, offset);
16783 break;
16784 case SBE:
16785 mips32_op = OPC_SBE;
16786 goto do_st_lr;
16787 case SHE:
16788 mips32_op = OPC_SHE;
16789 goto do_st_lr;
16790 case SCE:
16791 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16792 break;
16793 case SWE:
16794 mips32_op = OPC_SWE;
16795 goto do_st_lr;
16797 break;
16798 case PREF:
16799 /* Treat as no-op */
16800 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16801 /* hint codes 24-31 are reserved and signal RI */
16802 generate_exception(ctx, EXCP_RI);
16804 break;
16805 default:
16806 MIPS_INVAL("pool32c");
16807 generate_exception_end(ctx, EXCP_RI);
16808 break;
16810 break;
16811 case ADDI32: /* AUI, LUI */
16812 if (ctx->insn_flags & ISA_MIPS32R6) {
16813 /* AUI, LUI */
16814 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16815 } else {
16816 /* ADDI32 */
16817 mips32_op = OPC_ADDI;
16818 goto do_addi;
16820 break;
16821 case ADDIU32:
16822 mips32_op = OPC_ADDIU;
16823 do_addi:
16824 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16825 break;
16827 /* Logical operations */
16828 case ORI32:
16829 mips32_op = OPC_ORI;
16830 goto do_logici;
16831 case XORI32:
16832 mips32_op = OPC_XORI;
16833 goto do_logici;
16834 case ANDI32:
16835 mips32_op = OPC_ANDI;
16836 do_logici:
16837 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16838 break;
16840 /* Set less than immediate */
16841 case SLTI32:
16842 mips32_op = OPC_SLTI;
16843 goto do_slti;
16844 case SLTIU32:
16845 mips32_op = OPC_SLTIU;
16846 do_slti:
16847 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16848 break;
16849 case JALX32:
16850 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16851 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16852 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16853 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16854 break;
16855 case JALS32: /* BOVC, BEQC, BEQZALC */
16856 if (ctx->insn_flags & ISA_MIPS32R6) {
16857 if (rs >= rt) {
16858 /* BOVC */
16859 mips32_op = OPC_BOVC;
16860 } else if (rs < rt && rs == 0) {
16861 /* BEQZALC */
16862 mips32_op = OPC_BEQZALC;
16863 } else {
16864 /* BEQC */
16865 mips32_op = OPC_BEQC;
16867 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16868 } else {
16869 /* JALS32 */
16870 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16871 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16872 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16874 break;
16875 case BEQ32: /* BC */
16876 if (ctx->insn_flags & ISA_MIPS32R6) {
16877 /* BC */
16878 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16879 sextract32(ctx->opcode << 1, 0, 27));
16880 } else {
16881 /* BEQ32 */
16882 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16884 break;
16885 case BNE32: /* BALC */
16886 if (ctx->insn_flags & ISA_MIPS32R6) {
16887 /* BALC */
16888 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16889 sextract32(ctx->opcode << 1, 0, 27));
16890 } else {
16891 /* BNE32 */
16892 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16894 break;
16895 case J32: /* BGTZC, BLTZC, BLTC */
16896 if (ctx->insn_flags & ISA_MIPS32R6) {
16897 if (rs == 0 && rt != 0) {
16898 /* BGTZC */
16899 mips32_op = OPC_BGTZC;
16900 } else if (rs != 0 && rt != 0 && rs == rt) {
16901 /* BLTZC */
16902 mips32_op = OPC_BLTZC;
16903 } else {
16904 /* BLTC */
16905 mips32_op = OPC_BLTC;
16907 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16908 } else {
16909 /* J32 */
16910 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16911 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16913 break;
16914 case JAL32: /* BLEZC, BGEZC, BGEC */
16915 if (ctx->insn_flags & ISA_MIPS32R6) {
16916 if (rs == 0 && rt != 0) {
16917 /* BLEZC */
16918 mips32_op = OPC_BLEZC;
16919 } else if (rs != 0 && rt != 0 && rs == rt) {
16920 /* BGEZC */
16921 mips32_op = OPC_BGEZC;
16922 } else {
16923 /* BGEC */
16924 mips32_op = OPC_BGEC;
16926 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16927 } else {
16928 /* JAL32 */
16929 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16930 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16931 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16933 break;
16934 /* Floating point (COP1) */
16935 case LWC132:
16936 mips32_op = OPC_LWC1;
16937 goto do_cop1;
16938 case LDC132:
16939 mips32_op = OPC_LDC1;
16940 goto do_cop1;
16941 case SWC132:
16942 mips32_op = OPC_SWC1;
16943 goto do_cop1;
16944 case SDC132:
16945 mips32_op = OPC_SDC1;
16946 do_cop1:
16947 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16948 break;
16949 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16950 if (ctx->insn_flags & ISA_MIPS32R6) {
16951 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16952 switch ((ctx->opcode >> 16) & 0x1f) {
16953 case ADDIUPC_00:
16954 case ADDIUPC_01:
16955 case ADDIUPC_02:
16956 case ADDIUPC_03:
16957 case ADDIUPC_04:
16958 case ADDIUPC_05:
16959 case ADDIUPC_06:
16960 case ADDIUPC_07:
16961 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16962 break;
16963 case AUIPC:
16964 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16965 break;
16966 case ALUIPC:
16967 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16968 break;
16969 case LWPC_08:
16970 case LWPC_09:
16971 case LWPC_0A:
16972 case LWPC_0B:
16973 case LWPC_0C:
16974 case LWPC_0D:
16975 case LWPC_0E:
16976 case LWPC_0F:
16977 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16978 break;
16979 default:
16980 generate_exception(ctx, EXCP_RI);
16981 break;
16983 } else {
16984 /* ADDIUPC */
16985 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16986 offset = SIMM(ctx->opcode, 0, 23) << 2;
16988 gen_addiupc(ctx, reg, offset, 0, 0);
16990 break;
16991 case BNVC: /* BNEC, BNEZALC */
16992 check_insn(ctx, ISA_MIPS32R6);
16993 if (rs >= rt) {
16994 /* BNVC */
16995 mips32_op = OPC_BNVC;
16996 } else if (rs < rt && rs == 0) {
16997 /* BNEZALC */
16998 mips32_op = OPC_BNEZALC;
16999 } else {
17000 /* BNEC */
17001 mips32_op = OPC_BNEC;
17003 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17004 break;
17005 case R6_BNEZC: /* JIALC */
17006 check_insn(ctx, ISA_MIPS32R6);
17007 if (rt != 0) {
17008 /* BNEZC */
17009 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17010 sextract32(ctx->opcode << 1, 0, 22));
17011 } else {
17012 /* JIALC */
17013 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17015 break;
17016 case R6_BEQZC: /* JIC */
17017 check_insn(ctx, ISA_MIPS32R6);
17018 if (rt != 0) {
17019 /* BEQZC */
17020 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17021 sextract32(ctx->opcode << 1, 0, 22));
17022 } else {
17023 /* JIC */
17024 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17026 break;
17027 case BLEZALC: /* BGEZALC, BGEUC */
17028 check_insn(ctx, ISA_MIPS32R6);
17029 if (rs == 0 && rt != 0) {
17030 /* BLEZALC */
17031 mips32_op = OPC_BLEZALC;
17032 } else if (rs != 0 && rt != 0 && rs == rt) {
17033 /* BGEZALC */
17034 mips32_op = OPC_BGEZALC;
17035 } else {
17036 /* BGEUC */
17037 mips32_op = OPC_BGEUC;
17039 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17040 break;
17041 case BGTZALC: /* BLTZALC, BLTUC */
17042 check_insn(ctx, ISA_MIPS32R6);
17043 if (rs == 0 && rt != 0) {
17044 /* BGTZALC */
17045 mips32_op = OPC_BGTZALC;
17046 } else if (rs != 0 && rt != 0 && rs == rt) {
17047 /* BLTZALC */
17048 mips32_op = OPC_BLTZALC;
17049 } else {
17050 /* BLTUC */
17051 mips32_op = OPC_BLTUC;
17053 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17054 break;
17055 /* Loads and stores */
17056 case LB32:
17057 mips32_op = OPC_LB;
17058 goto do_ld;
17059 case LBU32:
17060 mips32_op = OPC_LBU;
17061 goto do_ld;
17062 case LH32:
17063 mips32_op = OPC_LH;
17064 goto do_ld;
17065 case LHU32:
17066 mips32_op = OPC_LHU;
17067 goto do_ld;
17068 case LW32:
17069 mips32_op = OPC_LW;
17070 goto do_ld;
17071 #ifdef TARGET_MIPS64
17072 case LD32:
17073 check_insn(ctx, ISA_MIPS3);
17074 check_mips_64(ctx);
17075 mips32_op = OPC_LD;
17076 goto do_ld;
17077 case SD32:
17078 check_insn(ctx, ISA_MIPS3);
17079 check_mips_64(ctx);
17080 mips32_op = OPC_SD;
17081 goto do_st;
17082 #endif
17083 case SB32:
17084 mips32_op = OPC_SB;
17085 goto do_st;
17086 case SH32:
17087 mips32_op = OPC_SH;
17088 goto do_st;
17089 case SW32:
17090 mips32_op = OPC_SW;
17091 goto do_st;
17092 do_ld:
17093 gen_ld(ctx, mips32_op, rt, rs, imm);
17094 break;
17095 do_st:
17096 gen_st(ctx, mips32_op, rt, rs, imm);
17097 break;
17098 default:
17099 generate_exception_end(ctx, EXCP_RI);
17100 break;
17104 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
17106 uint32_t op;
17108 /* make sure instructions are on a halfword boundary */
17109 if (ctx->base.pc_next & 0x1) {
17110 env->CP0_BadVAddr = ctx->base.pc_next;
17111 generate_exception_end(ctx, EXCP_AdEL);
17112 return 2;
17115 op = (ctx->opcode >> 10) & 0x3f;
17116 /* Enforce properly-sized instructions in a delay slot */
17117 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17118 switch (op & 0x7) { /* MSB-3..MSB-5 */
17119 case 0:
17120 /* POOL32A, POOL32B, POOL32I, POOL32C */
17121 case 4:
17122 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17123 case 5:
17124 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17125 case 6:
17126 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17127 case 7:
17128 /* LB32, LH32, LWC132, LDC132, LW32 */
17129 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17130 generate_exception_end(ctx, EXCP_RI);
17131 return 2;
17133 break;
17134 case 1:
17135 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17136 case 2:
17137 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17138 case 3:
17139 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17140 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17141 generate_exception_end(ctx, EXCP_RI);
17142 return 2;
17144 break;
17148 switch (op) {
17149 case POOL16A:
17151 int rd = mmreg(uMIPS_RD(ctx->opcode));
17152 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17153 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17154 uint32_t opc = 0;
17156 switch (ctx->opcode & 0x1) {
17157 case ADDU16:
17158 opc = OPC_ADDU;
17159 break;
17160 case SUBU16:
17161 opc = OPC_SUBU;
17162 break;
17164 if (ctx->insn_flags & ISA_MIPS32R6) {
17165 /* In the Release 6 the register number location in
17166 * the instruction encoding has changed.
17168 gen_arith(ctx, opc, rs1, rd, rs2);
17169 } else {
17170 gen_arith(ctx, opc, rd, rs1, rs2);
17173 break;
17174 case POOL16B:
17176 int rd = mmreg(uMIPS_RD(ctx->opcode));
17177 int rs = mmreg(uMIPS_RS(ctx->opcode));
17178 int amount = (ctx->opcode >> 1) & 0x7;
17179 uint32_t opc = 0;
17180 amount = amount == 0 ? 8 : amount;
17182 switch (ctx->opcode & 0x1) {
17183 case SLL16:
17184 opc = OPC_SLL;
17185 break;
17186 case SRL16:
17187 opc = OPC_SRL;
17188 break;
17191 gen_shift_imm(ctx, opc, rd, rs, amount);
17193 break;
17194 case POOL16C:
17195 if (ctx->insn_flags & ISA_MIPS32R6) {
17196 gen_pool16c_r6_insn(ctx);
17197 } else {
17198 gen_pool16c_insn(ctx);
17200 break;
17201 case LWGP16:
17203 int rd = mmreg(uMIPS_RD(ctx->opcode));
17204 int rb = 28; /* GP */
17205 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17207 gen_ld(ctx, OPC_LW, rd, rb, offset);
17209 break;
17210 case POOL16F:
17211 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17212 if (ctx->opcode & 1) {
17213 generate_exception_end(ctx, EXCP_RI);
17214 } else {
17215 /* MOVEP */
17216 int enc_dest = uMIPS_RD(ctx->opcode);
17217 int enc_rt = uMIPS_RS2(ctx->opcode);
17218 int enc_rs = uMIPS_RS1(ctx->opcode);
17219 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17221 break;
17222 case LBU16:
17224 int rd = mmreg(uMIPS_RD(ctx->opcode));
17225 int rb = mmreg(uMIPS_RS(ctx->opcode));
17226 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17227 offset = (offset == 0xf ? -1 : offset);
17229 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17231 break;
17232 case LHU16:
17234 int rd = mmreg(uMIPS_RD(ctx->opcode));
17235 int rb = mmreg(uMIPS_RS(ctx->opcode));
17236 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17238 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17240 break;
17241 case LWSP16:
17243 int rd = (ctx->opcode >> 5) & 0x1f;
17244 int rb = 29; /* SP */
17245 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17247 gen_ld(ctx, OPC_LW, rd, rb, offset);
17249 break;
17250 case LW16:
17252 int rd = mmreg(uMIPS_RD(ctx->opcode));
17253 int rb = mmreg(uMIPS_RS(ctx->opcode));
17254 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17256 gen_ld(ctx, OPC_LW, rd, rb, offset);
17258 break;
17259 case SB16:
17261 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17262 int rb = mmreg(uMIPS_RS(ctx->opcode));
17263 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17265 gen_st(ctx, OPC_SB, rd, rb, offset);
17267 break;
17268 case SH16:
17270 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17271 int rb = mmreg(uMIPS_RS(ctx->opcode));
17272 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17274 gen_st(ctx, OPC_SH, rd, rb, offset);
17276 break;
17277 case SWSP16:
17279 int rd = (ctx->opcode >> 5) & 0x1f;
17280 int rb = 29; /* SP */
17281 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17283 gen_st(ctx, OPC_SW, rd, rb, offset);
17285 break;
17286 case SW16:
17288 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17289 int rb = mmreg(uMIPS_RS(ctx->opcode));
17290 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17292 gen_st(ctx, OPC_SW, rd, rb, offset);
17294 break;
17295 case MOVE16:
17297 int rd = uMIPS_RD5(ctx->opcode);
17298 int rs = uMIPS_RS5(ctx->opcode);
17300 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17302 break;
17303 case ANDI16:
17304 gen_andi16(ctx);
17305 break;
17306 case POOL16D:
17307 switch (ctx->opcode & 0x1) {
17308 case ADDIUS5:
17309 gen_addius5(ctx);
17310 break;
17311 case ADDIUSP:
17312 gen_addiusp(ctx);
17313 break;
17315 break;
17316 case POOL16E:
17317 switch (ctx->opcode & 0x1) {
17318 case ADDIUR2:
17319 gen_addiur2(ctx);
17320 break;
17321 case ADDIUR1SP:
17322 gen_addiur1sp(ctx);
17323 break;
17325 break;
17326 case B16: /* BC16 */
17327 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17328 sextract32(ctx->opcode, 0, 10) << 1,
17329 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17330 break;
17331 case BNEZ16: /* BNEZC16 */
17332 case BEQZ16: /* BEQZC16 */
17333 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17334 mmreg(uMIPS_RD(ctx->opcode)),
17335 0, sextract32(ctx->opcode, 0, 7) << 1,
17336 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17338 break;
17339 case LI16:
17341 int reg = mmreg(uMIPS_RD(ctx->opcode));
17342 int imm = ZIMM(ctx->opcode, 0, 7);
17344 imm = (imm == 0x7f ? -1 : imm);
17345 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17347 break;
17348 case RES_29:
17349 case RES_31:
17350 case RES_39:
17351 generate_exception_end(ctx, EXCP_RI);
17352 break;
17353 default:
17354 decode_micromips32_opc(env, ctx);
17355 return 4;
17358 return 2;
17363 * nanoMIPS opcodes
17367 /* MAJOR, P16, and P32 pools opcodes */
17368 enum {
17369 NM_P_ADDIU = 0x00,
17370 NM_ADDIUPC = 0x01,
17371 NM_MOVE_BALC = 0x02,
17372 NM_P16_MV = 0x04,
17373 NM_LW16 = 0x05,
17374 NM_BC16 = 0x06,
17375 NM_P16_SR = 0x07,
17377 NM_POOL32A = 0x08,
17378 NM_P_BAL = 0x0a,
17379 NM_P16_SHIFT = 0x0c,
17380 NM_LWSP16 = 0x0d,
17381 NM_BALC16 = 0x0e,
17382 NM_P16_4X4 = 0x0f,
17384 NM_P_GP_W = 0x10,
17385 NM_P_GP_BH = 0x11,
17386 NM_P_J = 0x12,
17387 NM_P16C = 0x14,
17388 NM_LWGP16 = 0x15,
17389 NM_P16_LB = 0x17,
17391 NM_P48I = 0x18,
17392 NM_P16_A1 = 0x1c,
17393 NM_LW4X4 = 0x1d,
17394 NM_P16_LH = 0x1f,
17396 NM_P_U12 = 0x20,
17397 NM_P_LS_U12 = 0x21,
17398 NM_P_BR1 = 0x22,
17399 NM_P16_A2 = 0x24,
17400 NM_SW16 = 0x25,
17401 NM_BEQZC16 = 0x26,
17403 NM_POOL32F = 0x28,
17404 NM_P_LS_S9 = 0x29,
17405 NM_P_BR2 = 0x2a,
17407 NM_P16_ADDU = 0x2c,
17408 NM_SWSP16 = 0x2d,
17409 NM_BNEZC16 = 0x2e,
17410 NM_MOVEP = 0x2f,
17412 NM_POOL32S = 0x30,
17413 NM_P_BRI = 0x32,
17414 NM_LI16 = 0x34,
17415 NM_SWGP16 = 0x35,
17416 NM_P16_BR = 0x36,
17418 NM_P_LUI = 0x38,
17419 NM_ANDI16 = 0x3c,
17420 NM_SW4X4 = 0x3d,
17421 NM_MOVEPREV = 0x3f,
17424 /* POOL32A instruction pool */
17425 enum {
17426 NM_POOL32A0 = 0x00,
17427 NM_SPECIAL2 = 0x01,
17428 NM_COP2_1 = 0x02,
17429 NM_UDI = 0x03,
17430 NM_POOL32A5 = 0x05,
17431 NM_POOL32A7 = 0x07,
17434 /* P.GP.W instruction pool */
17435 enum {
17436 NM_ADDIUGP_W = 0x00,
17437 NM_LWGP = 0x02,
17438 NM_SWGP = 0x03,
17441 /* P48I instruction pool */
17442 enum {
17443 NM_LI48 = 0x00,
17444 NM_ADDIU48 = 0x01,
17445 NM_ADDIUGP48 = 0x02,
17446 NM_ADDIUPC48 = 0x03,
17447 NM_LWPC48 = 0x0b,
17448 NM_SWPC48 = 0x0f,
17451 /* P.U12 instruction pool */
17452 enum {
17453 NM_ORI = 0x00,
17454 NM_XORI = 0x01,
17455 NM_ANDI = 0x02,
17456 NM_P_SR = 0x03,
17457 NM_SLTI = 0x04,
17458 NM_SLTIU = 0x05,
17459 NM_SEQI = 0x06,
17460 NM_ADDIUNEG = 0x08,
17461 NM_P_SHIFT = 0x0c,
17462 NM_P_ROTX = 0x0d,
17463 NM_P_INS = 0x0e,
17464 NM_P_EXT = 0x0f,
17467 /* POOL32F instruction pool */
17468 enum {
17469 NM_POOL32F_0 = 0x00,
17470 NM_POOL32F_3 = 0x03,
17471 NM_POOL32F_5 = 0x05,
17474 /* POOL32S instruction pool */
17475 enum {
17476 NM_POOL32S_0 = 0x00,
17477 NM_POOL32S_4 = 0x04,
17480 /* P.LUI instruction pool */
17481 enum {
17482 NM_LUI = 0x00,
17483 NM_ALUIPC = 0x01,
17486 /* P.GP.BH instruction pool */
17487 enum {
17488 NM_LBGP = 0x00,
17489 NM_SBGP = 0x01,
17490 NM_LBUGP = 0x02,
17491 NM_ADDIUGP_B = 0x03,
17492 NM_P_GP_LH = 0x04,
17493 NM_P_GP_SH = 0x05,
17494 NM_P_GP_CP1 = 0x06,
17497 /* P.LS.U12 instruction pool */
17498 enum {
17499 NM_LB = 0x00,
17500 NM_SB = 0x01,
17501 NM_LBU = 0x02,
17502 NM_P_PREFU12 = 0x03,
17503 NM_LH = 0x04,
17504 NM_SH = 0x05,
17505 NM_LHU = 0x06,
17506 NM_LWU = 0x07,
17507 NM_LW = 0x08,
17508 NM_SW = 0x09,
17509 NM_LWC1 = 0x0a,
17510 NM_SWC1 = 0x0b,
17511 NM_LDC1 = 0x0e,
17512 NM_SDC1 = 0x0f,
17515 /* P.LS.S9 instruction pool */
17516 enum {
17517 NM_P_LS_S0 = 0x00,
17518 NM_P_LS_S1 = 0x01,
17519 NM_P_LS_E0 = 0x02,
17520 NM_P_LS_WM = 0x04,
17521 NM_P_LS_UAWM = 0x05,
17524 /* P.BAL instruction pool */
17525 enum {
17526 NM_BC = 0x00,
17527 NM_BALC = 0x01,
17530 /* P.J instruction pool */
17531 enum {
17532 NM_JALRC = 0x00,
17533 NM_JALRC_HB = 0x01,
17534 NM_P_BALRSC = 0x08,
17537 /* P.BR1 instruction pool */
17538 enum {
17539 NM_BEQC = 0x00,
17540 NM_P_BR3A = 0x01,
17541 NM_BGEC = 0x02,
17542 NM_BGEUC = 0x03,
17545 /* P.BR2 instruction pool */
17546 enum {
17547 NM_BNEC = 0x00,
17548 NM_BLTC = 0x02,
17549 NM_BLTUC = 0x03,
17552 /* P.BRI instruction pool */
17553 enum {
17554 NM_BEQIC = 0x00,
17555 NM_BBEQZC = 0x01,
17556 NM_BGEIC = 0x02,
17557 NM_BGEIUC = 0x03,
17558 NM_BNEIC = 0x04,
17559 NM_BBNEZC = 0x05,
17560 NM_BLTIC = 0x06,
17561 NM_BLTIUC = 0x07,
17564 /* P16.SHIFT instruction pool */
17565 enum {
17566 NM_SLL16 = 0x00,
17567 NM_SRL16 = 0x01,
17570 /* POOL16C instruction pool */
17571 enum {
17572 NM_POOL16C_0 = 0x00,
17573 NM_LWXS16 = 0x01,
17576 /* P16.A1 instruction pool */
17577 enum {
17578 NM_ADDIUR1SP = 0x01,
17581 /* P16.A2 instruction pool */
17582 enum {
17583 NM_ADDIUR2 = 0x00,
17584 NM_P_ADDIURS5 = 0x01,
17587 /* P16.ADDU instruction pool */
17588 enum {
17589 NM_ADDU16 = 0x00,
17590 NM_SUBU16 = 0x01,
17593 /* P16.SR instruction pool */
17594 enum {
17595 NM_SAVE16 = 0x00,
17596 NM_RESTORE_JRC16 = 0x01,
17599 /* P16.4X4 instruction pool */
17600 enum {
17601 NM_ADDU4X4 = 0x00,
17602 NM_MUL4X4 = 0x01,
17605 /* P16.LB instruction pool */
17606 enum {
17607 NM_LB16 = 0x00,
17608 NM_SB16 = 0x01,
17609 NM_LBU16 = 0x02,
17612 /* P16.LH instruction pool */
17613 enum {
17614 NM_LH16 = 0x00,
17615 NM_SH16 = 0x01,
17616 NM_LHU16 = 0x02,
17619 /* P.RI instruction pool */
17620 enum {
17621 NM_SIGRIE = 0x00,
17622 NM_P_SYSCALL = 0x01,
17623 NM_BREAK = 0x02,
17624 NM_SDBBP = 0x03,
17627 /* POOL32A0 instruction pool */
17628 enum {
17629 NM_P_TRAP = 0x00,
17630 NM_SEB = 0x01,
17631 NM_SLLV = 0x02,
17632 NM_MUL = 0x03,
17633 NM_MFC0 = 0x06,
17634 NM_MFHC0 = 0x07,
17635 NM_SEH = 0x09,
17636 NM_SRLV = 0x0a,
17637 NM_MUH = 0x0b,
17638 NM_MTC0 = 0x0e,
17639 NM_MTHC0 = 0x0f,
17640 NM_SRAV = 0x12,
17641 NM_MULU = 0x13,
17642 NM_ROTRV = 0x1a,
17643 NM_MUHU = 0x1b,
17644 NM_ADD = 0x22,
17645 NM_DIV = 0x23,
17646 NM_ADDU = 0x2a,
17647 NM_MOD = 0x2b,
17648 NM_SUB = 0x32,
17649 NM_DIVU = 0x33,
17650 NM_RDHWR = 0x38,
17651 NM_SUBU = 0x3a,
17652 NM_MODU = 0x3b,
17653 NM_P_CMOVE = 0x42,
17654 NM_FORK = 0x45,
17655 NM_MFTR = 0x46,
17656 NM_MFHTR = 0x47,
17657 NM_AND = 0x4a,
17658 NM_YIELD = 0x4d,
17659 NM_MTTR = 0x4e,
17660 NM_MTHTR = 0x4f,
17661 NM_OR = 0x52,
17662 NM_D_E_MT_VPE = 0x56,
17663 NM_NOR = 0x5a,
17664 NM_XOR = 0x62,
17665 NM_SLT = 0x6a,
17666 NM_P_SLTU = 0x72,
17667 NM_SOV = 0x7a,
17670 /* CRC32 instruction pool */
17671 enum {
17672 NM_CRC32B = 0x00,
17673 NM_CRC32H = 0x01,
17674 NM_CRC32W = 0x02,
17675 NM_CRC32CB = 0x04,
17676 NM_CRC32CH = 0x05,
17677 NM_CRC32CW = 0x06,
17680 /* POOL32A5 instruction pool */
17681 enum {
17682 NM_CMP_EQ_PH = 0x00,
17683 NM_CMP_LT_PH = 0x08,
17684 NM_CMP_LE_PH = 0x10,
17685 NM_CMPGU_EQ_QB = 0x18,
17686 NM_CMPGU_LT_QB = 0x20,
17687 NM_CMPGU_LE_QB = 0x28,
17688 NM_CMPGDU_EQ_QB = 0x30,
17689 NM_CMPGDU_LT_QB = 0x38,
17690 NM_CMPGDU_LE_QB = 0x40,
17691 NM_CMPU_EQ_QB = 0x48,
17692 NM_CMPU_LT_QB = 0x50,
17693 NM_CMPU_LE_QB = 0x58,
17694 NM_ADDQ_S_W = 0x60,
17695 NM_SUBQ_S_W = 0x68,
17696 NM_ADDSC = 0x70,
17697 NM_ADDWC = 0x78,
17699 NM_ADDQ_S_PH = 0x01,
17700 NM_ADDQH_R_PH = 0x09,
17701 NM_ADDQH_R_W = 0x11,
17702 NM_ADDU_S_QB = 0x19,
17703 NM_ADDU_S_PH = 0x21,
17704 NM_ADDUH_R_QB = 0x29,
17705 NM_SHRAV_R_PH = 0x31,
17706 NM_SHRAV_R_QB = 0x39,
17707 NM_SUBQ_S_PH = 0x41,
17708 NM_SUBQH_R_PH = 0x49,
17709 NM_SUBQH_R_W = 0x51,
17710 NM_SUBU_S_QB = 0x59,
17711 NM_SUBU_S_PH = 0x61,
17712 NM_SUBUH_R_QB = 0x69,
17713 NM_SHLLV_S_PH = 0x71,
17714 NM_PRECR_SRA_R_PH_W = 0x79,
17716 NM_MULEU_S_PH_QBL = 0x12,
17717 NM_MULEU_S_PH_QBR = 0x1a,
17718 NM_MULQ_RS_PH = 0x22,
17719 NM_MULQ_S_PH = 0x2a,
17720 NM_MULQ_RS_W = 0x32,
17721 NM_MULQ_S_W = 0x3a,
17722 NM_APPEND = 0x42,
17723 NM_MODSUB = 0x52,
17724 NM_SHRAV_R_W = 0x5a,
17725 NM_SHRLV_PH = 0x62,
17726 NM_SHRLV_QB = 0x6a,
17727 NM_SHLLV_QB = 0x72,
17728 NM_SHLLV_S_W = 0x7a,
17730 NM_SHILO = 0x03,
17732 NM_MULEQ_S_W_PHL = 0x04,
17733 NM_MULEQ_S_W_PHR = 0x0c,
17735 NM_MUL_S_PH = 0x05,
17736 NM_PRECR_QB_PH = 0x0d,
17737 NM_PRECRQ_QB_PH = 0x15,
17738 NM_PRECRQ_PH_W = 0x1d,
17739 NM_PRECRQ_RS_PH_W = 0x25,
17740 NM_PRECRQU_S_QB_PH = 0x2d,
17741 NM_PACKRL_PH = 0x35,
17742 NM_PICK_QB = 0x3d,
17743 NM_PICK_PH = 0x45,
17745 NM_SHRA_R_W = 0x5e,
17746 NM_SHRA_R_PH = 0x66,
17747 NM_SHLL_S_PH = 0x76,
17748 NM_SHLL_S_W = 0x7e,
17750 NM_REPL_PH = 0x07
17753 /* POOL32A7 instruction pool */
17754 enum {
17755 NM_P_LSX = 0x00,
17756 NM_LSA = 0x01,
17757 NM_EXTW = 0x03,
17758 NM_POOL32AXF = 0x07,
17761 /* P.SR instruction pool */
17762 enum {
17763 NM_PP_SR = 0x00,
17764 NM_P_SR_F = 0x01,
17767 /* P.SHIFT instruction pool */
17768 enum {
17769 NM_P_SLL = 0x00,
17770 NM_SRL = 0x02,
17771 NM_SRA = 0x04,
17772 NM_ROTR = 0x06,
17775 /* P.ROTX instruction pool */
17776 enum {
17777 NM_ROTX = 0x00,
17780 /* P.INS instruction pool */
17781 enum {
17782 NM_INS = 0x00,
17785 /* P.EXT instruction pool */
17786 enum {
17787 NM_EXT = 0x00,
17790 /* POOL32F_0 (fmt) instruction pool */
17791 enum {
17792 NM_RINT_S = 0x04,
17793 NM_RINT_D = 0x44,
17794 NM_ADD_S = 0x06,
17795 NM_SELEQZ_S = 0x07,
17796 NM_SELEQZ_D = 0x47,
17797 NM_CLASS_S = 0x0c,
17798 NM_CLASS_D = 0x4c,
17799 NM_SUB_S = 0x0e,
17800 NM_SELNEZ_S = 0x0f,
17801 NM_SELNEZ_D = 0x4f,
17802 NM_MUL_S = 0x16,
17803 NM_SEL_S = 0x17,
17804 NM_SEL_D = 0x57,
17805 NM_DIV_S = 0x1e,
17806 NM_ADD_D = 0x26,
17807 NM_SUB_D = 0x2e,
17808 NM_MUL_D = 0x36,
17809 NM_MADDF_S = 0x37,
17810 NM_MADDF_D = 0x77,
17811 NM_DIV_D = 0x3e,
17812 NM_MSUBF_S = 0x3f,
17813 NM_MSUBF_D = 0x7f,
17816 /* POOL32F_3 instruction pool */
17817 enum {
17818 NM_MIN_FMT = 0x00,
17819 NM_MAX_FMT = 0x01,
17820 NM_MINA_FMT = 0x04,
17821 NM_MAXA_FMT = 0x05,
17822 NM_POOL32FXF = 0x07,
17825 /* POOL32F_5 instruction pool */
17826 enum {
17827 NM_CMP_CONDN_S = 0x00,
17828 NM_CMP_CONDN_D = 0x02,
17831 /* P.GP.LH instruction pool */
17832 enum {
17833 NM_LHGP = 0x00,
17834 NM_LHUGP = 0x01,
17837 /* P.GP.SH instruction pool */
17838 enum {
17839 NM_SHGP = 0x00,
17842 /* P.GP.CP1 instruction pool */
17843 enum {
17844 NM_LWC1GP = 0x00,
17845 NM_SWC1GP = 0x01,
17846 NM_LDC1GP = 0x02,
17847 NM_SDC1GP = 0x03,
17850 /* P.LS.S0 instruction pool */
17851 enum {
17852 NM_LBS9 = 0x00,
17853 NM_LHS9 = 0x04,
17854 NM_LWS9 = 0x08,
17855 NM_LDS9 = 0x0c,
17857 NM_SBS9 = 0x01,
17858 NM_SHS9 = 0x05,
17859 NM_SWS9 = 0x09,
17860 NM_SDS9 = 0x0d,
17862 NM_LBUS9 = 0x02,
17863 NM_LHUS9 = 0x06,
17864 NM_LWC1S9 = 0x0a,
17865 NM_LDC1S9 = 0x0e,
17867 NM_P_PREFS9 = 0x03,
17868 NM_LWUS9 = 0x07,
17869 NM_SWC1S9 = 0x0b,
17870 NM_SDC1S9 = 0x0f,
17873 /* P.LS.S1 instruction pool */
17874 enum {
17875 NM_ASET_ACLR = 0x02,
17876 NM_UALH = 0x04,
17877 NM_UASH = 0x05,
17878 NM_CACHE = 0x07,
17879 NM_P_LL = 0x0a,
17880 NM_P_SC = 0x0b,
17883 /* P.LS.E0 instruction pool */
17884 enum {
17885 NM_LBE = 0x00,
17886 NM_SBE = 0x01,
17887 NM_LBUE = 0x02,
17888 NM_P_PREFE = 0x03,
17889 NM_LHE = 0x04,
17890 NM_SHE = 0x05,
17891 NM_LHUE = 0x06,
17892 NM_CACHEE = 0x07,
17893 NM_LWE = 0x08,
17894 NM_SWE = 0x09,
17895 NM_P_LLE = 0x0a,
17896 NM_P_SCE = 0x0b,
17899 /* P.PREFE instruction pool */
17900 enum {
17901 NM_SYNCIE = 0x00,
17902 NM_PREFE = 0x01,
17905 /* P.LLE instruction pool */
17906 enum {
17907 NM_LLE = 0x00,
17908 NM_LLWPE = 0x01,
17911 /* P.SCE instruction pool */
17912 enum {
17913 NM_SCE = 0x00,
17914 NM_SCWPE = 0x01,
17917 /* P.LS.WM instruction pool */
17918 enum {
17919 NM_LWM = 0x00,
17920 NM_SWM = 0x01,
17923 /* P.LS.UAWM instruction pool */
17924 enum {
17925 NM_UALWM = 0x00,
17926 NM_UASWM = 0x01,
17929 /* P.BR3A instruction pool */
17930 enum {
17931 NM_BC1EQZC = 0x00,
17932 NM_BC1NEZC = 0x01,
17933 NM_BC2EQZC = 0x02,
17934 NM_BC2NEZC = 0x03,
17935 NM_BPOSGE32C = 0x04,
17938 /* P16.RI instruction pool */
17939 enum {
17940 NM_P16_SYSCALL = 0x01,
17941 NM_BREAK16 = 0x02,
17942 NM_SDBBP16 = 0x03,
17945 /* POOL16C_0 instruction pool */
17946 enum {
17947 NM_POOL16C_00 = 0x00,
17950 /* P16.JRC instruction pool */
17951 enum {
17952 NM_JRC = 0x00,
17953 NM_JALRC16 = 0x01,
17956 /* P.SYSCALL instruction pool */
17957 enum {
17958 NM_SYSCALL = 0x00,
17959 NM_HYPCALL = 0x01,
17962 /* P.TRAP instruction pool */
17963 enum {
17964 NM_TEQ = 0x00,
17965 NM_TNE = 0x01,
17968 /* P.CMOVE instruction pool */
17969 enum {
17970 NM_MOVZ = 0x00,
17971 NM_MOVN = 0x01,
17974 /* POOL32Axf instruction pool */
17975 enum {
17976 NM_POOL32AXF_1 = 0x01,
17977 NM_POOL32AXF_2 = 0x02,
17978 NM_POOL32AXF_4 = 0x04,
17979 NM_POOL32AXF_5 = 0x05,
17980 NM_POOL32AXF_7 = 0x07,
17983 /* POOL32Axf_1 instruction pool */
17984 enum {
17985 NM_POOL32AXF_1_0 = 0x00,
17986 NM_POOL32AXF_1_1 = 0x01,
17987 NM_POOL32AXF_1_3 = 0x03,
17988 NM_POOL32AXF_1_4 = 0x04,
17989 NM_POOL32AXF_1_5 = 0x05,
17990 NM_POOL32AXF_1_7 = 0x07,
17993 /* POOL32Axf_2 instruction pool */
17994 enum {
17995 NM_POOL32AXF_2_0_7 = 0x00,
17996 NM_POOL32AXF_2_8_15 = 0x01,
17997 NM_POOL32AXF_2_16_23 = 0x02,
17998 NM_POOL32AXF_2_24_31 = 0x03,
18001 /* POOL32Axf_7 instruction pool */
18002 enum {
18003 NM_SHRA_R_QB = 0x0,
18004 NM_SHRL_PH = 0x1,
18005 NM_REPL_QB = 0x2,
18008 /* POOL32Axf_1_0 instruction pool */
18009 enum {
18010 NM_MFHI = 0x0,
18011 NM_MFLO = 0x1,
18012 NM_MTHI = 0x2,
18013 NM_MTLO = 0x3,
18016 /* POOL32Axf_1_1 instruction pool */
18017 enum {
18018 NM_MTHLIP = 0x0,
18019 NM_SHILOV = 0x1,
18022 /* POOL32Axf_1_3 instruction pool */
18023 enum {
18024 NM_RDDSP = 0x0,
18025 NM_WRDSP = 0x1,
18026 NM_EXTP = 0x2,
18027 NM_EXTPDP = 0x3,
18030 /* POOL32Axf_1_4 instruction pool */
18031 enum {
18032 NM_SHLL_QB = 0x0,
18033 NM_SHRL_QB = 0x1,
18036 /* POOL32Axf_1_5 instruction pool */
18037 enum {
18038 NM_MAQ_S_W_PHR = 0x0,
18039 NM_MAQ_S_W_PHL = 0x1,
18040 NM_MAQ_SA_W_PHR = 0x2,
18041 NM_MAQ_SA_W_PHL = 0x3,
18044 /* POOL32Axf_1_7 instruction pool */
18045 enum {
18046 NM_EXTR_W = 0x0,
18047 NM_EXTR_R_W = 0x1,
18048 NM_EXTR_RS_W = 0x2,
18049 NM_EXTR_S_H = 0x3,
18052 /* POOL32Axf_2_0_7 instruction pool */
18053 enum {
18054 NM_DPA_W_PH = 0x0,
18055 NM_DPAQ_S_W_PH = 0x1,
18056 NM_DPS_W_PH = 0x2,
18057 NM_DPSQ_S_W_PH = 0x3,
18058 NM_BALIGN = 0x4,
18059 NM_MADD = 0x5,
18060 NM_MULT = 0x6,
18061 NM_EXTRV_W = 0x7,
18064 /* POOL32Axf_2_8_15 instruction pool */
18065 enum {
18066 NM_DPAX_W_PH = 0x0,
18067 NM_DPAQ_SA_L_W = 0x1,
18068 NM_DPSX_W_PH = 0x2,
18069 NM_DPSQ_SA_L_W = 0x3,
18070 NM_MADDU = 0x5,
18071 NM_MULTU = 0x6,
18072 NM_EXTRV_R_W = 0x7,
18075 /* POOL32Axf_2_16_23 instruction pool */
18076 enum {
18077 NM_DPAU_H_QBL = 0x0,
18078 NM_DPAQX_S_W_PH = 0x1,
18079 NM_DPSU_H_QBL = 0x2,
18080 NM_DPSQX_S_W_PH = 0x3,
18081 NM_EXTPV = 0x4,
18082 NM_MSUB = 0x5,
18083 NM_MULSA_W_PH = 0x6,
18084 NM_EXTRV_RS_W = 0x7,
18087 /* POOL32Axf_2_24_31 instruction pool */
18088 enum {
18089 NM_DPAU_H_QBR = 0x0,
18090 NM_DPAQX_SA_W_PH = 0x1,
18091 NM_DPSU_H_QBR = 0x2,
18092 NM_DPSQX_SA_W_PH = 0x3,
18093 NM_EXTPDPV = 0x4,
18094 NM_MSUBU = 0x5,
18095 NM_MULSAQ_S_W_PH = 0x6,
18096 NM_EXTRV_S_H = 0x7,
18099 /* POOL32Axf_{4, 5} instruction pool */
18100 enum {
18101 NM_CLO = 0x25,
18102 NM_CLZ = 0x2d,
18104 NM_TLBP = 0x01,
18105 NM_TLBR = 0x09,
18106 NM_TLBWI = 0x11,
18107 NM_TLBWR = 0x19,
18108 NM_TLBINV = 0x03,
18109 NM_TLBINVF = 0x0b,
18110 NM_DI = 0x23,
18111 NM_EI = 0x2b,
18112 NM_RDPGPR = 0x70,
18113 NM_WRPGPR = 0x78,
18114 NM_WAIT = 0x61,
18115 NM_DERET = 0x71,
18116 NM_ERETX = 0x79,
18118 /* nanoMIPS DSP instructions */
18119 NM_ABSQ_S_QB = 0x00,
18120 NM_ABSQ_S_PH = 0x08,
18121 NM_ABSQ_S_W = 0x10,
18122 NM_PRECEQ_W_PHL = 0x28,
18123 NM_PRECEQ_W_PHR = 0x30,
18124 NM_PRECEQU_PH_QBL = 0x38,
18125 NM_PRECEQU_PH_QBR = 0x48,
18126 NM_PRECEU_PH_QBL = 0x58,
18127 NM_PRECEU_PH_QBR = 0x68,
18128 NM_PRECEQU_PH_QBLA = 0x39,
18129 NM_PRECEQU_PH_QBRA = 0x49,
18130 NM_PRECEU_PH_QBLA = 0x59,
18131 NM_PRECEU_PH_QBRA = 0x69,
18132 NM_REPLV_PH = 0x01,
18133 NM_REPLV_QB = 0x09,
18134 NM_BITREV = 0x18,
18135 NM_INSV = 0x20,
18136 NM_RADDU_W_QB = 0x78,
18138 NM_BITSWAP = 0x05,
18139 NM_WSBH = 0x3d,
18142 /* PP.SR instruction pool */
18143 enum {
18144 NM_SAVE = 0x00,
18145 NM_RESTORE = 0x02,
18146 NM_RESTORE_JRC = 0x03,
18149 /* P.SR.F instruction pool */
18150 enum {
18151 NM_SAVEF = 0x00,
18152 NM_RESTOREF = 0x01,
18155 /* P16.SYSCALL instruction pool */
18156 enum {
18157 NM_SYSCALL16 = 0x00,
18158 NM_HYPCALL16 = 0x01,
18161 /* POOL16C_00 instruction pool */
18162 enum {
18163 NM_NOT16 = 0x00,
18164 NM_XOR16 = 0x01,
18165 NM_AND16 = 0x02,
18166 NM_OR16 = 0x03,
18169 /* PP.LSX and PP.LSXS instruction pool */
18170 enum {
18171 NM_LBX = 0x00,
18172 NM_LHX = 0x04,
18173 NM_LWX = 0x08,
18174 NM_LDX = 0x0c,
18176 NM_SBX = 0x01,
18177 NM_SHX = 0x05,
18178 NM_SWX = 0x09,
18179 NM_SDX = 0x0d,
18181 NM_LBUX = 0x02,
18182 NM_LHUX = 0x06,
18183 NM_LWC1X = 0x0a,
18184 NM_LDC1X = 0x0e,
18186 NM_LWUX = 0x07,
18187 NM_SWC1X = 0x0b,
18188 NM_SDC1X = 0x0f,
18190 NM_LHXS = 0x04,
18191 NM_LWXS = 0x08,
18192 NM_LDXS = 0x0c,
18194 NM_SHXS = 0x05,
18195 NM_SWXS = 0x09,
18196 NM_SDXS = 0x0d,
18198 NM_LHUXS = 0x06,
18199 NM_LWC1XS = 0x0a,
18200 NM_LDC1XS = 0x0e,
18202 NM_LWUXS = 0x07,
18203 NM_SWC1XS = 0x0b,
18204 NM_SDC1XS = 0x0f,
18207 /* ERETx instruction pool */
18208 enum {
18209 NM_ERET = 0x00,
18210 NM_ERETNC = 0x01,
18213 /* POOL32FxF_{0, 1} insturction pool */
18214 enum {
18215 NM_CFC1 = 0x40,
18216 NM_CTC1 = 0x60,
18217 NM_MFC1 = 0x80,
18218 NM_MTC1 = 0xa0,
18219 NM_MFHC1 = 0xc0,
18220 NM_MTHC1 = 0xe0,
18222 NM_CVT_S_PL = 0x84,
18223 NM_CVT_S_PU = 0xa4,
18225 NM_CVT_L_S = 0x004,
18226 NM_CVT_L_D = 0x104,
18227 NM_CVT_W_S = 0x024,
18228 NM_CVT_W_D = 0x124,
18230 NM_RSQRT_S = 0x008,
18231 NM_RSQRT_D = 0x108,
18233 NM_SQRT_S = 0x028,
18234 NM_SQRT_D = 0x128,
18236 NM_RECIP_S = 0x048,
18237 NM_RECIP_D = 0x148,
18239 NM_FLOOR_L_S = 0x00c,
18240 NM_FLOOR_L_D = 0x10c,
18242 NM_FLOOR_W_S = 0x02c,
18243 NM_FLOOR_W_D = 0x12c,
18245 NM_CEIL_L_S = 0x04c,
18246 NM_CEIL_L_D = 0x14c,
18247 NM_CEIL_W_S = 0x06c,
18248 NM_CEIL_W_D = 0x16c,
18249 NM_TRUNC_L_S = 0x08c,
18250 NM_TRUNC_L_D = 0x18c,
18251 NM_TRUNC_W_S = 0x0ac,
18252 NM_TRUNC_W_D = 0x1ac,
18253 NM_ROUND_L_S = 0x0cc,
18254 NM_ROUND_L_D = 0x1cc,
18255 NM_ROUND_W_S = 0x0ec,
18256 NM_ROUND_W_D = 0x1ec,
18258 NM_MOV_S = 0x01,
18259 NM_MOV_D = 0x81,
18260 NM_ABS_S = 0x0d,
18261 NM_ABS_D = 0x8d,
18262 NM_NEG_S = 0x2d,
18263 NM_NEG_D = 0xad,
18264 NM_CVT_D_S = 0x04d,
18265 NM_CVT_D_W = 0x0cd,
18266 NM_CVT_D_L = 0x14d,
18267 NM_CVT_S_D = 0x06d,
18268 NM_CVT_S_W = 0x0ed,
18269 NM_CVT_S_L = 0x16d,
18272 /* P.LL instruction pool */
18273 enum {
18274 NM_LL = 0x00,
18275 NM_LLWP = 0x01,
18278 /* P.SC instruction pool */
18279 enum {
18280 NM_SC = 0x00,
18281 NM_SCWP = 0x01,
18284 /* P.DVP instruction pool */
18285 enum {
18286 NM_DVP = 0x00,
18287 NM_EVP = 0x01,
18293 * nanoMIPS decoding engine
18298 /* extraction utilities */
18300 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18301 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18302 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18303 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18304 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18305 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18307 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18308 static inline int decode_gpr_gpr3(int r)
18310 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18312 return map[r & 0x7];
18315 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18316 static inline int decode_gpr_gpr3_src_store(int r)
18318 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18320 return map[r & 0x7];
18323 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18324 static inline int decode_gpr_gpr4(int r)
18326 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18327 16, 17, 18, 19, 20, 21, 22, 23 };
18329 return map[r & 0xf];
18332 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18333 static inline int decode_gpr_gpr4_zero(int r)
18335 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18336 16, 17, 18, 19, 20, 21, 22, 23 };
18338 return map[r & 0xf];
18342 /* extraction utilities */
18344 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18345 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18346 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18347 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18348 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18349 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18352 static void gen_adjust_sp(DisasContext *ctx, int u)
18354 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18357 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18358 uint8_t gp, uint16_t u)
18360 int counter = 0;
18361 TCGv va = tcg_temp_new();
18362 TCGv t0 = tcg_temp_new();
18364 while (counter != count) {
18365 bool use_gp = gp && (counter == count - 1);
18366 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18367 int this_offset = -((counter + 1) << 2);
18368 gen_base_offset_addr(ctx, va, 29, this_offset);
18369 gen_load_gpr(t0, this_rt);
18370 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18371 (MO_TEUL | ctx->default_tcg_memop_mask));
18372 counter++;
18375 /* adjust stack pointer */
18376 gen_adjust_sp(ctx, -u);
18378 tcg_temp_free(t0);
18379 tcg_temp_free(va);
18382 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18383 uint8_t gp, uint16_t u)
18385 int counter = 0;
18386 TCGv va = tcg_temp_new();
18387 TCGv t0 = tcg_temp_new();
18389 while (counter != count) {
18390 bool use_gp = gp && (counter == count - 1);
18391 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18392 int this_offset = u - ((counter + 1) << 2);
18393 gen_base_offset_addr(ctx, va, 29, this_offset);
18394 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18395 ctx->default_tcg_memop_mask);
18396 tcg_gen_ext32s_tl(t0, t0);
18397 gen_store_gpr(t0, this_rt);
18398 counter++;
18401 /* adjust stack pointer */
18402 gen_adjust_sp(ctx, u);
18404 tcg_temp_free(t0);
18405 tcg_temp_free(va);
18408 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18410 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18411 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18413 switch (extract32(ctx->opcode, 2, 2)) {
18414 case NM_NOT16:
18415 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18416 break;
18417 case NM_AND16:
18418 gen_logic(ctx, OPC_AND, rt, rt, rs);
18419 break;
18420 case NM_XOR16:
18421 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18422 break;
18423 case NM_OR16:
18424 gen_logic(ctx, OPC_OR, rt, rt, rs);
18425 break;
18429 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18431 int rt = extract32(ctx->opcode, 21, 5);
18432 int rs = extract32(ctx->opcode, 16, 5);
18433 int rd = extract32(ctx->opcode, 11, 5);
18435 switch (extract32(ctx->opcode, 3, 7)) {
18436 case NM_P_TRAP:
18437 switch (extract32(ctx->opcode, 10, 1)) {
18438 case NM_TEQ:
18439 check_nms(ctx);
18440 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18441 break;
18442 case NM_TNE:
18443 check_nms(ctx);
18444 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18445 break;
18447 break;
18448 case NM_RDHWR:
18449 check_nms(ctx);
18450 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18451 break;
18452 case NM_SEB:
18453 check_nms(ctx);
18454 gen_bshfl(ctx, OPC_SEB, rs, rt);
18455 break;
18456 case NM_SEH:
18457 gen_bshfl(ctx, OPC_SEH, rs, rt);
18458 break;
18459 case NM_SLLV:
18460 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18461 break;
18462 case NM_SRLV:
18463 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18464 break;
18465 case NM_SRAV:
18466 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18467 break;
18468 case NM_ROTRV:
18469 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18470 break;
18471 case NM_ADD:
18472 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18473 break;
18474 case NM_ADDU:
18475 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18476 break;
18477 case NM_SUB:
18478 check_nms(ctx);
18479 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18480 break;
18481 case NM_SUBU:
18482 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18483 break;
18484 case NM_P_CMOVE:
18485 switch (extract32(ctx->opcode, 10, 1)) {
18486 case NM_MOVZ:
18487 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18488 break;
18489 case NM_MOVN:
18490 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18491 break;
18493 break;
18494 case NM_AND:
18495 gen_logic(ctx, OPC_AND, rd, rs, rt);
18496 break;
18497 case NM_OR:
18498 gen_logic(ctx, OPC_OR, rd, rs, rt);
18499 break;
18500 case NM_NOR:
18501 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18502 break;
18503 case NM_XOR:
18504 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18505 break;
18506 case NM_SLT:
18507 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18508 break;
18509 case NM_P_SLTU:
18510 if (rd == 0) {
18511 /* P_DVP */
18512 #ifndef CONFIG_USER_ONLY
18513 TCGv t0 = tcg_temp_new();
18514 switch (extract32(ctx->opcode, 10, 1)) {
18515 case NM_DVP:
18516 if (ctx->vp) {
18517 check_cp0_enabled(ctx);
18518 gen_helper_dvp(t0, cpu_env);
18519 gen_store_gpr(t0, rt);
18521 break;
18522 case NM_EVP:
18523 if (ctx->vp) {
18524 check_cp0_enabled(ctx);
18525 gen_helper_evp(t0, cpu_env);
18526 gen_store_gpr(t0, rt);
18528 break;
18530 tcg_temp_free(t0);
18531 #endif
18532 } else {
18533 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18535 break;
18536 case NM_SOV:
18538 TCGv t0 = tcg_temp_new();
18539 TCGv t1 = tcg_temp_new();
18540 TCGv t2 = tcg_temp_new();
18542 gen_load_gpr(t1, rs);
18543 gen_load_gpr(t2, rt);
18544 tcg_gen_add_tl(t0, t1, t2);
18545 tcg_gen_ext32s_tl(t0, t0);
18546 tcg_gen_xor_tl(t1, t1, t2);
18547 tcg_gen_xor_tl(t2, t0, t2);
18548 tcg_gen_andc_tl(t1, t2, t1);
18550 /* operands of same sign, result different sign */
18551 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18552 gen_store_gpr(t0, rd);
18554 tcg_temp_free(t0);
18555 tcg_temp_free(t1);
18556 tcg_temp_free(t2);
18558 break;
18559 case NM_MUL:
18560 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18561 break;
18562 case NM_MUH:
18563 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18564 break;
18565 case NM_MULU:
18566 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18567 break;
18568 case NM_MUHU:
18569 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18570 break;
18571 case NM_DIV:
18572 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18573 break;
18574 case NM_MOD:
18575 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18576 break;
18577 case NM_DIVU:
18578 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18579 break;
18580 case NM_MODU:
18581 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18582 break;
18583 #ifndef CONFIG_USER_ONLY
18584 case NM_MFC0:
18585 check_cp0_enabled(ctx);
18586 if (rt == 0) {
18587 /* Treat as NOP. */
18588 break;
18590 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18591 break;
18592 case NM_MTC0:
18593 check_cp0_enabled(ctx);
18595 TCGv t0 = tcg_temp_new();
18597 gen_load_gpr(t0, rt);
18598 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18599 tcg_temp_free(t0);
18601 break;
18602 case NM_D_E_MT_VPE:
18604 uint8_t sc = extract32(ctx->opcode, 10, 1);
18605 TCGv t0 = tcg_temp_new();
18607 switch (sc) {
18608 case 0:
18609 if (rs == 1) {
18610 /* DMT */
18611 check_cp0_mt(ctx);
18612 gen_helper_dmt(t0);
18613 gen_store_gpr(t0, rt);
18614 } else if (rs == 0) {
18615 /* DVPE */
18616 check_cp0_mt(ctx);
18617 gen_helper_dvpe(t0, cpu_env);
18618 gen_store_gpr(t0, rt);
18619 } else {
18620 generate_exception_end(ctx, EXCP_RI);
18622 break;
18623 case 1:
18624 if (rs == 1) {
18625 /* EMT */
18626 check_cp0_mt(ctx);
18627 gen_helper_emt(t0);
18628 gen_store_gpr(t0, rt);
18629 } else if (rs == 0) {
18630 /* EVPE */
18631 check_cp0_mt(ctx);
18632 gen_helper_evpe(t0, cpu_env);
18633 gen_store_gpr(t0, rt);
18634 } else {
18635 generate_exception_end(ctx, EXCP_RI);
18637 break;
18640 tcg_temp_free(t0);
18642 break;
18643 case NM_FORK:
18644 check_mt(ctx);
18646 TCGv t0 = tcg_temp_new();
18647 TCGv t1 = tcg_temp_new();
18649 gen_load_gpr(t0, rt);
18650 gen_load_gpr(t1, rs);
18651 gen_helper_fork(t0, t1);
18652 tcg_temp_free(t0);
18653 tcg_temp_free(t1);
18655 break;
18656 case NM_MFTR:
18657 case NM_MFHTR:
18658 check_cp0_enabled(ctx);
18659 if (rd == 0) {
18660 /* Treat as NOP. */
18661 return;
18663 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18664 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18665 break;
18666 case NM_MTTR:
18667 case NM_MTHTR:
18668 check_cp0_enabled(ctx);
18669 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18670 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18671 break;
18672 case NM_YIELD:
18673 check_mt(ctx);
18675 TCGv t0 = tcg_temp_new();
18677 gen_load_gpr(t0, rs);
18678 gen_helper_yield(t0, cpu_env, t0);
18679 gen_store_gpr(t0, rt);
18680 tcg_temp_free(t0);
18682 break;
18683 #endif
18684 default:
18685 generate_exception_end(ctx, EXCP_RI);
18686 break;
18690 /* dsp */
18691 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18692 int ret, int v1, int v2)
18694 TCGv_i32 t0;
18695 TCGv v0_t;
18696 TCGv v1_t;
18698 t0 = tcg_temp_new_i32();
18700 v0_t = tcg_temp_new();
18701 v1_t = tcg_temp_new();
18703 tcg_gen_movi_i32(t0, v2 >> 3);
18705 gen_load_gpr(v0_t, ret);
18706 gen_load_gpr(v1_t, v1);
18708 switch (opc) {
18709 case NM_MAQ_S_W_PHR:
18710 check_dsp(ctx);
18711 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18712 break;
18713 case NM_MAQ_S_W_PHL:
18714 check_dsp(ctx);
18715 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18716 break;
18717 case NM_MAQ_SA_W_PHR:
18718 check_dsp(ctx);
18719 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18720 break;
18721 case NM_MAQ_SA_W_PHL:
18722 check_dsp(ctx);
18723 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18724 break;
18725 default:
18726 generate_exception_end(ctx, EXCP_RI);
18727 break;
18730 tcg_temp_free_i32(t0);
18732 tcg_temp_free(v0_t);
18733 tcg_temp_free(v1_t);
18737 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18738 int ret, int v1, int v2)
18740 int16_t imm;
18741 TCGv t0 = tcg_temp_new();
18742 TCGv t1 = tcg_temp_new();
18743 TCGv v0_t = tcg_temp_new();
18745 gen_load_gpr(v0_t, v1);
18747 switch (opc) {
18748 case NM_POOL32AXF_1_0:
18749 check_dsp(ctx);
18750 switch (extract32(ctx->opcode, 12, 2)) {
18751 case NM_MFHI:
18752 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18753 break;
18754 case NM_MFLO:
18755 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18756 break;
18757 case NM_MTHI:
18758 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18759 break;
18760 case NM_MTLO:
18761 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18762 break;
18764 break;
18765 case NM_POOL32AXF_1_1:
18766 check_dsp(ctx);
18767 switch (extract32(ctx->opcode, 12, 2)) {
18768 case NM_MTHLIP:
18769 tcg_gen_movi_tl(t0, v2);
18770 gen_helper_mthlip(t0, v0_t, cpu_env);
18771 break;
18772 case NM_SHILOV:
18773 tcg_gen_movi_tl(t0, v2 >> 3);
18774 gen_helper_shilo(t0, v0_t, cpu_env);
18775 break;
18776 default:
18777 generate_exception_end(ctx, EXCP_RI);
18778 break;
18780 break;
18781 case NM_POOL32AXF_1_3:
18782 check_dsp(ctx);
18783 imm = extract32(ctx->opcode, 14, 7);
18784 switch (extract32(ctx->opcode, 12, 2)) {
18785 case NM_RDDSP:
18786 tcg_gen_movi_tl(t0, imm);
18787 gen_helper_rddsp(t0, t0, cpu_env);
18788 gen_store_gpr(t0, ret);
18789 break;
18790 case NM_WRDSP:
18791 gen_load_gpr(t0, ret);
18792 tcg_gen_movi_tl(t1, imm);
18793 gen_helper_wrdsp(t0, t1, cpu_env);
18794 break;
18795 case NM_EXTP:
18796 tcg_gen_movi_tl(t0, v2 >> 3);
18797 tcg_gen_movi_tl(t1, v1);
18798 gen_helper_extp(t0, t0, t1, cpu_env);
18799 gen_store_gpr(t0, ret);
18800 break;
18801 case NM_EXTPDP:
18802 tcg_gen_movi_tl(t0, v2 >> 3);
18803 tcg_gen_movi_tl(t1, v1);
18804 gen_helper_extpdp(t0, t0, t1, cpu_env);
18805 gen_store_gpr(t0, ret);
18806 break;
18808 break;
18809 case NM_POOL32AXF_1_4:
18810 check_dsp(ctx);
18811 tcg_gen_movi_tl(t0, v2 >> 2);
18812 switch (extract32(ctx->opcode, 12, 1)) {
18813 case NM_SHLL_QB:
18814 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18815 gen_store_gpr(t0, ret);
18816 break;
18817 case NM_SHRL_QB:
18818 gen_helper_shrl_qb(t0, t0, v0_t);
18819 gen_store_gpr(t0, ret);
18820 break;
18822 break;
18823 case NM_POOL32AXF_1_5:
18824 opc = extract32(ctx->opcode, 12, 2);
18825 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18826 break;
18827 case NM_POOL32AXF_1_7:
18828 check_dsp(ctx);
18829 tcg_gen_movi_tl(t0, v2 >> 3);
18830 tcg_gen_movi_tl(t1, v1);
18831 switch (extract32(ctx->opcode, 12, 2)) {
18832 case NM_EXTR_W:
18833 gen_helper_extr_w(t0, t0, t1, cpu_env);
18834 gen_store_gpr(t0, ret);
18835 break;
18836 case NM_EXTR_R_W:
18837 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18838 gen_store_gpr(t0, ret);
18839 break;
18840 case NM_EXTR_RS_W:
18841 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18842 gen_store_gpr(t0, ret);
18843 break;
18844 case NM_EXTR_S_H:
18845 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18846 gen_store_gpr(t0, ret);
18847 break;
18849 break;
18850 default:
18851 generate_exception_end(ctx, EXCP_RI);
18852 break;
18855 tcg_temp_free(t0);
18856 tcg_temp_free(t1);
18857 tcg_temp_free(v0_t);
18860 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18861 TCGv v0, TCGv v1, int rd)
18863 TCGv_i32 t0;
18865 t0 = tcg_temp_new_i32();
18867 tcg_gen_movi_i32(t0, rd >> 3);
18869 switch (opc) {
18870 case NM_POOL32AXF_2_0_7:
18871 switch (extract32(ctx->opcode, 9, 3)) {
18872 case NM_DPA_W_PH:
18873 check_dsp_r2(ctx);
18874 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18875 break;
18876 case NM_DPAQ_S_W_PH:
18877 check_dsp(ctx);
18878 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18879 break;
18880 case NM_DPS_W_PH:
18881 check_dsp_r2(ctx);
18882 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18883 break;
18884 case NM_DPSQ_S_W_PH:
18885 check_dsp(ctx);
18886 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18887 break;
18888 default:
18889 generate_exception_end(ctx, EXCP_RI);
18890 break;
18892 break;
18893 case NM_POOL32AXF_2_8_15:
18894 switch (extract32(ctx->opcode, 9, 3)) {
18895 case NM_DPAX_W_PH:
18896 check_dsp_r2(ctx);
18897 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18898 break;
18899 case NM_DPAQ_SA_L_W:
18900 check_dsp(ctx);
18901 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18902 break;
18903 case NM_DPSX_W_PH:
18904 check_dsp_r2(ctx);
18905 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18906 break;
18907 case NM_DPSQ_SA_L_W:
18908 check_dsp(ctx);
18909 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18910 break;
18911 default:
18912 generate_exception_end(ctx, EXCP_RI);
18913 break;
18915 break;
18916 case NM_POOL32AXF_2_16_23:
18917 switch (extract32(ctx->opcode, 9, 3)) {
18918 case NM_DPAU_H_QBL:
18919 check_dsp(ctx);
18920 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18921 break;
18922 case NM_DPAQX_S_W_PH:
18923 check_dsp_r2(ctx);
18924 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18925 break;
18926 case NM_DPSU_H_QBL:
18927 check_dsp(ctx);
18928 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18929 break;
18930 case NM_DPSQX_S_W_PH:
18931 check_dsp_r2(ctx);
18932 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18933 break;
18934 case NM_MULSA_W_PH:
18935 check_dsp_r2(ctx);
18936 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18937 break;
18938 default:
18939 generate_exception_end(ctx, EXCP_RI);
18940 break;
18942 break;
18943 case NM_POOL32AXF_2_24_31:
18944 switch (extract32(ctx->opcode, 9, 3)) {
18945 case NM_DPAU_H_QBR:
18946 check_dsp(ctx);
18947 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18948 break;
18949 case NM_DPAQX_SA_W_PH:
18950 check_dsp_r2(ctx);
18951 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18952 break;
18953 case NM_DPSU_H_QBR:
18954 check_dsp(ctx);
18955 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18956 break;
18957 case NM_DPSQX_SA_W_PH:
18958 check_dsp_r2(ctx);
18959 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18960 break;
18961 case NM_MULSAQ_S_W_PH:
18962 check_dsp(ctx);
18963 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18964 break;
18965 default:
18966 generate_exception_end(ctx, EXCP_RI);
18967 break;
18969 break;
18970 default:
18971 generate_exception_end(ctx, EXCP_RI);
18972 break;
18975 tcg_temp_free_i32(t0);
18978 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18979 int rt, int rs, int rd)
18981 int ret = rt;
18982 TCGv t0 = tcg_temp_new();
18983 TCGv t1 = tcg_temp_new();
18984 TCGv v0_t = tcg_temp_new();
18985 TCGv v1_t = tcg_temp_new();
18987 gen_load_gpr(v0_t, rt);
18988 gen_load_gpr(v1_t, rs);
18990 switch (opc) {
18991 case NM_POOL32AXF_2_0_7:
18992 switch (extract32(ctx->opcode, 9, 3)) {
18993 case NM_DPA_W_PH:
18994 case NM_DPAQ_S_W_PH:
18995 case NM_DPS_W_PH:
18996 case NM_DPSQ_S_W_PH:
18997 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18998 break;
18999 case NM_BALIGN:
19000 check_dsp_r2(ctx);
19001 if (rt != 0) {
19002 gen_load_gpr(t0, rs);
19003 rd &= 3;
19004 if (rd != 0 && rd != 2) {
19005 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19006 tcg_gen_ext32u_tl(t0, t0);
19007 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19008 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19010 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19012 break;
19013 case NM_MADD:
19014 check_dsp(ctx);
19016 int acc = extract32(ctx->opcode, 14, 2);
19017 TCGv_i64 t2 = tcg_temp_new_i64();
19018 TCGv_i64 t3 = tcg_temp_new_i64();
19020 gen_load_gpr(t0, rt);
19021 gen_load_gpr(t1, rs);
19022 tcg_gen_ext_tl_i64(t2, t0);
19023 tcg_gen_ext_tl_i64(t3, t1);
19024 tcg_gen_mul_i64(t2, t2, t3);
19025 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19026 tcg_gen_add_i64(t2, t2, t3);
19027 tcg_temp_free_i64(t3);
19028 gen_move_low32(cpu_LO[acc], t2);
19029 gen_move_high32(cpu_HI[acc], t2);
19030 tcg_temp_free_i64(t2);
19032 break;
19033 case NM_MULT:
19034 check_dsp(ctx);
19036 int acc = extract32(ctx->opcode, 14, 2);
19037 TCGv_i32 t2 = tcg_temp_new_i32();
19038 TCGv_i32 t3 = tcg_temp_new_i32();
19040 gen_load_gpr(t0, rs);
19041 gen_load_gpr(t1, rt);
19042 tcg_gen_trunc_tl_i32(t2, t0);
19043 tcg_gen_trunc_tl_i32(t3, t1);
19044 tcg_gen_muls2_i32(t2, t3, t2, t3);
19045 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19046 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19047 tcg_temp_free_i32(t2);
19048 tcg_temp_free_i32(t3);
19050 break;
19051 case NM_EXTRV_W:
19052 check_dsp(ctx);
19053 gen_load_gpr(v1_t, rs);
19054 tcg_gen_movi_tl(t0, rd >> 3);
19055 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19056 gen_store_gpr(t0, ret);
19057 break;
19059 break;
19060 case NM_POOL32AXF_2_8_15:
19061 switch (extract32(ctx->opcode, 9, 3)) {
19062 case NM_DPAX_W_PH:
19063 case NM_DPAQ_SA_L_W:
19064 case NM_DPSX_W_PH:
19065 case NM_DPSQ_SA_L_W:
19066 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19067 break;
19068 case NM_MADDU:
19069 check_dsp(ctx);
19071 int acc = extract32(ctx->opcode, 14, 2);
19072 TCGv_i64 t2 = tcg_temp_new_i64();
19073 TCGv_i64 t3 = tcg_temp_new_i64();
19075 gen_load_gpr(t0, rs);
19076 gen_load_gpr(t1, rt);
19077 tcg_gen_ext32u_tl(t0, t0);
19078 tcg_gen_ext32u_tl(t1, t1);
19079 tcg_gen_extu_tl_i64(t2, t0);
19080 tcg_gen_extu_tl_i64(t3, t1);
19081 tcg_gen_mul_i64(t2, t2, t3);
19082 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19083 tcg_gen_add_i64(t2, t2, t3);
19084 tcg_temp_free_i64(t3);
19085 gen_move_low32(cpu_LO[acc], t2);
19086 gen_move_high32(cpu_HI[acc], t2);
19087 tcg_temp_free_i64(t2);
19089 break;
19090 case NM_MULTU:
19091 check_dsp(ctx);
19093 int acc = extract32(ctx->opcode, 14, 2);
19094 TCGv_i32 t2 = tcg_temp_new_i32();
19095 TCGv_i32 t3 = tcg_temp_new_i32();
19097 gen_load_gpr(t0, rs);
19098 gen_load_gpr(t1, rt);
19099 tcg_gen_trunc_tl_i32(t2, t0);
19100 tcg_gen_trunc_tl_i32(t3, t1);
19101 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19102 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19103 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19104 tcg_temp_free_i32(t2);
19105 tcg_temp_free_i32(t3);
19107 break;
19108 case NM_EXTRV_R_W:
19109 check_dsp(ctx);
19110 tcg_gen_movi_tl(t0, rd >> 3);
19111 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19112 gen_store_gpr(t0, ret);
19113 break;
19114 default:
19115 generate_exception_end(ctx, EXCP_RI);
19116 break;
19118 break;
19119 case NM_POOL32AXF_2_16_23:
19120 switch (extract32(ctx->opcode, 9, 3)) {
19121 case NM_DPAU_H_QBL:
19122 case NM_DPAQX_S_W_PH:
19123 case NM_DPSU_H_QBL:
19124 case NM_DPSQX_S_W_PH:
19125 case NM_MULSA_W_PH:
19126 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19127 break;
19128 case NM_EXTPV:
19129 check_dsp(ctx);
19130 tcg_gen_movi_tl(t0, rd >> 3);
19131 gen_helper_extp(t0, t0, v1_t, cpu_env);
19132 gen_store_gpr(t0, ret);
19133 break;
19134 case NM_MSUB:
19135 check_dsp(ctx);
19137 int acc = extract32(ctx->opcode, 14, 2);
19138 TCGv_i64 t2 = tcg_temp_new_i64();
19139 TCGv_i64 t3 = tcg_temp_new_i64();
19141 gen_load_gpr(t0, rs);
19142 gen_load_gpr(t1, rt);
19143 tcg_gen_ext_tl_i64(t2, t0);
19144 tcg_gen_ext_tl_i64(t3, t1);
19145 tcg_gen_mul_i64(t2, t2, t3);
19146 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19147 tcg_gen_sub_i64(t2, t3, t2);
19148 tcg_temp_free_i64(t3);
19149 gen_move_low32(cpu_LO[acc], t2);
19150 gen_move_high32(cpu_HI[acc], t2);
19151 tcg_temp_free_i64(t2);
19153 break;
19154 case NM_EXTRV_RS_W:
19155 check_dsp(ctx);
19156 tcg_gen_movi_tl(t0, rd >> 3);
19157 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19158 gen_store_gpr(t0, ret);
19159 break;
19161 break;
19162 case NM_POOL32AXF_2_24_31:
19163 switch (extract32(ctx->opcode, 9, 3)) {
19164 case NM_DPAU_H_QBR:
19165 case NM_DPAQX_SA_W_PH:
19166 case NM_DPSU_H_QBR:
19167 case NM_DPSQX_SA_W_PH:
19168 case NM_MULSAQ_S_W_PH:
19169 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19170 break;
19171 case NM_EXTPDPV:
19172 check_dsp(ctx);
19173 tcg_gen_movi_tl(t0, rd >> 3);
19174 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19175 gen_store_gpr(t0, ret);
19176 break;
19177 case NM_MSUBU:
19178 check_dsp(ctx);
19180 int acc = extract32(ctx->opcode, 14, 2);
19181 TCGv_i64 t2 = tcg_temp_new_i64();
19182 TCGv_i64 t3 = tcg_temp_new_i64();
19184 gen_load_gpr(t0, rs);
19185 gen_load_gpr(t1, rt);
19186 tcg_gen_ext32u_tl(t0, t0);
19187 tcg_gen_ext32u_tl(t1, t1);
19188 tcg_gen_extu_tl_i64(t2, t0);
19189 tcg_gen_extu_tl_i64(t3, t1);
19190 tcg_gen_mul_i64(t2, t2, t3);
19191 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19192 tcg_gen_sub_i64(t2, t3, t2);
19193 tcg_temp_free_i64(t3);
19194 gen_move_low32(cpu_LO[acc], t2);
19195 gen_move_high32(cpu_HI[acc], t2);
19196 tcg_temp_free_i64(t2);
19198 break;
19199 case NM_EXTRV_S_H:
19200 check_dsp(ctx);
19201 tcg_gen_movi_tl(t0, rd >> 3);
19202 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19203 gen_store_gpr(t0, ret);
19204 break;
19206 break;
19207 default:
19208 generate_exception_end(ctx, EXCP_RI);
19209 break;
19212 tcg_temp_free(t0);
19213 tcg_temp_free(t1);
19215 tcg_temp_free(v0_t);
19216 tcg_temp_free(v1_t);
19219 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19220 int rt, int rs)
19222 int ret = rt;
19223 TCGv t0 = tcg_temp_new();
19224 TCGv v0_t = tcg_temp_new();
19226 gen_load_gpr(v0_t, rs);
19228 switch (opc) {
19229 case NM_ABSQ_S_QB:
19230 check_dsp_r2(ctx);
19231 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19232 gen_store_gpr(v0_t, ret);
19233 break;
19234 case NM_ABSQ_S_PH:
19235 check_dsp(ctx);
19236 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19237 gen_store_gpr(v0_t, ret);
19238 break;
19239 case NM_ABSQ_S_W:
19240 check_dsp(ctx);
19241 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19242 gen_store_gpr(v0_t, ret);
19243 break;
19244 case NM_PRECEQ_W_PHL:
19245 check_dsp(ctx);
19246 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19247 tcg_gen_ext32s_tl(v0_t, v0_t);
19248 gen_store_gpr(v0_t, ret);
19249 break;
19250 case NM_PRECEQ_W_PHR:
19251 check_dsp(ctx);
19252 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19253 tcg_gen_shli_tl(v0_t, v0_t, 16);
19254 tcg_gen_ext32s_tl(v0_t, v0_t);
19255 gen_store_gpr(v0_t, ret);
19256 break;
19257 case NM_PRECEQU_PH_QBL:
19258 check_dsp(ctx);
19259 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19260 gen_store_gpr(v0_t, ret);
19261 break;
19262 case NM_PRECEQU_PH_QBR:
19263 check_dsp(ctx);
19264 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19265 gen_store_gpr(v0_t, ret);
19266 break;
19267 case NM_PRECEQU_PH_QBLA:
19268 check_dsp(ctx);
19269 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19270 gen_store_gpr(v0_t, ret);
19271 break;
19272 case NM_PRECEQU_PH_QBRA:
19273 check_dsp(ctx);
19274 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19275 gen_store_gpr(v0_t, ret);
19276 break;
19277 case NM_PRECEU_PH_QBL:
19278 check_dsp(ctx);
19279 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19280 gen_store_gpr(v0_t, ret);
19281 break;
19282 case NM_PRECEU_PH_QBR:
19283 check_dsp(ctx);
19284 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19285 gen_store_gpr(v0_t, ret);
19286 break;
19287 case NM_PRECEU_PH_QBLA:
19288 check_dsp(ctx);
19289 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19290 gen_store_gpr(v0_t, ret);
19291 break;
19292 case NM_PRECEU_PH_QBRA:
19293 check_dsp(ctx);
19294 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19295 gen_store_gpr(v0_t, ret);
19296 break;
19297 case NM_REPLV_PH:
19298 check_dsp(ctx);
19299 tcg_gen_ext16u_tl(v0_t, v0_t);
19300 tcg_gen_shli_tl(t0, v0_t, 16);
19301 tcg_gen_or_tl(v0_t, v0_t, t0);
19302 tcg_gen_ext32s_tl(v0_t, v0_t);
19303 gen_store_gpr(v0_t, ret);
19304 break;
19305 case NM_REPLV_QB:
19306 check_dsp(ctx);
19307 tcg_gen_ext8u_tl(v0_t, v0_t);
19308 tcg_gen_shli_tl(t0, v0_t, 8);
19309 tcg_gen_or_tl(v0_t, v0_t, t0);
19310 tcg_gen_shli_tl(t0, v0_t, 16);
19311 tcg_gen_or_tl(v0_t, v0_t, t0);
19312 tcg_gen_ext32s_tl(v0_t, v0_t);
19313 gen_store_gpr(v0_t, ret);
19314 break;
19315 case NM_BITREV:
19316 check_dsp(ctx);
19317 gen_helper_bitrev(v0_t, v0_t);
19318 gen_store_gpr(v0_t, ret);
19319 break;
19320 case NM_INSV:
19321 check_dsp(ctx);
19323 TCGv tv0 = tcg_temp_new();
19325 gen_load_gpr(tv0, rt);
19326 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19327 gen_store_gpr(v0_t, ret);
19328 tcg_temp_free(tv0);
19330 break;
19331 case NM_RADDU_W_QB:
19332 check_dsp(ctx);
19333 gen_helper_raddu_w_qb(v0_t, v0_t);
19334 gen_store_gpr(v0_t, ret);
19335 break;
19336 case NM_BITSWAP:
19337 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19338 break;
19339 case NM_CLO:
19340 check_nms(ctx);
19341 gen_cl(ctx, OPC_CLO, ret, rs);
19342 break;
19343 case NM_CLZ:
19344 check_nms(ctx);
19345 gen_cl(ctx, OPC_CLZ, ret, rs);
19346 break;
19347 case NM_WSBH:
19348 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19349 break;
19350 default:
19351 generate_exception_end(ctx, EXCP_RI);
19352 break;
19355 tcg_temp_free(v0_t);
19356 tcg_temp_free(t0);
19359 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19360 int rt, int rs, int rd)
19362 TCGv t0 = tcg_temp_new();
19363 TCGv rs_t = tcg_temp_new();
19365 gen_load_gpr(rs_t, rs);
19367 switch (opc) {
19368 case NM_SHRA_R_QB:
19369 check_dsp_r2(ctx);
19370 tcg_gen_movi_tl(t0, rd >> 2);
19371 switch (extract32(ctx->opcode, 12, 1)) {
19372 case 0:
19373 /* NM_SHRA_QB */
19374 gen_helper_shra_qb(t0, t0, rs_t);
19375 gen_store_gpr(t0, rt);
19376 break;
19377 case 1:
19378 /* NM_SHRA_R_QB */
19379 gen_helper_shra_r_qb(t0, t0, rs_t);
19380 gen_store_gpr(t0, rt);
19381 break;
19383 break;
19384 case NM_SHRL_PH:
19385 check_dsp_r2(ctx);
19386 tcg_gen_movi_tl(t0, rd >> 1);
19387 gen_helper_shrl_ph(t0, t0, rs_t);
19388 gen_store_gpr(t0, rt);
19389 break;
19390 case NM_REPL_QB:
19391 check_dsp(ctx);
19393 int16_t imm;
19394 target_long result;
19395 imm = extract32(ctx->opcode, 13, 8);
19396 result = (uint32_t)imm << 24 |
19397 (uint32_t)imm << 16 |
19398 (uint32_t)imm << 8 |
19399 (uint32_t)imm;
19400 result = (int32_t)result;
19401 tcg_gen_movi_tl(t0, result);
19402 gen_store_gpr(t0, rt);
19404 break;
19405 default:
19406 generate_exception_end(ctx, EXCP_RI);
19407 break;
19409 tcg_temp_free(t0);
19410 tcg_temp_free(rs_t);
19414 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19416 int rt = extract32(ctx->opcode, 21, 5);
19417 int rs = extract32(ctx->opcode, 16, 5);
19418 int rd = extract32(ctx->opcode, 11, 5);
19420 switch (extract32(ctx->opcode, 6, 3)) {
19421 case NM_POOL32AXF_1:
19423 int32_t op1 = extract32(ctx->opcode, 9, 3);
19424 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19426 break;
19427 case NM_POOL32AXF_2:
19429 int32_t op1 = extract32(ctx->opcode, 12, 2);
19430 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19432 break;
19433 case NM_POOL32AXF_4:
19435 int32_t op1 = extract32(ctx->opcode, 9, 7);
19436 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19438 break;
19439 case NM_POOL32AXF_5:
19440 switch (extract32(ctx->opcode, 9, 7)) {
19441 #ifndef CONFIG_USER_ONLY
19442 case NM_TLBP:
19443 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19444 break;
19445 case NM_TLBR:
19446 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19447 break;
19448 case NM_TLBWI:
19449 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19450 break;
19451 case NM_TLBWR:
19452 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19453 break;
19454 case NM_TLBINV:
19455 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19456 break;
19457 case NM_TLBINVF:
19458 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19459 break;
19460 case NM_DI:
19461 check_cp0_enabled(ctx);
19463 TCGv t0 = tcg_temp_new();
19465 save_cpu_state(ctx, 1);
19466 gen_helper_di(t0, cpu_env);
19467 gen_store_gpr(t0, rt);
19468 /* Stop translation as we may have switched the execution mode */
19469 ctx->base.is_jmp = DISAS_STOP;
19470 tcg_temp_free(t0);
19472 break;
19473 case NM_EI:
19474 check_cp0_enabled(ctx);
19476 TCGv t0 = tcg_temp_new();
19478 save_cpu_state(ctx, 1);
19479 gen_helper_ei(t0, cpu_env);
19480 gen_store_gpr(t0, rt);
19481 /* Stop translation as we may have switched the execution mode */
19482 ctx->base.is_jmp = DISAS_STOP;
19483 tcg_temp_free(t0);
19485 break;
19486 case NM_RDPGPR:
19487 gen_load_srsgpr(rs, rt);
19488 break;
19489 case NM_WRPGPR:
19490 gen_store_srsgpr(rs, rt);
19491 break;
19492 case NM_WAIT:
19493 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19494 break;
19495 case NM_DERET:
19496 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19497 break;
19498 case NM_ERETX:
19499 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19500 break;
19501 #endif
19502 default:
19503 generate_exception_end(ctx, EXCP_RI);
19504 break;
19506 break;
19507 case NM_POOL32AXF_7:
19509 int32_t op1 = extract32(ctx->opcode, 9, 3);
19510 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19512 break;
19513 default:
19514 generate_exception_end(ctx, EXCP_RI);
19515 break;
19519 /* Immediate Value Compact Branches */
19520 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19521 int rt, int32_t imm, int32_t offset)
19523 TCGCond cond;
19524 int bcond_compute = 0;
19525 TCGv t0 = tcg_temp_new();
19526 TCGv t1 = tcg_temp_new();
19528 gen_load_gpr(t0, rt);
19529 tcg_gen_movi_tl(t1, imm);
19530 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19532 /* Load needed operands and calculate btarget */
19533 switch (opc) {
19534 case NM_BEQIC:
19535 if (rt == 0 && imm == 0) {
19536 /* Unconditional branch */
19537 } else if (rt == 0 && imm != 0) {
19538 /* Treat as NOP */
19539 goto out;
19540 } else {
19541 bcond_compute = 1;
19542 cond = TCG_COND_EQ;
19544 break;
19545 case NM_BBEQZC:
19546 case NM_BBNEZC:
19547 check_nms(ctx);
19548 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19549 generate_exception_end(ctx, EXCP_RI);
19550 goto out;
19551 } else if (rt == 0 && opc == NM_BBEQZC) {
19552 /* Unconditional branch */
19553 } else if (rt == 0 && opc == NM_BBNEZC) {
19554 /* Treat as NOP */
19555 goto out;
19556 } else {
19557 tcg_gen_shri_tl(t0, t0, imm);
19558 tcg_gen_andi_tl(t0, t0, 1);
19559 tcg_gen_movi_tl(t1, 0);
19560 bcond_compute = 1;
19561 if (opc == NM_BBEQZC) {
19562 cond = TCG_COND_EQ;
19563 } else {
19564 cond = TCG_COND_NE;
19567 break;
19568 case NM_BNEIC:
19569 if (rt == 0 && imm == 0) {
19570 /* Treat as NOP */
19571 goto out;
19572 } else if (rt == 0 && imm != 0) {
19573 /* Unconditional branch */
19574 } else {
19575 bcond_compute = 1;
19576 cond = TCG_COND_NE;
19578 break;
19579 case NM_BGEIC:
19580 if (rt == 0 && imm == 0) {
19581 /* Unconditional branch */
19582 } else {
19583 bcond_compute = 1;
19584 cond = TCG_COND_GE;
19586 break;
19587 case NM_BLTIC:
19588 bcond_compute = 1;
19589 cond = TCG_COND_LT;
19590 break;
19591 case NM_BGEIUC:
19592 if (rt == 0 && imm == 0) {
19593 /* Unconditional branch */
19594 } else {
19595 bcond_compute = 1;
19596 cond = TCG_COND_GEU;
19598 break;
19599 case NM_BLTIUC:
19600 bcond_compute = 1;
19601 cond = TCG_COND_LTU;
19602 break;
19603 default:
19604 MIPS_INVAL("Immediate Value Compact branch");
19605 generate_exception_end(ctx, EXCP_RI);
19606 goto out;
19609 if (bcond_compute == 0) {
19610 /* Uncoditional compact branch */
19611 gen_goto_tb(ctx, 0, ctx->btarget);
19612 } else {
19613 /* Conditional compact branch */
19614 TCGLabel *fs = gen_new_label();
19616 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19618 gen_goto_tb(ctx, 1, ctx->btarget);
19619 gen_set_label(fs);
19621 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19624 out:
19625 tcg_temp_free(t0);
19626 tcg_temp_free(t1);
19629 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19630 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19631 int rt)
19633 TCGv t0 = tcg_temp_new();
19634 TCGv t1 = tcg_temp_new();
19636 /* load rs */
19637 gen_load_gpr(t0, rs);
19639 /* link */
19640 if (rt != 0) {
19641 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19644 /* calculate btarget */
19645 tcg_gen_shli_tl(t0, t0, 1);
19646 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19647 gen_op_addr_add(ctx, btarget, t1, t0);
19649 /* unconditional branch to register */
19650 tcg_gen_mov_tl(cpu_PC, btarget);
19651 tcg_gen_lookup_and_goto_ptr();
19653 tcg_temp_free(t0);
19654 tcg_temp_free(t1);
19657 /* nanoMIPS Branches */
19658 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19659 int rs, int rt, int32_t offset)
19661 int bcond_compute = 0;
19662 TCGv t0 = tcg_temp_new();
19663 TCGv t1 = tcg_temp_new();
19665 /* Load needed operands and calculate btarget */
19666 switch (opc) {
19667 /* compact branch */
19668 case OPC_BGEC:
19669 case OPC_BLTC:
19670 gen_load_gpr(t0, rs);
19671 gen_load_gpr(t1, rt);
19672 bcond_compute = 1;
19673 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19674 break;
19675 case OPC_BGEUC:
19676 case OPC_BLTUC:
19677 if (rs == 0 || rs == rt) {
19678 /* OPC_BLEZALC, OPC_BGEZALC */
19679 /* OPC_BGTZALC, OPC_BLTZALC */
19680 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19682 gen_load_gpr(t0, rs);
19683 gen_load_gpr(t1, rt);
19684 bcond_compute = 1;
19685 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19686 break;
19687 case OPC_BC:
19688 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19689 break;
19690 case OPC_BEQZC:
19691 if (rs != 0) {
19692 /* OPC_BEQZC, OPC_BNEZC */
19693 gen_load_gpr(t0, rs);
19694 bcond_compute = 1;
19695 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19696 } else {
19697 /* OPC_JIC, OPC_JIALC */
19698 TCGv tbase = tcg_temp_new();
19699 TCGv toffset = tcg_temp_new();
19701 gen_load_gpr(tbase, rt);
19702 tcg_gen_movi_tl(toffset, offset);
19703 gen_op_addr_add(ctx, btarget, tbase, toffset);
19704 tcg_temp_free(tbase);
19705 tcg_temp_free(toffset);
19707 break;
19708 default:
19709 MIPS_INVAL("Compact branch/jump");
19710 generate_exception_end(ctx, EXCP_RI);
19711 goto out;
19714 if (bcond_compute == 0) {
19715 /* Uncoditional compact branch */
19716 switch (opc) {
19717 case OPC_BC:
19718 gen_goto_tb(ctx, 0, ctx->btarget);
19719 break;
19720 default:
19721 MIPS_INVAL("Compact branch/jump");
19722 generate_exception_end(ctx, EXCP_RI);
19723 goto out;
19725 } else {
19726 /* Conditional compact branch */
19727 TCGLabel *fs = gen_new_label();
19729 switch (opc) {
19730 case OPC_BGEUC:
19731 if (rs == 0 && rt != 0) {
19732 /* OPC_BLEZALC */
19733 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19734 } else if (rs != 0 && rt != 0 && rs == rt) {
19735 /* OPC_BGEZALC */
19736 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19737 } else {
19738 /* OPC_BGEUC */
19739 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19741 break;
19742 case OPC_BLTUC:
19743 if (rs == 0 && rt != 0) {
19744 /* OPC_BGTZALC */
19745 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19746 } else if (rs != 0 && rt != 0 && rs == rt) {
19747 /* OPC_BLTZALC */
19748 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19749 } else {
19750 /* OPC_BLTUC */
19751 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19753 break;
19754 case OPC_BGEC:
19755 if (rs == 0 && rt != 0) {
19756 /* OPC_BLEZC */
19757 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19758 } else if (rs != 0 && rt != 0 && rs == rt) {
19759 /* OPC_BGEZC */
19760 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19761 } else {
19762 /* OPC_BGEC */
19763 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19765 break;
19766 case OPC_BLTC:
19767 if (rs == 0 && rt != 0) {
19768 /* OPC_BGTZC */
19769 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19770 } else if (rs != 0 && rt != 0 && rs == rt) {
19771 /* OPC_BLTZC */
19772 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19773 } else {
19774 /* OPC_BLTC */
19775 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19777 break;
19778 case OPC_BEQZC:
19779 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19780 break;
19781 default:
19782 MIPS_INVAL("Compact conditional branch/jump");
19783 generate_exception_end(ctx, EXCP_RI);
19784 goto out;
19787 /* Generating branch here as compact branches don't have delay slot */
19788 gen_goto_tb(ctx, 1, ctx->btarget);
19789 gen_set_label(fs);
19791 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19794 out:
19795 tcg_temp_free(t0);
19796 tcg_temp_free(t1);
19800 /* nanoMIPS CP1 Branches */
19801 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19802 int32_t ft, int32_t offset)
19804 target_ulong btarget;
19805 TCGv_i64 t0 = tcg_temp_new_i64();
19807 gen_load_fpr64(ctx, t0, ft);
19808 tcg_gen_andi_i64(t0, t0, 1);
19810 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19812 switch (op) {
19813 case NM_BC1EQZC:
19814 tcg_gen_xori_i64(t0, t0, 1);
19815 ctx->hflags |= MIPS_HFLAG_BC;
19816 break;
19817 case NM_BC1NEZC:
19818 /* t0 already set */
19819 ctx->hflags |= MIPS_HFLAG_BC;
19820 break;
19821 default:
19822 MIPS_INVAL("cp1 cond branch");
19823 generate_exception_end(ctx, EXCP_RI);
19824 goto out;
19827 tcg_gen_trunc_i64_tl(bcond, t0);
19829 ctx->btarget = btarget;
19831 out:
19832 tcg_temp_free_i64(t0);
19836 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19838 TCGv t0, t1;
19839 t0 = tcg_temp_new();
19840 t1 = tcg_temp_new();
19842 gen_load_gpr(t0, rs);
19843 gen_load_gpr(t1, rt);
19845 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19846 /* PP.LSXS instructions require shifting */
19847 switch (extract32(ctx->opcode, 7, 4)) {
19848 case NM_SHXS:
19849 check_nms(ctx);
19850 case NM_LHXS:
19851 case NM_LHUXS:
19852 tcg_gen_shli_tl(t0, t0, 1);
19853 break;
19854 case NM_SWXS:
19855 check_nms(ctx);
19856 case NM_LWXS:
19857 case NM_LWC1XS:
19858 case NM_SWC1XS:
19859 tcg_gen_shli_tl(t0, t0, 2);
19860 break;
19861 case NM_LDC1XS:
19862 case NM_SDC1XS:
19863 tcg_gen_shli_tl(t0, t0, 3);
19864 break;
19867 gen_op_addr_add(ctx, t0, t0, t1);
19869 switch (extract32(ctx->opcode, 7, 4)) {
19870 case NM_LBX:
19871 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19872 MO_SB);
19873 gen_store_gpr(t0, rd);
19874 break;
19875 case NM_LHX:
19876 /*case NM_LHXS:*/
19877 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19878 MO_TESW);
19879 gen_store_gpr(t0, rd);
19880 break;
19881 case NM_LWX:
19882 /*case NM_LWXS:*/
19883 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19884 MO_TESL);
19885 gen_store_gpr(t0, rd);
19886 break;
19887 case NM_LBUX:
19888 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19889 MO_UB);
19890 gen_store_gpr(t0, rd);
19891 break;
19892 case NM_LHUX:
19893 /*case NM_LHUXS:*/
19894 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19895 MO_TEUW);
19896 gen_store_gpr(t0, rd);
19897 break;
19898 case NM_SBX:
19899 check_nms(ctx);
19900 gen_load_gpr(t1, rd);
19901 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19902 MO_8);
19903 break;
19904 case NM_SHX:
19905 /*case NM_SHXS:*/
19906 check_nms(ctx);
19907 gen_load_gpr(t1, rd);
19908 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19909 MO_TEUW);
19910 break;
19911 case NM_SWX:
19912 /*case NM_SWXS:*/
19913 check_nms(ctx);
19914 gen_load_gpr(t1, rd);
19915 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19916 MO_TEUL);
19917 break;
19918 case NM_LWC1X:
19919 /*case NM_LWC1XS:*/
19920 case NM_LDC1X:
19921 /*case NM_LDC1XS:*/
19922 case NM_SWC1X:
19923 /*case NM_SWC1XS:*/
19924 case NM_SDC1X:
19925 /*case NM_SDC1XS:*/
19926 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19927 check_cp1_enabled(ctx);
19928 switch (extract32(ctx->opcode, 7, 4)) {
19929 case NM_LWC1X:
19930 /*case NM_LWC1XS:*/
19931 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19932 break;
19933 case NM_LDC1X:
19934 /*case NM_LDC1XS:*/
19935 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19936 break;
19937 case NM_SWC1X:
19938 /*case NM_SWC1XS:*/
19939 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19940 break;
19941 case NM_SDC1X:
19942 /*case NM_SDC1XS:*/
19943 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19944 break;
19946 } else {
19947 generate_exception_err(ctx, EXCP_CpU, 1);
19949 break;
19950 default:
19951 generate_exception_end(ctx, EXCP_RI);
19952 break;
19955 tcg_temp_free(t0);
19956 tcg_temp_free(t1);
19959 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19961 int rt, rs, rd;
19963 rt = extract32(ctx->opcode, 21, 5);
19964 rs = extract32(ctx->opcode, 16, 5);
19965 rd = extract32(ctx->opcode, 11, 5);
19967 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19968 generate_exception_end(ctx, EXCP_RI);
19969 return;
19971 check_cp1_enabled(ctx);
19972 switch (extract32(ctx->opcode, 0, 3)) {
19973 case NM_POOL32F_0:
19974 switch (extract32(ctx->opcode, 3, 7)) {
19975 case NM_RINT_S:
19976 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19977 break;
19978 case NM_RINT_D:
19979 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19980 break;
19981 case NM_CLASS_S:
19982 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19983 break;
19984 case NM_CLASS_D:
19985 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19986 break;
19987 case NM_ADD_S:
19988 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19989 break;
19990 case NM_ADD_D:
19991 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19992 break;
19993 case NM_SUB_S:
19994 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19995 break;
19996 case NM_SUB_D:
19997 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19998 break;
19999 case NM_MUL_S:
20000 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20001 break;
20002 case NM_MUL_D:
20003 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20004 break;
20005 case NM_DIV_S:
20006 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20007 break;
20008 case NM_DIV_D:
20009 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20010 break;
20011 case NM_SELEQZ_S:
20012 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20013 break;
20014 case NM_SELEQZ_D:
20015 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20016 break;
20017 case NM_SELNEZ_S:
20018 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20019 break;
20020 case NM_SELNEZ_D:
20021 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20022 break;
20023 case NM_SEL_S:
20024 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20025 break;
20026 case NM_SEL_D:
20027 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20028 break;
20029 case NM_MADDF_S:
20030 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20031 break;
20032 case NM_MADDF_D:
20033 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20034 break;
20035 case NM_MSUBF_S:
20036 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20037 break;
20038 case NM_MSUBF_D:
20039 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20040 break;
20041 default:
20042 generate_exception_end(ctx, EXCP_RI);
20043 break;
20045 break;
20046 case NM_POOL32F_3:
20047 switch (extract32(ctx->opcode, 3, 3)) {
20048 case NM_MIN_FMT:
20049 switch (extract32(ctx->opcode, 9, 1)) {
20050 case FMT_SDPS_S:
20051 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20052 break;
20053 case FMT_SDPS_D:
20054 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20055 break;
20057 break;
20058 case NM_MAX_FMT:
20059 switch (extract32(ctx->opcode, 9, 1)) {
20060 case FMT_SDPS_S:
20061 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20062 break;
20063 case FMT_SDPS_D:
20064 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20065 break;
20067 break;
20068 case NM_MINA_FMT:
20069 switch (extract32(ctx->opcode, 9, 1)) {
20070 case FMT_SDPS_S:
20071 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20072 break;
20073 case FMT_SDPS_D:
20074 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20075 break;
20077 break;
20078 case NM_MAXA_FMT:
20079 switch (extract32(ctx->opcode, 9, 1)) {
20080 case FMT_SDPS_S:
20081 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20082 break;
20083 case FMT_SDPS_D:
20084 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20085 break;
20087 break;
20088 case NM_POOL32FXF:
20089 switch (extract32(ctx->opcode, 6, 8)) {
20090 case NM_CFC1:
20091 gen_cp1(ctx, OPC_CFC1, rt, rs);
20092 break;
20093 case NM_CTC1:
20094 gen_cp1(ctx, OPC_CTC1, rt, rs);
20095 break;
20096 case NM_MFC1:
20097 gen_cp1(ctx, OPC_MFC1, rt, rs);
20098 break;
20099 case NM_MTC1:
20100 gen_cp1(ctx, OPC_MTC1, rt, rs);
20101 break;
20102 case NM_MFHC1:
20103 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20104 break;
20105 case NM_MTHC1:
20106 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20107 break;
20108 case NM_CVT_S_PL:
20109 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20110 break;
20111 case NM_CVT_S_PU:
20112 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20113 break;
20114 default:
20115 switch (extract32(ctx->opcode, 6, 9)) {
20116 case NM_CVT_L_S:
20117 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20118 break;
20119 case NM_CVT_L_D:
20120 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20121 break;
20122 case NM_CVT_W_S:
20123 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20124 break;
20125 case NM_CVT_W_D:
20126 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20127 break;
20128 case NM_RSQRT_S:
20129 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20130 break;
20131 case NM_RSQRT_D:
20132 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20133 break;
20134 case NM_SQRT_S:
20135 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20136 break;
20137 case NM_SQRT_D:
20138 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20139 break;
20140 case NM_RECIP_S:
20141 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20142 break;
20143 case NM_RECIP_D:
20144 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20145 break;
20146 case NM_FLOOR_L_S:
20147 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20148 break;
20149 case NM_FLOOR_L_D:
20150 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20151 break;
20152 case NM_FLOOR_W_S:
20153 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20154 break;
20155 case NM_FLOOR_W_D:
20156 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20157 break;
20158 case NM_CEIL_L_S:
20159 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20160 break;
20161 case NM_CEIL_L_D:
20162 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20163 break;
20164 case NM_CEIL_W_S:
20165 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20166 break;
20167 case NM_CEIL_W_D:
20168 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20169 break;
20170 case NM_TRUNC_L_S:
20171 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20172 break;
20173 case NM_TRUNC_L_D:
20174 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20175 break;
20176 case NM_TRUNC_W_S:
20177 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20178 break;
20179 case NM_TRUNC_W_D:
20180 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20181 break;
20182 case NM_ROUND_L_S:
20183 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20184 break;
20185 case NM_ROUND_L_D:
20186 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20187 break;
20188 case NM_ROUND_W_S:
20189 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20190 break;
20191 case NM_ROUND_W_D:
20192 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20193 break;
20194 case NM_MOV_S:
20195 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20196 break;
20197 case NM_MOV_D:
20198 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20199 break;
20200 case NM_ABS_S:
20201 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20202 break;
20203 case NM_ABS_D:
20204 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20205 break;
20206 case NM_NEG_S:
20207 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20208 break;
20209 case NM_NEG_D:
20210 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20211 break;
20212 case NM_CVT_D_S:
20213 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20214 break;
20215 case NM_CVT_D_W:
20216 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20217 break;
20218 case NM_CVT_D_L:
20219 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20220 break;
20221 case NM_CVT_S_D:
20222 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20223 break;
20224 case NM_CVT_S_W:
20225 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20226 break;
20227 case NM_CVT_S_L:
20228 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20229 break;
20230 default:
20231 generate_exception_end(ctx, EXCP_RI);
20232 break;
20234 break;
20236 break;
20238 break;
20239 case NM_POOL32F_5:
20240 switch (extract32(ctx->opcode, 3, 3)) {
20241 case NM_CMP_CONDN_S:
20242 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20243 break;
20244 case NM_CMP_CONDN_D:
20245 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20246 break;
20247 default:
20248 generate_exception_end(ctx, EXCP_RI);
20249 break;
20251 break;
20252 default:
20253 generate_exception_end(ctx, EXCP_RI);
20254 break;
20258 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20259 int rd, int rs, int rt)
20261 int ret = rd;
20262 TCGv t0 = tcg_temp_new();
20263 TCGv v1_t = tcg_temp_new();
20264 TCGv v2_t = tcg_temp_new();
20266 gen_load_gpr(v1_t, rs);
20267 gen_load_gpr(v2_t, rt);
20269 switch (opc) {
20270 case NM_CMP_EQ_PH:
20271 check_dsp(ctx);
20272 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20273 break;
20274 case NM_CMP_LT_PH:
20275 check_dsp(ctx);
20276 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20277 break;
20278 case NM_CMP_LE_PH:
20279 check_dsp(ctx);
20280 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20281 break;
20282 case NM_CMPU_EQ_QB:
20283 check_dsp(ctx);
20284 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20285 break;
20286 case NM_CMPU_LT_QB:
20287 check_dsp(ctx);
20288 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20289 break;
20290 case NM_CMPU_LE_QB:
20291 check_dsp(ctx);
20292 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20293 break;
20294 case NM_CMPGU_EQ_QB:
20295 check_dsp(ctx);
20296 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20297 gen_store_gpr(v1_t, ret);
20298 break;
20299 case NM_CMPGU_LT_QB:
20300 check_dsp(ctx);
20301 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20302 gen_store_gpr(v1_t, ret);
20303 break;
20304 case NM_CMPGU_LE_QB:
20305 check_dsp(ctx);
20306 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20307 gen_store_gpr(v1_t, ret);
20308 break;
20309 case NM_CMPGDU_EQ_QB:
20310 check_dsp_r2(ctx);
20311 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20312 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20313 gen_store_gpr(v1_t, ret);
20314 break;
20315 case NM_CMPGDU_LT_QB:
20316 check_dsp_r2(ctx);
20317 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20318 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20319 gen_store_gpr(v1_t, ret);
20320 break;
20321 case NM_CMPGDU_LE_QB:
20322 check_dsp_r2(ctx);
20323 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20324 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20325 gen_store_gpr(v1_t, ret);
20326 break;
20327 case NM_PACKRL_PH:
20328 check_dsp(ctx);
20329 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20330 gen_store_gpr(v1_t, ret);
20331 break;
20332 case NM_PICK_QB:
20333 check_dsp(ctx);
20334 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20335 gen_store_gpr(v1_t, ret);
20336 break;
20337 case NM_PICK_PH:
20338 check_dsp(ctx);
20339 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20340 gen_store_gpr(v1_t, ret);
20341 break;
20342 case NM_ADDQ_S_W:
20343 check_dsp(ctx);
20344 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20345 gen_store_gpr(v1_t, ret);
20346 break;
20347 case NM_SUBQ_S_W:
20348 check_dsp(ctx);
20349 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20350 gen_store_gpr(v1_t, ret);
20351 break;
20352 case NM_ADDSC:
20353 check_dsp(ctx);
20354 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20355 gen_store_gpr(v1_t, ret);
20356 break;
20357 case NM_ADDWC:
20358 check_dsp(ctx);
20359 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20360 gen_store_gpr(v1_t, ret);
20361 break;
20362 case NM_ADDQ_S_PH:
20363 check_dsp(ctx);
20364 switch (extract32(ctx->opcode, 10, 1)) {
20365 case 0:
20366 /* ADDQ_PH */
20367 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20368 gen_store_gpr(v1_t, ret);
20369 break;
20370 case 1:
20371 /* ADDQ_S_PH */
20372 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20373 gen_store_gpr(v1_t, ret);
20374 break;
20376 break;
20377 case NM_ADDQH_R_PH:
20378 check_dsp_r2(ctx);
20379 switch (extract32(ctx->opcode, 10, 1)) {
20380 case 0:
20381 /* ADDQH_PH */
20382 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20383 gen_store_gpr(v1_t, ret);
20384 break;
20385 case 1:
20386 /* ADDQH_R_PH */
20387 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20388 gen_store_gpr(v1_t, ret);
20389 break;
20391 break;
20392 case NM_ADDQH_R_W:
20393 check_dsp_r2(ctx);
20394 switch (extract32(ctx->opcode, 10, 1)) {
20395 case 0:
20396 /* ADDQH_W */
20397 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20398 gen_store_gpr(v1_t, ret);
20399 break;
20400 case 1:
20401 /* ADDQH_R_W */
20402 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20403 gen_store_gpr(v1_t, ret);
20404 break;
20406 break;
20407 case NM_ADDU_S_QB:
20408 check_dsp(ctx);
20409 switch (extract32(ctx->opcode, 10, 1)) {
20410 case 0:
20411 /* ADDU_QB */
20412 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20413 gen_store_gpr(v1_t, ret);
20414 break;
20415 case 1:
20416 /* ADDU_S_QB */
20417 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20418 gen_store_gpr(v1_t, ret);
20419 break;
20421 break;
20422 case NM_ADDU_S_PH:
20423 check_dsp_r2(ctx);
20424 switch (extract32(ctx->opcode, 10, 1)) {
20425 case 0:
20426 /* ADDU_PH */
20427 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20428 gen_store_gpr(v1_t, ret);
20429 break;
20430 case 1:
20431 /* ADDU_S_PH */
20432 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20433 gen_store_gpr(v1_t, ret);
20434 break;
20436 break;
20437 case NM_ADDUH_R_QB:
20438 check_dsp_r2(ctx);
20439 switch (extract32(ctx->opcode, 10, 1)) {
20440 case 0:
20441 /* ADDUH_QB */
20442 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20443 gen_store_gpr(v1_t, ret);
20444 break;
20445 case 1:
20446 /* ADDUH_R_QB */
20447 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20448 gen_store_gpr(v1_t, ret);
20449 break;
20451 break;
20452 case NM_SHRAV_R_PH:
20453 check_dsp(ctx);
20454 switch (extract32(ctx->opcode, 10, 1)) {
20455 case 0:
20456 /* SHRAV_PH */
20457 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20458 gen_store_gpr(v1_t, ret);
20459 break;
20460 case 1:
20461 /* SHRAV_R_PH */
20462 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20463 gen_store_gpr(v1_t, ret);
20464 break;
20466 break;
20467 case NM_SHRAV_R_QB:
20468 check_dsp_r2(ctx);
20469 switch (extract32(ctx->opcode, 10, 1)) {
20470 case 0:
20471 /* SHRAV_QB */
20472 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20473 gen_store_gpr(v1_t, ret);
20474 break;
20475 case 1:
20476 /* SHRAV_R_QB */
20477 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20478 gen_store_gpr(v1_t, ret);
20479 break;
20481 break;
20482 case NM_SUBQ_S_PH:
20483 check_dsp(ctx);
20484 switch (extract32(ctx->opcode, 10, 1)) {
20485 case 0:
20486 /* SUBQ_PH */
20487 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20488 gen_store_gpr(v1_t, ret);
20489 break;
20490 case 1:
20491 /* SUBQ_S_PH */
20492 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20493 gen_store_gpr(v1_t, ret);
20494 break;
20496 break;
20497 case NM_SUBQH_R_PH:
20498 check_dsp_r2(ctx);
20499 switch (extract32(ctx->opcode, 10, 1)) {
20500 case 0:
20501 /* SUBQH_PH */
20502 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20503 gen_store_gpr(v1_t, ret);
20504 break;
20505 case 1:
20506 /* SUBQH_R_PH */
20507 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20508 gen_store_gpr(v1_t, ret);
20509 break;
20511 break;
20512 case NM_SUBQH_R_W:
20513 check_dsp_r2(ctx);
20514 switch (extract32(ctx->opcode, 10, 1)) {
20515 case 0:
20516 /* SUBQH_W */
20517 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20518 gen_store_gpr(v1_t, ret);
20519 break;
20520 case 1:
20521 /* SUBQH_R_W */
20522 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20523 gen_store_gpr(v1_t, ret);
20524 break;
20526 break;
20527 case NM_SUBU_S_QB:
20528 check_dsp(ctx);
20529 switch (extract32(ctx->opcode, 10, 1)) {
20530 case 0:
20531 /* SUBU_QB */
20532 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20533 gen_store_gpr(v1_t, ret);
20534 break;
20535 case 1:
20536 /* SUBU_S_QB */
20537 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20538 gen_store_gpr(v1_t, ret);
20539 break;
20541 break;
20542 case NM_SUBU_S_PH:
20543 check_dsp_r2(ctx);
20544 switch (extract32(ctx->opcode, 10, 1)) {
20545 case 0:
20546 /* SUBU_PH */
20547 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20548 gen_store_gpr(v1_t, ret);
20549 break;
20550 case 1:
20551 /* SUBU_S_PH */
20552 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20553 gen_store_gpr(v1_t, ret);
20554 break;
20556 break;
20557 case NM_SUBUH_R_QB:
20558 check_dsp_r2(ctx);
20559 switch (extract32(ctx->opcode, 10, 1)) {
20560 case 0:
20561 /* SUBUH_QB */
20562 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20563 gen_store_gpr(v1_t, ret);
20564 break;
20565 case 1:
20566 /* SUBUH_R_QB */
20567 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20568 gen_store_gpr(v1_t, ret);
20569 break;
20571 break;
20572 case NM_SHLLV_S_PH:
20573 check_dsp(ctx);
20574 switch (extract32(ctx->opcode, 10, 1)) {
20575 case 0:
20576 /* SHLLV_PH */
20577 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20578 gen_store_gpr(v1_t, ret);
20579 break;
20580 case 1:
20581 /* SHLLV_S_PH */
20582 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20583 gen_store_gpr(v1_t, ret);
20584 break;
20586 break;
20587 case NM_PRECR_SRA_R_PH_W:
20588 check_dsp_r2(ctx);
20589 switch (extract32(ctx->opcode, 10, 1)) {
20590 case 0:
20591 /* PRECR_SRA_PH_W */
20593 TCGv_i32 sa_t = tcg_const_i32(rd);
20594 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20595 cpu_gpr[rt]);
20596 gen_store_gpr(v1_t, rt);
20597 tcg_temp_free_i32(sa_t);
20599 break;
20600 case 1:
20601 /* PRECR_SRA_R_PH_W */
20603 TCGv_i32 sa_t = tcg_const_i32(rd);
20604 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20605 cpu_gpr[rt]);
20606 gen_store_gpr(v1_t, rt);
20607 tcg_temp_free_i32(sa_t);
20609 break;
20611 break;
20612 case NM_MULEU_S_PH_QBL:
20613 check_dsp(ctx);
20614 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20615 gen_store_gpr(v1_t, ret);
20616 break;
20617 case NM_MULEU_S_PH_QBR:
20618 check_dsp(ctx);
20619 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20620 gen_store_gpr(v1_t, ret);
20621 break;
20622 case NM_MULQ_RS_PH:
20623 check_dsp(ctx);
20624 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20625 gen_store_gpr(v1_t, ret);
20626 break;
20627 case NM_MULQ_S_PH:
20628 check_dsp_r2(ctx);
20629 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20630 gen_store_gpr(v1_t, ret);
20631 break;
20632 case NM_MULQ_RS_W:
20633 check_dsp_r2(ctx);
20634 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20635 gen_store_gpr(v1_t, ret);
20636 break;
20637 case NM_MULQ_S_W:
20638 check_dsp_r2(ctx);
20639 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20640 gen_store_gpr(v1_t, ret);
20641 break;
20642 case NM_APPEND:
20643 check_dsp_r2(ctx);
20644 gen_load_gpr(t0, rs);
20645 if (rd != 0) {
20646 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20648 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20649 break;
20650 case NM_MODSUB:
20651 check_dsp(ctx);
20652 gen_helper_modsub(v1_t, v1_t, v2_t);
20653 gen_store_gpr(v1_t, ret);
20654 break;
20655 case NM_SHRAV_R_W:
20656 check_dsp(ctx);
20657 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20658 gen_store_gpr(v1_t, ret);
20659 break;
20660 case NM_SHRLV_PH:
20661 check_dsp_r2(ctx);
20662 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20663 gen_store_gpr(v1_t, ret);
20664 break;
20665 case NM_SHRLV_QB:
20666 check_dsp(ctx);
20667 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20668 gen_store_gpr(v1_t, ret);
20669 break;
20670 case NM_SHLLV_QB:
20671 check_dsp(ctx);
20672 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20673 gen_store_gpr(v1_t, ret);
20674 break;
20675 case NM_SHLLV_S_W:
20676 check_dsp(ctx);
20677 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20678 gen_store_gpr(v1_t, ret);
20679 break;
20680 case NM_SHILO:
20681 check_dsp(ctx);
20683 TCGv tv0 = tcg_temp_new();
20684 TCGv tv1 = tcg_temp_new();
20685 int16_t imm = extract32(ctx->opcode, 16, 7);
20687 tcg_gen_movi_tl(tv0, rd >> 3);
20688 tcg_gen_movi_tl(tv1, imm);
20689 gen_helper_shilo(tv0, tv1, cpu_env);
20691 break;
20692 case NM_MULEQ_S_W_PHL:
20693 check_dsp(ctx);
20694 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20695 gen_store_gpr(v1_t, ret);
20696 break;
20697 case NM_MULEQ_S_W_PHR:
20698 check_dsp(ctx);
20699 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20700 gen_store_gpr(v1_t, ret);
20701 break;
20702 case NM_MUL_S_PH:
20703 check_dsp_r2(ctx);
20704 switch (extract32(ctx->opcode, 10, 1)) {
20705 case 0:
20706 /* MUL_PH */
20707 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20708 gen_store_gpr(v1_t, ret);
20709 break;
20710 case 1:
20711 /* MUL_S_PH */
20712 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20713 gen_store_gpr(v1_t, ret);
20714 break;
20716 break;
20717 case NM_PRECR_QB_PH:
20718 check_dsp_r2(ctx);
20719 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20720 gen_store_gpr(v1_t, ret);
20721 break;
20722 case NM_PRECRQ_QB_PH:
20723 check_dsp(ctx);
20724 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20725 gen_store_gpr(v1_t, ret);
20726 break;
20727 case NM_PRECRQ_PH_W:
20728 check_dsp(ctx);
20729 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20730 gen_store_gpr(v1_t, ret);
20731 break;
20732 case NM_PRECRQ_RS_PH_W:
20733 check_dsp(ctx);
20734 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20735 gen_store_gpr(v1_t, ret);
20736 break;
20737 case NM_PRECRQU_S_QB_PH:
20738 check_dsp(ctx);
20739 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20740 gen_store_gpr(v1_t, ret);
20741 break;
20742 case NM_SHRA_R_W:
20743 check_dsp(ctx);
20744 tcg_gen_movi_tl(t0, rd);
20745 gen_helper_shra_r_w(v1_t, t0, v1_t);
20746 gen_store_gpr(v1_t, rt);
20747 break;
20748 case NM_SHRA_R_PH:
20749 check_dsp(ctx);
20750 tcg_gen_movi_tl(t0, rd >> 1);
20751 switch (extract32(ctx->opcode, 10, 1)) {
20752 case 0:
20753 /* SHRA_PH */
20754 gen_helper_shra_ph(v1_t, t0, v1_t);
20755 gen_store_gpr(v1_t, rt);
20756 break;
20757 case 1:
20758 /* SHRA_R_PH */
20759 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20760 gen_store_gpr(v1_t, rt);
20761 break;
20763 break;
20764 case NM_SHLL_S_PH:
20765 check_dsp(ctx);
20766 tcg_gen_movi_tl(t0, rd >> 1);
20767 switch (extract32(ctx->opcode, 10, 2)) {
20768 case 0:
20769 /* SHLL_PH */
20770 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20771 gen_store_gpr(v1_t, rt);
20772 break;
20773 case 2:
20774 /* SHLL_S_PH */
20775 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20776 gen_store_gpr(v1_t, rt);
20777 break;
20778 default:
20779 generate_exception_end(ctx, EXCP_RI);
20780 break;
20782 break;
20783 case NM_SHLL_S_W:
20784 check_dsp(ctx);
20785 tcg_gen_movi_tl(t0, rd);
20786 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20787 gen_store_gpr(v1_t, rt);
20788 break;
20789 case NM_REPL_PH:
20790 check_dsp(ctx);
20792 int16_t imm;
20793 imm = sextract32(ctx->opcode, 11, 11);
20794 imm = (int16_t)(imm << 6) >> 6;
20795 if (rt != 0) {
20796 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20799 break;
20800 default:
20801 generate_exception_end(ctx, EXCP_RI);
20802 break;
20806 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20808 uint16_t insn;
20809 uint32_t op;
20810 int rt, rs, rd;
20811 int offset;
20812 int imm;
20814 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20815 ctx->opcode = (ctx->opcode << 16) | insn;
20817 rt = extract32(ctx->opcode, 21, 5);
20818 rs = extract32(ctx->opcode, 16, 5);
20819 rd = extract32(ctx->opcode, 11, 5);
20821 op = extract32(ctx->opcode, 26, 6);
20822 switch (op) {
20823 case NM_P_ADDIU:
20824 if (rt == 0) {
20825 /* P.RI */
20826 switch (extract32(ctx->opcode, 19, 2)) {
20827 case NM_SIGRIE:
20828 default:
20829 generate_exception_end(ctx, EXCP_RI);
20830 break;
20831 case NM_P_SYSCALL:
20832 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20833 generate_exception_end(ctx, EXCP_SYSCALL);
20834 } else {
20835 generate_exception_end(ctx, EXCP_RI);
20837 break;
20838 case NM_BREAK:
20839 generate_exception_end(ctx, EXCP_BREAK);
20840 break;
20841 case NM_SDBBP:
20842 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20843 gen_helper_do_semihosting(cpu_env);
20844 } else {
20845 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20846 generate_exception_end(ctx, EXCP_RI);
20847 } else {
20848 generate_exception_end(ctx, EXCP_DBp);
20851 break;
20853 } else {
20854 /* NM_ADDIU */
20855 imm = extract32(ctx->opcode, 0, 16);
20856 if (rs != 0) {
20857 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20858 } else {
20859 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20861 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20863 break;
20864 case NM_ADDIUPC:
20865 if (rt != 0) {
20866 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20867 extract32(ctx->opcode, 1, 20) << 1;
20868 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20869 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20871 break;
20872 case NM_POOL32A:
20873 switch (ctx->opcode & 0x07) {
20874 case NM_POOL32A0:
20875 gen_pool32a0_nanomips_insn(env, ctx);
20876 break;
20877 case NM_POOL32A5:
20879 int32_t op1 = extract32(ctx->opcode, 3, 7);
20880 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20882 break;
20883 case NM_POOL32A7:
20884 switch (extract32(ctx->opcode, 3, 3)) {
20885 case NM_P_LSX:
20886 gen_p_lsx(ctx, rd, rs, rt);
20887 break;
20888 case NM_LSA:
20889 /* In nanoMIPS, the shift field directly encodes the shift
20890 * amount, meaning that the supported shift values are in
20891 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20892 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20893 extract32(ctx->opcode, 9, 2) - 1);
20894 break;
20895 case NM_EXTW:
20896 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20897 break;
20898 case NM_POOL32AXF:
20899 gen_pool32axf_nanomips_insn(env, ctx);
20900 break;
20901 default:
20902 generate_exception_end(ctx, EXCP_RI);
20903 break;
20905 break;
20906 default:
20907 generate_exception_end(ctx, EXCP_RI);
20908 break;
20910 break;
20911 case NM_P_GP_W:
20912 switch (ctx->opcode & 0x03) {
20913 case NM_ADDIUGP_W:
20914 if (rt != 0) {
20915 offset = extract32(ctx->opcode, 0, 21);
20916 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20918 break;
20919 case NM_LWGP:
20920 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20921 break;
20922 case NM_SWGP:
20923 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20924 break;
20925 default:
20926 generate_exception_end(ctx, EXCP_RI);
20927 break;
20929 break;
20930 case NM_P48I:
20932 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20933 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20934 switch (extract32(ctx->opcode, 16, 5)) {
20935 case NM_LI48:
20936 check_nms(ctx);
20937 if (rt != 0) {
20938 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20940 break;
20941 case NM_ADDIU48:
20942 check_nms(ctx);
20943 if (rt != 0) {
20944 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20945 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20947 break;
20948 case NM_ADDIUGP48:
20949 check_nms(ctx);
20950 if (rt != 0) {
20951 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20953 break;
20954 case NM_ADDIUPC48:
20955 check_nms(ctx);
20956 if (rt != 0) {
20957 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20958 addr_off);
20960 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20962 break;
20963 case NM_LWPC48:
20964 check_nms(ctx);
20965 if (rt != 0) {
20966 TCGv t0;
20967 t0 = tcg_temp_new();
20969 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20970 addr_off);
20972 tcg_gen_movi_tl(t0, addr);
20973 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20974 tcg_temp_free(t0);
20976 break;
20977 case NM_SWPC48:
20978 check_nms(ctx);
20980 TCGv t0, t1;
20981 t0 = tcg_temp_new();
20982 t1 = tcg_temp_new();
20984 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20985 addr_off);
20987 tcg_gen_movi_tl(t0, addr);
20988 gen_load_gpr(t1, rt);
20990 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20992 tcg_temp_free(t0);
20993 tcg_temp_free(t1);
20995 break;
20996 default:
20997 generate_exception_end(ctx, EXCP_RI);
20998 break;
21000 return 6;
21002 case NM_P_U12:
21003 switch (extract32(ctx->opcode, 12, 4)) {
21004 case NM_ORI:
21005 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21006 break;
21007 case NM_XORI:
21008 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21009 break;
21010 case NM_ANDI:
21011 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21012 break;
21013 case NM_P_SR:
21014 switch (extract32(ctx->opcode, 20, 1)) {
21015 case NM_PP_SR:
21016 switch (ctx->opcode & 3) {
21017 case NM_SAVE:
21018 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21019 extract32(ctx->opcode, 2, 1),
21020 extract32(ctx->opcode, 3, 9) << 3);
21021 break;
21022 case NM_RESTORE:
21023 case NM_RESTORE_JRC:
21024 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21025 extract32(ctx->opcode, 2, 1),
21026 extract32(ctx->opcode, 3, 9) << 3);
21027 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21028 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21030 break;
21031 default:
21032 generate_exception_end(ctx, EXCP_RI);
21033 break;
21035 break;
21036 case NM_P_SR_F:
21037 generate_exception_end(ctx, EXCP_RI);
21038 break;
21040 break;
21041 case NM_SLTI:
21042 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21043 break;
21044 case NM_SLTIU:
21045 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21046 break;
21047 case NM_SEQI:
21049 TCGv t0 = tcg_temp_new();
21051 imm = extract32(ctx->opcode, 0, 12);
21052 gen_load_gpr(t0, rs);
21053 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21054 gen_store_gpr(t0, rt);
21056 tcg_temp_free(t0);
21058 break;
21059 case NM_ADDIUNEG:
21060 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21061 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21062 break;
21063 case NM_P_SHIFT:
21065 int shift = extract32(ctx->opcode, 0, 5);
21066 switch (extract32(ctx->opcode, 5, 4)) {
21067 case NM_P_SLL:
21068 if (rt == 0 && shift == 0) {
21069 /* NOP */
21070 } else if (rt == 0 && shift == 3) {
21071 /* EHB - treat as NOP */
21072 } else if (rt == 0 && shift == 5) {
21073 /* PAUSE - treat as NOP */
21074 } else if (rt == 0 && shift == 6) {
21075 /* SYNC */
21076 gen_sync(extract32(ctx->opcode, 16, 5));
21077 } else {
21078 /* SLL */
21079 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21080 extract32(ctx->opcode, 0, 5));
21082 break;
21083 case NM_SRL:
21084 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21085 extract32(ctx->opcode, 0, 5));
21086 break;
21087 case NM_SRA:
21088 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21089 extract32(ctx->opcode, 0, 5));
21090 break;
21091 case NM_ROTR:
21092 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21093 extract32(ctx->opcode, 0, 5));
21094 break;
21097 break;
21098 case NM_P_ROTX:
21099 check_nms(ctx);
21100 if (rt != 0) {
21101 TCGv t0 = tcg_temp_new();
21102 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21103 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21104 << 1);
21105 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21107 gen_load_gpr(t0, rs);
21108 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21109 tcg_temp_free(t0);
21111 tcg_temp_free_i32(shift);
21112 tcg_temp_free_i32(shiftx);
21113 tcg_temp_free_i32(stripe);
21115 break;
21116 case NM_P_INS:
21117 switch (((ctx->opcode >> 10) & 2) |
21118 (extract32(ctx->opcode, 5, 1))) {
21119 case NM_INS:
21120 check_nms(ctx);
21121 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21122 extract32(ctx->opcode, 6, 5));
21123 break;
21124 default:
21125 generate_exception_end(ctx, EXCP_RI);
21126 break;
21128 break;
21129 case NM_P_EXT:
21130 switch (((ctx->opcode >> 10) & 2) |
21131 (extract32(ctx->opcode, 5, 1))) {
21132 case NM_EXT:
21133 check_nms(ctx);
21134 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21135 extract32(ctx->opcode, 6, 5));
21136 break;
21137 default:
21138 generate_exception_end(ctx, EXCP_RI);
21139 break;
21141 break;
21142 default:
21143 generate_exception_end(ctx, EXCP_RI);
21144 break;
21146 break;
21147 case NM_POOL32F:
21148 gen_pool32f_nanomips_insn(ctx);
21149 break;
21150 case NM_POOL32S:
21151 break;
21152 case NM_P_LUI:
21153 switch (extract32(ctx->opcode, 1, 1)) {
21154 case NM_LUI:
21155 if (rt != 0) {
21156 tcg_gen_movi_tl(cpu_gpr[rt],
21157 sextract32(ctx->opcode, 0, 1) << 31 |
21158 extract32(ctx->opcode, 2, 10) << 21 |
21159 extract32(ctx->opcode, 12, 9) << 12);
21161 break;
21162 case NM_ALUIPC:
21163 if (rt != 0) {
21164 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21165 extract32(ctx->opcode, 2, 10) << 21 |
21166 extract32(ctx->opcode, 12, 9) << 12;
21167 target_long addr;
21168 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21169 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21171 break;
21173 break;
21174 case NM_P_GP_BH:
21176 uint32_t u = extract32(ctx->opcode, 0, 18);
21178 switch (extract32(ctx->opcode, 18, 3)) {
21179 case NM_LBGP:
21180 gen_ld(ctx, OPC_LB, rt, 28, u);
21181 break;
21182 case NM_SBGP:
21183 gen_st(ctx, OPC_SB, rt, 28, u);
21184 break;
21185 case NM_LBUGP:
21186 gen_ld(ctx, OPC_LBU, rt, 28, u);
21187 break;
21188 case NM_ADDIUGP_B:
21189 if (rt != 0) {
21190 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21192 break;
21193 case NM_P_GP_LH:
21194 u &= ~1;
21195 switch (ctx->opcode & 1) {
21196 case NM_LHGP:
21197 gen_ld(ctx, OPC_LH, rt, 28, u);
21198 break;
21199 case NM_LHUGP:
21200 gen_ld(ctx, OPC_LHU, rt, 28, u);
21201 break;
21203 break;
21204 case NM_P_GP_SH:
21205 u &= ~1;
21206 switch (ctx->opcode & 1) {
21207 case NM_SHGP:
21208 gen_st(ctx, OPC_SH, rt, 28, u);
21209 break;
21210 default:
21211 generate_exception_end(ctx, EXCP_RI);
21212 break;
21214 break;
21215 case NM_P_GP_CP1:
21216 u &= ~0x3;
21217 switch (ctx->opcode & 0x3) {
21218 case NM_LWC1GP:
21219 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21220 break;
21221 case NM_LDC1GP:
21222 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21223 break;
21224 case NM_SWC1GP:
21225 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21226 break;
21227 case NM_SDC1GP:
21228 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21229 break;
21231 break;
21232 default:
21233 generate_exception_end(ctx, EXCP_RI);
21234 break;
21237 break;
21238 case NM_P_LS_U12:
21240 uint32_t u = extract32(ctx->opcode, 0, 12);
21242 switch (extract32(ctx->opcode, 12, 4)) {
21243 case NM_P_PREFU12:
21244 if (rt == 31) {
21245 /* SYNCI */
21246 /* Break the TB to be able to sync copied instructions
21247 immediately */
21248 ctx->base.is_jmp = DISAS_STOP;
21249 } else {
21250 /* PREF */
21251 /* Treat as NOP. */
21253 break;
21254 case NM_LB:
21255 gen_ld(ctx, OPC_LB, rt, rs, u);
21256 break;
21257 case NM_LH:
21258 gen_ld(ctx, OPC_LH, rt, rs, u);
21259 break;
21260 case NM_LW:
21261 gen_ld(ctx, OPC_LW, rt, rs, u);
21262 break;
21263 case NM_LBU:
21264 gen_ld(ctx, OPC_LBU, rt, rs, u);
21265 break;
21266 case NM_LHU:
21267 gen_ld(ctx, OPC_LHU, rt, rs, u);
21268 break;
21269 case NM_SB:
21270 gen_st(ctx, OPC_SB, rt, rs, u);
21271 break;
21272 case NM_SH:
21273 gen_st(ctx, OPC_SH, rt, rs, u);
21274 break;
21275 case NM_SW:
21276 gen_st(ctx, OPC_SW, rt, rs, u);
21277 break;
21278 case NM_LWC1:
21279 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21280 break;
21281 case NM_LDC1:
21282 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21283 break;
21284 case NM_SWC1:
21285 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21286 break;
21287 case NM_SDC1:
21288 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21289 break;
21290 default:
21291 generate_exception_end(ctx, EXCP_RI);
21292 break;
21295 break;
21296 case NM_P_LS_S9:
21298 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21299 extract32(ctx->opcode, 0, 8);
21301 switch (extract32(ctx->opcode, 8, 3)) {
21302 case NM_P_LS_S0:
21303 switch (extract32(ctx->opcode, 11, 4)) {
21304 case NM_LBS9:
21305 gen_ld(ctx, OPC_LB, rt, rs, s);
21306 break;
21307 case NM_LHS9:
21308 gen_ld(ctx, OPC_LH, rt, rs, s);
21309 break;
21310 case NM_LWS9:
21311 gen_ld(ctx, OPC_LW, rt, rs, s);
21312 break;
21313 case NM_LBUS9:
21314 gen_ld(ctx, OPC_LBU, rt, rs, s);
21315 break;
21316 case NM_LHUS9:
21317 gen_ld(ctx, OPC_LHU, rt, rs, s);
21318 break;
21319 case NM_SBS9:
21320 gen_st(ctx, OPC_SB, rt, rs, s);
21321 break;
21322 case NM_SHS9:
21323 gen_st(ctx, OPC_SH, rt, rs, s);
21324 break;
21325 case NM_SWS9:
21326 gen_st(ctx, OPC_SW, rt, rs, s);
21327 break;
21328 case NM_LWC1S9:
21329 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21330 break;
21331 case NM_LDC1S9:
21332 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21333 break;
21334 case NM_SWC1S9:
21335 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21336 break;
21337 case NM_SDC1S9:
21338 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21339 break;
21340 case NM_P_PREFS9:
21341 if (rt == 31) {
21342 /* SYNCI */
21343 /* Break the TB to be able to sync copied instructions
21344 immediately */
21345 ctx->base.is_jmp = DISAS_STOP;
21346 } else {
21347 /* PREF */
21348 /* Treat as NOP. */
21350 break;
21351 default:
21352 generate_exception_end(ctx, EXCP_RI);
21353 break;
21355 break;
21356 case NM_P_LS_S1:
21357 switch (extract32(ctx->opcode, 11, 4)) {
21358 case NM_UALH:
21359 case NM_UASH:
21360 check_nms(ctx);
21362 TCGv t0 = tcg_temp_new();
21363 TCGv t1 = tcg_temp_new();
21365 gen_base_offset_addr(ctx, t0, rs, s);
21367 switch (extract32(ctx->opcode, 11, 4)) {
21368 case NM_UALH:
21369 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21370 MO_UNALN);
21371 gen_store_gpr(t0, rt);
21372 break;
21373 case NM_UASH:
21374 gen_load_gpr(t1, rt);
21375 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21376 MO_UNALN);
21377 break;
21379 tcg_temp_free(t0);
21380 tcg_temp_free(t1);
21382 break;
21383 case NM_P_LL:
21384 switch (ctx->opcode & 0x03) {
21385 case NM_LL:
21386 gen_ld(ctx, OPC_LL, rt, rs, s);
21387 break;
21388 case NM_LLWP:
21389 check_xnp(ctx);
21390 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21391 break;
21393 break;
21394 case NM_P_SC:
21395 switch (ctx->opcode & 0x03) {
21396 case NM_SC:
21397 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21398 break;
21399 case NM_SCWP:
21400 check_xnp(ctx);
21401 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21402 break;
21404 break;
21405 case NM_CACHE:
21406 check_cp0_enabled(ctx);
21407 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21408 gen_cache_operation(ctx, rt, rs, s);
21410 break;
21412 break;
21413 case NM_P_LS_E0:
21414 switch (extract32(ctx->opcode, 11, 4)) {
21415 case NM_LBE:
21416 check_eva(ctx);
21417 check_cp0_enabled(ctx);
21418 gen_ld(ctx, OPC_LBE, rt, rs, s);
21419 break;
21420 case NM_SBE:
21421 check_eva(ctx);
21422 check_cp0_enabled(ctx);
21423 gen_st(ctx, OPC_SBE, rt, rs, s);
21424 break;
21425 case NM_LBUE:
21426 check_eva(ctx);
21427 check_cp0_enabled(ctx);
21428 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21429 break;
21430 case NM_P_PREFE:
21431 if (rt == 31) {
21432 /* case NM_SYNCIE */
21433 check_eva(ctx);
21434 check_cp0_enabled(ctx);
21435 /* Break the TB to be able to sync copied instructions
21436 immediately */
21437 ctx->base.is_jmp = DISAS_STOP;
21438 } else {
21439 /* case NM_PREFE */
21440 check_eva(ctx);
21441 check_cp0_enabled(ctx);
21442 /* Treat as NOP. */
21444 break;
21445 case NM_LHE:
21446 check_eva(ctx);
21447 check_cp0_enabled(ctx);
21448 gen_ld(ctx, OPC_LHE, rt, rs, s);
21449 break;
21450 case NM_SHE:
21451 check_eva(ctx);
21452 check_cp0_enabled(ctx);
21453 gen_st(ctx, OPC_SHE, rt, rs, s);
21454 break;
21455 case NM_LHUE:
21456 check_eva(ctx);
21457 check_cp0_enabled(ctx);
21458 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21459 break;
21460 case NM_CACHEE:
21461 check_nms_dl_il_sl_tl_l2c(ctx);
21462 gen_cache_operation(ctx, rt, rs, s);
21463 break;
21464 case NM_LWE:
21465 check_eva(ctx);
21466 check_cp0_enabled(ctx);
21467 gen_ld(ctx, OPC_LWE, rt, rs, s);
21468 break;
21469 case NM_SWE:
21470 check_eva(ctx);
21471 check_cp0_enabled(ctx);
21472 gen_st(ctx, OPC_SWE, rt, rs, s);
21473 break;
21474 case NM_P_LLE:
21475 switch (extract32(ctx->opcode, 2, 2)) {
21476 case NM_LLE:
21477 check_xnp(ctx);
21478 check_eva(ctx);
21479 check_cp0_enabled(ctx);
21480 gen_ld(ctx, OPC_LLE, rt, rs, s);
21481 break;
21482 case NM_LLWPE:
21483 check_xnp(ctx);
21484 check_eva(ctx);
21485 check_cp0_enabled(ctx);
21486 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21487 break;
21488 default:
21489 generate_exception_end(ctx, EXCP_RI);
21490 break;
21492 break;
21493 case NM_P_SCE:
21494 switch (extract32(ctx->opcode, 2, 2)) {
21495 case NM_SCE:
21496 check_xnp(ctx);
21497 check_eva(ctx);
21498 check_cp0_enabled(ctx);
21499 gen_st_cond(ctx, OPC_SCE, rt, rs, s);
21500 break;
21501 case NM_SCWPE:
21502 check_xnp(ctx);
21503 check_eva(ctx);
21504 check_cp0_enabled(ctx);
21505 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21506 break;
21507 default:
21508 generate_exception_end(ctx, EXCP_RI);
21509 break;
21511 break;
21513 break;
21514 case NM_P_LS_WM:
21515 case NM_P_LS_UAWM:
21516 check_nms(ctx);
21518 int count = extract32(ctx->opcode, 12, 3);
21519 int counter = 0;
21521 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21522 extract32(ctx->opcode, 0, 8);
21523 TCGv va = tcg_temp_new();
21524 TCGv t1 = tcg_temp_new();
21525 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21526 NM_P_LS_UAWM ? MO_UNALN : 0;
21528 count = (count == 0) ? 8 : count;
21529 while (counter != count) {
21530 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21531 int this_offset = offset + (counter << 2);
21533 gen_base_offset_addr(ctx, va, rs, this_offset);
21535 switch (extract32(ctx->opcode, 11, 1)) {
21536 case NM_LWM:
21537 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21538 memop | MO_TESL);
21539 gen_store_gpr(t1, this_rt);
21540 if ((this_rt == rs) &&
21541 (counter != (count - 1))) {
21542 /* UNPREDICTABLE */
21544 break;
21545 case NM_SWM:
21546 this_rt = (rt == 0) ? 0 : this_rt;
21547 gen_load_gpr(t1, this_rt);
21548 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21549 memop | MO_TEUL);
21550 break;
21552 counter++;
21554 tcg_temp_free(va);
21555 tcg_temp_free(t1);
21557 break;
21558 default:
21559 generate_exception_end(ctx, EXCP_RI);
21560 break;
21563 break;
21564 case NM_MOVE_BALC:
21565 check_nms(ctx);
21567 TCGv t0 = tcg_temp_new();
21568 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21569 extract32(ctx->opcode, 1, 20) << 1;
21570 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21571 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21572 extract32(ctx->opcode, 21, 3));
21573 gen_load_gpr(t0, rt);
21574 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21575 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21576 tcg_temp_free(t0);
21578 break;
21579 case NM_P_BAL:
21581 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21582 extract32(ctx->opcode, 1, 24) << 1;
21584 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21585 /* BC */
21586 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21587 } else {
21588 /* BALC */
21589 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21592 break;
21593 case NM_P_J:
21594 switch (extract32(ctx->opcode, 12, 4)) {
21595 case NM_JALRC:
21596 case NM_JALRC_HB:
21597 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21598 break;
21599 case NM_P_BALRSC:
21600 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21601 break;
21602 default:
21603 generate_exception_end(ctx, EXCP_RI);
21604 break;
21606 break;
21607 case NM_P_BR1:
21609 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21610 extract32(ctx->opcode, 1, 13) << 1;
21611 switch (extract32(ctx->opcode, 14, 2)) {
21612 case NM_BEQC:
21613 check_nms(ctx);
21614 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21615 break;
21616 case NM_P_BR3A:
21617 s = sextract32(ctx->opcode, 0, 1) << 14 |
21618 extract32(ctx->opcode, 1, 13) << 1;
21619 check_cp1_enabled(ctx);
21620 switch (extract32(ctx->opcode, 16, 5)) {
21621 case NM_BC1EQZC:
21622 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21623 break;
21624 case NM_BC1NEZC:
21625 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21626 break;
21627 case NM_BPOSGE32C:
21628 check_dsp_r3(ctx);
21630 int32_t imm = extract32(ctx->opcode, 1, 13) |
21631 extract32(ctx->opcode, 0, 1) << 13;
21633 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21634 imm);
21636 break;
21637 default:
21638 generate_exception_end(ctx, EXCP_RI);
21639 break;
21641 break;
21642 case NM_BGEC:
21643 if (rs == rt) {
21644 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21645 } else {
21646 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21648 break;
21649 case NM_BGEUC:
21650 if (rs == rt || rt == 0) {
21651 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21652 } else if (rs == 0) {
21653 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21654 } else {
21655 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21657 break;
21660 break;
21661 case NM_P_BR2:
21663 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21664 extract32(ctx->opcode, 1, 13) << 1;
21665 switch (extract32(ctx->opcode, 14, 2)) {
21666 case NM_BNEC:
21667 check_nms(ctx);
21668 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21669 break;
21670 case NM_BLTC:
21671 if (rs != 0 && rt != 0 && rs == rt) {
21672 /* NOP */
21673 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21674 } else {
21675 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21677 break;
21678 case NM_BLTUC:
21679 if (rs == 0 || rs == rt) {
21680 /* NOP */
21681 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21682 } else {
21683 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21685 break;
21686 default:
21687 generate_exception_end(ctx, EXCP_RI);
21688 break;
21691 break;
21692 case NM_P_BRI:
21694 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21695 extract32(ctx->opcode, 1, 10) << 1;
21696 uint32_t u = extract32(ctx->opcode, 11, 7);
21698 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21699 rt, u, s);
21701 break;
21702 default:
21703 generate_exception_end(ctx, EXCP_RI);
21704 break;
21706 return 4;
21709 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21711 uint32_t op;
21712 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21713 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21714 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21715 int offset;
21716 int imm;
21718 /* make sure instructions are on a halfword boundary */
21719 if (ctx->base.pc_next & 0x1) {
21720 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21721 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21722 tcg_temp_free(tmp);
21723 generate_exception_end(ctx, EXCP_AdEL);
21724 return 2;
21727 op = extract32(ctx->opcode, 10, 6);
21728 switch (op) {
21729 case NM_P16_MV:
21730 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21731 if (rt != 0) {
21732 /* MOVE */
21733 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21734 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21735 } else {
21736 /* P16.RI */
21737 switch (extract32(ctx->opcode, 3, 2)) {
21738 case NM_P16_SYSCALL:
21739 if (extract32(ctx->opcode, 2, 1) == 0) {
21740 generate_exception_end(ctx, EXCP_SYSCALL);
21741 } else {
21742 generate_exception_end(ctx, EXCP_RI);
21744 break;
21745 case NM_BREAK16:
21746 generate_exception_end(ctx, EXCP_BREAK);
21747 break;
21748 case NM_SDBBP16:
21749 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21750 gen_helper_do_semihosting(cpu_env);
21751 } else {
21752 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21753 generate_exception_end(ctx, EXCP_RI);
21754 } else {
21755 generate_exception_end(ctx, EXCP_DBp);
21758 break;
21759 default:
21760 generate_exception_end(ctx, EXCP_RI);
21761 break;
21764 break;
21765 case NM_P16_SHIFT:
21767 int shift = extract32(ctx->opcode, 0, 3);
21768 uint32_t opc = 0;
21769 shift = (shift == 0) ? 8 : shift;
21771 switch (extract32(ctx->opcode, 3, 1)) {
21772 case NM_SLL16:
21773 opc = OPC_SLL;
21774 break;
21775 case NM_SRL16:
21776 opc = OPC_SRL;
21777 break;
21779 gen_shift_imm(ctx, opc, rt, rs, shift);
21781 break;
21782 case NM_P16C:
21783 switch (ctx->opcode & 1) {
21784 case NM_POOL16C_0:
21785 gen_pool16c_nanomips_insn(ctx);
21786 break;
21787 case NM_LWXS16:
21788 gen_ldxs(ctx, rt, rs, rd);
21789 break;
21791 break;
21792 case NM_P16_A1:
21793 switch (extract32(ctx->opcode, 6, 1)) {
21794 case NM_ADDIUR1SP:
21795 imm = extract32(ctx->opcode, 0, 6) << 2;
21796 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21797 break;
21798 default:
21799 generate_exception_end(ctx, EXCP_RI);
21800 break;
21802 break;
21803 case NM_P16_A2:
21804 switch (extract32(ctx->opcode, 3, 1)) {
21805 case NM_ADDIUR2:
21806 imm = extract32(ctx->opcode, 0, 3) << 2;
21807 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21808 break;
21809 case NM_P_ADDIURS5:
21810 rt = extract32(ctx->opcode, 5, 5);
21811 if (rt != 0) {
21812 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21813 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21814 (extract32(ctx->opcode, 0, 3));
21815 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21817 break;
21819 break;
21820 case NM_P16_ADDU:
21821 switch (ctx->opcode & 0x1) {
21822 case NM_ADDU16:
21823 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21824 break;
21825 case NM_SUBU16:
21826 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21827 break;
21829 break;
21830 case NM_P16_4X4:
21831 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21832 extract32(ctx->opcode, 5, 3);
21833 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21834 extract32(ctx->opcode, 0, 3);
21835 rt = decode_gpr_gpr4(rt);
21836 rs = decode_gpr_gpr4(rs);
21837 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21838 (extract32(ctx->opcode, 3, 1))) {
21839 case NM_ADDU4X4:
21840 check_nms(ctx);
21841 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21842 break;
21843 case NM_MUL4X4:
21844 check_nms(ctx);
21845 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21846 break;
21847 default:
21848 generate_exception_end(ctx, EXCP_RI);
21849 break;
21851 break;
21852 case NM_LI16:
21854 int imm = extract32(ctx->opcode, 0, 7);
21855 imm = (imm == 0x7f ? -1 : imm);
21856 if (rt != 0) {
21857 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21860 break;
21861 case NM_ANDI16:
21863 uint32_t u = extract32(ctx->opcode, 0, 4);
21864 u = (u == 12) ? 0xff :
21865 (u == 13) ? 0xffff : u;
21866 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21868 break;
21869 case NM_P16_LB:
21870 offset = extract32(ctx->opcode, 0, 2);
21871 switch (extract32(ctx->opcode, 2, 2)) {
21872 case NM_LB16:
21873 gen_ld(ctx, OPC_LB, rt, rs, offset);
21874 break;
21875 case NM_SB16:
21876 rt = decode_gpr_gpr3_src_store(
21877 NANOMIPS_EXTRACT_RD(ctx->opcode));
21878 gen_st(ctx, OPC_SB, rt, rs, offset);
21879 break;
21880 case NM_LBU16:
21881 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21882 break;
21883 default:
21884 generate_exception_end(ctx, EXCP_RI);
21885 break;
21887 break;
21888 case NM_P16_LH:
21889 offset = extract32(ctx->opcode, 1, 2) << 1;
21890 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21891 case NM_LH16:
21892 gen_ld(ctx, OPC_LH, rt, rs, offset);
21893 break;
21894 case NM_SH16:
21895 rt = decode_gpr_gpr3_src_store(
21896 NANOMIPS_EXTRACT_RD(ctx->opcode));
21897 gen_st(ctx, OPC_SH, rt, rs, offset);
21898 break;
21899 case NM_LHU16:
21900 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21901 break;
21902 default:
21903 generate_exception_end(ctx, EXCP_RI);
21904 break;
21906 break;
21907 case NM_LW16:
21908 offset = extract32(ctx->opcode, 0, 4) << 2;
21909 gen_ld(ctx, OPC_LW, rt, rs, offset);
21910 break;
21911 case NM_LWSP16:
21912 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21913 offset = extract32(ctx->opcode, 0, 5) << 2;
21914 gen_ld(ctx, OPC_LW, rt, 29, offset);
21915 break;
21916 case NM_LW4X4:
21917 check_nms(ctx);
21918 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21919 extract32(ctx->opcode, 5, 3);
21920 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21921 extract32(ctx->opcode, 0, 3);
21922 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21923 (extract32(ctx->opcode, 8, 1) << 2);
21924 rt = decode_gpr_gpr4(rt);
21925 rs = decode_gpr_gpr4(rs);
21926 gen_ld(ctx, OPC_LW, rt, rs, offset);
21927 break;
21928 case NM_SW4X4:
21929 check_nms(ctx);
21930 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21931 extract32(ctx->opcode, 5, 3);
21932 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21933 extract32(ctx->opcode, 0, 3);
21934 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21935 (extract32(ctx->opcode, 8, 1) << 2);
21936 rt = decode_gpr_gpr4_zero(rt);
21937 rs = decode_gpr_gpr4(rs);
21938 gen_st(ctx, OPC_SW, rt, rs, offset);
21939 break;
21940 case NM_LWGP16:
21941 offset = extract32(ctx->opcode, 0, 7) << 2;
21942 gen_ld(ctx, OPC_LW, rt, 28, offset);
21943 break;
21944 case NM_SWSP16:
21945 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21946 offset = extract32(ctx->opcode, 0, 5) << 2;
21947 gen_st(ctx, OPC_SW, rt, 29, offset);
21948 break;
21949 case NM_SW16:
21950 rt = decode_gpr_gpr3_src_store(
21951 NANOMIPS_EXTRACT_RD(ctx->opcode));
21952 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21953 offset = extract32(ctx->opcode, 0, 4) << 2;
21954 gen_st(ctx, OPC_SW, rt, rs, offset);
21955 break;
21956 case NM_SWGP16:
21957 rt = decode_gpr_gpr3_src_store(
21958 NANOMIPS_EXTRACT_RD(ctx->opcode));
21959 offset = extract32(ctx->opcode, 0, 7) << 2;
21960 gen_st(ctx, OPC_SW, rt, 28, offset);
21961 break;
21962 case NM_BC16:
21963 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21964 (sextract32(ctx->opcode, 0, 1) << 10) |
21965 (extract32(ctx->opcode, 1, 9) << 1));
21966 break;
21967 case NM_BALC16:
21968 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21969 (sextract32(ctx->opcode, 0, 1) << 10) |
21970 (extract32(ctx->opcode, 1, 9) << 1));
21971 break;
21972 case NM_BEQZC16:
21973 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21974 (sextract32(ctx->opcode, 0, 1) << 7) |
21975 (extract32(ctx->opcode, 1, 6) << 1));
21976 break;
21977 case NM_BNEZC16:
21978 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21979 (sextract32(ctx->opcode, 0, 1) << 7) |
21980 (extract32(ctx->opcode, 1, 6) << 1));
21981 break;
21982 case NM_P16_BR:
21983 switch (ctx->opcode & 0xf) {
21984 case 0:
21985 /* P16.JRC */
21986 switch (extract32(ctx->opcode, 4, 1)) {
21987 case NM_JRC:
21988 gen_compute_branch_nm(ctx, OPC_JR, 2,
21989 extract32(ctx->opcode, 5, 5), 0, 0);
21990 break;
21991 case NM_JALRC16:
21992 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21993 extract32(ctx->opcode, 5, 5), 31, 0);
21994 break;
21996 break;
21997 default:
21999 /* P16.BRI */
22000 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22001 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22002 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22003 extract32(ctx->opcode, 0, 4) << 1);
22005 break;
22007 break;
22008 case NM_P16_SR:
22010 int count = extract32(ctx->opcode, 0, 4);
22011 int u = extract32(ctx->opcode, 4, 4) << 4;
22013 rt = 30 + extract32(ctx->opcode, 9, 1);
22014 switch (extract32(ctx->opcode, 8, 1)) {
22015 case NM_SAVE16:
22016 gen_save(ctx, rt, count, 0, u);
22017 break;
22018 case NM_RESTORE_JRC16:
22019 gen_restore(ctx, rt, count, 0, u);
22020 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22021 break;
22024 break;
22025 case NM_MOVEP:
22026 case NM_MOVEPREV:
22027 check_nms(ctx);
22029 static const int gpr2reg1[] = {4, 5, 6, 7};
22030 static const int gpr2reg2[] = {5, 6, 7, 8};
22031 int re;
22032 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22033 extract32(ctx->opcode, 8, 1);
22034 int r1 = gpr2reg1[rd2];
22035 int r2 = gpr2reg2[rd2];
22036 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22037 extract32(ctx->opcode, 0, 3);
22038 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22039 extract32(ctx->opcode, 5, 3);
22040 TCGv t0 = tcg_temp_new();
22041 TCGv t1 = tcg_temp_new();
22042 if (op == NM_MOVEP) {
22043 rd = r1;
22044 re = r2;
22045 rs = decode_gpr_gpr4_zero(r3);
22046 rt = decode_gpr_gpr4_zero(r4);
22047 } else {
22048 rd = decode_gpr_gpr4(r3);
22049 re = decode_gpr_gpr4(r4);
22050 rs = r1;
22051 rt = r2;
22053 gen_load_gpr(t0, rs);
22054 gen_load_gpr(t1, rt);
22055 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22056 tcg_gen_mov_tl(cpu_gpr[re], t1);
22057 tcg_temp_free(t0);
22058 tcg_temp_free(t1);
22060 break;
22061 default:
22062 return decode_nanomips_32_48_opc(env, ctx);
22065 return 2;
22069 /* SmartMIPS extension to MIPS32 */
22071 #if defined(TARGET_MIPS64)
22073 /* MDMX extension to MIPS64 */
22075 #endif
22077 /* MIPSDSP functions. */
22078 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22079 int rd, int base, int offset)
22081 TCGv t0;
22083 check_dsp(ctx);
22084 t0 = tcg_temp_new();
22086 if (base == 0) {
22087 gen_load_gpr(t0, offset);
22088 } else if (offset == 0) {
22089 gen_load_gpr(t0, base);
22090 } else {
22091 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22094 switch (opc) {
22095 case OPC_LBUX:
22096 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22097 gen_store_gpr(t0, rd);
22098 break;
22099 case OPC_LHX:
22100 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22101 gen_store_gpr(t0, rd);
22102 break;
22103 case OPC_LWX:
22104 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22105 gen_store_gpr(t0, rd);
22106 break;
22107 #if defined(TARGET_MIPS64)
22108 case OPC_LDX:
22109 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22110 gen_store_gpr(t0, rd);
22111 break;
22112 #endif
22114 tcg_temp_free(t0);
22117 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22118 int ret, int v1, int v2)
22120 TCGv v1_t;
22121 TCGv v2_t;
22123 if (ret == 0) {
22124 /* Treat as NOP. */
22125 return;
22128 v1_t = tcg_temp_new();
22129 v2_t = tcg_temp_new();
22131 gen_load_gpr(v1_t, v1);
22132 gen_load_gpr(v2_t, v2);
22134 switch (op1) {
22135 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22136 case OPC_MULT_G_2E:
22137 check_dsp_r2(ctx);
22138 switch (op2) {
22139 case OPC_ADDUH_QB:
22140 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22141 break;
22142 case OPC_ADDUH_R_QB:
22143 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22144 break;
22145 case OPC_ADDQH_PH:
22146 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22147 break;
22148 case OPC_ADDQH_R_PH:
22149 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22150 break;
22151 case OPC_ADDQH_W:
22152 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22153 break;
22154 case OPC_ADDQH_R_W:
22155 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22156 break;
22157 case OPC_SUBUH_QB:
22158 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22159 break;
22160 case OPC_SUBUH_R_QB:
22161 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22162 break;
22163 case OPC_SUBQH_PH:
22164 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22165 break;
22166 case OPC_SUBQH_R_PH:
22167 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22168 break;
22169 case OPC_SUBQH_W:
22170 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22171 break;
22172 case OPC_SUBQH_R_W:
22173 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22174 break;
22176 break;
22177 case OPC_ABSQ_S_PH_DSP:
22178 switch (op2) {
22179 case OPC_ABSQ_S_QB:
22180 check_dsp_r2(ctx);
22181 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22182 break;
22183 case OPC_ABSQ_S_PH:
22184 check_dsp(ctx);
22185 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22186 break;
22187 case OPC_ABSQ_S_W:
22188 check_dsp(ctx);
22189 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22190 break;
22191 case OPC_PRECEQ_W_PHL:
22192 check_dsp(ctx);
22193 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22194 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22195 break;
22196 case OPC_PRECEQ_W_PHR:
22197 check_dsp(ctx);
22198 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22199 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22200 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22201 break;
22202 case OPC_PRECEQU_PH_QBL:
22203 check_dsp(ctx);
22204 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22205 break;
22206 case OPC_PRECEQU_PH_QBR:
22207 check_dsp(ctx);
22208 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22209 break;
22210 case OPC_PRECEQU_PH_QBLA:
22211 check_dsp(ctx);
22212 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22213 break;
22214 case OPC_PRECEQU_PH_QBRA:
22215 check_dsp(ctx);
22216 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22217 break;
22218 case OPC_PRECEU_PH_QBL:
22219 check_dsp(ctx);
22220 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22221 break;
22222 case OPC_PRECEU_PH_QBR:
22223 check_dsp(ctx);
22224 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22225 break;
22226 case OPC_PRECEU_PH_QBLA:
22227 check_dsp(ctx);
22228 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22229 break;
22230 case OPC_PRECEU_PH_QBRA:
22231 check_dsp(ctx);
22232 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22233 break;
22235 break;
22236 case OPC_ADDU_QB_DSP:
22237 switch (op2) {
22238 case OPC_ADDQ_PH:
22239 check_dsp(ctx);
22240 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22241 break;
22242 case OPC_ADDQ_S_PH:
22243 check_dsp(ctx);
22244 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22245 break;
22246 case OPC_ADDQ_S_W:
22247 check_dsp(ctx);
22248 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22249 break;
22250 case OPC_ADDU_QB:
22251 check_dsp(ctx);
22252 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22253 break;
22254 case OPC_ADDU_S_QB:
22255 check_dsp(ctx);
22256 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22257 break;
22258 case OPC_ADDU_PH:
22259 check_dsp_r2(ctx);
22260 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22261 break;
22262 case OPC_ADDU_S_PH:
22263 check_dsp_r2(ctx);
22264 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22265 break;
22266 case OPC_SUBQ_PH:
22267 check_dsp(ctx);
22268 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22269 break;
22270 case OPC_SUBQ_S_PH:
22271 check_dsp(ctx);
22272 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22273 break;
22274 case OPC_SUBQ_S_W:
22275 check_dsp(ctx);
22276 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22277 break;
22278 case OPC_SUBU_QB:
22279 check_dsp(ctx);
22280 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22281 break;
22282 case OPC_SUBU_S_QB:
22283 check_dsp(ctx);
22284 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22285 break;
22286 case OPC_SUBU_PH:
22287 check_dsp_r2(ctx);
22288 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22289 break;
22290 case OPC_SUBU_S_PH:
22291 check_dsp_r2(ctx);
22292 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22293 break;
22294 case OPC_ADDSC:
22295 check_dsp(ctx);
22296 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22297 break;
22298 case OPC_ADDWC:
22299 check_dsp(ctx);
22300 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22301 break;
22302 case OPC_MODSUB:
22303 check_dsp(ctx);
22304 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22305 break;
22306 case OPC_RADDU_W_QB:
22307 check_dsp(ctx);
22308 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22309 break;
22311 break;
22312 case OPC_CMPU_EQ_QB_DSP:
22313 switch (op2) {
22314 case OPC_PRECR_QB_PH:
22315 check_dsp_r2(ctx);
22316 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22317 break;
22318 case OPC_PRECRQ_QB_PH:
22319 check_dsp(ctx);
22320 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22321 break;
22322 case OPC_PRECR_SRA_PH_W:
22323 check_dsp_r2(ctx);
22325 TCGv_i32 sa_t = tcg_const_i32(v2);
22326 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22327 cpu_gpr[ret]);
22328 tcg_temp_free_i32(sa_t);
22329 break;
22331 case OPC_PRECR_SRA_R_PH_W:
22332 check_dsp_r2(ctx);
22334 TCGv_i32 sa_t = tcg_const_i32(v2);
22335 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22336 cpu_gpr[ret]);
22337 tcg_temp_free_i32(sa_t);
22338 break;
22340 case OPC_PRECRQ_PH_W:
22341 check_dsp(ctx);
22342 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22343 break;
22344 case OPC_PRECRQ_RS_PH_W:
22345 check_dsp(ctx);
22346 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22347 break;
22348 case OPC_PRECRQU_S_QB_PH:
22349 check_dsp(ctx);
22350 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22351 break;
22353 break;
22354 #ifdef TARGET_MIPS64
22355 case OPC_ABSQ_S_QH_DSP:
22356 switch (op2) {
22357 case OPC_PRECEQ_L_PWL:
22358 check_dsp(ctx);
22359 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22360 break;
22361 case OPC_PRECEQ_L_PWR:
22362 check_dsp(ctx);
22363 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22364 break;
22365 case OPC_PRECEQ_PW_QHL:
22366 check_dsp(ctx);
22367 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22368 break;
22369 case OPC_PRECEQ_PW_QHR:
22370 check_dsp(ctx);
22371 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22372 break;
22373 case OPC_PRECEQ_PW_QHLA:
22374 check_dsp(ctx);
22375 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22376 break;
22377 case OPC_PRECEQ_PW_QHRA:
22378 check_dsp(ctx);
22379 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22380 break;
22381 case OPC_PRECEQU_QH_OBL:
22382 check_dsp(ctx);
22383 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22384 break;
22385 case OPC_PRECEQU_QH_OBR:
22386 check_dsp(ctx);
22387 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22388 break;
22389 case OPC_PRECEQU_QH_OBLA:
22390 check_dsp(ctx);
22391 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22392 break;
22393 case OPC_PRECEQU_QH_OBRA:
22394 check_dsp(ctx);
22395 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22396 break;
22397 case OPC_PRECEU_QH_OBL:
22398 check_dsp(ctx);
22399 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22400 break;
22401 case OPC_PRECEU_QH_OBR:
22402 check_dsp(ctx);
22403 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22404 break;
22405 case OPC_PRECEU_QH_OBLA:
22406 check_dsp(ctx);
22407 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22408 break;
22409 case OPC_PRECEU_QH_OBRA:
22410 check_dsp(ctx);
22411 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22412 break;
22413 case OPC_ABSQ_S_OB:
22414 check_dsp_r2(ctx);
22415 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22416 break;
22417 case OPC_ABSQ_S_PW:
22418 check_dsp(ctx);
22419 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22420 break;
22421 case OPC_ABSQ_S_QH:
22422 check_dsp(ctx);
22423 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22424 break;
22426 break;
22427 case OPC_ADDU_OB_DSP:
22428 switch (op2) {
22429 case OPC_RADDU_L_OB:
22430 check_dsp(ctx);
22431 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22432 break;
22433 case OPC_SUBQ_PW:
22434 check_dsp(ctx);
22435 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22436 break;
22437 case OPC_SUBQ_S_PW:
22438 check_dsp(ctx);
22439 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22440 break;
22441 case OPC_SUBQ_QH:
22442 check_dsp(ctx);
22443 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22444 break;
22445 case OPC_SUBQ_S_QH:
22446 check_dsp(ctx);
22447 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22448 break;
22449 case OPC_SUBU_OB:
22450 check_dsp(ctx);
22451 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22452 break;
22453 case OPC_SUBU_S_OB:
22454 check_dsp(ctx);
22455 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22456 break;
22457 case OPC_SUBU_QH:
22458 check_dsp_r2(ctx);
22459 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22460 break;
22461 case OPC_SUBU_S_QH:
22462 check_dsp_r2(ctx);
22463 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22464 break;
22465 case OPC_SUBUH_OB:
22466 check_dsp_r2(ctx);
22467 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22468 break;
22469 case OPC_SUBUH_R_OB:
22470 check_dsp_r2(ctx);
22471 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22472 break;
22473 case OPC_ADDQ_PW:
22474 check_dsp(ctx);
22475 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22476 break;
22477 case OPC_ADDQ_S_PW:
22478 check_dsp(ctx);
22479 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22480 break;
22481 case OPC_ADDQ_QH:
22482 check_dsp(ctx);
22483 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22484 break;
22485 case OPC_ADDQ_S_QH:
22486 check_dsp(ctx);
22487 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22488 break;
22489 case OPC_ADDU_OB:
22490 check_dsp(ctx);
22491 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22492 break;
22493 case OPC_ADDU_S_OB:
22494 check_dsp(ctx);
22495 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22496 break;
22497 case OPC_ADDU_QH:
22498 check_dsp_r2(ctx);
22499 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22500 break;
22501 case OPC_ADDU_S_QH:
22502 check_dsp_r2(ctx);
22503 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22504 break;
22505 case OPC_ADDUH_OB:
22506 check_dsp_r2(ctx);
22507 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22508 break;
22509 case OPC_ADDUH_R_OB:
22510 check_dsp_r2(ctx);
22511 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22512 break;
22514 break;
22515 case OPC_CMPU_EQ_OB_DSP:
22516 switch (op2) {
22517 case OPC_PRECR_OB_QH:
22518 check_dsp_r2(ctx);
22519 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22520 break;
22521 case OPC_PRECR_SRA_QH_PW:
22522 check_dsp_r2(ctx);
22524 TCGv_i32 ret_t = tcg_const_i32(ret);
22525 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22526 tcg_temp_free_i32(ret_t);
22527 break;
22529 case OPC_PRECR_SRA_R_QH_PW:
22530 check_dsp_r2(ctx);
22532 TCGv_i32 sa_v = tcg_const_i32(ret);
22533 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22534 tcg_temp_free_i32(sa_v);
22535 break;
22537 case OPC_PRECRQ_OB_QH:
22538 check_dsp(ctx);
22539 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22540 break;
22541 case OPC_PRECRQ_PW_L:
22542 check_dsp(ctx);
22543 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22544 break;
22545 case OPC_PRECRQ_QH_PW:
22546 check_dsp(ctx);
22547 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22548 break;
22549 case OPC_PRECRQ_RS_QH_PW:
22550 check_dsp(ctx);
22551 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22552 break;
22553 case OPC_PRECRQU_S_OB_QH:
22554 check_dsp(ctx);
22555 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22556 break;
22558 break;
22559 #endif
22562 tcg_temp_free(v1_t);
22563 tcg_temp_free(v2_t);
22566 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22567 int ret, int v1, int v2)
22569 uint32_t op2;
22570 TCGv t0;
22571 TCGv v1_t;
22572 TCGv v2_t;
22574 if (ret == 0) {
22575 /* Treat as NOP. */
22576 return;
22579 t0 = tcg_temp_new();
22580 v1_t = tcg_temp_new();
22581 v2_t = tcg_temp_new();
22583 tcg_gen_movi_tl(t0, v1);
22584 gen_load_gpr(v1_t, v1);
22585 gen_load_gpr(v2_t, v2);
22587 switch (opc) {
22588 case OPC_SHLL_QB_DSP:
22590 op2 = MASK_SHLL_QB(ctx->opcode);
22591 switch (op2) {
22592 case OPC_SHLL_QB:
22593 check_dsp(ctx);
22594 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22595 break;
22596 case OPC_SHLLV_QB:
22597 check_dsp(ctx);
22598 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22599 break;
22600 case OPC_SHLL_PH:
22601 check_dsp(ctx);
22602 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22603 break;
22604 case OPC_SHLLV_PH:
22605 check_dsp(ctx);
22606 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22607 break;
22608 case OPC_SHLL_S_PH:
22609 check_dsp(ctx);
22610 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22611 break;
22612 case OPC_SHLLV_S_PH:
22613 check_dsp(ctx);
22614 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22615 break;
22616 case OPC_SHLL_S_W:
22617 check_dsp(ctx);
22618 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22619 break;
22620 case OPC_SHLLV_S_W:
22621 check_dsp(ctx);
22622 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22623 break;
22624 case OPC_SHRL_QB:
22625 check_dsp(ctx);
22626 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22627 break;
22628 case OPC_SHRLV_QB:
22629 check_dsp(ctx);
22630 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22631 break;
22632 case OPC_SHRL_PH:
22633 check_dsp_r2(ctx);
22634 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22635 break;
22636 case OPC_SHRLV_PH:
22637 check_dsp_r2(ctx);
22638 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22639 break;
22640 case OPC_SHRA_QB:
22641 check_dsp_r2(ctx);
22642 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22643 break;
22644 case OPC_SHRA_R_QB:
22645 check_dsp_r2(ctx);
22646 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22647 break;
22648 case OPC_SHRAV_QB:
22649 check_dsp_r2(ctx);
22650 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22651 break;
22652 case OPC_SHRAV_R_QB:
22653 check_dsp_r2(ctx);
22654 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22655 break;
22656 case OPC_SHRA_PH:
22657 check_dsp(ctx);
22658 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22659 break;
22660 case OPC_SHRA_R_PH:
22661 check_dsp(ctx);
22662 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22663 break;
22664 case OPC_SHRAV_PH:
22665 check_dsp(ctx);
22666 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22667 break;
22668 case OPC_SHRAV_R_PH:
22669 check_dsp(ctx);
22670 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22671 break;
22672 case OPC_SHRA_R_W:
22673 check_dsp(ctx);
22674 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22675 break;
22676 case OPC_SHRAV_R_W:
22677 check_dsp(ctx);
22678 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22679 break;
22680 default: /* Invalid */
22681 MIPS_INVAL("MASK SHLL.QB");
22682 generate_exception_end(ctx, EXCP_RI);
22683 break;
22685 break;
22687 #ifdef TARGET_MIPS64
22688 case OPC_SHLL_OB_DSP:
22689 op2 = MASK_SHLL_OB(ctx->opcode);
22690 switch (op2) {
22691 case OPC_SHLL_PW:
22692 check_dsp(ctx);
22693 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22694 break;
22695 case OPC_SHLLV_PW:
22696 check_dsp(ctx);
22697 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22698 break;
22699 case OPC_SHLL_S_PW:
22700 check_dsp(ctx);
22701 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22702 break;
22703 case OPC_SHLLV_S_PW:
22704 check_dsp(ctx);
22705 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22706 break;
22707 case OPC_SHLL_OB:
22708 check_dsp(ctx);
22709 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22710 break;
22711 case OPC_SHLLV_OB:
22712 check_dsp(ctx);
22713 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22714 break;
22715 case OPC_SHLL_QH:
22716 check_dsp(ctx);
22717 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22718 break;
22719 case OPC_SHLLV_QH:
22720 check_dsp(ctx);
22721 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22722 break;
22723 case OPC_SHLL_S_QH:
22724 check_dsp(ctx);
22725 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22726 break;
22727 case OPC_SHLLV_S_QH:
22728 check_dsp(ctx);
22729 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22730 break;
22731 case OPC_SHRA_OB:
22732 check_dsp_r2(ctx);
22733 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22734 break;
22735 case OPC_SHRAV_OB:
22736 check_dsp_r2(ctx);
22737 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22738 break;
22739 case OPC_SHRA_R_OB:
22740 check_dsp_r2(ctx);
22741 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22742 break;
22743 case OPC_SHRAV_R_OB:
22744 check_dsp_r2(ctx);
22745 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22746 break;
22747 case OPC_SHRA_PW:
22748 check_dsp(ctx);
22749 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22750 break;
22751 case OPC_SHRAV_PW:
22752 check_dsp(ctx);
22753 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22754 break;
22755 case OPC_SHRA_R_PW:
22756 check_dsp(ctx);
22757 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22758 break;
22759 case OPC_SHRAV_R_PW:
22760 check_dsp(ctx);
22761 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22762 break;
22763 case OPC_SHRA_QH:
22764 check_dsp(ctx);
22765 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22766 break;
22767 case OPC_SHRAV_QH:
22768 check_dsp(ctx);
22769 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22770 break;
22771 case OPC_SHRA_R_QH:
22772 check_dsp(ctx);
22773 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22774 break;
22775 case OPC_SHRAV_R_QH:
22776 check_dsp(ctx);
22777 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22778 break;
22779 case OPC_SHRL_OB:
22780 check_dsp(ctx);
22781 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22782 break;
22783 case OPC_SHRLV_OB:
22784 check_dsp(ctx);
22785 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22786 break;
22787 case OPC_SHRL_QH:
22788 check_dsp_r2(ctx);
22789 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22790 break;
22791 case OPC_SHRLV_QH:
22792 check_dsp_r2(ctx);
22793 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22794 break;
22795 default: /* Invalid */
22796 MIPS_INVAL("MASK SHLL.OB");
22797 generate_exception_end(ctx, EXCP_RI);
22798 break;
22800 break;
22801 #endif
22804 tcg_temp_free(t0);
22805 tcg_temp_free(v1_t);
22806 tcg_temp_free(v2_t);
22809 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22810 int ret, int v1, int v2, int check_ret)
22812 TCGv_i32 t0;
22813 TCGv v1_t;
22814 TCGv v2_t;
22816 if ((ret == 0) && (check_ret == 1)) {
22817 /* Treat as NOP. */
22818 return;
22821 t0 = tcg_temp_new_i32();
22822 v1_t = tcg_temp_new();
22823 v2_t = tcg_temp_new();
22825 tcg_gen_movi_i32(t0, ret);
22826 gen_load_gpr(v1_t, v1);
22827 gen_load_gpr(v2_t, v2);
22829 switch (op1) {
22830 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22831 * the same mask and op1. */
22832 case OPC_MULT_G_2E:
22833 check_dsp_r2(ctx);
22834 switch (op2) {
22835 case OPC_MUL_PH:
22836 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22837 break;
22838 case OPC_MUL_S_PH:
22839 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22840 break;
22841 case OPC_MULQ_S_W:
22842 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22843 break;
22844 case OPC_MULQ_RS_W:
22845 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22846 break;
22848 break;
22849 case OPC_DPA_W_PH_DSP:
22850 switch (op2) {
22851 case OPC_DPAU_H_QBL:
22852 check_dsp(ctx);
22853 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22854 break;
22855 case OPC_DPAU_H_QBR:
22856 check_dsp(ctx);
22857 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22858 break;
22859 case OPC_DPSU_H_QBL:
22860 check_dsp(ctx);
22861 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22862 break;
22863 case OPC_DPSU_H_QBR:
22864 check_dsp(ctx);
22865 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22866 break;
22867 case OPC_DPA_W_PH:
22868 check_dsp_r2(ctx);
22869 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22870 break;
22871 case OPC_DPAX_W_PH:
22872 check_dsp_r2(ctx);
22873 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22874 break;
22875 case OPC_DPAQ_S_W_PH:
22876 check_dsp(ctx);
22877 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22878 break;
22879 case OPC_DPAQX_S_W_PH:
22880 check_dsp_r2(ctx);
22881 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22882 break;
22883 case OPC_DPAQX_SA_W_PH:
22884 check_dsp_r2(ctx);
22885 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22886 break;
22887 case OPC_DPS_W_PH:
22888 check_dsp_r2(ctx);
22889 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22890 break;
22891 case OPC_DPSX_W_PH:
22892 check_dsp_r2(ctx);
22893 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22894 break;
22895 case OPC_DPSQ_S_W_PH:
22896 check_dsp(ctx);
22897 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22898 break;
22899 case OPC_DPSQX_S_W_PH:
22900 check_dsp_r2(ctx);
22901 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22902 break;
22903 case OPC_DPSQX_SA_W_PH:
22904 check_dsp_r2(ctx);
22905 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22906 break;
22907 case OPC_MULSAQ_S_W_PH:
22908 check_dsp(ctx);
22909 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22910 break;
22911 case OPC_DPAQ_SA_L_W:
22912 check_dsp(ctx);
22913 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22914 break;
22915 case OPC_DPSQ_SA_L_W:
22916 check_dsp(ctx);
22917 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22918 break;
22919 case OPC_MAQ_S_W_PHL:
22920 check_dsp(ctx);
22921 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22922 break;
22923 case OPC_MAQ_S_W_PHR:
22924 check_dsp(ctx);
22925 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22926 break;
22927 case OPC_MAQ_SA_W_PHL:
22928 check_dsp(ctx);
22929 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22930 break;
22931 case OPC_MAQ_SA_W_PHR:
22932 check_dsp(ctx);
22933 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22934 break;
22935 case OPC_MULSA_W_PH:
22936 check_dsp_r2(ctx);
22937 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22938 break;
22940 break;
22941 #ifdef TARGET_MIPS64
22942 case OPC_DPAQ_W_QH_DSP:
22944 int ac = ret & 0x03;
22945 tcg_gen_movi_i32(t0, ac);
22947 switch (op2) {
22948 case OPC_DMADD:
22949 check_dsp(ctx);
22950 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22951 break;
22952 case OPC_DMADDU:
22953 check_dsp(ctx);
22954 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22955 break;
22956 case OPC_DMSUB:
22957 check_dsp(ctx);
22958 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22959 break;
22960 case OPC_DMSUBU:
22961 check_dsp(ctx);
22962 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22963 break;
22964 case OPC_DPA_W_QH:
22965 check_dsp_r2(ctx);
22966 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22967 break;
22968 case OPC_DPAQ_S_W_QH:
22969 check_dsp(ctx);
22970 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22971 break;
22972 case OPC_DPAQ_SA_L_PW:
22973 check_dsp(ctx);
22974 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22975 break;
22976 case OPC_DPAU_H_OBL:
22977 check_dsp(ctx);
22978 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22979 break;
22980 case OPC_DPAU_H_OBR:
22981 check_dsp(ctx);
22982 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22983 break;
22984 case OPC_DPS_W_QH:
22985 check_dsp_r2(ctx);
22986 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22987 break;
22988 case OPC_DPSQ_S_W_QH:
22989 check_dsp(ctx);
22990 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22991 break;
22992 case OPC_DPSQ_SA_L_PW:
22993 check_dsp(ctx);
22994 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22995 break;
22996 case OPC_DPSU_H_OBL:
22997 check_dsp(ctx);
22998 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22999 break;
23000 case OPC_DPSU_H_OBR:
23001 check_dsp(ctx);
23002 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23003 break;
23004 case OPC_MAQ_S_L_PWL:
23005 check_dsp(ctx);
23006 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23007 break;
23008 case OPC_MAQ_S_L_PWR:
23009 check_dsp(ctx);
23010 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23011 break;
23012 case OPC_MAQ_S_W_QHLL:
23013 check_dsp(ctx);
23014 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23015 break;
23016 case OPC_MAQ_SA_W_QHLL:
23017 check_dsp(ctx);
23018 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23019 break;
23020 case OPC_MAQ_S_W_QHLR:
23021 check_dsp(ctx);
23022 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23023 break;
23024 case OPC_MAQ_SA_W_QHLR:
23025 check_dsp(ctx);
23026 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23027 break;
23028 case OPC_MAQ_S_W_QHRL:
23029 check_dsp(ctx);
23030 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23031 break;
23032 case OPC_MAQ_SA_W_QHRL:
23033 check_dsp(ctx);
23034 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23035 break;
23036 case OPC_MAQ_S_W_QHRR:
23037 check_dsp(ctx);
23038 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23039 break;
23040 case OPC_MAQ_SA_W_QHRR:
23041 check_dsp(ctx);
23042 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23043 break;
23044 case OPC_MULSAQ_S_L_PW:
23045 check_dsp(ctx);
23046 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23047 break;
23048 case OPC_MULSAQ_S_W_QH:
23049 check_dsp(ctx);
23050 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23051 break;
23054 break;
23055 #endif
23056 case OPC_ADDU_QB_DSP:
23057 switch (op2) {
23058 case OPC_MULEU_S_PH_QBL:
23059 check_dsp(ctx);
23060 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23061 break;
23062 case OPC_MULEU_S_PH_QBR:
23063 check_dsp(ctx);
23064 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23065 break;
23066 case OPC_MULQ_RS_PH:
23067 check_dsp(ctx);
23068 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23069 break;
23070 case OPC_MULEQ_S_W_PHL:
23071 check_dsp(ctx);
23072 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23073 break;
23074 case OPC_MULEQ_S_W_PHR:
23075 check_dsp(ctx);
23076 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23077 break;
23078 case OPC_MULQ_S_PH:
23079 check_dsp_r2(ctx);
23080 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23081 break;
23083 break;
23084 #ifdef TARGET_MIPS64
23085 case OPC_ADDU_OB_DSP:
23086 switch (op2) {
23087 case OPC_MULEQ_S_PW_QHL:
23088 check_dsp(ctx);
23089 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23090 break;
23091 case OPC_MULEQ_S_PW_QHR:
23092 check_dsp(ctx);
23093 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23094 break;
23095 case OPC_MULEU_S_QH_OBL:
23096 check_dsp(ctx);
23097 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23098 break;
23099 case OPC_MULEU_S_QH_OBR:
23100 check_dsp(ctx);
23101 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23102 break;
23103 case OPC_MULQ_RS_QH:
23104 check_dsp(ctx);
23105 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23106 break;
23108 break;
23109 #endif
23112 tcg_temp_free_i32(t0);
23113 tcg_temp_free(v1_t);
23114 tcg_temp_free(v2_t);
23117 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23118 int ret, int val)
23120 int16_t imm;
23121 TCGv t0;
23122 TCGv val_t;
23124 if (ret == 0) {
23125 /* Treat as NOP. */
23126 return;
23129 t0 = tcg_temp_new();
23130 val_t = tcg_temp_new();
23131 gen_load_gpr(val_t, val);
23133 switch (op1) {
23134 case OPC_ABSQ_S_PH_DSP:
23135 switch (op2) {
23136 case OPC_BITREV:
23137 check_dsp(ctx);
23138 gen_helper_bitrev(cpu_gpr[ret], val_t);
23139 break;
23140 case OPC_REPL_QB:
23141 check_dsp(ctx);
23143 target_long result;
23144 imm = (ctx->opcode >> 16) & 0xFF;
23145 result = (uint32_t)imm << 24 |
23146 (uint32_t)imm << 16 |
23147 (uint32_t)imm << 8 |
23148 (uint32_t)imm;
23149 result = (int32_t)result;
23150 tcg_gen_movi_tl(cpu_gpr[ret], result);
23152 break;
23153 case OPC_REPLV_QB:
23154 check_dsp(ctx);
23155 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23156 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23157 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23158 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23159 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23160 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23161 break;
23162 case OPC_REPL_PH:
23163 check_dsp(ctx);
23165 imm = (ctx->opcode >> 16) & 0x03FF;
23166 imm = (int16_t)(imm << 6) >> 6;
23167 tcg_gen_movi_tl(cpu_gpr[ret], \
23168 (target_long)((int32_t)imm << 16 | \
23169 (uint16_t)imm));
23171 break;
23172 case OPC_REPLV_PH:
23173 check_dsp(ctx);
23174 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23175 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23176 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23177 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23178 break;
23180 break;
23181 #ifdef TARGET_MIPS64
23182 case OPC_ABSQ_S_QH_DSP:
23183 switch (op2) {
23184 case OPC_REPL_OB:
23185 check_dsp(ctx);
23187 target_long temp;
23189 imm = (ctx->opcode >> 16) & 0xFF;
23190 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23191 temp = (temp << 16) | temp;
23192 temp = (temp << 32) | temp;
23193 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23194 break;
23196 case OPC_REPL_PW:
23197 check_dsp(ctx);
23199 target_long temp;
23201 imm = (ctx->opcode >> 16) & 0x03FF;
23202 imm = (int16_t)(imm << 6) >> 6;
23203 temp = ((target_long)imm << 32) \
23204 | ((target_long)imm & 0xFFFFFFFF);
23205 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23206 break;
23208 case OPC_REPL_QH:
23209 check_dsp(ctx);
23211 target_long temp;
23213 imm = (ctx->opcode >> 16) & 0x03FF;
23214 imm = (int16_t)(imm << 6) >> 6;
23216 temp = ((uint64_t)(uint16_t)imm << 48) |
23217 ((uint64_t)(uint16_t)imm << 32) |
23218 ((uint64_t)(uint16_t)imm << 16) |
23219 (uint64_t)(uint16_t)imm;
23220 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23221 break;
23223 case OPC_REPLV_OB:
23224 check_dsp(ctx);
23225 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23226 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23227 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23228 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23229 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23230 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23231 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23232 break;
23233 case OPC_REPLV_PW:
23234 check_dsp(ctx);
23235 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23236 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23237 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23238 break;
23239 case OPC_REPLV_QH:
23240 check_dsp(ctx);
23241 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23242 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23243 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23244 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23245 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23246 break;
23248 break;
23249 #endif
23251 tcg_temp_free(t0);
23252 tcg_temp_free(val_t);
23255 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23256 uint32_t op1, uint32_t op2,
23257 int ret, int v1, int v2, int check_ret)
23259 TCGv t1;
23260 TCGv v1_t;
23261 TCGv v2_t;
23263 if ((ret == 0) && (check_ret == 1)) {
23264 /* Treat as NOP. */
23265 return;
23268 t1 = tcg_temp_new();
23269 v1_t = tcg_temp_new();
23270 v2_t = tcg_temp_new();
23272 gen_load_gpr(v1_t, v1);
23273 gen_load_gpr(v2_t, v2);
23275 switch (op1) {
23276 case OPC_CMPU_EQ_QB_DSP:
23277 switch (op2) {
23278 case OPC_CMPU_EQ_QB:
23279 check_dsp(ctx);
23280 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23281 break;
23282 case OPC_CMPU_LT_QB:
23283 check_dsp(ctx);
23284 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23285 break;
23286 case OPC_CMPU_LE_QB:
23287 check_dsp(ctx);
23288 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23289 break;
23290 case OPC_CMPGU_EQ_QB:
23291 check_dsp(ctx);
23292 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23293 break;
23294 case OPC_CMPGU_LT_QB:
23295 check_dsp(ctx);
23296 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23297 break;
23298 case OPC_CMPGU_LE_QB:
23299 check_dsp(ctx);
23300 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23301 break;
23302 case OPC_CMPGDU_EQ_QB:
23303 check_dsp_r2(ctx);
23304 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23305 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23306 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23307 tcg_gen_shli_tl(t1, t1, 24);
23308 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23309 break;
23310 case OPC_CMPGDU_LT_QB:
23311 check_dsp_r2(ctx);
23312 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23313 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23314 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23315 tcg_gen_shli_tl(t1, t1, 24);
23316 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23317 break;
23318 case OPC_CMPGDU_LE_QB:
23319 check_dsp_r2(ctx);
23320 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23321 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23322 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23323 tcg_gen_shli_tl(t1, t1, 24);
23324 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23325 break;
23326 case OPC_CMP_EQ_PH:
23327 check_dsp(ctx);
23328 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23329 break;
23330 case OPC_CMP_LT_PH:
23331 check_dsp(ctx);
23332 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23333 break;
23334 case OPC_CMP_LE_PH:
23335 check_dsp(ctx);
23336 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23337 break;
23338 case OPC_PICK_QB:
23339 check_dsp(ctx);
23340 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23341 break;
23342 case OPC_PICK_PH:
23343 check_dsp(ctx);
23344 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23345 break;
23346 case OPC_PACKRL_PH:
23347 check_dsp(ctx);
23348 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23349 break;
23351 break;
23352 #ifdef TARGET_MIPS64
23353 case OPC_CMPU_EQ_OB_DSP:
23354 switch (op2) {
23355 case OPC_CMP_EQ_PW:
23356 check_dsp(ctx);
23357 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23358 break;
23359 case OPC_CMP_LT_PW:
23360 check_dsp(ctx);
23361 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23362 break;
23363 case OPC_CMP_LE_PW:
23364 check_dsp(ctx);
23365 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23366 break;
23367 case OPC_CMP_EQ_QH:
23368 check_dsp(ctx);
23369 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23370 break;
23371 case OPC_CMP_LT_QH:
23372 check_dsp(ctx);
23373 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23374 break;
23375 case OPC_CMP_LE_QH:
23376 check_dsp(ctx);
23377 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23378 break;
23379 case OPC_CMPGDU_EQ_OB:
23380 check_dsp_r2(ctx);
23381 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23382 break;
23383 case OPC_CMPGDU_LT_OB:
23384 check_dsp_r2(ctx);
23385 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23386 break;
23387 case OPC_CMPGDU_LE_OB:
23388 check_dsp_r2(ctx);
23389 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23390 break;
23391 case OPC_CMPGU_EQ_OB:
23392 check_dsp(ctx);
23393 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23394 break;
23395 case OPC_CMPGU_LT_OB:
23396 check_dsp(ctx);
23397 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23398 break;
23399 case OPC_CMPGU_LE_OB:
23400 check_dsp(ctx);
23401 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23402 break;
23403 case OPC_CMPU_EQ_OB:
23404 check_dsp(ctx);
23405 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23406 break;
23407 case OPC_CMPU_LT_OB:
23408 check_dsp(ctx);
23409 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23410 break;
23411 case OPC_CMPU_LE_OB:
23412 check_dsp(ctx);
23413 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23414 break;
23415 case OPC_PACKRL_PW:
23416 check_dsp(ctx);
23417 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23418 break;
23419 case OPC_PICK_OB:
23420 check_dsp(ctx);
23421 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23422 break;
23423 case OPC_PICK_PW:
23424 check_dsp(ctx);
23425 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23426 break;
23427 case OPC_PICK_QH:
23428 check_dsp(ctx);
23429 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23430 break;
23432 break;
23433 #endif
23436 tcg_temp_free(t1);
23437 tcg_temp_free(v1_t);
23438 tcg_temp_free(v2_t);
23441 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23442 uint32_t op1, int rt, int rs, int sa)
23444 TCGv t0;
23446 check_dsp_r2(ctx);
23448 if (rt == 0) {
23449 /* Treat as NOP. */
23450 return;
23453 t0 = tcg_temp_new();
23454 gen_load_gpr(t0, rs);
23456 switch (op1) {
23457 case OPC_APPEND_DSP:
23458 switch (MASK_APPEND(ctx->opcode)) {
23459 case OPC_APPEND:
23460 if (sa != 0) {
23461 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23463 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23464 break;
23465 case OPC_PREPEND:
23466 if (sa != 0) {
23467 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23468 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23469 tcg_gen_shli_tl(t0, t0, 32 - sa);
23470 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23472 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23473 break;
23474 case OPC_BALIGN:
23475 sa &= 3;
23476 if (sa != 0 && sa != 2) {
23477 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23478 tcg_gen_ext32u_tl(t0, t0);
23479 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23480 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23482 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23483 break;
23484 default: /* Invalid */
23485 MIPS_INVAL("MASK APPEND");
23486 generate_exception_end(ctx, EXCP_RI);
23487 break;
23489 break;
23490 #ifdef TARGET_MIPS64
23491 case OPC_DAPPEND_DSP:
23492 switch (MASK_DAPPEND(ctx->opcode)) {
23493 case OPC_DAPPEND:
23494 if (sa != 0) {
23495 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23497 break;
23498 case OPC_PREPENDD:
23499 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23500 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23501 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23502 break;
23503 case OPC_PREPENDW:
23504 if (sa != 0) {
23505 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23506 tcg_gen_shli_tl(t0, t0, 64 - sa);
23507 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23509 break;
23510 case OPC_DBALIGN:
23511 sa &= 7;
23512 if (sa != 0 && sa != 2 && sa != 4) {
23513 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23514 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23515 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23517 break;
23518 default: /* Invalid */
23519 MIPS_INVAL("MASK DAPPEND");
23520 generate_exception_end(ctx, EXCP_RI);
23521 break;
23523 break;
23524 #endif
23526 tcg_temp_free(t0);
23529 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23530 int ret, int v1, int v2, int check_ret)
23533 TCGv t0;
23534 TCGv t1;
23535 TCGv v1_t;
23536 TCGv v2_t;
23537 int16_t imm;
23539 if ((ret == 0) && (check_ret == 1)) {
23540 /* Treat as NOP. */
23541 return;
23544 t0 = tcg_temp_new();
23545 t1 = tcg_temp_new();
23546 v1_t = tcg_temp_new();
23547 v2_t = tcg_temp_new();
23549 gen_load_gpr(v1_t, v1);
23550 gen_load_gpr(v2_t, v2);
23552 switch (op1) {
23553 case OPC_EXTR_W_DSP:
23554 check_dsp(ctx);
23555 switch (op2) {
23556 case OPC_EXTR_W:
23557 tcg_gen_movi_tl(t0, v2);
23558 tcg_gen_movi_tl(t1, v1);
23559 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23560 break;
23561 case OPC_EXTR_R_W:
23562 tcg_gen_movi_tl(t0, v2);
23563 tcg_gen_movi_tl(t1, v1);
23564 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23565 break;
23566 case OPC_EXTR_RS_W:
23567 tcg_gen_movi_tl(t0, v2);
23568 tcg_gen_movi_tl(t1, v1);
23569 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23570 break;
23571 case OPC_EXTR_S_H:
23572 tcg_gen_movi_tl(t0, v2);
23573 tcg_gen_movi_tl(t1, v1);
23574 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23575 break;
23576 case OPC_EXTRV_S_H:
23577 tcg_gen_movi_tl(t0, v2);
23578 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23579 break;
23580 case OPC_EXTRV_W:
23581 tcg_gen_movi_tl(t0, v2);
23582 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23583 break;
23584 case OPC_EXTRV_R_W:
23585 tcg_gen_movi_tl(t0, v2);
23586 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23587 break;
23588 case OPC_EXTRV_RS_W:
23589 tcg_gen_movi_tl(t0, v2);
23590 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23591 break;
23592 case OPC_EXTP:
23593 tcg_gen_movi_tl(t0, v2);
23594 tcg_gen_movi_tl(t1, v1);
23595 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23596 break;
23597 case OPC_EXTPV:
23598 tcg_gen_movi_tl(t0, v2);
23599 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23600 break;
23601 case OPC_EXTPDP:
23602 tcg_gen_movi_tl(t0, v2);
23603 tcg_gen_movi_tl(t1, v1);
23604 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23605 break;
23606 case OPC_EXTPDPV:
23607 tcg_gen_movi_tl(t0, v2);
23608 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23609 break;
23610 case OPC_SHILO:
23611 imm = (ctx->opcode >> 20) & 0x3F;
23612 tcg_gen_movi_tl(t0, ret);
23613 tcg_gen_movi_tl(t1, imm);
23614 gen_helper_shilo(t0, t1, cpu_env);
23615 break;
23616 case OPC_SHILOV:
23617 tcg_gen_movi_tl(t0, ret);
23618 gen_helper_shilo(t0, v1_t, cpu_env);
23619 break;
23620 case OPC_MTHLIP:
23621 tcg_gen_movi_tl(t0, ret);
23622 gen_helper_mthlip(t0, v1_t, cpu_env);
23623 break;
23624 case OPC_WRDSP:
23625 imm = (ctx->opcode >> 11) & 0x3FF;
23626 tcg_gen_movi_tl(t0, imm);
23627 gen_helper_wrdsp(v1_t, t0, cpu_env);
23628 break;
23629 case OPC_RDDSP:
23630 imm = (ctx->opcode >> 16) & 0x03FF;
23631 tcg_gen_movi_tl(t0, imm);
23632 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23633 break;
23635 break;
23636 #ifdef TARGET_MIPS64
23637 case OPC_DEXTR_W_DSP:
23638 check_dsp(ctx);
23639 switch (op2) {
23640 case OPC_DMTHLIP:
23641 tcg_gen_movi_tl(t0, ret);
23642 gen_helper_dmthlip(v1_t, t0, cpu_env);
23643 break;
23644 case OPC_DSHILO:
23646 int shift = (ctx->opcode >> 19) & 0x7F;
23647 int ac = (ctx->opcode >> 11) & 0x03;
23648 tcg_gen_movi_tl(t0, shift);
23649 tcg_gen_movi_tl(t1, ac);
23650 gen_helper_dshilo(t0, t1, cpu_env);
23651 break;
23653 case OPC_DSHILOV:
23655 int ac = (ctx->opcode >> 11) & 0x03;
23656 tcg_gen_movi_tl(t0, ac);
23657 gen_helper_dshilo(v1_t, t0, cpu_env);
23658 break;
23660 case OPC_DEXTP:
23661 tcg_gen_movi_tl(t0, v2);
23662 tcg_gen_movi_tl(t1, v1);
23664 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23665 break;
23666 case OPC_DEXTPV:
23667 tcg_gen_movi_tl(t0, v2);
23668 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23669 break;
23670 case OPC_DEXTPDP:
23671 tcg_gen_movi_tl(t0, v2);
23672 tcg_gen_movi_tl(t1, v1);
23673 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23674 break;
23675 case OPC_DEXTPDPV:
23676 tcg_gen_movi_tl(t0, v2);
23677 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23678 break;
23679 case OPC_DEXTR_L:
23680 tcg_gen_movi_tl(t0, v2);
23681 tcg_gen_movi_tl(t1, v1);
23682 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23683 break;
23684 case OPC_DEXTR_R_L:
23685 tcg_gen_movi_tl(t0, v2);
23686 tcg_gen_movi_tl(t1, v1);
23687 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23688 break;
23689 case OPC_DEXTR_RS_L:
23690 tcg_gen_movi_tl(t0, v2);
23691 tcg_gen_movi_tl(t1, v1);
23692 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23693 break;
23694 case OPC_DEXTR_W:
23695 tcg_gen_movi_tl(t0, v2);
23696 tcg_gen_movi_tl(t1, v1);
23697 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23698 break;
23699 case OPC_DEXTR_R_W:
23700 tcg_gen_movi_tl(t0, v2);
23701 tcg_gen_movi_tl(t1, v1);
23702 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23703 break;
23704 case OPC_DEXTR_RS_W:
23705 tcg_gen_movi_tl(t0, v2);
23706 tcg_gen_movi_tl(t1, v1);
23707 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23708 break;
23709 case OPC_DEXTR_S_H:
23710 tcg_gen_movi_tl(t0, v2);
23711 tcg_gen_movi_tl(t1, v1);
23712 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23713 break;
23714 case OPC_DEXTRV_S_H:
23715 tcg_gen_movi_tl(t0, v2);
23716 tcg_gen_movi_tl(t1, v1);
23717 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23718 break;
23719 case OPC_DEXTRV_L:
23720 tcg_gen_movi_tl(t0, v2);
23721 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23722 break;
23723 case OPC_DEXTRV_R_L:
23724 tcg_gen_movi_tl(t0, v2);
23725 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23726 break;
23727 case OPC_DEXTRV_RS_L:
23728 tcg_gen_movi_tl(t0, v2);
23729 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23730 break;
23731 case OPC_DEXTRV_W:
23732 tcg_gen_movi_tl(t0, v2);
23733 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23734 break;
23735 case OPC_DEXTRV_R_W:
23736 tcg_gen_movi_tl(t0, v2);
23737 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23738 break;
23739 case OPC_DEXTRV_RS_W:
23740 tcg_gen_movi_tl(t0, v2);
23741 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23742 break;
23744 break;
23745 #endif
23748 tcg_temp_free(t0);
23749 tcg_temp_free(t1);
23750 tcg_temp_free(v1_t);
23751 tcg_temp_free(v2_t);
23754 /* End MIPSDSP functions. */
23756 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23758 int rs, rt, rd, sa;
23759 uint32_t op1, op2;
23761 rs = (ctx->opcode >> 21) & 0x1f;
23762 rt = (ctx->opcode >> 16) & 0x1f;
23763 rd = (ctx->opcode >> 11) & 0x1f;
23764 sa = (ctx->opcode >> 6) & 0x1f;
23766 op1 = MASK_SPECIAL(ctx->opcode);
23767 switch (op1) {
23768 case OPC_LSA:
23769 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23770 break;
23771 case OPC_MULT:
23772 case OPC_MULTU:
23773 case OPC_DIV:
23774 case OPC_DIVU:
23775 op2 = MASK_R6_MULDIV(ctx->opcode);
23776 switch (op2) {
23777 case R6_OPC_MUL:
23778 case R6_OPC_MUH:
23779 case R6_OPC_MULU:
23780 case R6_OPC_MUHU:
23781 case R6_OPC_DIV:
23782 case R6_OPC_MOD:
23783 case R6_OPC_DIVU:
23784 case R6_OPC_MODU:
23785 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23786 break;
23787 default:
23788 MIPS_INVAL("special_r6 muldiv");
23789 generate_exception_end(ctx, EXCP_RI);
23790 break;
23792 break;
23793 case OPC_SELEQZ:
23794 case OPC_SELNEZ:
23795 gen_cond_move(ctx, op1, rd, rs, rt);
23796 break;
23797 case R6_OPC_CLO:
23798 case R6_OPC_CLZ:
23799 if (rt == 0 && sa == 1) {
23800 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23801 We need additionally to check other fields */
23802 gen_cl(ctx, op1, rd, rs);
23803 } else {
23804 generate_exception_end(ctx, EXCP_RI);
23806 break;
23807 case R6_OPC_SDBBP:
23808 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23809 gen_helper_do_semihosting(cpu_env);
23810 } else {
23811 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23812 generate_exception_end(ctx, EXCP_RI);
23813 } else {
23814 generate_exception_end(ctx, EXCP_DBp);
23817 break;
23818 #if defined(TARGET_MIPS64)
23819 case OPC_DLSA:
23820 check_mips_64(ctx);
23821 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23822 break;
23823 case R6_OPC_DCLO:
23824 case R6_OPC_DCLZ:
23825 if (rt == 0 && sa == 1) {
23826 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23827 We need additionally to check other fields */
23828 check_mips_64(ctx);
23829 gen_cl(ctx, op1, rd, rs);
23830 } else {
23831 generate_exception_end(ctx, EXCP_RI);
23833 break;
23834 case OPC_DMULT:
23835 case OPC_DMULTU:
23836 case OPC_DDIV:
23837 case OPC_DDIVU:
23839 op2 = MASK_R6_MULDIV(ctx->opcode);
23840 switch (op2) {
23841 case R6_OPC_DMUL:
23842 case R6_OPC_DMUH:
23843 case R6_OPC_DMULU:
23844 case R6_OPC_DMUHU:
23845 case R6_OPC_DDIV:
23846 case R6_OPC_DMOD:
23847 case R6_OPC_DDIVU:
23848 case R6_OPC_DMODU:
23849 check_mips_64(ctx);
23850 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23851 break;
23852 default:
23853 MIPS_INVAL("special_r6 muldiv");
23854 generate_exception_end(ctx, EXCP_RI);
23855 break;
23857 break;
23858 #endif
23859 default: /* Invalid */
23860 MIPS_INVAL("special_r6");
23861 generate_exception_end(ctx, EXCP_RI);
23862 break;
23866 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23868 int rs = extract32(ctx->opcode, 21, 5);
23869 int rt = extract32(ctx->opcode, 16, 5);
23870 int rd = extract32(ctx->opcode, 11, 5);
23871 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23873 switch (op1) {
23874 case OPC_MOVN: /* Conditional move */
23875 case OPC_MOVZ:
23876 gen_cond_move(ctx, op1, rd, rs, rt);
23877 break;
23878 case OPC_MFHI: /* Move from HI/LO */
23879 case OPC_MFLO:
23880 gen_HILO(ctx, op1, 0, rd);
23881 break;
23882 case OPC_MTHI:
23883 case OPC_MTLO: /* Move to HI/LO */
23884 gen_HILO(ctx, op1, 0, rs);
23885 break;
23886 case OPC_MULT:
23887 case OPC_MULTU:
23888 gen_mul_txx9(ctx, op1, rd, rs, rt);
23889 break;
23890 case OPC_DIV:
23891 case OPC_DIVU:
23892 gen_muldiv(ctx, op1, 0, rs, rt);
23893 break;
23894 #if defined(TARGET_MIPS64)
23895 case OPC_DMULT:
23896 case OPC_DMULTU:
23897 case OPC_DDIV:
23898 case OPC_DDIVU:
23899 check_insn_opc_user_only(ctx, INSN_R5900);
23900 gen_muldiv(ctx, op1, 0, rs, rt);
23901 break;
23902 #endif
23903 case OPC_JR:
23904 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23905 break;
23906 default: /* Invalid */
23907 MIPS_INVAL("special_tx79");
23908 generate_exception_end(ctx, EXCP_RI);
23909 break;
23913 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23915 int rs, rt, rd, sa;
23916 uint32_t op1;
23918 rs = (ctx->opcode >> 21) & 0x1f;
23919 rt = (ctx->opcode >> 16) & 0x1f;
23920 rd = (ctx->opcode >> 11) & 0x1f;
23921 sa = (ctx->opcode >> 6) & 0x1f;
23923 op1 = MASK_SPECIAL(ctx->opcode);
23924 switch (op1) {
23925 case OPC_MOVN: /* Conditional move */
23926 case OPC_MOVZ:
23927 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23928 INSN_LOONGSON2E | INSN_LOONGSON2F);
23929 gen_cond_move(ctx, op1, rd, rs, rt);
23930 break;
23931 case OPC_MFHI: /* Move from HI/LO */
23932 case OPC_MFLO:
23933 gen_HILO(ctx, op1, rs & 3, rd);
23934 break;
23935 case OPC_MTHI:
23936 case OPC_MTLO: /* Move to HI/LO */
23937 gen_HILO(ctx, op1, rd & 3, rs);
23938 break;
23939 case OPC_MOVCI:
23940 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23941 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23942 check_cp1_enabled(ctx);
23943 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23944 (ctx->opcode >> 16) & 1);
23945 } else {
23946 generate_exception_err(ctx, EXCP_CpU, 1);
23948 break;
23949 case OPC_MULT:
23950 case OPC_MULTU:
23951 if (sa) {
23952 check_insn(ctx, INSN_VR54XX);
23953 op1 = MASK_MUL_VR54XX(ctx->opcode);
23954 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23955 } else {
23956 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23958 break;
23959 case OPC_DIV:
23960 case OPC_DIVU:
23961 gen_muldiv(ctx, op1, 0, rs, rt);
23962 break;
23963 #if defined(TARGET_MIPS64)
23964 case OPC_DMULT:
23965 case OPC_DMULTU:
23966 case OPC_DDIV:
23967 case OPC_DDIVU:
23968 check_insn(ctx, ISA_MIPS3);
23969 check_mips_64(ctx);
23970 gen_muldiv(ctx, op1, 0, rs, rt);
23971 break;
23972 #endif
23973 case OPC_JR:
23974 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23975 break;
23976 case OPC_SPIM:
23977 #ifdef MIPS_STRICT_STANDARD
23978 MIPS_INVAL("SPIM");
23979 generate_exception_end(ctx, EXCP_RI);
23980 #else
23981 /* Implemented as RI exception for now. */
23982 MIPS_INVAL("spim (unofficial)");
23983 generate_exception_end(ctx, EXCP_RI);
23984 #endif
23985 break;
23986 default: /* Invalid */
23987 MIPS_INVAL("special_legacy");
23988 generate_exception_end(ctx, EXCP_RI);
23989 break;
23993 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23995 int rs, rt, rd, sa;
23996 uint32_t op1;
23998 rs = (ctx->opcode >> 21) & 0x1f;
23999 rt = (ctx->opcode >> 16) & 0x1f;
24000 rd = (ctx->opcode >> 11) & 0x1f;
24001 sa = (ctx->opcode >> 6) & 0x1f;
24003 op1 = MASK_SPECIAL(ctx->opcode);
24004 switch (op1) {
24005 case OPC_SLL: /* Shift with immediate */
24006 if (sa == 5 && rd == 0 &&
24007 rs == 0 && rt == 0) { /* PAUSE */
24008 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24009 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24010 generate_exception_end(ctx, EXCP_RI);
24011 break;
24014 /* Fallthrough */
24015 case OPC_SRA:
24016 gen_shift_imm(ctx, op1, rd, rt, sa);
24017 break;
24018 case OPC_SRL:
24019 switch ((ctx->opcode >> 21) & 0x1f) {
24020 case 1:
24021 /* rotr is decoded as srl on non-R2 CPUs */
24022 if (ctx->insn_flags & ISA_MIPS32R2) {
24023 op1 = OPC_ROTR;
24025 /* Fallthrough */
24026 case 0:
24027 gen_shift_imm(ctx, op1, rd, rt, sa);
24028 break;
24029 default:
24030 generate_exception_end(ctx, EXCP_RI);
24031 break;
24033 break;
24034 case OPC_ADD:
24035 case OPC_ADDU:
24036 case OPC_SUB:
24037 case OPC_SUBU:
24038 gen_arith(ctx, op1, rd, rs, rt);
24039 break;
24040 case OPC_SLLV: /* Shifts */
24041 case OPC_SRAV:
24042 gen_shift(ctx, op1, rd, rs, rt);
24043 break;
24044 case OPC_SRLV:
24045 switch ((ctx->opcode >> 6) & 0x1f) {
24046 case 1:
24047 /* rotrv is decoded as srlv on non-R2 CPUs */
24048 if (ctx->insn_flags & ISA_MIPS32R2) {
24049 op1 = OPC_ROTRV;
24051 /* Fallthrough */
24052 case 0:
24053 gen_shift(ctx, op1, rd, rs, rt);
24054 break;
24055 default:
24056 generate_exception_end(ctx, EXCP_RI);
24057 break;
24059 break;
24060 case OPC_SLT: /* Set on less than */
24061 case OPC_SLTU:
24062 gen_slt(ctx, op1, rd, rs, rt);
24063 break;
24064 case OPC_AND: /* Logic*/
24065 case OPC_OR:
24066 case OPC_NOR:
24067 case OPC_XOR:
24068 gen_logic(ctx, op1, rd, rs, rt);
24069 break;
24070 case OPC_JALR:
24071 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24072 break;
24073 case OPC_TGE: /* Traps */
24074 case OPC_TGEU:
24075 case OPC_TLT:
24076 case OPC_TLTU:
24077 case OPC_TEQ:
24078 case OPC_TNE:
24079 check_insn(ctx, ISA_MIPS2);
24080 gen_trap(ctx, op1, rs, rt, -1);
24081 break;
24082 case OPC_LSA: /* OPC_PMON */
24083 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24084 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24085 decode_opc_special_r6(env, ctx);
24086 } else {
24087 /* Pmon entry point, also R4010 selsl */
24088 #ifdef MIPS_STRICT_STANDARD
24089 MIPS_INVAL("PMON / selsl");
24090 generate_exception_end(ctx, EXCP_RI);
24091 #else
24092 gen_helper_0e0i(pmon, sa);
24093 #endif
24095 break;
24096 case OPC_SYSCALL:
24097 generate_exception_end(ctx, EXCP_SYSCALL);
24098 break;
24099 case OPC_BREAK:
24100 generate_exception_end(ctx, EXCP_BREAK);
24101 break;
24102 case OPC_SYNC:
24103 check_insn(ctx, ISA_MIPS2);
24104 gen_sync(extract32(ctx->opcode, 6, 5));
24105 break;
24107 #if defined(TARGET_MIPS64)
24108 /* MIPS64 specific opcodes */
24109 case OPC_DSLL:
24110 case OPC_DSRA:
24111 case OPC_DSLL32:
24112 case OPC_DSRA32:
24113 check_insn(ctx, ISA_MIPS3);
24114 check_mips_64(ctx);
24115 gen_shift_imm(ctx, op1, rd, rt, sa);
24116 break;
24117 case OPC_DSRL:
24118 switch ((ctx->opcode >> 21) & 0x1f) {
24119 case 1:
24120 /* drotr is decoded as dsrl on non-R2 CPUs */
24121 if (ctx->insn_flags & ISA_MIPS32R2) {
24122 op1 = OPC_DROTR;
24124 /* Fallthrough */
24125 case 0:
24126 check_insn(ctx, ISA_MIPS3);
24127 check_mips_64(ctx);
24128 gen_shift_imm(ctx, op1, rd, rt, sa);
24129 break;
24130 default:
24131 generate_exception_end(ctx, EXCP_RI);
24132 break;
24134 break;
24135 case OPC_DSRL32:
24136 switch ((ctx->opcode >> 21) & 0x1f) {
24137 case 1:
24138 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24139 if (ctx->insn_flags & ISA_MIPS32R2) {
24140 op1 = OPC_DROTR32;
24142 /* Fallthrough */
24143 case 0:
24144 check_insn(ctx, ISA_MIPS3);
24145 check_mips_64(ctx);
24146 gen_shift_imm(ctx, op1, rd, rt, sa);
24147 break;
24148 default:
24149 generate_exception_end(ctx, EXCP_RI);
24150 break;
24152 break;
24153 case OPC_DADD:
24154 case OPC_DADDU:
24155 case OPC_DSUB:
24156 case OPC_DSUBU:
24157 check_insn(ctx, ISA_MIPS3);
24158 check_mips_64(ctx);
24159 gen_arith(ctx, op1, rd, rs, rt);
24160 break;
24161 case OPC_DSLLV:
24162 case OPC_DSRAV:
24163 check_insn(ctx, ISA_MIPS3);
24164 check_mips_64(ctx);
24165 gen_shift(ctx, op1, rd, rs, rt);
24166 break;
24167 case OPC_DSRLV:
24168 switch ((ctx->opcode >> 6) & 0x1f) {
24169 case 1:
24170 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24171 if (ctx->insn_flags & ISA_MIPS32R2) {
24172 op1 = OPC_DROTRV;
24174 /* Fallthrough */
24175 case 0:
24176 check_insn(ctx, ISA_MIPS3);
24177 check_mips_64(ctx);
24178 gen_shift(ctx, op1, rd, rs, rt);
24179 break;
24180 default:
24181 generate_exception_end(ctx, EXCP_RI);
24182 break;
24184 break;
24185 case OPC_DLSA:
24186 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24187 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24188 decode_opc_special_r6(env, ctx);
24190 break;
24191 #endif
24192 default:
24193 if (ctx->insn_flags & ISA_MIPS32R6) {
24194 decode_opc_special_r6(env, ctx);
24195 } else if (ctx->insn_flags & INSN_R5900) {
24196 decode_opc_special_tx79(env, ctx);
24197 } else {
24198 decode_opc_special_legacy(env, ctx);
24204 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24205 #define MXU_APTN1_A 0
24206 #define MXU_APTN1_S 1
24208 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24209 #define MXU_APTN2_AA 0
24210 #define MXU_APTN2_AS 1
24211 #define MXU_APTN2_SA 2
24212 #define MXU_APTN2_SS 3
24214 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24215 #define MXU_EPTN2_AA 0
24216 #define MXU_EPTN2_AS 1
24217 #define MXU_EPTN2_SA 2
24218 #define MXU_EPTN2_SS 3
24220 /* MXU operand getting pattern 'optn2' */
24221 #define MXU_OPTN2_WW 0
24222 #define MXU_OPTN2_LW 1
24223 #define MXU_OPTN2_HW 2
24224 #define MXU_OPTN2_XW 3
24226 /* MXU operand getting pattern 'optn3' */
24227 #define MXU_OPTN3_PTN0 0
24228 #define MXU_OPTN3_PTN1 1
24229 #define MXU_OPTN3_PTN2 2
24230 #define MXU_OPTN3_PTN3 3
24231 #define MXU_OPTN3_PTN4 4
24232 #define MXU_OPTN3_PTN5 5
24233 #define MXU_OPTN3_PTN6 6
24234 #define MXU_OPTN3_PTN7 7
24238 * S32I2M XRa, rb - Register move from GRF to XRF
24240 static void gen_mxu_s32i2m(DisasContext *ctx)
24242 TCGv t0;
24243 uint32_t XRa, Rb;
24245 t0 = tcg_temp_new();
24247 XRa = extract32(ctx->opcode, 6, 5);
24248 Rb = extract32(ctx->opcode, 16, 5);
24250 gen_load_gpr(t0, Rb);
24251 if (XRa <= 15) {
24252 gen_store_mxu_gpr(t0, XRa);
24253 } else if (XRa == 16) {
24254 gen_store_mxu_cr(t0);
24257 tcg_temp_free(t0);
24261 * S32M2I XRa, rb - Register move from XRF to GRF
24263 static void gen_mxu_s32m2i(DisasContext *ctx)
24265 TCGv t0;
24266 uint32_t XRa, Rb;
24268 t0 = tcg_temp_new();
24270 XRa = extract32(ctx->opcode, 6, 5);
24271 Rb = extract32(ctx->opcode, 16, 5);
24273 if (XRa <= 15) {
24274 gen_load_mxu_gpr(t0, XRa);
24275 } else if (XRa == 16) {
24276 gen_load_mxu_cr(t0);
24279 gen_store_gpr(t0, Rb);
24281 tcg_temp_free(t0);
24285 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24287 static void gen_mxu_s8ldd(DisasContext *ctx)
24289 TCGv t0, t1;
24290 uint32_t XRa, Rb, s8, optn3;
24292 t0 = tcg_temp_new();
24293 t1 = tcg_temp_new();
24295 XRa = extract32(ctx->opcode, 6, 4);
24296 s8 = extract32(ctx->opcode, 10, 8);
24297 optn3 = extract32(ctx->opcode, 18, 3);
24298 Rb = extract32(ctx->opcode, 21, 5);
24300 gen_load_gpr(t0, Rb);
24301 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
24303 switch (optn3) {
24304 /* XRa[7:0] = tmp8 */
24305 case MXU_OPTN3_PTN0:
24306 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24307 gen_load_mxu_gpr(t0, XRa);
24308 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
24309 break;
24310 /* XRa[15:8] = tmp8 */
24311 case MXU_OPTN3_PTN1:
24312 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24313 gen_load_mxu_gpr(t0, XRa);
24314 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
24315 break;
24316 /* XRa[23:16] = tmp8 */
24317 case MXU_OPTN3_PTN2:
24318 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24319 gen_load_mxu_gpr(t0, XRa);
24320 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
24321 break;
24322 /* XRa[31:24] = tmp8 */
24323 case MXU_OPTN3_PTN3:
24324 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24325 gen_load_mxu_gpr(t0, XRa);
24326 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
24327 break;
24328 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
24329 case MXU_OPTN3_PTN4:
24330 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24331 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24332 break;
24333 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
24334 case MXU_OPTN3_PTN5:
24335 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24336 tcg_gen_shli_tl(t1, t1, 8);
24337 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24338 break;
24339 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
24340 case MXU_OPTN3_PTN6:
24341 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
24342 tcg_gen_mov_tl(t0, t1);
24343 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
24344 tcg_gen_shli_tl(t1, t1, 16);
24345 tcg_gen_or_tl(t0, t0, t1);
24346 break;
24347 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
24348 case MXU_OPTN3_PTN7:
24349 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
24350 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
24351 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
24352 break;
24355 gen_store_mxu_gpr(t0, XRa);
24357 tcg_temp_free(t0);
24358 tcg_temp_free(t1);
24362 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
24364 static void gen_mxu_d16mul(DisasContext *ctx)
24366 TCGv t0, t1, t2, t3;
24367 uint32_t XRa, XRb, XRc, XRd, optn2;
24369 t0 = tcg_temp_new();
24370 t1 = tcg_temp_new();
24371 t2 = tcg_temp_new();
24372 t3 = tcg_temp_new();
24374 XRa = extract32(ctx->opcode, 6, 4);
24375 XRb = extract32(ctx->opcode, 10, 4);
24376 XRc = extract32(ctx->opcode, 14, 4);
24377 XRd = extract32(ctx->opcode, 18, 4);
24378 optn2 = extract32(ctx->opcode, 22, 2);
24380 gen_load_mxu_gpr(t1, XRb);
24381 tcg_gen_sextract_tl(t0, t1, 0, 16);
24382 tcg_gen_sextract_tl(t1, t1, 16, 16);
24383 gen_load_mxu_gpr(t3, XRc);
24384 tcg_gen_sextract_tl(t2, t3, 0, 16);
24385 tcg_gen_sextract_tl(t3, t3, 16, 16);
24387 switch (optn2) {
24388 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24389 tcg_gen_mul_tl(t3, t1, t3);
24390 tcg_gen_mul_tl(t2, t0, t2);
24391 break;
24392 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24393 tcg_gen_mul_tl(t3, t0, t3);
24394 tcg_gen_mul_tl(t2, t0, t2);
24395 break;
24396 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24397 tcg_gen_mul_tl(t3, t1, t3);
24398 tcg_gen_mul_tl(t2, t1, t2);
24399 break;
24400 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24401 tcg_gen_mul_tl(t3, t0, t3);
24402 tcg_gen_mul_tl(t2, t1, t2);
24403 break;
24405 gen_store_mxu_gpr(t3, XRa);
24406 gen_store_mxu_gpr(t2, XRd);
24408 tcg_temp_free(t0);
24409 tcg_temp_free(t1);
24410 tcg_temp_free(t2);
24411 tcg_temp_free(t3);
24415 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
24416 * and accumulate
24418 static void gen_mxu_d16mac(DisasContext *ctx)
24420 TCGv t0, t1, t2, t3;
24421 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
24423 t0 = tcg_temp_new();
24424 t1 = tcg_temp_new();
24425 t2 = tcg_temp_new();
24426 t3 = tcg_temp_new();
24428 XRa = extract32(ctx->opcode, 6, 4);
24429 XRb = extract32(ctx->opcode, 10, 4);
24430 XRc = extract32(ctx->opcode, 14, 4);
24431 XRd = extract32(ctx->opcode, 18, 4);
24432 optn2 = extract32(ctx->opcode, 22, 2);
24433 aptn2 = extract32(ctx->opcode, 24, 2);
24435 gen_load_mxu_gpr(t1, XRb);
24436 tcg_gen_sextract_tl(t0, t1, 0, 16);
24437 tcg_gen_sextract_tl(t1, t1, 16, 16);
24439 gen_load_mxu_gpr(t3, XRc);
24440 tcg_gen_sextract_tl(t2, t3, 0, 16);
24441 tcg_gen_sextract_tl(t3, t3, 16, 16);
24443 switch (optn2) {
24444 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
24445 tcg_gen_mul_tl(t3, t1, t3);
24446 tcg_gen_mul_tl(t2, t0, t2);
24447 break;
24448 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
24449 tcg_gen_mul_tl(t3, t0, t3);
24450 tcg_gen_mul_tl(t2, t0, t2);
24451 break;
24452 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
24453 tcg_gen_mul_tl(t3, t1, t3);
24454 tcg_gen_mul_tl(t2, t1, t2);
24455 break;
24456 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
24457 tcg_gen_mul_tl(t3, t0, t3);
24458 tcg_gen_mul_tl(t2, t1, t2);
24459 break;
24461 gen_load_mxu_gpr(t0, XRa);
24462 gen_load_mxu_gpr(t1, XRd);
24464 switch (aptn2) {
24465 case MXU_APTN2_AA:
24466 tcg_gen_add_tl(t3, t0, t3);
24467 tcg_gen_add_tl(t2, t1, t2);
24468 break;
24469 case MXU_APTN2_AS:
24470 tcg_gen_add_tl(t3, t0, t3);
24471 tcg_gen_sub_tl(t2, t1, t2);
24472 break;
24473 case MXU_APTN2_SA:
24474 tcg_gen_sub_tl(t3, t0, t3);
24475 tcg_gen_add_tl(t2, t1, t2);
24476 break;
24477 case MXU_APTN2_SS:
24478 tcg_gen_sub_tl(t3, t0, t3);
24479 tcg_gen_sub_tl(t2, t1, t2);
24480 break;
24482 gen_store_mxu_gpr(t3, XRa);
24483 gen_store_mxu_gpr(t2, XRd);
24485 tcg_temp_free(t0);
24486 tcg_temp_free(t1);
24487 tcg_temp_free(t2);
24488 tcg_temp_free(t3);
24492 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
24493 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
24495 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
24497 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
24498 uint32_t XRa, XRb, XRc, XRd, sel;
24500 t0 = tcg_temp_new();
24501 t1 = tcg_temp_new();
24502 t2 = tcg_temp_new();
24503 t3 = tcg_temp_new();
24504 t4 = tcg_temp_new();
24505 t5 = tcg_temp_new();
24506 t6 = tcg_temp_new();
24507 t7 = tcg_temp_new();
24509 XRa = extract32(ctx->opcode, 6, 4);
24510 XRb = extract32(ctx->opcode, 10, 4);
24511 XRc = extract32(ctx->opcode, 14, 4);
24512 XRd = extract32(ctx->opcode, 18, 4);
24513 sel = extract32(ctx->opcode, 22, 2);
24515 gen_load_mxu_gpr(t3, XRb);
24516 gen_load_mxu_gpr(t7, XRc);
24518 if (sel == 0x2) {
24519 /* Q8MULSU */
24520 tcg_gen_ext8s_tl(t0, t3);
24521 tcg_gen_shri_tl(t3, t3, 8);
24522 tcg_gen_ext8s_tl(t1, t3);
24523 tcg_gen_shri_tl(t3, t3, 8);
24524 tcg_gen_ext8s_tl(t2, t3);
24525 tcg_gen_shri_tl(t3, t3, 8);
24526 tcg_gen_ext8s_tl(t3, t3);
24527 } else {
24528 /* Q8MUL */
24529 tcg_gen_ext8u_tl(t0, t3);
24530 tcg_gen_shri_tl(t3, t3, 8);
24531 tcg_gen_ext8u_tl(t1, t3);
24532 tcg_gen_shri_tl(t3, t3, 8);
24533 tcg_gen_ext8u_tl(t2, t3);
24534 tcg_gen_shri_tl(t3, t3, 8);
24535 tcg_gen_ext8u_tl(t3, t3);
24538 tcg_gen_ext8u_tl(t4, t7);
24539 tcg_gen_shri_tl(t7, t7, 8);
24540 tcg_gen_ext8u_tl(t5, t7);
24541 tcg_gen_shri_tl(t7, t7, 8);
24542 tcg_gen_ext8u_tl(t6, t7);
24543 tcg_gen_shri_tl(t7, t7, 8);
24544 tcg_gen_ext8u_tl(t7, t7);
24546 tcg_gen_mul_tl(t0, t0, t4);
24547 tcg_gen_mul_tl(t1, t1, t5);
24548 tcg_gen_mul_tl(t2, t2, t6);
24549 tcg_gen_mul_tl(t3, t3, t7);
24551 tcg_gen_andi_tl(t0, t0, 0xFFFF);
24552 tcg_gen_andi_tl(t1, t1, 0xFFFF);
24553 tcg_gen_andi_tl(t2, t2, 0xFFFF);
24554 tcg_gen_andi_tl(t3, t3, 0xFFFF);
24556 tcg_gen_shli_tl(t1, t1, 16);
24557 tcg_gen_shli_tl(t3, t3, 16);
24559 tcg_gen_or_tl(t0, t0, t1);
24560 tcg_gen_or_tl(t1, t2, t3);
24562 gen_store_mxu_gpr(t0, XRd);
24563 gen_store_mxu_gpr(t1, XRa);
24565 tcg_temp_free(t0);
24566 tcg_temp_free(t1);
24567 tcg_temp_free(t2);
24568 tcg_temp_free(t3);
24569 tcg_temp_free(t4);
24570 tcg_temp_free(t5);
24571 tcg_temp_free(t6);
24572 tcg_temp_free(t7);
24576 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
24577 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
24579 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
24581 TCGv t0, t1;
24582 uint32_t XRa, Rb, s12, sel;
24584 t0 = tcg_temp_new();
24585 t1 = tcg_temp_new();
24587 XRa = extract32(ctx->opcode, 6, 4);
24588 s12 = extract32(ctx->opcode, 10, 10);
24589 sel = extract32(ctx->opcode, 20, 1);
24590 Rb = extract32(ctx->opcode, 21, 5);
24592 gen_load_gpr(t0, Rb);
24594 tcg_gen_movi_tl(t1, s12);
24595 tcg_gen_shli_tl(t1, t1, 2);
24596 if (s12 & 0x200) {
24597 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
24599 tcg_gen_add_tl(t1, t0, t1);
24600 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
24602 if (sel == 1) {
24603 /* S32LDDR */
24604 tcg_gen_bswap32_tl(t1, t1);
24606 gen_store_mxu_gpr(t1, XRa);
24608 tcg_temp_free(t0);
24609 tcg_temp_free(t1);
24614 * Decoding engine for MXU
24615 * =======================
24620 * Decode MXU pool00
24622 * 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
24623 * +-----------+---------+-----+-------+-------+-------+-----------+
24624 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
24625 * +-----------+---------+-----+-------+-------+-------+-----------+
24628 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
24630 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24632 switch (opcode) {
24633 case OPC_MXU_S32MAX:
24634 /* TODO: Implement emulation of S32MAX instruction. */
24635 MIPS_INVAL("OPC_MXU_S32MAX");
24636 generate_exception_end(ctx, EXCP_RI);
24637 break;
24638 case OPC_MXU_S32MIN:
24639 /* TODO: Implement emulation of S32MIN instruction. */
24640 MIPS_INVAL("OPC_MXU_S32MIN");
24641 generate_exception_end(ctx, EXCP_RI);
24642 break;
24643 case OPC_MXU_D16MAX:
24644 /* TODO: Implement emulation of D16MAX instruction. */
24645 MIPS_INVAL("OPC_MXU_D16MAX");
24646 generate_exception_end(ctx, EXCP_RI);
24647 break;
24648 case OPC_MXU_D16MIN:
24649 /* TODO: Implement emulation of D16MIN instruction. */
24650 MIPS_INVAL("OPC_MXU_D16MIN");
24651 generate_exception_end(ctx, EXCP_RI);
24652 break;
24653 case OPC_MXU_Q8MAX:
24654 /* TODO: Implement emulation of Q8MAX instruction. */
24655 MIPS_INVAL("OPC_MXU_Q8MAX");
24656 generate_exception_end(ctx, EXCP_RI);
24657 break;
24658 case OPC_MXU_Q8MIN:
24659 /* TODO: Implement emulation of Q8MIN instruction. */
24660 MIPS_INVAL("OPC_MXU_Q8MIN");
24661 generate_exception_end(ctx, EXCP_RI);
24662 break;
24663 case OPC_MXU_Q8SLT:
24664 /* TODO: Implement emulation of Q8SLT instruction. */
24665 MIPS_INVAL("OPC_MXU_Q8SLT");
24666 generate_exception_end(ctx, EXCP_RI);
24667 break;
24668 case OPC_MXU_Q8SLTU:
24669 /* TODO: Implement emulation of Q8SLTU instruction. */
24670 MIPS_INVAL("OPC_MXU_Q8SLTU");
24671 generate_exception_end(ctx, EXCP_RI);
24672 break;
24673 default:
24674 MIPS_INVAL("decode_opc_mxu");
24675 generate_exception_end(ctx, EXCP_RI);
24676 break;
24682 * Decode MXU pool01
24684 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
24685 * 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
24686 * +-----------+---------+-----+-------+-------+-------+-----------+
24687 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
24688 * +-----------+---------+-----+-------+-------+-------+-----------+
24690 * Q8ADD:
24691 * 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
24692 * +-----------+---+-----+-----+-------+-------+-------+-----------+
24693 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
24694 * +-----------+---+-----+-----+-------+-------+-------+-----------+
24697 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
24699 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24701 switch (opcode) {
24702 case OPC_MXU_S32SLT:
24703 /* TODO: Implement emulation of S32SLT instruction. */
24704 MIPS_INVAL("OPC_MXU_S32SLT");
24705 generate_exception_end(ctx, EXCP_RI);
24706 break;
24707 case OPC_MXU_D16SLT:
24708 /* TODO: Implement emulation of D16SLT instruction. */
24709 MIPS_INVAL("OPC_MXU_D16SLT");
24710 generate_exception_end(ctx, EXCP_RI);
24711 break;
24712 case OPC_MXU_D16AVG:
24713 /* TODO: Implement emulation of D16AVG instruction. */
24714 MIPS_INVAL("OPC_MXU_D16AVG");
24715 generate_exception_end(ctx, EXCP_RI);
24716 break;
24717 case OPC_MXU_D16AVGR:
24718 /* TODO: Implement emulation of D16AVGR instruction. */
24719 MIPS_INVAL("OPC_MXU_D16AVGR");
24720 generate_exception_end(ctx, EXCP_RI);
24721 break;
24722 case OPC_MXU_Q8AVG:
24723 /* TODO: Implement emulation of Q8AVG instruction. */
24724 MIPS_INVAL("OPC_MXU_Q8AVG");
24725 generate_exception_end(ctx, EXCP_RI);
24726 break;
24727 case OPC_MXU_Q8AVGR:
24728 /* TODO: Implement emulation of Q8AVGR instruction. */
24729 MIPS_INVAL("OPC_MXU_Q8AVGR");
24730 generate_exception_end(ctx, EXCP_RI);
24731 break;
24732 case OPC_MXU_Q8ADD:
24733 /* TODO: Implement emulation of Q8ADD instruction. */
24734 MIPS_INVAL("OPC_MXU_Q8ADD");
24735 generate_exception_end(ctx, EXCP_RI);
24736 break;
24737 default:
24738 MIPS_INVAL("decode_opc_mxu");
24739 generate_exception_end(ctx, EXCP_RI);
24740 break;
24746 * Decode MXU pool02
24748 * 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
24749 * +-----------+---------+-----+-------+-------+-------+-----------+
24750 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
24751 * +-----------+---------+-----+-------+-------+-------+-----------+
24754 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
24756 uint32_t opcode = extract32(ctx->opcode, 18, 3);
24758 switch (opcode) {
24759 case OPC_MXU_S32CPS:
24760 /* TODO: Implement emulation of S32CPS instruction. */
24761 MIPS_INVAL("OPC_MXU_S32CPS");
24762 generate_exception_end(ctx, EXCP_RI);
24763 break;
24764 case OPC_MXU_D16CPS:
24765 /* TODO: Implement emulation of D16CPS instruction. */
24766 MIPS_INVAL("OPC_MXU_D16CPS");
24767 generate_exception_end(ctx, EXCP_RI);
24768 break;
24769 case OPC_MXU_Q8ABD:
24770 /* TODO: Implement emulation of Q8ABD instruction. */
24771 MIPS_INVAL("OPC_MXU_Q8ABD");
24772 generate_exception_end(ctx, EXCP_RI);
24773 break;
24774 case OPC_MXU_Q16SAT:
24775 /* TODO: Implement emulation of Q16SAT instruction. */
24776 MIPS_INVAL("OPC_MXU_Q16SAT");
24777 generate_exception_end(ctx, EXCP_RI);
24778 break;
24779 default:
24780 MIPS_INVAL("decode_opc_mxu");
24781 generate_exception_end(ctx, EXCP_RI);
24782 break;
24788 * Decode MXU pool03
24790 * D16MULF:
24791 * 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
24792 * +-----------+---+---+-------+-------+-------+-------+-----------+
24793 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
24794 * +-----------+---+---+-------+-------+-------+-------+-----------+
24796 * D16MULE:
24797 * 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
24798 * +-----------+---+---+-------+-------+-------+-------+-----------+
24799 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
24800 * +-----------+---+---+-------+-------+-------+-------+-----------+
24803 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
24805 uint32_t opcode = extract32(ctx->opcode, 24, 2);
24807 switch (opcode) {
24808 case OPC_MXU_D16MULF:
24809 /* TODO: Implement emulation of D16MULF instruction. */
24810 MIPS_INVAL("OPC_MXU_D16MULF");
24811 generate_exception_end(ctx, EXCP_RI);
24812 break;
24813 case OPC_MXU_D16MULE:
24814 /* TODO: Implement emulation of D16MULE instruction. */
24815 MIPS_INVAL("OPC_MXU_D16MULE");
24816 generate_exception_end(ctx, EXCP_RI);
24817 break;
24818 default:
24819 MIPS_INVAL("decode_opc_mxu");
24820 generate_exception_end(ctx, EXCP_RI);
24821 break;
24827 * Decode MXU pool04
24829 * 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
24830 * +-----------+---------+-+-------------------+-------+-----------+
24831 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
24832 * +-----------+---------+-+-------------------+-------+-----------+
24835 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
24837 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24839 switch (opcode) {
24840 case OPC_MXU_S32LDD:
24841 case OPC_MXU_S32LDDR:
24842 gen_mxu_s32ldd_s32lddr(ctx);
24843 break;
24844 default:
24845 MIPS_INVAL("decode_opc_mxu");
24846 generate_exception_end(ctx, EXCP_RI);
24847 break;
24853 * Decode MXU pool05
24855 * 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
24856 * +-----------+---------+-+-------------------+-------+-----------+
24857 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
24858 * +-----------+---------+-+-------------------+-------+-----------+
24861 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
24863 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24865 switch (opcode) {
24866 case OPC_MXU_S32STD:
24867 /* TODO: Implement emulation of S32STD instruction. */
24868 MIPS_INVAL("OPC_MXU_S32STD");
24869 generate_exception_end(ctx, EXCP_RI);
24870 break;
24871 case OPC_MXU_S32STDR:
24872 /* TODO: Implement emulation of S32STDR instruction. */
24873 MIPS_INVAL("OPC_MXU_S32STDR");
24874 generate_exception_end(ctx, EXCP_RI);
24875 break;
24876 default:
24877 MIPS_INVAL("decode_opc_mxu");
24878 generate_exception_end(ctx, EXCP_RI);
24879 break;
24885 * Decode MXU pool06
24887 * 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
24888 * +-----------+---------+---------+---+-------+-------+-----------+
24889 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
24890 * +-----------+---------+---------+---+-------+-------+-----------+
24893 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
24895 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24897 switch (opcode) {
24898 case OPC_MXU_S32LDDV:
24899 /* TODO: Implement emulation of S32LDDV instruction. */
24900 MIPS_INVAL("OPC_MXU_S32LDDV");
24901 generate_exception_end(ctx, EXCP_RI);
24902 break;
24903 case OPC_MXU_S32LDDVR:
24904 /* TODO: Implement emulation of S32LDDVR instruction. */
24905 MIPS_INVAL("OPC_MXU_S32LDDVR");
24906 generate_exception_end(ctx, EXCP_RI);
24907 break;
24908 default:
24909 MIPS_INVAL("decode_opc_mxu");
24910 generate_exception_end(ctx, EXCP_RI);
24911 break;
24917 * Decode MXU pool07
24919 * 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
24920 * +-----------+---------+---------+---+-------+-------+-----------+
24921 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
24922 * +-----------+---------+---------+---+-------+-------+-----------+
24925 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
24927 uint32_t opcode = extract32(ctx->opcode, 10, 4);
24929 switch (opcode) {
24930 case OPC_MXU_S32STDV:
24931 /* TODO: Implement emulation of S32TDV instruction. */
24932 MIPS_INVAL("OPC_MXU_S32TDV");
24933 generate_exception_end(ctx, EXCP_RI);
24934 break;
24935 case OPC_MXU_S32STDVR:
24936 /* TODO: Implement emulation of S32TDVR instruction. */
24937 MIPS_INVAL("OPC_MXU_S32TDVR");
24938 generate_exception_end(ctx, EXCP_RI);
24939 break;
24940 default:
24941 MIPS_INVAL("decode_opc_mxu");
24942 generate_exception_end(ctx, EXCP_RI);
24943 break;
24949 * Decode MXU pool08
24951 * 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
24952 * +-----------+---------+-+-------------------+-------+-----------+
24953 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
24954 * +-----------+---------+-+-------------------+-------+-----------+
24957 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
24959 uint32_t opcode = extract32(ctx->opcode, 20, 1);
24961 switch (opcode) {
24962 case OPC_MXU_S32LDI:
24963 /* TODO: Implement emulation of S32LDI instruction. */
24964 MIPS_INVAL("OPC_MXU_S32LDI");
24965 generate_exception_end(ctx, EXCP_RI);
24966 break;
24967 case OPC_MXU_S32LDIR:
24968 /* TODO: Implement emulation of S32LDIR instruction. */
24969 MIPS_INVAL("OPC_MXU_S32LDIR");
24970 generate_exception_end(ctx, EXCP_RI);
24971 break;
24972 default:
24973 MIPS_INVAL("decode_opc_mxu");
24974 generate_exception_end(ctx, EXCP_RI);
24975 break;
24981 * Decode MXU pool09
24983 * 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
24984 * +-----------+---------+-+-------------------+-------+-----------+
24985 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
24986 * +-----------+---------+-+-------------------+-------+-----------+
24989 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
24991 uint32_t opcode = extract32(ctx->opcode, 5, 0);
24993 switch (opcode) {
24994 case OPC_MXU_S32SDI:
24995 /* TODO: Implement emulation of S32SDI instruction. */
24996 MIPS_INVAL("OPC_MXU_S32SDI");
24997 generate_exception_end(ctx, EXCP_RI);
24998 break;
24999 case OPC_MXU_S32SDIR:
25000 /* TODO: Implement emulation of S32SDIR instruction. */
25001 MIPS_INVAL("OPC_MXU_S32SDIR");
25002 generate_exception_end(ctx, EXCP_RI);
25003 break;
25004 default:
25005 MIPS_INVAL("decode_opc_mxu");
25006 generate_exception_end(ctx, EXCP_RI);
25007 break;
25013 * Decode MXU pool10
25015 * 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
25016 * +-----------+---------+---------+---+-------+-------+-----------+
25017 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
25018 * +-----------+---------+---------+---+-------+-------+-----------+
25021 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
25023 uint32_t opcode = extract32(ctx->opcode, 5, 0);
25025 switch (opcode) {
25026 case OPC_MXU_S32LDIV:
25027 /* TODO: Implement emulation of S32LDIV instruction. */
25028 MIPS_INVAL("OPC_MXU_S32LDIV");
25029 generate_exception_end(ctx, EXCP_RI);
25030 break;
25031 case OPC_MXU_S32LDIVR:
25032 /* TODO: Implement emulation of S32LDIVR instruction. */
25033 MIPS_INVAL("OPC_MXU_S32LDIVR");
25034 generate_exception_end(ctx, EXCP_RI);
25035 break;
25036 default:
25037 MIPS_INVAL("decode_opc_mxu");
25038 generate_exception_end(ctx, EXCP_RI);
25039 break;
25045 * Decode MXU pool11
25047 * 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
25048 * +-----------+---------+---------+---+-------+-------+-----------+
25049 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
25050 * +-----------+---------+---------+---+-------+-------+-----------+
25053 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
25055 uint32_t opcode = extract32(ctx->opcode, 10, 4);
25057 switch (opcode) {
25058 case OPC_MXU_S32SDIV:
25059 /* TODO: Implement emulation of S32SDIV instruction. */
25060 MIPS_INVAL("OPC_MXU_S32SDIV");
25061 generate_exception_end(ctx, EXCP_RI);
25062 break;
25063 case OPC_MXU_S32SDIVR:
25064 /* TODO: Implement emulation of S32SDIVR instruction. */
25065 MIPS_INVAL("OPC_MXU_S32SDIVR");
25066 generate_exception_end(ctx, EXCP_RI);
25067 break;
25068 default:
25069 MIPS_INVAL("decode_opc_mxu");
25070 generate_exception_end(ctx, EXCP_RI);
25071 break;
25077 * Decode MXU pool12
25079 * 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
25080 * +-----------+---+---+-------+-------+-------+-------+-----------+
25081 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
25082 * +-----------+---+---+-------+-------+-------+-------+-----------+
25085 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
25087 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25089 switch (opcode) {
25090 case OPC_MXU_D32ACC:
25091 /* TODO: Implement emulation of D32ACC instruction. */
25092 MIPS_INVAL("OPC_MXU_D32ACC");
25093 generate_exception_end(ctx, EXCP_RI);
25094 break;
25095 case OPC_MXU_D32ACCM:
25096 /* TODO: Implement emulation of D32ACCM instruction. */
25097 MIPS_INVAL("OPC_MXU_D32ACCM");
25098 generate_exception_end(ctx, EXCP_RI);
25099 break;
25100 case OPC_MXU_D32ASUM:
25101 /* TODO: Implement emulation of D32ASUM instruction. */
25102 MIPS_INVAL("OPC_MXU_D32ASUM");
25103 generate_exception_end(ctx, EXCP_RI);
25104 break;
25105 default:
25106 MIPS_INVAL("decode_opc_mxu");
25107 generate_exception_end(ctx, EXCP_RI);
25108 break;
25114 * Decode MXU pool13
25116 * 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
25117 * +-----------+---+---+-------+-------+-------+-------+-----------+
25118 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
25119 * +-----------+---+---+-------+-------+-------+-------+-----------+
25122 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
25124 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25126 switch (opcode) {
25127 case OPC_MXU_Q16ACC:
25128 /* TODO: Implement emulation of Q16ACC instruction. */
25129 MIPS_INVAL("OPC_MXU_Q16ACC");
25130 generate_exception_end(ctx, EXCP_RI);
25131 break;
25132 case OPC_MXU_Q16ACCM:
25133 /* TODO: Implement emulation of Q16ACCM instruction. */
25134 MIPS_INVAL("OPC_MXU_Q16ACCM");
25135 generate_exception_end(ctx, EXCP_RI);
25136 break;
25137 case OPC_MXU_Q16ASUM:
25138 /* TODO: Implement emulation of Q16ASUM instruction. */
25139 MIPS_INVAL("OPC_MXU_Q16ASUM");
25140 generate_exception_end(ctx, EXCP_RI);
25141 break;
25142 default:
25143 MIPS_INVAL("decode_opc_mxu");
25144 generate_exception_end(ctx, EXCP_RI);
25145 break;
25151 * Decode MXU pool14
25153 * Q8ADDE, Q8ACCE:
25154 * 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
25155 * +-----------+---+---+-------+-------+-------+-------+-----------+
25156 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
25157 * +-----------+---+---+-------+-------+-------+-------+-----------+
25159 * D8SUM, D8SUMC:
25160 * 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
25161 * +-----------+---+---+-------+-------+-------+-------+-----------+
25162 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
25163 * +-----------+---+---+-------+-------+-------+-------+-----------+
25166 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
25168 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25170 switch (opcode) {
25171 case OPC_MXU_Q8ADDE:
25172 /* TODO: Implement emulation of Q8ADDE instruction. */
25173 MIPS_INVAL("OPC_MXU_Q8ADDE");
25174 generate_exception_end(ctx, EXCP_RI);
25175 break;
25176 case OPC_MXU_D8SUM:
25177 /* TODO: Implement emulation of D8SUM instruction. */
25178 MIPS_INVAL("OPC_MXU_D8SUM");
25179 generate_exception_end(ctx, EXCP_RI);
25180 break;
25181 case OPC_MXU_D8SUMC:
25182 /* TODO: Implement emulation of D8SUMC instruction. */
25183 MIPS_INVAL("OPC_MXU_D8SUMC");
25184 generate_exception_end(ctx, EXCP_RI);
25185 break;
25186 default:
25187 MIPS_INVAL("decode_opc_mxu");
25188 generate_exception_end(ctx, EXCP_RI);
25189 break;
25195 * Decode MXU pool15
25197 * S32MUL, S32MULU, S32EXTRV:
25198 * 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
25199 * +-----------+---------+---------+---+-------+-------+-----------+
25200 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
25201 * +-----------+---------+---------+---+-------+-------+-----------+
25203 * S32EXTR:
25204 * 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
25205 * +-----------+---------+---------+---+-------+-------+-----------+
25206 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
25207 * +-----------+---------+---------+---+-------+-------+-----------+
25210 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
25212 uint32_t opcode = extract32(ctx->opcode, 14, 2);
25214 switch (opcode) {
25215 case OPC_MXU_S32MUL:
25216 /* TODO: Implement emulation of S32MUL instruction. */
25217 MIPS_INVAL("OPC_MXU_S32MUL");
25218 generate_exception_end(ctx, EXCP_RI);
25219 break;
25220 case OPC_MXU_S32MULU:
25221 /* TODO: Implement emulation of S32MULU instruction. */
25222 MIPS_INVAL("OPC_MXU_S32MULU");
25223 generate_exception_end(ctx, EXCP_RI);
25224 break;
25225 case OPC_MXU_S32EXTR:
25226 /* TODO: Implement emulation of S32EXTR instruction. */
25227 MIPS_INVAL("OPC_MXU_S32EXTR");
25228 generate_exception_end(ctx, EXCP_RI);
25229 break;
25230 case OPC_MXU_S32EXTRV:
25231 /* TODO: Implement emulation of S32EXTRV instruction. */
25232 MIPS_INVAL("OPC_MXU_S32EXTRV");
25233 generate_exception_end(ctx, EXCP_RI);
25234 break;
25235 default:
25236 MIPS_INVAL("decode_opc_mxu");
25237 generate_exception_end(ctx, EXCP_RI);
25238 break;
25244 * Decode MXU pool16
25246 * D32SARW:
25247 * 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
25248 * +-----------+---------+-----+-------+-------+-------+-----------+
25249 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
25250 * +-----------+---------+-----+-------+-------+-------+-----------+
25252 * S32ALN:
25253 * 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
25254 * +-----------+---------+-----+-------+-------+-------+-----------+
25255 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
25256 * +-----------+---------+-----+-------+-------+-------+-----------+
25258 * S32ALNI:
25259 * 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
25260 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25261 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25262 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25264 * S32NOR, S32AND, S32OR, S32XOR:
25265 * 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
25266 * +-----------+---------+-----+-------+-------+-------+-----------+
25267 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25268 * +-----------+---------+-----+-------+-------+-------+-----------+
25270 * S32LUI:
25271 * 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
25272 * +-----------+-----+---+-----+-------+---------------+-----------+
25273 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
25274 * +-----------+-----+---+-----+-------+---------------+-----------+
25277 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
25279 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25281 switch (opcode) {
25282 case OPC_MXU_D32SARW:
25283 /* TODO: Implement emulation of D32SARW instruction. */
25284 MIPS_INVAL("OPC_MXU_D32SARW");
25285 generate_exception_end(ctx, EXCP_RI);
25286 break;
25287 case OPC_MXU_S32ALN:
25288 /* TODO: Implement emulation of S32ALN instruction. */
25289 MIPS_INVAL("OPC_MXU_S32ALN");
25290 generate_exception_end(ctx, EXCP_RI);
25291 break;
25292 case OPC_MXU_S32ALNI:
25293 /* TODO: Implement emulation of S32ALNI instruction. */
25294 MIPS_INVAL("OPC_MXU_S32ALNI");
25295 generate_exception_end(ctx, EXCP_RI);
25296 break;
25297 case OPC_MXU_S32NOR:
25298 /* TODO: Implement emulation of S32NOR instruction. */
25299 MIPS_INVAL("OPC_MXU_S32NOR");
25300 generate_exception_end(ctx, EXCP_RI);
25301 break;
25302 case OPC_MXU_S32AND:
25303 /* TODO: Implement emulation of S32AND instruction. */
25304 MIPS_INVAL("OPC_MXU_S32AND");
25305 generate_exception_end(ctx, EXCP_RI);
25306 break;
25307 case OPC_MXU_S32OR:
25308 /* TODO: Implement emulation of S32OR instruction. */
25309 MIPS_INVAL("OPC_MXU_S32OR");
25310 generate_exception_end(ctx, EXCP_RI);
25311 break;
25312 case OPC_MXU_S32XOR:
25313 /* TODO: Implement emulation of S32XOR instruction. */
25314 MIPS_INVAL("OPC_MXU_S32XOR");
25315 generate_exception_end(ctx, EXCP_RI);
25316 break;
25317 case OPC_MXU_S32LUI:
25318 /* TODO: Implement emulation of S32LUI instruction. */
25319 MIPS_INVAL("OPC_MXU_S32LUI");
25320 generate_exception_end(ctx, EXCP_RI);
25321 break;
25322 default:
25323 MIPS_INVAL("decode_opc_mxu");
25324 generate_exception_end(ctx, EXCP_RI);
25325 break;
25331 * Decode MXU pool17
25333 * 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
25334 * +-----------+---------+-----+-------+-------+-------+-----------+
25335 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL17|
25336 * +-----------+---------+-----+-------+-------+-------+-----------+
25339 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
25341 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25343 switch (opcode) {
25344 case OPC_MXU_D32SLLV:
25345 /* TODO: Implement emulation of D32SLLV instruction. */
25346 MIPS_INVAL("OPC_MXU_D32SLLV");
25347 generate_exception_end(ctx, EXCP_RI);
25348 break;
25349 case OPC_MXU_D32SLRV:
25350 /* TODO: Implement emulation of D32SLRV instruction. */
25351 MIPS_INVAL("OPC_MXU_D32SLRV");
25352 generate_exception_end(ctx, EXCP_RI);
25353 break;
25354 case OPC_MXU_D32SARV:
25355 /* TODO: Implement emulation of D32SARV instruction. */
25356 MIPS_INVAL("OPC_MXU_D32SARV");
25357 generate_exception_end(ctx, EXCP_RI);
25358 break;
25359 case OPC_MXU_Q16SLLV:
25360 /* TODO: Implement emulation of Q16SLLV instruction. */
25361 MIPS_INVAL("OPC_MXU_Q16SLLV");
25362 generate_exception_end(ctx, EXCP_RI);
25363 break;
25364 case OPC_MXU_Q16SLRV:
25365 /* TODO: Implement emulation of Q16SLRV instruction. */
25366 MIPS_INVAL("OPC_MXU_Q16SLRV");
25367 generate_exception_end(ctx, EXCP_RI);
25368 break;
25369 case OPC_MXU_Q16SARV:
25370 /* TODO: Implement emulation of Q16SARV instruction. */
25371 MIPS_INVAL("OPC_MXU_Q16SARV");
25372 generate_exception_end(ctx, EXCP_RI);
25373 break;
25374 default:
25375 MIPS_INVAL("decode_opc_mxu");
25376 generate_exception_end(ctx, EXCP_RI);
25377 break;
25383 * Decode MXU pool18
25385 * 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
25386 * +-----------+---+---+-------+-------+-------+-------+-----------+
25387 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL18|
25388 * +-----------+---+---+-------+-------+-------+-------+-----------+
25391 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
25393 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25395 switch (opcode) {
25396 case OPC_MXU_Q8MUL:
25397 case OPC_MXU_Q8MULSU:
25398 gen_mxu_q8mul_q8mulsu(ctx);
25399 break;
25400 default:
25401 MIPS_INVAL("decode_opc_mxu");
25402 generate_exception_end(ctx, EXCP_RI);
25403 break;
25409 * Decode MXU pool19
25411 * 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
25412 * +-----------+---------+-----+-------+-------+-------+-----------+
25413 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL19|
25414 * +-----------+---------+-----+-------+-------+-------+-----------+
25417 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
25419 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25421 switch (opcode) {
25422 case OPC_MXU_Q8MOVZ:
25423 /* TODO: Implement emulation of Q8MOVZ instruction. */
25424 MIPS_INVAL("OPC_MXU_Q8MOVZ");
25425 generate_exception_end(ctx, EXCP_RI);
25426 break;
25427 case OPC_MXU_Q8MOVN:
25428 /* TODO: Implement emulation of Q8MOVN instruction. */
25429 MIPS_INVAL("OPC_MXU_Q8MOVN");
25430 generate_exception_end(ctx, EXCP_RI);
25431 break;
25432 case OPC_MXU_D16MOVZ:
25433 /* TODO: Implement emulation of D16MOVZ instruction. */
25434 MIPS_INVAL("OPC_MXU_D16MOVZ");
25435 generate_exception_end(ctx, EXCP_RI);
25436 break;
25437 case OPC_MXU_D16MOVN:
25438 /* TODO: Implement emulation of D16MOVN instruction. */
25439 MIPS_INVAL("OPC_MXU_D16MOVN");
25440 generate_exception_end(ctx, EXCP_RI);
25441 break;
25442 case OPC_MXU_S32MOVZ:
25443 /* TODO: Implement emulation of S32MOVZ instruction. */
25444 MIPS_INVAL("OPC_MXU_S32MOVZ");
25445 generate_exception_end(ctx, EXCP_RI);
25446 break;
25447 case OPC_MXU_S32MOVN:
25448 /* TODO: Implement emulation of S32MOVN instruction. */
25449 MIPS_INVAL("OPC_MXU_S32MOVN");
25450 generate_exception_end(ctx, EXCP_RI);
25451 break;
25452 default:
25453 MIPS_INVAL("decode_opc_mxu");
25454 generate_exception_end(ctx, EXCP_RI);
25455 break;
25461 * Decode MXU pool20
25463 * 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
25464 * +-----------+---+---+-------+-------+-------+-------+-----------+
25465 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL20|
25466 * +-----------+---+---+-------+-------+-------+-------+-----------+
25469 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
25471 uint32_t opcode = extract32(ctx->opcode, 22, 2);
25473 switch (opcode) {
25474 case OPC_MXU_Q8MAC:
25475 /* TODO: Implement emulation of Q8MAC instruction. */
25476 MIPS_INVAL("OPC_MXU_Q8MAC");
25477 generate_exception_end(ctx, EXCP_RI);
25478 break;
25479 case OPC_MXU_Q8MACSU:
25480 /* TODO: Implement emulation of Q8MACSU instruction. */
25481 MIPS_INVAL("OPC_MXU_Q8MACSU");
25482 generate_exception_end(ctx, EXCP_RI);
25483 break;
25484 default:
25485 MIPS_INVAL("decode_opc_mxu");
25486 generate_exception_end(ctx, EXCP_RI);
25487 break;
25493 * Main MXU decoding function
25495 * 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
25496 * +-----------+---------------------------------------+-----------+
25497 * | SPECIAL2 | |x x x x x x|
25498 * +-----------+---------------------------------------+-----------+
25501 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
25504 * TODO: Investigate necessity of including handling of
25505 * CLZ, CLO, SDBB in this function, as they belong to
25506 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
25508 uint32_t opcode = extract32(ctx->opcode, 0, 6);
25510 if (opcode == OPC__MXU_MUL) {
25511 uint32_t rs, rt, rd, op1;
25513 rs = extract32(ctx->opcode, 21, 5);
25514 rt = extract32(ctx->opcode, 16, 5);
25515 rd = extract32(ctx->opcode, 11, 5);
25516 op1 = MASK_SPECIAL2(ctx->opcode);
25518 gen_arith(ctx, op1, rd, rs, rt);
25520 return;
25523 if (opcode == OPC_MXU_S32M2I) {
25524 gen_mxu_s32m2i(ctx);
25525 return;
25528 if (opcode == OPC_MXU_S32I2M) {
25529 gen_mxu_s32i2m(ctx);
25530 return;
25534 TCGv t_mxu_cr = tcg_temp_new();
25535 TCGLabel *l_exit = gen_new_label();
25537 gen_load_mxu_cr(t_mxu_cr);
25538 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
25539 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
25541 switch (opcode) {
25542 case OPC_MXU_S32MADD:
25543 /* TODO: Implement emulation of S32MADD instruction. */
25544 MIPS_INVAL("OPC_MXU_S32MADD");
25545 generate_exception_end(ctx, EXCP_RI);
25546 break;
25547 case OPC_MXU_S32MADDU:
25548 /* TODO: Implement emulation of S32MADDU instruction. */
25549 MIPS_INVAL("OPC_MXU_S32MADDU");
25550 generate_exception_end(ctx, EXCP_RI);
25551 break;
25552 case OPC_MXU__POOL00:
25553 decode_opc_mxu__pool00(env, ctx);
25554 break;
25555 case OPC_MXU_S32MSUB:
25556 /* TODO: Implement emulation of S32MSUB instruction. */
25557 MIPS_INVAL("OPC_MXU_S32MSUB");
25558 generate_exception_end(ctx, EXCP_RI);
25559 break;
25560 case OPC_MXU_S32MSUBU:
25561 /* TODO: Implement emulation of S32MSUBU instruction. */
25562 MIPS_INVAL("OPC_MXU_S32MSUBU");
25563 generate_exception_end(ctx, EXCP_RI);
25564 break;
25565 case OPC_MXU__POOL01:
25566 decode_opc_mxu__pool01(env, ctx);
25567 break;
25568 case OPC_MXU__POOL02:
25569 decode_opc_mxu__pool02(env, ctx);
25570 break;
25571 case OPC_MXU_D16MUL:
25572 gen_mxu_d16mul(ctx);
25573 break;
25574 case OPC_MXU__POOL03:
25575 decode_opc_mxu__pool03(env, ctx);
25576 break;
25577 case OPC_MXU_D16MAC:
25578 gen_mxu_d16mac(ctx);
25579 break;
25580 case OPC_MXU_D16MACF:
25581 /* TODO: Implement emulation of D16MACF instruction. */
25582 MIPS_INVAL("OPC_MXU_D16MACF");
25583 generate_exception_end(ctx, EXCP_RI);
25584 break;
25585 case OPC_MXU_D16MADL:
25586 /* TODO: Implement emulation of D16MADL instruction. */
25587 MIPS_INVAL("OPC_MXU_D16MADL");
25588 generate_exception_end(ctx, EXCP_RI);
25589 break;
25590 case OPC_MXU_S16MAD:
25591 /* TODO: Implement emulation of S16MAD instruction. */
25592 MIPS_INVAL("OPC_MXU_S16MAD");
25593 generate_exception_end(ctx, EXCP_RI);
25594 break;
25595 case OPC_MXU_Q16ADD:
25596 /* TODO: Implement emulation of Q16ADD instruction. */
25597 MIPS_INVAL("OPC_MXU_Q16ADD");
25598 generate_exception_end(ctx, EXCP_RI);
25599 break;
25600 case OPC_MXU_D16MACE:
25601 /* TODO: Implement emulation of D16MACE instruction. */
25602 MIPS_INVAL("OPC_MXU_D16MACE");
25603 generate_exception_end(ctx, EXCP_RI);
25604 break;
25605 case OPC_MXU__POOL04:
25606 decode_opc_mxu__pool04(env, ctx);
25607 break;
25608 case OPC_MXU__POOL05:
25609 decode_opc_mxu__pool05(env, ctx);
25610 break;
25611 case OPC_MXU__POOL06:
25612 decode_opc_mxu__pool06(env, ctx);
25613 break;
25614 case OPC_MXU__POOL07:
25615 decode_opc_mxu__pool07(env, ctx);
25616 break;
25617 case OPC_MXU__POOL08:
25618 decode_opc_mxu__pool08(env, ctx);
25619 break;
25620 case OPC_MXU__POOL09:
25621 decode_opc_mxu__pool09(env, ctx);
25622 break;
25623 case OPC_MXU__POOL10:
25624 decode_opc_mxu__pool10(env, ctx);
25625 break;
25626 case OPC_MXU__POOL11:
25627 decode_opc_mxu__pool11(env, ctx);
25628 break;
25629 case OPC_MXU_D32ADD:
25630 /* TODO: Implement emulation of D32ADD instruction. */
25631 MIPS_INVAL("OPC_MXU_D32ADD");
25632 generate_exception_end(ctx, EXCP_RI);
25633 break;
25634 case OPC_MXU__POOL12:
25635 decode_opc_mxu__pool12(env, ctx);
25636 break;
25637 case OPC_MXU__POOL13:
25638 decode_opc_mxu__pool13(env, ctx);
25639 break;
25640 case OPC_MXU__POOL14:
25641 decode_opc_mxu__pool14(env, ctx);
25642 break;
25643 case OPC_MXU_Q8ACCE:
25644 /* TODO: Implement emulation of Q8ACCE instruction. */
25645 MIPS_INVAL("OPC_MXU_Q8ACCE");
25646 generate_exception_end(ctx, EXCP_RI);
25647 break;
25648 case OPC_MXU_S8LDD:
25649 gen_mxu_s8ldd(ctx);
25650 break;
25651 case OPC_MXU_S8STD:
25652 /* TODO: Implement emulation of S8STD instruction. */
25653 MIPS_INVAL("OPC_MXU_S8STD");
25654 generate_exception_end(ctx, EXCP_RI);
25655 break;
25656 case OPC_MXU_S8LDI:
25657 /* TODO: Implement emulation of S8LDI instruction. */
25658 MIPS_INVAL("OPC_MXU_S8LDI");
25659 generate_exception_end(ctx, EXCP_RI);
25660 break;
25661 case OPC_MXU_S8SDI:
25662 /* TODO: Implement emulation of S8SDI instruction. */
25663 MIPS_INVAL("OPC_MXU_S8SDI");
25664 generate_exception_end(ctx, EXCP_RI);
25665 break;
25666 case OPC_MXU__POOL15:
25667 decode_opc_mxu__pool15(env, ctx);
25668 break;
25669 case OPC_MXU__POOL16:
25670 decode_opc_mxu__pool16(env, ctx);
25671 break;
25672 case OPC_MXU_LXB:
25673 /* TODO: Implement emulation of LXB instruction. */
25674 MIPS_INVAL("OPC_MXU_LXB");
25675 generate_exception_end(ctx, EXCP_RI);
25676 break;
25677 case OPC_MXU_S16LDD:
25678 /* TODO: Implement emulation of S16LDD instruction. */
25679 MIPS_INVAL("OPC_MXU_S16LDD");
25680 generate_exception_end(ctx, EXCP_RI);
25681 break;
25682 case OPC_MXU_S16STD:
25683 /* TODO: Implement emulation of S16STD instruction. */
25684 MIPS_INVAL("OPC_MXU_S16STD");
25685 generate_exception_end(ctx, EXCP_RI);
25686 break;
25687 case OPC_MXU_S16LDI:
25688 /* TODO: Implement emulation of S16LDI instruction. */
25689 MIPS_INVAL("OPC_MXU_S16LDI");
25690 generate_exception_end(ctx, EXCP_RI);
25691 break;
25692 case OPC_MXU_S16SDI:
25693 /* TODO: Implement emulation of S16SDI instruction. */
25694 MIPS_INVAL("OPC_MXU_S16SDI");
25695 generate_exception_end(ctx, EXCP_RI);
25696 break;
25697 case OPC_MXU_D32SLL:
25698 /* TODO: Implement emulation of D32SLL instruction. */
25699 MIPS_INVAL("OPC_MXU_D32SLL");
25700 generate_exception_end(ctx, EXCP_RI);
25701 break;
25702 case OPC_MXU_D32SLR:
25703 /* TODO: Implement emulation of D32SLR instruction. */
25704 MIPS_INVAL("OPC_MXU_D32SLR");
25705 generate_exception_end(ctx, EXCP_RI);
25706 break;
25707 case OPC_MXU_D32SARL:
25708 /* TODO: Implement emulation of D32SARL instruction. */
25709 MIPS_INVAL("OPC_MXU_D32SARL");
25710 generate_exception_end(ctx, EXCP_RI);
25711 break;
25712 case OPC_MXU_D32SAR:
25713 /* TODO: Implement emulation of D32SAR instruction. */
25714 MIPS_INVAL("OPC_MXU_D32SAR");
25715 generate_exception_end(ctx, EXCP_RI);
25716 break;
25717 case OPC_MXU_Q16SLL:
25718 /* TODO: Implement emulation of Q16SLL instruction. */
25719 MIPS_INVAL("OPC_MXU_Q16SLL");
25720 generate_exception_end(ctx, EXCP_RI);
25721 break;
25722 case OPC_MXU_Q16SLR:
25723 /* TODO: Implement emulation of Q16SLR instruction. */
25724 MIPS_INVAL("OPC_MXU_Q16SLR");
25725 generate_exception_end(ctx, EXCP_RI);
25726 break;
25727 case OPC_MXU__POOL17:
25728 decode_opc_mxu__pool17(env, ctx);
25729 break;
25730 case OPC_MXU_Q16SAR:
25731 /* TODO: Implement emulation of Q16SAR instruction. */
25732 MIPS_INVAL("OPC_MXU_Q16SAR");
25733 generate_exception_end(ctx, EXCP_RI);
25734 break;
25735 case OPC_MXU__POOL18:
25736 decode_opc_mxu__pool18(env, ctx);
25737 break;
25738 case OPC_MXU__POOL19:
25739 decode_opc_mxu__pool19(env, ctx);
25740 break;
25741 case OPC_MXU__POOL20:
25742 decode_opc_mxu__pool20(env, ctx);
25743 break;
25744 case OPC_MXU_Q16SCOP:
25745 /* TODO: Implement emulation of Q16SCOP instruction. */
25746 MIPS_INVAL("OPC_MXU_Q16SCOP");
25747 generate_exception_end(ctx, EXCP_RI);
25748 break;
25749 case OPC_MXU_Q8MADL:
25750 /* TODO: Implement emulation of Q8MADL instruction. */
25751 MIPS_INVAL("OPC_MXU_Q8MADL");
25752 generate_exception_end(ctx, EXCP_RI);
25753 break;
25754 case OPC_MXU_S32SFL:
25755 /* TODO: Implement emulation of S32SFL instruction. */
25756 MIPS_INVAL("OPC_MXU_S32SFL");
25757 generate_exception_end(ctx, EXCP_RI);
25758 break;
25759 case OPC_MXU_Q8SAD:
25760 /* TODO: Implement emulation of Q8SAD instruction. */
25761 MIPS_INVAL("OPC_MXU_Q8SAD");
25762 generate_exception_end(ctx, EXCP_RI);
25763 break;
25764 default:
25765 MIPS_INVAL("decode_opc_mxu");
25766 generate_exception_end(ctx, EXCP_RI);
25769 gen_set_label(l_exit);
25770 tcg_temp_free(t_mxu_cr);
25775 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
25777 int rs, rt, rd;
25778 uint32_t op1;
25780 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25782 rs = (ctx->opcode >> 21) & 0x1f;
25783 rt = (ctx->opcode >> 16) & 0x1f;
25784 rd = (ctx->opcode >> 11) & 0x1f;
25786 op1 = MASK_SPECIAL2(ctx->opcode);
25787 switch (op1) {
25788 case OPC_MADD: /* Multiply and add/sub */
25789 case OPC_MADDU:
25790 case OPC_MSUB:
25791 case OPC_MSUBU:
25792 check_insn(ctx, ISA_MIPS32);
25793 gen_muldiv(ctx, op1, rd & 3, rs, rt);
25794 break;
25795 case OPC_MUL:
25796 gen_arith(ctx, op1, rd, rs, rt);
25797 break;
25798 case OPC_DIV_G_2F:
25799 case OPC_DIVU_G_2F:
25800 case OPC_MULT_G_2F:
25801 case OPC_MULTU_G_2F:
25802 case OPC_MOD_G_2F:
25803 case OPC_MODU_G_2F:
25804 check_insn(ctx, INSN_LOONGSON2F);
25805 gen_loongson_integer(ctx, op1, rd, rs, rt);
25806 break;
25807 case OPC_CLO:
25808 case OPC_CLZ:
25809 check_insn(ctx, ISA_MIPS32);
25810 gen_cl(ctx, op1, rd, rs);
25811 break;
25812 case OPC_SDBBP:
25813 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
25814 gen_helper_do_semihosting(cpu_env);
25815 } else {
25816 /* XXX: not clear which exception should be raised
25817 * when in debug mode...
25819 check_insn(ctx, ISA_MIPS32);
25820 generate_exception_end(ctx, EXCP_DBp);
25822 break;
25823 #if defined(TARGET_MIPS64)
25824 case OPC_DCLO:
25825 case OPC_DCLZ:
25826 check_insn(ctx, ISA_MIPS64);
25827 check_mips_64(ctx);
25828 gen_cl(ctx, op1, rd, rs);
25829 break;
25830 case OPC_DMULT_G_2F:
25831 case OPC_DMULTU_G_2F:
25832 case OPC_DDIV_G_2F:
25833 case OPC_DDIVU_G_2F:
25834 case OPC_DMOD_G_2F:
25835 case OPC_DMODU_G_2F:
25836 check_insn(ctx, INSN_LOONGSON2F);
25837 gen_loongson_integer(ctx, op1, rd, rs, rt);
25838 break;
25839 #endif
25840 default: /* Invalid */
25841 MIPS_INVAL("special2_legacy");
25842 generate_exception_end(ctx, EXCP_RI);
25843 break;
25847 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
25849 int rs, rt, rd, sa;
25850 uint32_t op1, op2;
25851 int16_t imm;
25853 rs = (ctx->opcode >> 21) & 0x1f;
25854 rt = (ctx->opcode >> 16) & 0x1f;
25855 rd = (ctx->opcode >> 11) & 0x1f;
25856 sa = (ctx->opcode >> 6) & 0x1f;
25857 imm = (int16_t)ctx->opcode >> 7;
25859 op1 = MASK_SPECIAL3(ctx->opcode);
25860 switch (op1) {
25861 case R6_OPC_PREF:
25862 if (rt >= 24) {
25863 /* hint codes 24-31 are reserved and signal RI */
25864 generate_exception_end(ctx, EXCP_RI);
25866 /* Treat as NOP. */
25867 break;
25868 case R6_OPC_CACHE:
25869 check_cp0_enabled(ctx);
25870 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25871 gen_cache_operation(ctx, rt, rs, imm);
25873 break;
25874 case R6_OPC_SC:
25875 gen_st_cond(ctx, op1, rt, rs, imm);
25876 break;
25877 case R6_OPC_LL:
25878 gen_ld(ctx, op1, rt, rs, imm);
25879 break;
25880 case OPC_BSHFL:
25882 if (rd == 0) {
25883 /* Treat as NOP. */
25884 break;
25886 op2 = MASK_BSHFL(ctx->opcode);
25887 switch (op2) {
25888 case OPC_ALIGN:
25889 case OPC_ALIGN_1:
25890 case OPC_ALIGN_2:
25891 case OPC_ALIGN_3:
25892 gen_align(ctx, 32, rd, rs, rt, sa & 3);
25893 break;
25894 case OPC_BITSWAP:
25895 gen_bitswap(ctx, op2, rd, rt);
25896 break;
25899 break;
25900 #if defined(TARGET_MIPS64)
25901 case R6_OPC_SCD:
25902 gen_st_cond(ctx, op1, rt, rs, imm);
25903 break;
25904 case R6_OPC_LLD:
25905 gen_ld(ctx, op1, rt, rs, imm);
25906 break;
25907 case OPC_DBSHFL:
25908 check_mips_64(ctx);
25910 if (rd == 0) {
25911 /* Treat as NOP. */
25912 break;
25914 op2 = MASK_DBSHFL(ctx->opcode);
25915 switch (op2) {
25916 case OPC_DALIGN:
25917 case OPC_DALIGN_1:
25918 case OPC_DALIGN_2:
25919 case OPC_DALIGN_3:
25920 case OPC_DALIGN_4:
25921 case OPC_DALIGN_5:
25922 case OPC_DALIGN_6:
25923 case OPC_DALIGN_7:
25924 gen_align(ctx, 64, rd, rs, rt, sa & 7);
25925 break;
25926 case OPC_DBITSWAP:
25927 gen_bitswap(ctx, op2, rd, rt);
25928 break;
25932 break;
25933 #endif
25934 default: /* Invalid */
25935 MIPS_INVAL("special3_r6");
25936 generate_exception_end(ctx, EXCP_RI);
25937 break;
25941 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
25943 int rs, rt, rd;
25944 uint32_t op1, op2;
25946 rs = (ctx->opcode >> 21) & 0x1f;
25947 rt = (ctx->opcode >> 16) & 0x1f;
25948 rd = (ctx->opcode >> 11) & 0x1f;
25950 op1 = MASK_SPECIAL3(ctx->opcode);
25951 switch (op1) {
25952 case OPC_DIV_G_2E:
25953 case OPC_DIVU_G_2E:
25954 case OPC_MOD_G_2E:
25955 case OPC_MODU_G_2E:
25956 case OPC_MULT_G_2E:
25957 case OPC_MULTU_G_2E:
25958 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
25959 * the same mask and op1. */
25960 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
25961 op2 = MASK_ADDUH_QB(ctx->opcode);
25962 switch (op2) {
25963 case OPC_ADDUH_QB:
25964 case OPC_ADDUH_R_QB:
25965 case OPC_ADDQH_PH:
25966 case OPC_ADDQH_R_PH:
25967 case OPC_ADDQH_W:
25968 case OPC_ADDQH_R_W:
25969 case OPC_SUBUH_QB:
25970 case OPC_SUBUH_R_QB:
25971 case OPC_SUBQH_PH:
25972 case OPC_SUBQH_R_PH:
25973 case OPC_SUBQH_W:
25974 case OPC_SUBQH_R_W:
25975 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
25976 break;
25977 case OPC_MUL_PH:
25978 case OPC_MUL_S_PH:
25979 case OPC_MULQ_S_W:
25980 case OPC_MULQ_RS_W:
25981 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
25982 break;
25983 default:
25984 MIPS_INVAL("MASK ADDUH.QB");
25985 generate_exception_end(ctx, EXCP_RI);
25986 break;
25988 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
25989 gen_loongson_integer(ctx, op1, rd, rs, rt);
25990 } else {
25991 generate_exception_end(ctx, EXCP_RI);
25993 break;
25994 case OPC_LX_DSP:
25995 op2 = MASK_LX(ctx->opcode);
25996 switch (op2) {
25997 #if defined(TARGET_MIPS64)
25998 case OPC_LDX:
25999 #endif
26000 case OPC_LBUX:
26001 case OPC_LHX:
26002 case OPC_LWX:
26003 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
26004 break;
26005 default: /* Invalid */
26006 MIPS_INVAL("MASK LX");
26007 generate_exception_end(ctx, EXCP_RI);
26008 break;
26010 break;
26011 case OPC_ABSQ_S_PH_DSP:
26012 op2 = MASK_ABSQ_S_PH(ctx->opcode);
26013 switch (op2) {
26014 case OPC_ABSQ_S_QB:
26015 case OPC_ABSQ_S_PH:
26016 case OPC_ABSQ_S_W:
26017 case OPC_PRECEQ_W_PHL:
26018 case OPC_PRECEQ_W_PHR:
26019 case OPC_PRECEQU_PH_QBL:
26020 case OPC_PRECEQU_PH_QBR:
26021 case OPC_PRECEQU_PH_QBLA:
26022 case OPC_PRECEQU_PH_QBRA:
26023 case OPC_PRECEU_PH_QBL:
26024 case OPC_PRECEU_PH_QBR:
26025 case OPC_PRECEU_PH_QBLA:
26026 case OPC_PRECEU_PH_QBRA:
26027 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26028 break;
26029 case OPC_BITREV:
26030 case OPC_REPL_QB:
26031 case OPC_REPLV_QB:
26032 case OPC_REPL_PH:
26033 case OPC_REPLV_PH:
26034 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26035 break;
26036 default:
26037 MIPS_INVAL("MASK ABSQ_S.PH");
26038 generate_exception_end(ctx, EXCP_RI);
26039 break;
26041 break;
26042 case OPC_ADDU_QB_DSP:
26043 op2 = MASK_ADDU_QB(ctx->opcode);
26044 switch (op2) {
26045 case OPC_ADDQ_PH:
26046 case OPC_ADDQ_S_PH:
26047 case OPC_ADDQ_S_W:
26048 case OPC_ADDU_QB:
26049 case OPC_ADDU_S_QB:
26050 case OPC_ADDU_PH:
26051 case OPC_ADDU_S_PH:
26052 case OPC_SUBQ_PH:
26053 case OPC_SUBQ_S_PH:
26054 case OPC_SUBQ_S_W:
26055 case OPC_SUBU_QB:
26056 case OPC_SUBU_S_QB:
26057 case OPC_SUBU_PH:
26058 case OPC_SUBU_S_PH:
26059 case OPC_ADDSC:
26060 case OPC_ADDWC:
26061 case OPC_MODSUB:
26062 case OPC_RADDU_W_QB:
26063 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26064 break;
26065 case OPC_MULEU_S_PH_QBL:
26066 case OPC_MULEU_S_PH_QBR:
26067 case OPC_MULQ_RS_PH:
26068 case OPC_MULEQ_S_W_PHL:
26069 case OPC_MULEQ_S_W_PHR:
26070 case OPC_MULQ_S_PH:
26071 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26072 break;
26073 default: /* Invalid */
26074 MIPS_INVAL("MASK ADDU.QB");
26075 generate_exception_end(ctx, EXCP_RI);
26076 break;
26079 break;
26080 case OPC_CMPU_EQ_QB_DSP:
26081 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
26082 switch (op2) {
26083 case OPC_PRECR_SRA_PH_W:
26084 case OPC_PRECR_SRA_R_PH_W:
26085 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26086 break;
26087 case OPC_PRECR_QB_PH:
26088 case OPC_PRECRQ_QB_PH:
26089 case OPC_PRECRQ_PH_W:
26090 case OPC_PRECRQ_RS_PH_W:
26091 case OPC_PRECRQU_S_QB_PH:
26092 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26093 break;
26094 case OPC_CMPU_EQ_QB:
26095 case OPC_CMPU_LT_QB:
26096 case OPC_CMPU_LE_QB:
26097 case OPC_CMP_EQ_PH:
26098 case OPC_CMP_LT_PH:
26099 case OPC_CMP_LE_PH:
26100 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26101 break;
26102 case OPC_CMPGU_EQ_QB:
26103 case OPC_CMPGU_LT_QB:
26104 case OPC_CMPGU_LE_QB:
26105 case OPC_CMPGDU_EQ_QB:
26106 case OPC_CMPGDU_LT_QB:
26107 case OPC_CMPGDU_LE_QB:
26108 case OPC_PICK_QB:
26109 case OPC_PICK_PH:
26110 case OPC_PACKRL_PH:
26111 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26112 break;
26113 default: /* Invalid */
26114 MIPS_INVAL("MASK CMPU.EQ.QB");
26115 generate_exception_end(ctx, EXCP_RI);
26116 break;
26118 break;
26119 case OPC_SHLL_QB_DSP:
26120 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26121 break;
26122 case OPC_DPA_W_PH_DSP:
26123 op2 = MASK_DPA_W_PH(ctx->opcode);
26124 switch (op2) {
26125 case OPC_DPAU_H_QBL:
26126 case OPC_DPAU_H_QBR:
26127 case OPC_DPSU_H_QBL:
26128 case OPC_DPSU_H_QBR:
26129 case OPC_DPA_W_PH:
26130 case OPC_DPAX_W_PH:
26131 case OPC_DPAQ_S_W_PH:
26132 case OPC_DPAQX_S_W_PH:
26133 case OPC_DPAQX_SA_W_PH:
26134 case OPC_DPS_W_PH:
26135 case OPC_DPSX_W_PH:
26136 case OPC_DPSQ_S_W_PH:
26137 case OPC_DPSQX_S_W_PH:
26138 case OPC_DPSQX_SA_W_PH:
26139 case OPC_MULSAQ_S_W_PH:
26140 case OPC_DPAQ_SA_L_W:
26141 case OPC_DPSQ_SA_L_W:
26142 case OPC_MAQ_S_W_PHL:
26143 case OPC_MAQ_S_W_PHR:
26144 case OPC_MAQ_SA_W_PHL:
26145 case OPC_MAQ_SA_W_PHR:
26146 case OPC_MULSA_W_PH:
26147 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26148 break;
26149 default: /* Invalid */
26150 MIPS_INVAL("MASK DPAW.PH");
26151 generate_exception_end(ctx, EXCP_RI);
26152 break;
26154 break;
26155 case OPC_INSV_DSP:
26156 op2 = MASK_INSV(ctx->opcode);
26157 switch (op2) {
26158 case OPC_INSV:
26159 check_dsp(ctx);
26161 TCGv t0, t1;
26163 if (rt == 0) {
26164 break;
26167 t0 = tcg_temp_new();
26168 t1 = tcg_temp_new();
26170 gen_load_gpr(t0, rt);
26171 gen_load_gpr(t1, rs);
26173 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
26175 tcg_temp_free(t0);
26176 tcg_temp_free(t1);
26177 break;
26179 default: /* Invalid */
26180 MIPS_INVAL("MASK INSV");
26181 generate_exception_end(ctx, EXCP_RI);
26182 break;
26184 break;
26185 case OPC_APPEND_DSP:
26186 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26187 break;
26188 case OPC_EXTR_W_DSP:
26189 op2 = MASK_EXTR_W(ctx->opcode);
26190 switch (op2) {
26191 case OPC_EXTR_W:
26192 case OPC_EXTR_R_W:
26193 case OPC_EXTR_RS_W:
26194 case OPC_EXTR_S_H:
26195 case OPC_EXTRV_S_H:
26196 case OPC_EXTRV_W:
26197 case OPC_EXTRV_R_W:
26198 case OPC_EXTRV_RS_W:
26199 case OPC_EXTP:
26200 case OPC_EXTPV:
26201 case OPC_EXTPDP:
26202 case OPC_EXTPDPV:
26203 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
26204 break;
26205 case OPC_RDDSP:
26206 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
26207 break;
26208 case OPC_SHILO:
26209 case OPC_SHILOV:
26210 case OPC_MTHLIP:
26211 case OPC_WRDSP:
26212 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
26213 break;
26214 default: /* Invalid */
26215 MIPS_INVAL("MASK EXTR.W");
26216 generate_exception_end(ctx, EXCP_RI);
26217 break;
26219 break;
26220 #if defined(TARGET_MIPS64)
26221 case OPC_DDIV_G_2E:
26222 case OPC_DDIVU_G_2E:
26223 case OPC_DMULT_G_2E:
26224 case OPC_DMULTU_G_2E:
26225 case OPC_DMOD_G_2E:
26226 case OPC_DMODU_G_2E:
26227 check_insn(ctx, INSN_LOONGSON2E);
26228 gen_loongson_integer(ctx, op1, rd, rs, rt);
26229 break;
26230 case OPC_ABSQ_S_QH_DSP:
26231 op2 = MASK_ABSQ_S_QH(ctx->opcode);
26232 switch (op2) {
26233 case OPC_PRECEQ_L_PWL:
26234 case OPC_PRECEQ_L_PWR:
26235 case OPC_PRECEQ_PW_QHL:
26236 case OPC_PRECEQ_PW_QHR:
26237 case OPC_PRECEQ_PW_QHLA:
26238 case OPC_PRECEQ_PW_QHRA:
26239 case OPC_PRECEQU_QH_OBL:
26240 case OPC_PRECEQU_QH_OBR:
26241 case OPC_PRECEQU_QH_OBLA:
26242 case OPC_PRECEQU_QH_OBRA:
26243 case OPC_PRECEU_QH_OBL:
26244 case OPC_PRECEU_QH_OBR:
26245 case OPC_PRECEU_QH_OBLA:
26246 case OPC_PRECEU_QH_OBRA:
26247 case OPC_ABSQ_S_OB:
26248 case OPC_ABSQ_S_PW:
26249 case OPC_ABSQ_S_QH:
26250 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26251 break;
26252 case OPC_REPL_OB:
26253 case OPC_REPL_PW:
26254 case OPC_REPL_QH:
26255 case OPC_REPLV_OB:
26256 case OPC_REPLV_PW:
26257 case OPC_REPLV_QH:
26258 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
26259 break;
26260 default: /* Invalid */
26261 MIPS_INVAL("MASK ABSQ_S.QH");
26262 generate_exception_end(ctx, EXCP_RI);
26263 break;
26265 break;
26266 case OPC_ADDU_OB_DSP:
26267 op2 = MASK_ADDU_OB(ctx->opcode);
26268 switch (op2) {
26269 case OPC_RADDU_L_OB:
26270 case OPC_SUBQ_PW:
26271 case OPC_SUBQ_S_PW:
26272 case OPC_SUBQ_QH:
26273 case OPC_SUBQ_S_QH:
26274 case OPC_SUBU_OB:
26275 case OPC_SUBU_S_OB:
26276 case OPC_SUBU_QH:
26277 case OPC_SUBU_S_QH:
26278 case OPC_SUBUH_OB:
26279 case OPC_SUBUH_R_OB:
26280 case OPC_ADDQ_PW:
26281 case OPC_ADDQ_S_PW:
26282 case OPC_ADDQ_QH:
26283 case OPC_ADDQ_S_QH:
26284 case OPC_ADDU_OB:
26285 case OPC_ADDU_S_OB:
26286 case OPC_ADDU_QH:
26287 case OPC_ADDU_S_QH:
26288 case OPC_ADDUH_OB:
26289 case OPC_ADDUH_R_OB:
26290 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26291 break;
26292 case OPC_MULEQ_S_PW_QHL:
26293 case OPC_MULEQ_S_PW_QHR:
26294 case OPC_MULEU_S_QH_OBL:
26295 case OPC_MULEU_S_QH_OBR:
26296 case OPC_MULQ_RS_QH:
26297 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
26298 break;
26299 default: /* Invalid */
26300 MIPS_INVAL("MASK ADDU.OB");
26301 generate_exception_end(ctx, EXCP_RI);
26302 break;
26304 break;
26305 case OPC_CMPU_EQ_OB_DSP:
26306 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
26307 switch (op2) {
26308 case OPC_PRECR_SRA_QH_PW:
26309 case OPC_PRECR_SRA_R_QH_PW:
26310 /* Return value is rt. */
26311 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
26312 break;
26313 case OPC_PRECR_OB_QH:
26314 case OPC_PRECRQ_OB_QH:
26315 case OPC_PRECRQ_PW_L:
26316 case OPC_PRECRQ_QH_PW:
26317 case OPC_PRECRQ_RS_QH_PW:
26318 case OPC_PRECRQU_S_OB_QH:
26319 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
26320 break;
26321 case OPC_CMPU_EQ_OB:
26322 case OPC_CMPU_LT_OB:
26323 case OPC_CMPU_LE_OB:
26324 case OPC_CMP_EQ_QH:
26325 case OPC_CMP_LT_QH:
26326 case OPC_CMP_LE_QH:
26327 case OPC_CMP_EQ_PW:
26328 case OPC_CMP_LT_PW:
26329 case OPC_CMP_LE_PW:
26330 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
26331 break;
26332 case OPC_CMPGDU_EQ_OB:
26333 case OPC_CMPGDU_LT_OB:
26334 case OPC_CMPGDU_LE_OB:
26335 case OPC_CMPGU_EQ_OB:
26336 case OPC_CMPGU_LT_OB:
26337 case OPC_CMPGU_LE_OB:
26338 case OPC_PACKRL_PW:
26339 case OPC_PICK_OB:
26340 case OPC_PICK_PW:
26341 case OPC_PICK_QH:
26342 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
26343 break;
26344 default: /* Invalid */
26345 MIPS_INVAL("MASK CMPU_EQ.OB");
26346 generate_exception_end(ctx, EXCP_RI);
26347 break;
26349 break;
26350 case OPC_DAPPEND_DSP:
26351 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
26352 break;
26353 case OPC_DEXTR_W_DSP:
26354 op2 = MASK_DEXTR_W(ctx->opcode);
26355 switch (op2) {
26356 case OPC_DEXTP:
26357 case OPC_DEXTPDP:
26358 case OPC_DEXTPDPV:
26359 case OPC_DEXTPV:
26360 case OPC_DEXTR_L:
26361 case OPC_DEXTR_R_L:
26362 case OPC_DEXTR_RS_L:
26363 case OPC_DEXTR_W:
26364 case OPC_DEXTR_R_W:
26365 case OPC_DEXTR_RS_W:
26366 case OPC_DEXTR_S_H:
26367 case OPC_DEXTRV_L:
26368 case OPC_DEXTRV_R_L:
26369 case OPC_DEXTRV_RS_L:
26370 case OPC_DEXTRV_S_H:
26371 case OPC_DEXTRV_W:
26372 case OPC_DEXTRV_R_W:
26373 case OPC_DEXTRV_RS_W:
26374 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
26375 break;
26376 case OPC_DMTHLIP:
26377 case OPC_DSHILO:
26378 case OPC_DSHILOV:
26379 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
26380 break;
26381 default: /* Invalid */
26382 MIPS_INVAL("MASK EXTR.W");
26383 generate_exception_end(ctx, EXCP_RI);
26384 break;
26386 break;
26387 case OPC_DPAQ_W_QH_DSP:
26388 op2 = MASK_DPAQ_W_QH(ctx->opcode);
26389 switch (op2) {
26390 case OPC_DPAU_H_OBL:
26391 case OPC_DPAU_H_OBR:
26392 case OPC_DPSU_H_OBL:
26393 case OPC_DPSU_H_OBR:
26394 case OPC_DPA_W_QH:
26395 case OPC_DPAQ_S_W_QH:
26396 case OPC_DPS_W_QH:
26397 case OPC_DPSQ_S_W_QH:
26398 case OPC_MULSAQ_S_W_QH:
26399 case OPC_DPAQ_SA_L_PW:
26400 case OPC_DPSQ_SA_L_PW:
26401 case OPC_MULSAQ_S_L_PW:
26402 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26403 break;
26404 case OPC_MAQ_S_W_QHLL:
26405 case OPC_MAQ_S_W_QHLR:
26406 case OPC_MAQ_S_W_QHRL:
26407 case OPC_MAQ_S_W_QHRR:
26408 case OPC_MAQ_SA_W_QHLL:
26409 case OPC_MAQ_SA_W_QHLR:
26410 case OPC_MAQ_SA_W_QHRL:
26411 case OPC_MAQ_SA_W_QHRR:
26412 case OPC_MAQ_S_L_PWL:
26413 case OPC_MAQ_S_L_PWR:
26414 case OPC_DMADD:
26415 case OPC_DMADDU:
26416 case OPC_DMSUB:
26417 case OPC_DMSUBU:
26418 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
26419 break;
26420 default: /* Invalid */
26421 MIPS_INVAL("MASK DPAQ.W.QH");
26422 generate_exception_end(ctx, EXCP_RI);
26423 break;
26425 break;
26426 case OPC_DINSV_DSP:
26427 op2 = MASK_INSV(ctx->opcode);
26428 switch (op2) {
26429 case OPC_DINSV:
26431 TCGv t0, t1;
26433 if (rt == 0) {
26434 break;
26436 check_dsp(ctx);
26438 t0 = tcg_temp_new();
26439 t1 = tcg_temp_new();
26441 gen_load_gpr(t0, rt);
26442 gen_load_gpr(t1, rs);
26444 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
26446 tcg_temp_free(t0);
26447 tcg_temp_free(t1);
26448 break;
26450 default: /* Invalid */
26451 MIPS_INVAL("MASK DINSV");
26452 generate_exception_end(ctx, EXCP_RI);
26453 break;
26455 break;
26456 case OPC_SHLL_OB_DSP:
26457 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
26458 break;
26459 #endif
26460 default: /* Invalid */
26461 MIPS_INVAL("special3_legacy");
26462 generate_exception_end(ctx, EXCP_RI);
26463 break;
26467 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
26469 uint32_t opc = MASK_MMI0(ctx->opcode);
26471 switch (opc) {
26472 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
26473 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
26474 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
26475 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
26476 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
26477 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
26478 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
26479 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
26480 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
26481 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
26482 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
26483 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
26484 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
26485 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
26486 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
26487 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
26488 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
26489 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
26490 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
26491 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
26492 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
26493 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
26494 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
26495 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
26496 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
26497 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
26498 break;
26499 default:
26500 MIPS_INVAL("TX79 MMI class MMI0");
26501 generate_exception_end(ctx, EXCP_RI);
26502 break;
26506 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
26508 uint32_t opc = MASK_MMI1(ctx->opcode);
26510 switch (opc) {
26511 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
26512 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
26513 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
26514 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
26515 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
26516 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
26517 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
26518 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
26519 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
26520 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
26521 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
26522 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
26523 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
26524 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
26525 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
26526 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
26527 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
26528 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
26529 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
26530 break;
26531 default:
26532 MIPS_INVAL("TX79 MMI class MMI1");
26533 generate_exception_end(ctx, EXCP_RI);
26534 break;
26538 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
26540 uint32_t opc = MASK_MMI2(ctx->opcode);
26542 switch (opc) {
26543 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
26544 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
26545 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
26546 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
26547 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
26548 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
26549 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
26550 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
26551 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
26552 case MMI_OPC_2_PCPYLD: /* TODO: MMI_OPC_2_PCPYLD */
26553 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
26554 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
26555 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
26556 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
26557 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
26558 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
26559 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
26560 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
26561 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
26562 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
26563 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
26564 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
26565 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
26566 break;
26567 default:
26568 MIPS_INVAL("TX79 MMI class MMI2");
26569 generate_exception_end(ctx, EXCP_RI);
26570 break;
26574 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
26576 uint32_t opc = MASK_MMI3(ctx->opcode);
26578 switch (opc) {
26579 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
26580 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
26581 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
26582 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
26583 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
26584 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
26585 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
26586 case MMI_OPC_3_PCPYUD: /* TODO: MMI_OPC_3_PCPYUD */
26587 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
26588 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
26589 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
26590 case MMI_OPC_3_PCPYH: /* TODO: MMI_OPC_3_PCPYH */
26591 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
26592 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
26593 break;
26594 default:
26595 MIPS_INVAL("TX79 MMI class MMI3");
26596 generate_exception_end(ctx, EXCP_RI);
26597 break;
26601 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
26603 uint32_t opc = MASK_MMI(ctx->opcode);
26604 int rs = extract32(ctx->opcode, 21, 5);
26605 int rt = extract32(ctx->opcode, 16, 5);
26606 int rd = extract32(ctx->opcode, 11, 5);
26608 switch (opc) {
26609 case MMI_OPC_CLASS_MMI0:
26610 decode_mmi0(env, ctx);
26611 break;
26612 case MMI_OPC_CLASS_MMI1:
26613 decode_mmi1(env, ctx);
26614 break;
26615 case MMI_OPC_CLASS_MMI2:
26616 decode_mmi2(env, ctx);
26617 break;
26618 case MMI_OPC_CLASS_MMI3:
26619 decode_mmi3(env, ctx);
26620 break;
26621 case MMI_OPC_MULT1:
26622 case MMI_OPC_MULTU1:
26623 gen_mul_txx9(ctx, opc, rd, rs, rt);
26624 break;
26625 case MMI_OPC_DIV1:
26626 case MMI_OPC_DIVU1:
26627 gen_div1_tx79(ctx, opc, rs, rt);
26628 break;
26629 case MMI_OPC_MTLO1:
26630 case MMI_OPC_MTHI1:
26631 gen_HILO1_tx79(ctx, opc, rs);
26632 break;
26633 case MMI_OPC_MFLO1:
26634 case MMI_OPC_MFHI1:
26635 gen_HILO1_tx79(ctx, opc, rd);
26636 break;
26637 case MMI_OPC_MADD: /* TODO: MMI_OPC_MADD */
26638 case MMI_OPC_MADDU: /* TODO: MMI_OPC_MADDU */
26639 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
26640 case MMI_OPC_MADD1: /* TODO: MMI_OPC_MADD1 */
26641 case MMI_OPC_MADDU1: /* TODO: MMI_OPC_MADDU1 */
26642 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
26643 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
26644 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
26645 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
26646 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
26647 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
26648 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
26649 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
26650 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
26651 break;
26652 default:
26653 MIPS_INVAL("TX79 MMI class");
26654 generate_exception_end(ctx, EXCP_RI);
26655 break;
26659 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
26661 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
26664 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
26666 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
26670 * The TX79-specific instruction Store Quadword
26672 * +--------+-------+-------+------------------------+
26673 * | 011111 | base | rt | offset | SQ
26674 * +--------+-------+-------+------------------------+
26675 * 6 5 5 16
26677 * has the same opcode as the Read Hardware Register instruction
26679 * +--------+-------+-------+-------+-------+--------+
26680 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
26681 * +--------+-------+-------+-------+-------+--------+
26682 * 6 5 5 5 5 6
26684 * that is required, trapped and emulated by the Linux kernel. However, all
26685 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
26686 * offset is odd. Therefore all valid SQ instructions can execute normally.
26687 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
26688 * between SQ and RDHWR, as the Linux kernel does.
26690 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
26692 int base = extract32(ctx->opcode, 21, 5);
26693 int rt = extract32(ctx->opcode, 16, 5);
26694 int offset = extract32(ctx->opcode, 0, 16);
26696 #ifdef CONFIG_USER_ONLY
26697 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
26698 uint32_t op2 = extract32(ctx->opcode, 6, 5);
26700 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
26701 int rd = extract32(ctx->opcode, 11, 5);
26703 gen_rdhwr(ctx, rt, rd, 0);
26704 return;
26706 #endif
26708 gen_mmi_sq(ctx, base, rt, offset);
26711 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
26713 int rs, rt, rd, sa;
26714 uint32_t op1, op2;
26715 int16_t imm;
26717 rs = (ctx->opcode >> 21) & 0x1f;
26718 rt = (ctx->opcode >> 16) & 0x1f;
26719 rd = (ctx->opcode >> 11) & 0x1f;
26720 sa = (ctx->opcode >> 6) & 0x1f;
26721 imm = sextract32(ctx->opcode, 7, 9);
26723 op1 = MASK_SPECIAL3(ctx->opcode);
26726 * EVA loads and stores overlap Loongson 2E instructions decoded by
26727 * decode_opc_special3_legacy(), so be careful to allow their decoding when
26728 * EVA is absent.
26730 if (ctx->eva) {
26731 switch (op1) {
26732 case OPC_LWLE:
26733 case OPC_LWRE:
26734 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26735 /* fall through */
26736 case OPC_LBUE:
26737 case OPC_LHUE:
26738 case OPC_LBE:
26739 case OPC_LHE:
26740 case OPC_LLE:
26741 case OPC_LWE:
26742 check_cp0_enabled(ctx);
26743 gen_ld(ctx, op1, rt, rs, imm);
26744 return;
26745 case OPC_SWLE:
26746 case OPC_SWRE:
26747 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26748 /* fall through */
26749 case OPC_SBE:
26750 case OPC_SHE:
26751 case OPC_SWE:
26752 check_cp0_enabled(ctx);
26753 gen_st(ctx, op1, rt, rs, imm);
26754 return;
26755 case OPC_SCE:
26756 check_cp0_enabled(ctx);
26757 gen_st_cond(ctx, op1, rt, rs, imm);
26758 return;
26759 case OPC_CACHEE:
26760 check_cp0_enabled(ctx);
26761 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26762 gen_cache_operation(ctx, rt, rs, imm);
26764 /* Treat as NOP. */
26765 return;
26766 case OPC_PREFE:
26767 check_cp0_enabled(ctx);
26768 /* Treat as NOP. */
26769 return;
26773 switch (op1) {
26774 case OPC_EXT:
26775 case OPC_INS:
26776 check_insn(ctx, ISA_MIPS32R2);
26777 gen_bitops(ctx, op1, rt, rs, sa, rd);
26778 break;
26779 case OPC_BSHFL:
26780 op2 = MASK_BSHFL(ctx->opcode);
26781 switch (op2) {
26782 case OPC_ALIGN:
26783 case OPC_ALIGN_1:
26784 case OPC_ALIGN_2:
26785 case OPC_ALIGN_3:
26786 case OPC_BITSWAP:
26787 check_insn(ctx, ISA_MIPS32R6);
26788 decode_opc_special3_r6(env, ctx);
26789 break;
26790 default:
26791 check_insn(ctx, ISA_MIPS32R2);
26792 gen_bshfl(ctx, op2, rt, rd);
26793 break;
26795 break;
26796 #if defined(TARGET_MIPS64)
26797 case OPC_DEXTM:
26798 case OPC_DEXTU:
26799 case OPC_DEXT:
26800 case OPC_DINSM:
26801 case OPC_DINSU:
26802 case OPC_DINS:
26803 check_insn(ctx, ISA_MIPS64R2);
26804 check_mips_64(ctx);
26805 gen_bitops(ctx, op1, rt, rs, sa, rd);
26806 break;
26807 case OPC_DBSHFL:
26808 op2 = MASK_DBSHFL(ctx->opcode);
26809 switch (op2) {
26810 case OPC_DALIGN:
26811 case OPC_DALIGN_1:
26812 case OPC_DALIGN_2:
26813 case OPC_DALIGN_3:
26814 case OPC_DALIGN_4:
26815 case OPC_DALIGN_5:
26816 case OPC_DALIGN_6:
26817 case OPC_DALIGN_7:
26818 case OPC_DBITSWAP:
26819 check_insn(ctx, ISA_MIPS32R6);
26820 decode_opc_special3_r6(env, ctx);
26821 break;
26822 default:
26823 check_insn(ctx, ISA_MIPS64R2);
26824 check_mips_64(ctx);
26825 op2 = MASK_DBSHFL(ctx->opcode);
26826 gen_bshfl(ctx, op2, rt, rd);
26827 break;
26829 break;
26830 #endif
26831 case OPC_RDHWR:
26832 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
26833 break;
26834 case OPC_FORK:
26835 check_mt(ctx);
26837 TCGv t0 = tcg_temp_new();
26838 TCGv t1 = tcg_temp_new();
26840 gen_load_gpr(t0, rt);
26841 gen_load_gpr(t1, rs);
26842 gen_helper_fork(t0, t1);
26843 tcg_temp_free(t0);
26844 tcg_temp_free(t1);
26846 break;
26847 case OPC_YIELD:
26848 check_mt(ctx);
26850 TCGv t0 = tcg_temp_new();
26852 gen_load_gpr(t0, rs);
26853 gen_helper_yield(t0, cpu_env, t0);
26854 gen_store_gpr(t0, rd);
26855 tcg_temp_free(t0);
26857 break;
26858 default:
26859 if (ctx->insn_flags & ISA_MIPS32R6) {
26860 decode_opc_special3_r6(env, ctx);
26861 } else {
26862 decode_opc_special3_legacy(env, ctx);
26867 /* MIPS SIMD Architecture (MSA) */
26868 static inline int check_msa_access(DisasContext *ctx)
26870 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
26871 !(ctx->hflags & MIPS_HFLAG_F64))) {
26872 generate_exception_end(ctx, EXCP_RI);
26873 return 0;
26876 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
26877 if (ctx->insn_flags & ASE_MSA) {
26878 generate_exception_end(ctx, EXCP_MSADIS);
26879 return 0;
26880 } else {
26881 generate_exception_end(ctx, EXCP_RI);
26882 return 0;
26885 return 1;
26888 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
26890 /* generates tcg ops to check if any element is 0 */
26891 /* Note this function only works with MSA_WRLEN = 128 */
26892 uint64_t eval_zero_or_big = 0;
26893 uint64_t eval_big = 0;
26894 TCGv_i64 t0 = tcg_temp_new_i64();
26895 TCGv_i64 t1 = tcg_temp_new_i64();
26896 switch (df) {
26897 case DF_BYTE:
26898 eval_zero_or_big = 0x0101010101010101ULL;
26899 eval_big = 0x8080808080808080ULL;
26900 break;
26901 case DF_HALF:
26902 eval_zero_or_big = 0x0001000100010001ULL;
26903 eval_big = 0x8000800080008000ULL;
26904 break;
26905 case DF_WORD:
26906 eval_zero_or_big = 0x0000000100000001ULL;
26907 eval_big = 0x8000000080000000ULL;
26908 break;
26909 case DF_DOUBLE:
26910 eval_zero_or_big = 0x0000000000000001ULL;
26911 eval_big = 0x8000000000000000ULL;
26912 break;
26914 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
26915 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
26916 tcg_gen_andi_i64(t0, t0, eval_big);
26917 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
26918 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
26919 tcg_gen_andi_i64(t1, t1, eval_big);
26920 tcg_gen_or_i64(t0, t0, t1);
26921 /* if all bits are zero then all elements are not zero */
26922 /* if some bit is non-zero then some element is zero */
26923 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
26924 tcg_gen_trunc_i64_tl(tresult, t0);
26925 tcg_temp_free_i64(t0);
26926 tcg_temp_free_i64(t1);
26929 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
26931 uint8_t df = (ctx->opcode >> 21) & 0x3;
26932 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
26933 int64_t s16 = (int16_t)ctx->opcode;
26935 check_msa_access(ctx);
26937 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26938 generate_exception_end(ctx, EXCP_RI);
26939 return;
26941 switch (op1) {
26942 case OPC_BZ_V:
26943 case OPC_BNZ_V:
26945 TCGv_i64 t0 = tcg_temp_new_i64();
26946 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
26947 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
26948 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
26949 tcg_gen_trunc_i64_tl(bcond, t0);
26950 tcg_temp_free_i64(t0);
26952 break;
26953 case OPC_BZ_B:
26954 case OPC_BZ_H:
26955 case OPC_BZ_W:
26956 case OPC_BZ_D:
26957 gen_check_zero_element(bcond, df, wt);
26958 break;
26959 case OPC_BNZ_B:
26960 case OPC_BNZ_H:
26961 case OPC_BNZ_W:
26962 case OPC_BNZ_D:
26963 gen_check_zero_element(bcond, df, wt);
26964 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
26965 break;
26968 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
26970 ctx->hflags |= MIPS_HFLAG_BC;
26971 ctx->hflags |= MIPS_HFLAG_BDS32;
26974 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
26976 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
26977 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
26978 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
26979 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26981 TCGv_i32 twd = tcg_const_i32(wd);
26982 TCGv_i32 tws = tcg_const_i32(ws);
26983 TCGv_i32 ti8 = tcg_const_i32(i8);
26985 switch (MASK_MSA_I8(ctx->opcode)) {
26986 case OPC_ANDI_B:
26987 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
26988 break;
26989 case OPC_ORI_B:
26990 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
26991 break;
26992 case OPC_NORI_B:
26993 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
26994 break;
26995 case OPC_XORI_B:
26996 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
26997 break;
26998 case OPC_BMNZI_B:
26999 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
27000 break;
27001 case OPC_BMZI_B:
27002 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
27003 break;
27004 case OPC_BSELI_B:
27005 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
27006 break;
27007 case OPC_SHF_B:
27008 case OPC_SHF_H:
27009 case OPC_SHF_W:
27011 uint8_t df = (ctx->opcode >> 24) & 0x3;
27012 if (df == DF_DOUBLE) {
27013 generate_exception_end(ctx, EXCP_RI);
27014 } else {
27015 TCGv_i32 tdf = tcg_const_i32(df);
27016 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
27017 tcg_temp_free_i32(tdf);
27020 break;
27021 default:
27022 MIPS_INVAL("MSA instruction");
27023 generate_exception_end(ctx, EXCP_RI);
27024 break;
27027 tcg_temp_free_i32(twd);
27028 tcg_temp_free_i32(tws);
27029 tcg_temp_free_i32(ti8);
27032 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
27034 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27035 uint8_t df = (ctx->opcode >> 21) & 0x3;
27036 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
27037 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
27038 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27039 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27041 TCGv_i32 tdf = tcg_const_i32(df);
27042 TCGv_i32 twd = tcg_const_i32(wd);
27043 TCGv_i32 tws = tcg_const_i32(ws);
27044 TCGv_i32 timm = tcg_temp_new_i32();
27045 tcg_gen_movi_i32(timm, u5);
27047 switch (MASK_MSA_I5(ctx->opcode)) {
27048 case OPC_ADDVI_df:
27049 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
27050 break;
27051 case OPC_SUBVI_df:
27052 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
27053 break;
27054 case OPC_MAXI_S_df:
27055 tcg_gen_movi_i32(timm, s5);
27056 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
27057 break;
27058 case OPC_MAXI_U_df:
27059 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
27060 break;
27061 case OPC_MINI_S_df:
27062 tcg_gen_movi_i32(timm, s5);
27063 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
27064 break;
27065 case OPC_MINI_U_df:
27066 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
27067 break;
27068 case OPC_CEQI_df:
27069 tcg_gen_movi_i32(timm, s5);
27070 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
27071 break;
27072 case OPC_CLTI_S_df:
27073 tcg_gen_movi_i32(timm, s5);
27074 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
27075 break;
27076 case OPC_CLTI_U_df:
27077 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
27078 break;
27079 case OPC_CLEI_S_df:
27080 tcg_gen_movi_i32(timm, s5);
27081 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
27082 break;
27083 case OPC_CLEI_U_df:
27084 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
27085 break;
27086 case OPC_LDI_df:
27088 int32_t s10 = sextract32(ctx->opcode, 11, 10);
27089 tcg_gen_movi_i32(timm, s10);
27090 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
27092 break;
27093 default:
27094 MIPS_INVAL("MSA instruction");
27095 generate_exception_end(ctx, EXCP_RI);
27096 break;
27099 tcg_temp_free_i32(tdf);
27100 tcg_temp_free_i32(twd);
27101 tcg_temp_free_i32(tws);
27102 tcg_temp_free_i32(timm);
27105 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
27107 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27108 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
27109 uint32_t df = 0, m = 0;
27110 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27111 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27113 TCGv_i32 tdf;
27114 TCGv_i32 tm;
27115 TCGv_i32 twd;
27116 TCGv_i32 tws;
27118 if ((dfm & 0x40) == 0x00) {
27119 m = dfm & 0x3f;
27120 df = DF_DOUBLE;
27121 } else if ((dfm & 0x60) == 0x40) {
27122 m = dfm & 0x1f;
27123 df = DF_WORD;
27124 } else if ((dfm & 0x70) == 0x60) {
27125 m = dfm & 0x0f;
27126 df = DF_HALF;
27127 } else if ((dfm & 0x78) == 0x70) {
27128 m = dfm & 0x7;
27129 df = DF_BYTE;
27130 } else {
27131 generate_exception_end(ctx, EXCP_RI);
27132 return;
27135 tdf = tcg_const_i32(df);
27136 tm = tcg_const_i32(m);
27137 twd = tcg_const_i32(wd);
27138 tws = tcg_const_i32(ws);
27140 switch (MASK_MSA_BIT(ctx->opcode)) {
27141 case OPC_SLLI_df:
27142 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
27143 break;
27144 case OPC_SRAI_df:
27145 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
27146 break;
27147 case OPC_SRLI_df:
27148 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
27149 break;
27150 case OPC_BCLRI_df:
27151 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
27152 break;
27153 case OPC_BSETI_df:
27154 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
27155 break;
27156 case OPC_BNEGI_df:
27157 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
27158 break;
27159 case OPC_BINSLI_df:
27160 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
27161 break;
27162 case OPC_BINSRI_df:
27163 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
27164 break;
27165 case OPC_SAT_S_df:
27166 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
27167 break;
27168 case OPC_SAT_U_df:
27169 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
27170 break;
27171 case OPC_SRARI_df:
27172 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
27173 break;
27174 case OPC_SRLRI_df:
27175 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
27176 break;
27177 default:
27178 MIPS_INVAL("MSA instruction");
27179 generate_exception_end(ctx, EXCP_RI);
27180 break;
27183 tcg_temp_free_i32(tdf);
27184 tcg_temp_free_i32(tm);
27185 tcg_temp_free_i32(twd);
27186 tcg_temp_free_i32(tws);
27189 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
27191 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
27192 uint8_t df = (ctx->opcode >> 21) & 0x3;
27193 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27194 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27195 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27197 TCGv_i32 tdf = tcg_const_i32(df);
27198 TCGv_i32 twd = tcg_const_i32(wd);
27199 TCGv_i32 tws = tcg_const_i32(ws);
27200 TCGv_i32 twt = tcg_const_i32(wt);
27202 switch (MASK_MSA_3R(ctx->opcode)) {
27203 case OPC_SLL_df:
27204 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
27205 break;
27206 case OPC_ADDV_df:
27207 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
27208 break;
27209 case OPC_CEQ_df:
27210 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
27211 break;
27212 case OPC_ADD_A_df:
27213 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
27214 break;
27215 case OPC_SUBS_S_df:
27216 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
27217 break;
27218 case OPC_MULV_df:
27219 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
27220 break;
27221 case OPC_SLD_df:
27222 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
27223 break;
27224 case OPC_VSHF_df:
27225 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
27226 break;
27227 case OPC_SRA_df:
27228 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
27229 break;
27230 case OPC_SUBV_df:
27231 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
27232 break;
27233 case OPC_ADDS_A_df:
27234 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
27235 break;
27236 case OPC_SUBS_U_df:
27237 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
27238 break;
27239 case OPC_MADDV_df:
27240 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
27241 break;
27242 case OPC_SPLAT_df:
27243 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
27244 break;
27245 case OPC_SRAR_df:
27246 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
27247 break;
27248 case OPC_SRL_df:
27249 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
27250 break;
27251 case OPC_MAX_S_df:
27252 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
27253 break;
27254 case OPC_CLT_S_df:
27255 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
27256 break;
27257 case OPC_ADDS_S_df:
27258 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
27259 break;
27260 case OPC_SUBSUS_U_df:
27261 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
27262 break;
27263 case OPC_MSUBV_df:
27264 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
27265 break;
27266 case OPC_PCKEV_df:
27267 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
27268 break;
27269 case OPC_SRLR_df:
27270 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
27271 break;
27272 case OPC_BCLR_df:
27273 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
27274 break;
27275 case OPC_MAX_U_df:
27276 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
27277 break;
27278 case OPC_CLT_U_df:
27279 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
27280 break;
27281 case OPC_ADDS_U_df:
27282 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
27283 break;
27284 case OPC_SUBSUU_S_df:
27285 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
27286 break;
27287 case OPC_PCKOD_df:
27288 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
27289 break;
27290 case OPC_BSET_df:
27291 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
27292 break;
27293 case OPC_MIN_S_df:
27294 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
27295 break;
27296 case OPC_CLE_S_df:
27297 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
27298 break;
27299 case OPC_AVE_S_df:
27300 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
27301 break;
27302 case OPC_ASUB_S_df:
27303 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
27304 break;
27305 case OPC_DIV_S_df:
27306 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
27307 break;
27308 case OPC_ILVL_df:
27309 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
27310 break;
27311 case OPC_BNEG_df:
27312 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
27313 break;
27314 case OPC_MIN_U_df:
27315 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
27316 break;
27317 case OPC_CLE_U_df:
27318 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
27319 break;
27320 case OPC_AVE_U_df:
27321 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
27322 break;
27323 case OPC_ASUB_U_df:
27324 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
27325 break;
27326 case OPC_DIV_U_df:
27327 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
27328 break;
27329 case OPC_ILVR_df:
27330 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
27331 break;
27332 case OPC_BINSL_df:
27333 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
27334 break;
27335 case OPC_MAX_A_df:
27336 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
27337 break;
27338 case OPC_AVER_S_df:
27339 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
27340 break;
27341 case OPC_MOD_S_df:
27342 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
27343 break;
27344 case OPC_ILVEV_df:
27345 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
27346 break;
27347 case OPC_BINSR_df:
27348 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
27349 break;
27350 case OPC_MIN_A_df:
27351 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
27352 break;
27353 case OPC_AVER_U_df:
27354 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
27355 break;
27356 case OPC_MOD_U_df:
27357 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
27358 break;
27359 case OPC_ILVOD_df:
27360 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
27361 break;
27363 case OPC_DOTP_S_df:
27364 case OPC_DOTP_U_df:
27365 case OPC_DPADD_S_df:
27366 case OPC_DPADD_U_df:
27367 case OPC_DPSUB_S_df:
27368 case OPC_HADD_S_df:
27369 case OPC_DPSUB_U_df:
27370 case OPC_HADD_U_df:
27371 case OPC_HSUB_S_df:
27372 case OPC_HSUB_U_df:
27373 if (df == DF_BYTE) {
27374 generate_exception_end(ctx, EXCP_RI);
27375 break;
27377 switch (MASK_MSA_3R(ctx->opcode)) {
27378 case OPC_DOTP_S_df:
27379 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
27380 break;
27381 case OPC_DOTP_U_df:
27382 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
27383 break;
27384 case OPC_DPADD_S_df:
27385 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
27386 break;
27387 case OPC_DPADD_U_df:
27388 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
27389 break;
27390 case OPC_DPSUB_S_df:
27391 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
27392 break;
27393 case OPC_HADD_S_df:
27394 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
27395 break;
27396 case OPC_DPSUB_U_df:
27397 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
27398 break;
27399 case OPC_HADD_U_df:
27400 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
27401 break;
27402 case OPC_HSUB_S_df:
27403 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
27404 break;
27405 case OPC_HSUB_U_df:
27406 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
27407 break;
27409 break;
27410 default:
27411 MIPS_INVAL("MSA instruction");
27412 generate_exception_end(ctx, EXCP_RI);
27413 break;
27415 tcg_temp_free_i32(twd);
27416 tcg_temp_free_i32(tws);
27417 tcg_temp_free_i32(twt);
27418 tcg_temp_free_i32(tdf);
27421 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
27423 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
27424 uint8_t source = (ctx->opcode >> 11) & 0x1f;
27425 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
27426 TCGv telm = tcg_temp_new();
27427 TCGv_i32 tsr = tcg_const_i32(source);
27428 TCGv_i32 tdt = tcg_const_i32(dest);
27430 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
27431 case OPC_CTCMSA:
27432 gen_load_gpr(telm, source);
27433 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
27434 break;
27435 case OPC_CFCMSA:
27436 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
27437 gen_store_gpr(telm, dest);
27438 break;
27439 case OPC_MOVE_V:
27440 gen_helper_msa_move_v(cpu_env, tdt, tsr);
27441 break;
27442 default:
27443 MIPS_INVAL("MSA instruction");
27444 generate_exception_end(ctx, EXCP_RI);
27445 break;
27448 tcg_temp_free(telm);
27449 tcg_temp_free_i32(tdt);
27450 tcg_temp_free_i32(tsr);
27453 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
27454 uint32_t n)
27456 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
27457 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27458 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27460 TCGv_i32 tws = tcg_const_i32(ws);
27461 TCGv_i32 twd = tcg_const_i32(wd);
27462 TCGv_i32 tn = tcg_const_i32(n);
27463 TCGv_i32 tdf = tcg_const_i32(df);
27465 switch (MASK_MSA_ELM(ctx->opcode)) {
27466 case OPC_SLDI_df:
27467 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
27468 break;
27469 case OPC_SPLATI_df:
27470 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
27471 break;
27472 case OPC_INSVE_df:
27473 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
27474 break;
27475 case OPC_COPY_S_df:
27476 case OPC_COPY_U_df:
27477 case OPC_INSERT_df:
27478 #if !defined(TARGET_MIPS64)
27479 /* Double format valid only for MIPS64 */
27480 if (df == DF_DOUBLE) {
27481 generate_exception_end(ctx, EXCP_RI);
27482 break;
27484 #endif
27485 switch (MASK_MSA_ELM(ctx->opcode)) {
27486 case OPC_COPY_S_df:
27487 if (likely(wd != 0)) {
27488 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
27490 break;
27491 case OPC_COPY_U_df:
27492 if (likely(wd != 0)) {
27493 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
27495 break;
27496 case OPC_INSERT_df:
27497 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
27498 break;
27500 break;
27501 default:
27502 MIPS_INVAL("MSA instruction");
27503 generate_exception_end(ctx, EXCP_RI);
27505 tcg_temp_free_i32(twd);
27506 tcg_temp_free_i32(tws);
27507 tcg_temp_free_i32(tn);
27508 tcg_temp_free_i32(tdf);
27511 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
27513 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
27514 uint32_t df = 0, n = 0;
27516 if ((dfn & 0x30) == 0x00) {
27517 n = dfn & 0x0f;
27518 df = DF_BYTE;
27519 } else if ((dfn & 0x38) == 0x20) {
27520 n = dfn & 0x07;
27521 df = DF_HALF;
27522 } else if ((dfn & 0x3c) == 0x30) {
27523 n = dfn & 0x03;
27524 df = DF_WORD;
27525 } else if ((dfn & 0x3e) == 0x38) {
27526 n = dfn & 0x01;
27527 df = DF_DOUBLE;
27528 } else if (dfn == 0x3E) {
27529 /* CTCMSA, CFCMSA, MOVE.V */
27530 gen_msa_elm_3e(env, ctx);
27531 return;
27532 } else {
27533 generate_exception_end(ctx, EXCP_RI);
27534 return;
27537 gen_msa_elm_df(env, ctx, df, n);
27540 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
27542 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
27543 uint8_t df = (ctx->opcode >> 21) & 0x1;
27544 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27545 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27546 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27548 TCGv_i32 twd = tcg_const_i32(wd);
27549 TCGv_i32 tws = tcg_const_i32(ws);
27550 TCGv_i32 twt = tcg_const_i32(wt);
27551 TCGv_i32 tdf = tcg_temp_new_i32();
27553 /* adjust df value for floating-point instruction */
27554 tcg_gen_movi_i32(tdf, df + 2);
27556 switch (MASK_MSA_3RF(ctx->opcode)) {
27557 case OPC_FCAF_df:
27558 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
27559 break;
27560 case OPC_FADD_df:
27561 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
27562 break;
27563 case OPC_FCUN_df:
27564 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
27565 break;
27566 case OPC_FSUB_df:
27567 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
27568 break;
27569 case OPC_FCOR_df:
27570 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
27571 break;
27572 case OPC_FCEQ_df:
27573 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
27574 break;
27575 case OPC_FMUL_df:
27576 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
27577 break;
27578 case OPC_FCUNE_df:
27579 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
27580 break;
27581 case OPC_FCUEQ_df:
27582 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
27583 break;
27584 case OPC_FDIV_df:
27585 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
27586 break;
27587 case OPC_FCNE_df:
27588 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
27589 break;
27590 case OPC_FCLT_df:
27591 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
27592 break;
27593 case OPC_FMADD_df:
27594 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
27595 break;
27596 case OPC_MUL_Q_df:
27597 tcg_gen_movi_i32(tdf, df + 1);
27598 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
27599 break;
27600 case OPC_FCULT_df:
27601 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
27602 break;
27603 case OPC_FMSUB_df:
27604 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
27605 break;
27606 case OPC_MADD_Q_df:
27607 tcg_gen_movi_i32(tdf, df + 1);
27608 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
27609 break;
27610 case OPC_FCLE_df:
27611 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
27612 break;
27613 case OPC_MSUB_Q_df:
27614 tcg_gen_movi_i32(tdf, df + 1);
27615 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
27616 break;
27617 case OPC_FCULE_df:
27618 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
27619 break;
27620 case OPC_FEXP2_df:
27621 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
27622 break;
27623 case OPC_FSAF_df:
27624 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
27625 break;
27626 case OPC_FEXDO_df:
27627 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
27628 break;
27629 case OPC_FSUN_df:
27630 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
27631 break;
27632 case OPC_FSOR_df:
27633 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
27634 break;
27635 case OPC_FSEQ_df:
27636 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
27637 break;
27638 case OPC_FTQ_df:
27639 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
27640 break;
27641 case OPC_FSUNE_df:
27642 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
27643 break;
27644 case OPC_FSUEQ_df:
27645 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
27646 break;
27647 case OPC_FSNE_df:
27648 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
27649 break;
27650 case OPC_FSLT_df:
27651 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
27652 break;
27653 case OPC_FMIN_df:
27654 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
27655 break;
27656 case OPC_MULR_Q_df:
27657 tcg_gen_movi_i32(tdf, df + 1);
27658 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
27659 break;
27660 case OPC_FSULT_df:
27661 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
27662 break;
27663 case OPC_FMIN_A_df:
27664 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
27665 break;
27666 case OPC_MADDR_Q_df:
27667 tcg_gen_movi_i32(tdf, df + 1);
27668 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
27669 break;
27670 case OPC_FSLE_df:
27671 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
27672 break;
27673 case OPC_FMAX_df:
27674 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
27675 break;
27676 case OPC_MSUBR_Q_df:
27677 tcg_gen_movi_i32(tdf, df + 1);
27678 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
27679 break;
27680 case OPC_FSULE_df:
27681 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
27682 break;
27683 case OPC_FMAX_A_df:
27684 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
27685 break;
27686 default:
27687 MIPS_INVAL("MSA instruction");
27688 generate_exception_end(ctx, EXCP_RI);
27689 break;
27692 tcg_temp_free_i32(twd);
27693 tcg_temp_free_i32(tws);
27694 tcg_temp_free_i32(twt);
27695 tcg_temp_free_i32(tdf);
27698 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
27700 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
27701 (op & (0x7 << 18)))
27702 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27703 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27704 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27705 uint8_t df = (ctx->opcode >> 16) & 0x3;
27706 TCGv_i32 twd = tcg_const_i32(wd);
27707 TCGv_i32 tws = tcg_const_i32(ws);
27708 TCGv_i32 twt = tcg_const_i32(wt);
27709 TCGv_i32 tdf = tcg_const_i32(df);
27711 switch (MASK_MSA_2R(ctx->opcode)) {
27712 case OPC_FILL_df:
27713 #if !defined(TARGET_MIPS64)
27714 /* Double format valid only for MIPS64 */
27715 if (df == DF_DOUBLE) {
27716 generate_exception_end(ctx, EXCP_RI);
27717 break;
27719 #endif
27720 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
27721 break;
27722 case OPC_PCNT_df:
27723 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
27724 break;
27725 case OPC_NLOC_df:
27726 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
27727 break;
27728 case OPC_NLZC_df:
27729 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
27730 break;
27731 default:
27732 MIPS_INVAL("MSA instruction");
27733 generate_exception_end(ctx, EXCP_RI);
27734 break;
27737 tcg_temp_free_i32(twd);
27738 tcg_temp_free_i32(tws);
27739 tcg_temp_free_i32(twt);
27740 tcg_temp_free_i32(tdf);
27743 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
27745 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
27746 (op & (0xf << 17)))
27747 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27748 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27749 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27750 uint8_t df = (ctx->opcode >> 16) & 0x1;
27751 TCGv_i32 twd = tcg_const_i32(wd);
27752 TCGv_i32 tws = tcg_const_i32(ws);
27753 TCGv_i32 twt = tcg_const_i32(wt);
27754 /* adjust df value for floating-point instruction */
27755 TCGv_i32 tdf = tcg_const_i32(df + 2);
27757 switch (MASK_MSA_2RF(ctx->opcode)) {
27758 case OPC_FCLASS_df:
27759 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
27760 break;
27761 case OPC_FTRUNC_S_df:
27762 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
27763 break;
27764 case OPC_FTRUNC_U_df:
27765 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
27766 break;
27767 case OPC_FSQRT_df:
27768 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
27769 break;
27770 case OPC_FRSQRT_df:
27771 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
27772 break;
27773 case OPC_FRCP_df:
27774 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
27775 break;
27776 case OPC_FRINT_df:
27777 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
27778 break;
27779 case OPC_FLOG2_df:
27780 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
27781 break;
27782 case OPC_FEXUPL_df:
27783 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
27784 break;
27785 case OPC_FEXUPR_df:
27786 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
27787 break;
27788 case OPC_FFQL_df:
27789 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
27790 break;
27791 case OPC_FFQR_df:
27792 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
27793 break;
27794 case OPC_FTINT_S_df:
27795 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
27796 break;
27797 case OPC_FTINT_U_df:
27798 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
27799 break;
27800 case OPC_FFINT_S_df:
27801 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
27802 break;
27803 case OPC_FFINT_U_df:
27804 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
27805 break;
27808 tcg_temp_free_i32(twd);
27809 tcg_temp_free_i32(tws);
27810 tcg_temp_free_i32(twt);
27811 tcg_temp_free_i32(tdf);
27814 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
27816 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
27817 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
27818 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
27819 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27820 TCGv_i32 twd = tcg_const_i32(wd);
27821 TCGv_i32 tws = tcg_const_i32(ws);
27822 TCGv_i32 twt = tcg_const_i32(wt);
27824 switch (MASK_MSA_VEC(ctx->opcode)) {
27825 case OPC_AND_V:
27826 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
27827 break;
27828 case OPC_OR_V:
27829 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
27830 break;
27831 case OPC_NOR_V:
27832 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
27833 break;
27834 case OPC_XOR_V:
27835 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
27836 break;
27837 case OPC_BMNZ_V:
27838 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
27839 break;
27840 case OPC_BMZ_V:
27841 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
27842 break;
27843 case OPC_BSEL_V:
27844 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
27845 break;
27846 default:
27847 MIPS_INVAL("MSA instruction");
27848 generate_exception_end(ctx, EXCP_RI);
27849 break;
27852 tcg_temp_free_i32(twd);
27853 tcg_temp_free_i32(tws);
27854 tcg_temp_free_i32(twt);
27857 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
27859 switch (MASK_MSA_VEC(ctx->opcode)) {
27860 case OPC_AND_V:
27861 case OPC_OR_V:
27862 case OPC_NOR_V:
27863 case OPC_XOR_V:
27864 case OPC_BMNZ_V:
27865 case OPC_BMZ_V:
27866 case OPC_BSEL_V:
27867 gen_msa_vec_v(env, ctx);
27868 break;
27869 case OPC_MSA_2R:
27870 gen_msa_2r(env, ctx);
27871 break;
27872 case OPC_MSA_2RF:
27873 gen_msa_2rf(env, ctx);
27874 break;
27875 default:
27876 MIPS_INVAL("MSA instruction");
27877 generate_exception_end(ctx, EXCP_RI);
27878 break;
27882 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
27884 uint32_t opcode = ctx->opcode;
27885 check_insn(ctx, ASE_MSA);
27886 check_msa_access(ctx);
27888 switch (MASK_MSA_MINOR(opcode)) {
27889 case OPC_MSA_I8_00:
27890 case OPC_MSA_I8_01:
27891 case OPC_MSA_I8_02:
27892 gen_msa_i8(env, ctx);
27893 break;
27894 case OPC_MSA_I5_06:
27895 case OPC_MSA_I5_07:
27896 gen_msa_i5(env, ctx);
27897 break;
27898 case OPC_MSA_BIT_09:
27899 case OPC_MSA_BIT_0A:
27900 gen_msa_bit(env, ctx);
27901 break;
27902 case OPC_MSA_3R_0D:
27903 case OPC_MSA_3R_0E:
27904 case OPC_MSA_3R_0F:
27905 case OPC_MSA_3R_10:
27906 case OPC_MSA_3R_11:
27907 case OPC_MSA_3R_12:
27908 case OPC_MSA_3R_13:
27909 case OPC_MSA_3R_14:
27910 case OPC_MSA_3R_15:
27911 gen_msa_3r(env, ctx);
27912 break;
27913 case OPC_MSA_ELM:
27914 gen_msa_elm(env, ctx);
27915 break;
27916 case OPC_MSA_3RF_1A:
27917 case OPC_MSA_3RF_1B:
27918 case OPC_MSA_3RF_1C:
27919 gen_msa_3rf(env, ctx);
27920 break;
27921 case OPC_MSA_VEC:
27922 gen_msa_vec(env, ctx);
27923 break;
27924 case OPC_LD_B:
27925 case OPC_LD_H:
27926 case OPC_LD_W:
27927 case OPC_LD_D:
27928 case OPC_ST_B:
27929 case OPC_ST_H:
27930 case OPC_ST_W:
27931 case OPC_ST_D:
27933 int32_t s10 = sextract32(ctx->opcode, 16, 10);
27934 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
27935 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
27936 uint8_t df = (ctx->opcode >> 0) & 0x3;
27938 TCGv_i32 twd = tcg_const_i32(wd);
27939 TCGv taddr = tcg_temp_new();
27940 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
27942 switch (MASK_MSA_MINOR(opcode)) {
27943 case OPC_LD_B:
27944 gen_helper_msa_ld_b(cpu_env, twd, taddr);
27945 break;
27946 case OPC_LD_H:
27947 gen_helper_msa_ld_h(cpu_env, twd, taddr);
27948 break;
27949 case OPC_LD_W:
27950 gen_helper_msa_ld_w(cpu_env, twd, taddr);
27951 break;
27952 case OPC_LD_D:
27953 gen_helper_msa_ld_d(cpu_env, twd, taddr);
27954 break;
27955 case OPC_ST_B:
27956 gen_helper_msa_st_b(cpu_env, twd, taddr);
27957 break;
27958 case OPC_ST_H:
27959 gen_helper_msa_st_h(cpu_env, twd, taddr);
27960 break;
27961 case OPC_ST_W:
27962 gen_helper_msa_st_w(cpu_env, twd, taddr);
27963 break;
27964 case OPC_ST_D:
27965 gen_helper_msa_st_d(cpu_env, twd, taddr);
27966 break;
27969 tcg_temp_free_i32(twd);
27970 tcg_temp_free(taddr);
27972 break;
27973 default:
27974 MIPS_INVAL("MSA instruction");
27975 generate_exception_end(ctx, EXCP_RI);
27976 break;
27981 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
27983 int32_t offset;
27984 int rs, rt, rd, sa;
27985 uint32_t op, op1;
27986 int16_t imm;
27988 /* make sure instructions are on a word boundary */
27989 if (ctx->base.pc_next & 0x3) {
27990 env->CP0_BadVAddr = ctx->base.pc_next;
27991 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
27992 return;
27995 /* Handle blikely not taken case */
27996 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
27997 TCGLabel *l1 = gen_new_label();
27999 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
28000 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
28001 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
28002 gen_set_label(l1);
28005 op = MASK_OP_MAJOR(ctx->opcode);
28006 rs = (ctx->opcode >> 21) & 0x1f;
28007 rt = (ctx->opcode >> 16) & 0x1f;
28008 rd = (ctx->opcode >> 11) & 0x1f;
28009 sa = (ctx->opcode >> 6) & 0x1f;
28010 imm = (int16_t)ctx->opcode;
28011 switch (op) {
28012 case OPC_SPECIAL:
28013 decode_opc_special(env, ctx);
28014 break;
28015 case OPC_SPECIAL2:
28016 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
28017 decode_mmi(env, ctx);
28018 } else if (ctx->insn_flags & ASE_MXU) {
28019 decode_opc_mxu(env, ctx);
28020 } else {
28021 decode_opc_special2_legacy(env, ctx);
28023 break;
28024 case OPC_SPECIAL3:
28025 if (ctx->insn_flags & INSN_R5900) {
28026 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
28027 } else {
28028 decode_opc_special3(env, ctx);
28030 break;
28031 case OPC_REGIMM:
28032 op1 = MASK_REGIMM(ctx->opcode);
28033 switch (op1) {
28034 case OPC_BLTZL: /* REGIMM branches */
28035 case OPC_BGEZL:
28036 case OPC_BLTZALL:
28037 case OPC_BGEZALL:
28038 check_insn(ctx, ISA_MIPS2);
28039 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28040 /* Fallthrough */
28041 case OPC_BLTZ:
28042 case OPC_BGEZ:
28043 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28044 break;
28045 case OPC_BLTZAL:
28046 case OPC_BGEZAL:
28047 if (ctx->insn_flags & ISA_MIPS32R6) {
28048 if (rs == 0) {
28049 /* OPC_NAL, OPC_BAL */
28050 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
28051 } else {
28052 generate_exception_end(ctx, EXCP_RI);
28054 } else {
28055 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
28057 break;
28058 case OPC_TGEI: /* REGIMM traps */
28059 case OPC_TGEIU:
28060 case OPC_TLTI:
28061 case OPC_TLTIU:
28062 case OPC_TEQI:
28064 case OPC_TNEI:
28065 check_insn(ctx, ISA_MIPS2);
28066 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28067 gen_trap(ctx, op1, rs, -1, imm);
28068 break;
28069 case OPC_SIGRIE:
28070 check_insn(ctx, ISA_MIPS32R6);
28071 generate_exception_end(ctx, EXCP_RI);
28072 break;
28073 case OPC_SYNCI:
28074 check_insn(ctx, ISA_MIPS32R2);
28075 /* Break the TB to be able to sync copied instructions
28076 immediately */
28077 ctx->base.is_jmp = DISAS_STOP;
28078 break;
28079 case OPC_BPOSGE32: /* MIPS DSP branch */
28080 #if defined(TARGET_MIPS64)
28081 case OPC_BPOSGE64:
28082 #endif
28083 check_dsp(ctx);
28084 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
28085 break;
28086 #if defined(TARGET_MIPS64)
28087 case OPC_DAHI:
28088 check_insn(ctx, ISA_MIPS32R6);
28089 check_mips_64(ctx);
28090 if (rs != 0) {
28091 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
28093 break;
28094 case OPC_DATI:
28095 check_insn(ctx, ISA_MIPS32R6);
28096 check_mips_64(ctx);
28097 if (rs != 0) {
28098 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
28100 break;
28101 #endif
28102 default: /* Invalid */
28103 MIPS_INVAL("regimm");
28104 generate_exception_end(ctx, EXCP_RI);
28105 break;
28107 break;
28108 case OPC_CP0:
28109 check_cp0_enabled(ctx);
28110 op1 = MASK_CP0(ctx->opcode);
28111 switch (op1) {
28112 case OPC_MFC0:
28113 case OPC_MTC0:
28114 case OPC_MFTR:
28115 case OPC_MTTR:
28116 case OPC_MFHC0:
28117 case OPC_MTHC0:
28118 #if defined(TARGET_MIPS64)
28119 case OPC_DMFC0:
28120 case OPC_DMTC0:
28121 #endif
28122 #ifndef CONFIG_USER_ONLY
28123 gen_cp0(env, ctx, op1, rt, rd);
28124 #endif /* !CONFIG_USER_ONLY */
28125 break;
28126 case OPC_C0:
28127 case OPC_C0_1:
28128 case OPC_C0_2:
28129 case OPC_C0_3:
28130 case OPC_C0_4:
28131 case OPC_C0_5:
28132 case OPC_C0_6:
28133 case OPC_C0_7:
28134 case OPC_C0_8:
28135 case OPC_C0_9:
28136 case OPC_C0_A:
28137 case OPC_C0_B:
28138 case OPC_C0_C:
28139 case OPC_C0_D:
28140 case OPC_C0_E:
28141 case OPC_C0_F:
28142 #ifndef CONFIG_USER_ONLY
28143 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
28144 #endif /* !CONFIG_USER_ONLY */
28145 break;
28146 case OPC_MFMC0:
28147 #ifndef CONFIG_USER_ONLY
28149 uint32_t op2;
28150 TCGv t0 = tcg_temp_new();
28152 op2 = MASK_MFMC0(ctx->opcode);
28153 switch (op2) {
28154 case OPC_DMT:
28155 check_cp0_mt(ctx);
28156 gen_helper_dmt(t0);
28157 gen_store_gpr(t0, rt);
28158 break;
28159 case OPC_EMT:
28160 check_cp0_mt(ctx);
28161 gen_helper_emt(t0);
28162 gen_store_gpr(t0, rt);
28163 break;
28164 case OPC_DVPE:
28165 check_cp0_mt(ctx);
28166 gen_helper_dvpe(t0, cpu_env);
28167 gen_store_gpr(t0, rt);
28168 break;
28169 case OPC_EVPE:
28170 check_cp0_mt(ctx);
28171 gen_helper_evpe(t0, cpu_env);
28172 gen_store_gpr(t0, rt);
28173 break;
28174 case OPC_DVP:
28175 check_insn(ctx, ISA_MIPS32R6);
28176 if (ctx->vp) {
28177 gen_helper_dvp(t0, cpu_env);
28178 gen_store_gpr(t0, rt);
28180 break;
28181 case OPC_EVP:
28182 check_insn(ctx, ISA_MIPS32R6);
28183 if (ctx->vp) {
28184 gen_helper_evp(t0, cpu_env);
28185 gen_store_gpr(t0, rt);
28187 break;
28188 case OPC_DI:
28189 check_insn(ctx, ISA_MIPS32R2);
28190 save_cpu_state(ctx, 1);
28191 gen_helper_di(t0, cpu_env);
28192 gen_store_gpr(t0, rt);
28193 /* Stop translation as we may have switched
28194 the execution mode. */
28195 ctx->base.is_jmp = DISAS_STOP;
28196 break;
28197 case OPC_EI:
28198 check_insn(ctx, ISA_MIPS32R2);
28199 save_cpu_state(ctx, 1);
28200 gen_helper_ei(t0, cpu_env);
28201 gen_store_gpr(t0, rt);
28202 /* DISAS_STOP isn't sufficient, we need to ensure we break
28203 out of translated code to check for pending interrupts */
28204 gen_save_pc(ctx->base.pc_next + 4);
28205 ctx->base.is_jmp = DISAS_EXIT;
28206 break;
28207 default: /* Invalid */
28208 MIPS_INVAL("mfmc0");
28209 generate_exception_end(ctx, EXCP_RI);
28210 break;
28212 tcg_temp_free(t0);
28214 #endif /* !CONFIG_USER_ONLY */
28215 break;
28216 case OPC_RDPGPR:
28217 check_insn(ctx, ISA_MIPS32R2);
28218 gen_load_srsgpr(rt, rd);
28219 break;
28220 case OPC_WRPGPR:
28221 check_insn(ctx, ISA_MIPS32R2);
28222 gen_store_srsgpr(rt, rd);
28223 break;
28224 default:
28225 MIPS_INVAL("cp0");
28226 generate_exception_end(ctx, EXCP_RI);
28227 break;
28229 break;
28230 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
28231 if (ctx->insn_flags & ISA_MIPS32R6) {
28232 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
28233 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28234 } else {
28235 /* OPC_ADDI */
28236 /* Arithmetic with immediate opcode */
28237 gen_arith_imm(ctx, op, rt, rs, imm);
28239 break;
28240 case OPC_ADDIU:
28241 gen_arith_imm(ctx, op, rt, rs, imm);
28242 break;
28243 case OPC_SLTI: /* Set on less than with immediate opcode */
28244 case OPC_SLTIU:
28245 gen_slt_imm(ctx, op, rt, rs, imm);
28246 break;
28247 case OPC_ANDI: /* Arithmetic with immediate opcode */
28248 case OPC_LUI: /* OPC_AUI */
28249 case OPC_ORI:
28250 case OPC_XORI:
28251 gen_logic_imm(ctx, op, rt, rs, imm);
28252 break;
28253 case OPC_J: /* Jump */
28254 case OPC_JAL:
28255 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28256 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28257 break;
28258 /* Branch */
28259 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
28260 if (ctx->insn_flags & ISA_MIPS32R6) {
28261 if (rt == 0) {
28262 generate_exception_end(ctx, EXCP_RI);
28263 break;
28265 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
28266 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28267 } else {
28268 /* OPC_BLEZL */
28269 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28271 break;
28272 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
28273 if (ctx->insn_flags & ISA_MIPS32R6) {
28274 if (rt == 0) {
28275 generate_exception_end(ctx, EXCP_RI);
28276 break;
28278 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
28279 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28280 } else {
28281 /* OPC_BGTZL */
28282 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28284 break;
28285 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
28286 if (rt == 0) {
28287 /* OPC_BLEZ */
28288 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28289 } else {
28290 check_insn(ctx, ISA_MIPS32R6);
28291 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
28292 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28294 break;
28295 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
28296 if (rt == 0) {
28297 /* OPC_BGTZ */
28298 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28299 } else {
28300 check_insn(ctx, ISA_MIPS32R6);
28301 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
28302 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28304 break;
28305 case OPC_BEQL:
28306 case OPC_BNEL:
28307 check_insn(ctx, ISA_MIPS2);
28308 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28309 /* Fallthrough */
28310 case OPC_BEQ:
28311 case OPC_BNE:
28312 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
28313 break;
28314 case OPC_LL: /* Load and stores */
28315 check_insn(ctx, ISA_MIPS2);
28316 if (ctx->insn_flags & INSN_R5900) {
28317 check_insn_opc_user_only(ctx, INSN_R5900);
28319 /* Fallthrough */
28320 case OPC_LWL:
28321 case OPC_LWR:
28322 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28323 /* Fallthrough */
28324 case OPC_LB:
28325 case OPC_LH:
28326 case OPC_LW:
28327 case OPC_LWPC:
28328 case OPC_LBU:
28329 case OPC_LHU:
28330 gen_ld(ctx, op, rt, rs, imm);
28331 break;
28332 case OPC_SWL:
28333 case OPC_SWR:
28334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28335 /* fall through */
28336 case OPC_SB:
28337 case OPC_SH:
28338 case OPC_SW:
28339 gen_st(ctx, op, rt, rs, imm);
28340 break;
28341 case OPC_SC:
28342 check_insn(ctx, ISA_MIPS2);
28343 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28344 if (ctx->insn_flags & INSN_R5900) {
28345 check_insn_opc_user_only(ctx, INSN_R5900);
28347 gen_st_cond(ctx, op, rt, rs, imm);
28348 break;
28349 case OPC_CACHE:
28350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28351 check_cp0_enabled(ctx);
28352 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
28353 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28354 gen_cache_operation(ctx, rt, rs, imm);
28356 /* Treat as NOP. */
28357 break;
28358 case OPC_PREF:
28359 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28360 if (ctx->insn_flags & INSN_R5900) {
28361 /* Treat as NOP. */
28362 } else {
28363 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
28364 /* Treat as NOP. */
28366 break;
28368 /* Floating point (COP1). */
28369 case OPC_LWC1:
28370 case OPC_LDC1:
28371 case OPC_SWC1:
28372 case OPC_SDC1:
28373 gen_cop1_ldst(ctx, op, rt, rs, imm);
28374 break;
28376 case OPC_CP1:
28377 op1 = MASK_CP1(ctx->opcode);
28379 switch (op1) {
28380 case OPC_MFHC1:
28381 case OPC_MTHC1:
28382 check_cp1_enabled(ctx);
28383 check_insn(ctx, ISA_MIPS32R2);
28384 /* fall through */
28385 case OPC_MFC1:
28386 case OPC_CFC1:
28387 case OPC_MTC1:
28388 case OPC_CTC1:
28389 check_cp1_enabled(ctx);
28390 gen_cp1(ctx, op1, rt, rd);
28391 break;
28392 #if defined(TARGET_MIPS64)
28393 case OPC_DMFC1:
28394 case OPC_DMTC1:
28395 check_cp1_enabled(ctx);
28396 check_insn(ctx, ISA_MIPS3);
28397 check_mips_64(ctx);
28398 gen_cp1(ctx, op1, rt, rd);
28399 break;
28400 #endif
28401 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
28402 check_cp1_enabled(ctx);
28403 if (ctx->insn_flags & ISA_MIPS32R6) {
28404 /* OPC_BC1EQZ */
28405 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28406 rt, imm << 2, 4);
28407 } else {
28408 /* OPC_BC1ANY2 */
28409 check_cop1x(ctx);
28410 check_insn(ctx, ASE_MIPS3D);
28411 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28412 (rt >> 2) & 0x7, imm << 2);
28414 break;
28415 case OPC_BC1NEZ:
28416 check_cp1_enabled(ctx);
28417 check_insn(ctx, ISA_MIPS32R6);
28418 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
28419 rt, imm << 2, 4);
28420 break;
28421 case OPC_BC1ANY4:
28422 check_cp1_enabled(ctx);
28423 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28424 check_cop1x(ctx);
28425 check_insn(ctx, ASE_MIPS3D);
28426 /* fall through */
28427 case OPC_BC1:
28428 check_cp1_enabled(ctx);
28429 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28430 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
28431 (rt >> 2) & 0x7, imm << 2);
28432 break;
28433 case OPC_PS_FMT:
28434 check_ps(ctx);
28435 /* fall through */
28436 case OPC_S_FMT:
28437 case OPC_D_FMT:
28438 check_cp1_enabled(ctx);
28439 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28440 (imm >> 8) & 0x7);
28441 break;
28442 case OPC_W_FMT:
28443 case OPC_L_FMT:
28445 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
28446 check_cp1_enabled(ctx);
28447 if (ctx->insn_flags & ISA_MIPS32R6) {
28448 switch (r6_op) {
28449 case R6_OPC_CMP_AF_S:
28450 case R6_OPC_CMP_UN_S:
28451 case R6_OPC_CMP_EQ_S:
28452 case R6_OPC_CMP_UEQ_S:
28453 case R6_OPC_CMP_LT_S:
28454 case R6_OPC_CMP_ULT_S:
28455 case R6_OPC_CMP_LE_S:
28456 case R6_OPC_CMP_ULE_S:
28457 case R6_OPC_CMP_SAF_S:
28458 case R6_OPC_CMP_SUN_S:
28459 case R6_OPC_CMP_SEQ_S:
28460 case R6_OPC_CMP_SEUQ_S:
28461 case R6_OPC_CMP_SLT_S:
28462 case R6_OPC_CMP_SULT_S:
28463 case R6_OPC_CMP_SLE_S:
28464 case R6_OPC_CMP_SULE_S:
28465 case R6_OPC_CMP_OR_S:
28466 case R6_OPC_CMP_UNE_S:
28467 case R6_OPC_CMP_NE_S:
28468 case R6_OPC_CMP_SOR_S:
28469 case R6_OPC_CMP_SUNE_S:
28470 case R6_OPC_CMP_SNE_S:
28471 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28472 break;
28473 case R6_OPC_CMP_AF_D:
28474 case R6_OPC_CMP_UN_D:
28475 case R6_OPC_CMP_EQ_D:
28476 case R6_OPC_CMP_UEQ_D:
28477 case R6_OPC_CMP_LT_D:
28478 case R6_OPC_CMP_ULT_D:
28479 case R6_OPC_CMP_LE_D:
28480 case R6_OPC_CMP_ULE_D:
28481 case R6_OPC_CMP_SAF_D:
28482 case R6_OPC_CMP_SUN_D:
28483 case R6_OPC_CMP_SEQ_D:
28484 case R6_OPC_CMP_SEUQ_D:
28485 case R6_OPC_CMP_SLT_D:
28486 case R6_OPC_CMP_SULT_D:
28487 case R6_OPC_CMP_SLE_D:
28488 case R6_OPC_CMP_SULE_D:
28489 case R6_OPC_CMP_OR_D:
28490 case R6_OPC_CMP_UNE_D:
28491 case R6_OPC_CMP_NE_D:
28492 case R6_OPC_CMP_SOR_D:
28493 case R6_OPC_CMP_SUNE_D:
28494 case R6_OPC_CMP_SNE_D:
28495 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
28496 break;
28497 default:
28498 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
28499 rt, rd, sa, (imm >> 8) & 0x7);
28501 break;
28503 } else {
28504 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
28505 (imm >> 8) & 0x7);
28507 break;
28509 case OPC_BZ_V:
28510 case OPC_BNZ_V:
28511 case OPC_BZ_B:
28512 case OPC_BZ_H:
28513 case OPC_BZ_W:
28514 case OPC_BZ_D:
28515 case OPC_BNZ_B:
28516 case OPC_BNZ_H:
28517 case OPC_BNZ_W:
28518 case OPC_BNZ_D:
28519 check_insn(ctx, ASE_MSA);
28520 gen_msa_branch(env, ctx, op1);
28521 break;
28522 default:
28523 MIPS_INVAL("cp1");
28524 generate_exception_end(ctx, EXCP_RI);
28525 break;
28527 break;
28529 /* Compact branches [R6] and COP2 [non-R6] */
28530 case OPC_BC: /* OPC_LWC2 */
28531 case OPC_BALC: /* OPC_SWC2 */
28532 if (ctx->insn_flags & ISA_MIPS32R6) {
28533 /* OPC_BC, OPC_BALC */
28534 gen_compute_compact_branch(ctx, op, 0, 0,
28535 sextract32(ctx->opcode << 2, 0, 28));
28536 } else {
28537 /* OPC_LWC2, OPC_SWC2 */
28538 /* COP2: Not implemented. */
28539 generate_exception_err(ctx, EXCP_CpU, 2);
28541 break;
28542 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
28543 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
28544 if (ctx->insn_flags & ISA_MIPS32R6) {
28545 if (rs != 0) {
28546 /* OPC_BEQZC, OPC_BNEZC */
28547 gen_compute_compact_branch(ctx, op, rs, 0,
28548 sextract32(ctx->opcode << 2, 0, 23));
28549 } else {
28550 /* OPC_JIC, OPC_JIALC */
28551 gen_compute_compact_branch(ctx, op, 0, rt, imm);
28553 } else {
28554 /* OPC_LWC2, OPC_SWC2 */
28555 /* COP2: Not implemented. */
28556 generate_exception_err(ctx, EXCP_CpU, 2);
28558 break;
28559 case OPC_CP2:
28560 check_insn(ctx, INSN_LOONGSON2F);
28561 /* Note that these instructions use different fields. */
28562 gen_loongson_multimedia(ctx, sa, rd, rt);
28563 break;
28565 case OPC_CP3:
28566 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28567 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
28568 check_cp1_enabled(ctx);
28569 op1 = MASK_CP3(ctx->opcode);
28570 switch (op1) {
28571 case OPC_LUXC1:
28572 case OPC_SUXC1:
28573 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
28574 /* Fallthrough */
28575 case OPC_LWXC1:
28576 case OPC_LDXC1:
28577 case OPC_SWXC1:
28578 case OPC_SDXC1:
28579 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
28580 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
28581 break;
28582 case OPC_PREFX:
28583 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
28584 /* Treat as NOP. */
28585 break;
28586 case OPC_ALNV_PS:
28587 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
28588 /* Fallthrough */
28589 case OPC_MADD_S:
28590 case OPC_MADD_D:
28591 case OPC_MADD_PS:
28592 case OPC_MSUB_S:
28593 case OPC_MSUB_D:
28594 case OPC_MSUB_PS:
28595 case OPC_NMADD_S:
28596 case OPC_NMADD_D:
28597 case OPC_NMADD_PS:
28598 case OPC_NMSUB_S:
28599 case OPC_NMSUB_D:
28600 case OPC_NMSUB_PS:
28601 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
28602 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
28603 break;
28604 default:
28605 MIPS_INVAL("cp3");
28606 generate_exception_end(ctx, EXCP_RI);
28607 break;
28609 } else {
28610 generate_exception_err(ctx, EXCP_CpU, 1);
28612 break;
28614 #if defined(TARGET_MIPS64)
28615 /* MIPS64 opcodes */
28616 case OPC_LLD:
28617 if (ctx->insn_flags & INSN_R5900) {
28618 check_insn_opc_user_only(ctx, INSN_R5900);
28620 /* fall through */
28621 case OPC_LDL:
28622 case OPC_LDR:
28623 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28624 /* fall through */
28625 case OPC_LWU:
28626 case OPC_LD:
28627 check_insn(ctx, ISA_MIPS3);
28628 check_mips_64(ctx);
28629 gen_ld(ctx, op, rt, rs, imm);
28630 break;
28631 case OPC_SDL:
28632 case OPC_SDR:
28633 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28634 /* fall through */
28635 case OPC_SD:
28636 check_insn(ctx, ISA_MIPS3);
28637 check_mips_64(ctx);
28638 gen_st(ctx, op, rt, rs, imm);
28639 break;
28640 case OPC_SCD:
28641 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28642 check_insn(ctx, ISA_MIPS3);
28643 if (ctx->insn_flags & INSN_R5900) {
28644 check_insn_opc_user_only(ctx, INSN_R5900);
28646 check_mips_64(ctx);
28647 gen_st_cond(ctx, op, rt, rs, imm);
28648 break;
28649 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
28650 if (ctx->insn_flags & ISA_MIPS32R6) {
28651 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
28652 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28653 } else {
28654 /* OPC_DADDI */
28655 check_insn(ctx, ISA_MIPS3);
28656 check_mips_64(ctx);
28657 gen_arith_imm(ctx, op, rt, rs, imm);
28659 break;
28660 case OPC_DADDIU:
28661 check_insn(ctx, ISA_MIPS3);
28662 check_mips_64(ctx);
28663 gen_arith_imm(ctx, op, rt, rs, imm);
28664 break;
28665 #else
28666 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
28667 if (ctx->insn_flags & ISA_MIPS32R6) {
28668 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
28669 } else {
28670 MIPS_INVAL("major opcode");
28671 generate_exception_end(ctx, EXCP_RI);
28673 break;
28674 #endif
28675 case OPC_DAUI: /* OPC_JALX */
28676 if (ctx->insn_flags & ISA_MIPS32R6) {
28677 #if defined(TARGET_MIPS64)
28678 /* OPC_DAUI */
28679 check_mips_64(ctx);
28680 if (rs == 0) {
28681 generate_exception(ctx, EXCP_RI);
28682 } else if (rt != 0) {
28683 TCGv t0 = tcg_temp_new();
28684 gen_load_gpr(t0, rs);
28685 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
28686 tcg_temp_free(t0);
28688 #else
28689 generate_exception_end(ctx, EXCP_RI);
28690 MIPS_INVAL("major opcode");
28691 #endif
28692 } else {
28693 /* OPC_JALX */
28694 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
28695 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
28696 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
28698 break;
28699 case OPC_MSA: /* OPC_MDMX */
28700 if (ctx->insn_flags & INSN_R5900) {
28701 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
28702 } else {
28703 /* MDMX: Not implemented. */
28704 gen_msa(env, ctx);
28706 break;
28707 case OPC_PCREL:
28708 check_insn(ctx, ISA_MIPS32R6);
28709 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
28710 break;
28711 default: /* Invalid */
28712 MIPS_INVAL("major opcode");
28713 generate_exception_end(ctx, EXCP_RI);
28714 break;
28718 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
28720 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28721 CPUMIPSState *env = cs->env_ptr;
28723 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
28724 ctx->saved_pc = -1;
28725 ctx->insn_flags = env->insn_flags;
28726 ctx->CP0_Config1 = env->CP0_Config1;
28727 ctx->CP0_Config2 = env->CP0_Config2;
28728 ctx->CP0_Config3 = env->CP0_Config3;
28729 ctx->CP0_Config5 = env->CP0_Config5;
28730 ctx->btarget = 0;
28731 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
28732 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
28733 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
28734 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
28735 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
28736 ctx->PAMask = env->PAMask;
28737 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
28738 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
28739 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
28740 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
28741 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
28742 /* Restore delay slot state from the tb context. */
28743 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
28744 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
28745 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
28746 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
28747 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
28748 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
28749 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
28750 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
28751 restore_cpu_state(env, ctx);
28752 #ifdef CONFIG_USER_ONLY
28753 ctx->mem_idx = MIPS_HFLAG_UM;
28754 #else
28755 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
28756 #endif
28757 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
28758 MO_UNALN : MO_ALIGN;
28760 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
28761 ctx->hflags);
28764 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
28768 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
28770 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28772 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
28773 ctx->btarget);
28776 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
28777 const CPUBreakpoint *bp)
28779 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28781 save_cpu_state(ctx, 1);
28782 ctx->base.is_jmp = DISAS_NORETURN;
28783 gen_helper_raise_exception_debug(cpu_env);
28784 /* The address covered by the breakpoint must be included in
28785 [tb->pc, tb->pc + tb->size) in order to for it to be
28786 properly cleared -- thus we increment the PC here so that
28787 the logic setting tb->size below does the right thing. */
28788 ctx->base.pc_next += 4;
28789 return true;
28792 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
28794 CPUMIPSState *env = cs->env_ptr;
28795 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28796 int insn_bytes;
28797 int is_slot;
28799 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
28800 if (ctx->insn_flags & ISA_NANOMIPS32) {
28801 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28802 insn_bytes = decode_nanomips_opc(env, ctx);
28803 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
28804 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
28805 insn_bytes = 4;
28806 decode_opc(env, ctx);
28807 } else if (ctx->insn_flags & ASE_MICROMIPS) {
28808 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28809 insn_bytes = decode_micromips_opc(env, ctx);
28810 } else if (ctx->insn_flags & ASE_MIPS16) {
28811 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
28812 insn_bytes = decode_mips16_opc(env, ctx);
28813 } else {
28814 generate_exception_end(ctx, EXCP_RI);
28815 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
28816 return;
28819 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28820 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
28821 MIPS_HFLAG_FBNSLOT))) {
28822 /* force to generate branch as there is neither delay nor
28823 forbidden slot */
28824 is_slot = 1;
28826 if ((ctx->hflags & MIPS_HFLAG_M16) &&
28827 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
28828 /* Force to generate branch as microMIPS R6 doesn't restrict
28829 branches in the forbidden slot. */
28830 is_slot = 1;
28833 if (is_slot) {
28834 gen_branch(ctx, insn_bytes);
28836 ctx->base.pc_next += insn_bytes;
28838 if (ctx->base.is_jmp != DISAS_NEXT) {
28839 return;
28841 /* Execute a branch and its delay slot as a single instruction.
28842 This is what GDB expects and is consistent with what the
28843 hardware does (e.g. if a delay slot instruction faults, the
28844 reported PC is the PC of the branch). */
28845 if (ctx->base.singlestep_enabled &&
28846 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
28847 ctx->base.is_jmp = DISAS_TOO_MANY;
28849 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
28850 ctx->base.is_jmp = DISAS_TOO_MANY;
28854 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
28856 DisasContext *ctx = container_of(dcbase, DisasContext, base);
28858 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
28859 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
28860 gen_helper_raise_exception_debug(cpu_env);
28861 } else {
28862 switch (ctx->base.is_jmp) {
28863 case DISAS_STOP:
28864 gen_save_pc(ctx->base.pc_next);
28865 tcg_gen_lookup_and_goto_ptr();
28866 break;
28867 case DISAS_NEXT:
28868 case DISAS_TOO_MANY:
28869 save_cpu_state(ctx, 0);
28870 gen_goto_tb(ctx, 0, ctx->base.pc_next);
28871 break;
28872 case DISAS_EXIT:
28873 tcg_gen_exit_tb(NULL, 0);
28874 break;
28875 case DISAS_NORETURN:
28876 break;
28877 default:
28878 g_assert_not_reached();
28883 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
28885 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
28886 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
28889 static const TranslatorOps mips_tr_ops = {
28890 .init_disas_context = mips_tr_init_disas_context,
28891 .tb_start = mips_tr_tb_start,
28892 .insn_start = mips_tr_insn_start,
28893 .breakpoint_check = mips_tr_breakpoint_check,
28894 .translate_insn = mips_tr_translate_insn,
28895 .tb_stop = mips_tr_tb_stop,
28896 .disas_log = mips_tr_disas_log,
28899 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
28901 DisasContext ctx;
28903 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
28906 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
28907 int flags)
28909 int i;
28910 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
28912 #define printfpr(fp) \
28913 do { \
28914 if (is_fpu64) \
28915 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
28916 " fd:%13g fs:%13g psu: %13g\n", \
28917 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
28918 (double)(fp)->fd, \
28919 (double)(fp)->fs[FP_ENDIAN_IDX], \
28920 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
28921 else { \
28922 fpr_t tmp; \
28923 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
28924 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
28925 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
28926 " fd:%13g fs:%13g psu:%13g\n", \
28927 tmp.w[FP_ENDIAN_IDX], tmp.d, \
28928 (double)tmp.fd, \
28929 (double)tmp.fs[FP_ENDIAN_IDX], \
28930 (double)tmp.fs[!FP_ENDIAN_IDX]); \
28932 } while(0)
28935 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
28936 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
28937 get_float_exception_flags(&env->active_fpu.fp_status));
28938 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
28939 fpu_fprintf(f, "%3s: ", fregnames[i]);
28940 printfpr(&env->active_fpu.fpr[i]);
28943 #undef printfpr
28946 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
28947 int flags)
28949 MIPSCPU *cpu = MIPS_CPU(cs);
28950 CPUMIPSState *env = &cpu->env;
28951 int i;
28953 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
28954 " LO=0x" TARGET_FMT_lx " ds %04x "
28955 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
28956 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
28957 env->hflags, env->btarget, env->bcond);
28958 for (i = 0; i < 32; i++) {
28959 if ((i & 3) == 0)
28960 cpu_fprintf(f, "GPR%02d:", i);
28961 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
28962 if ((i & 3) == 3)
28963 cpu_fprintf(f, "\n");
28966 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
28967 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
28968 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
28969 PRIx64 "\n",
28970 env->CP0_Config0, env->CP0_Config1, env->lladdr);
28971 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
28972 env->CP0_Config2, env->CP0_Config3);
28973 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
28974 env->CP0_Config4, env->CP0_Config5);
28975 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
28976 fpu_dump_state(env, f, cpu_fprintf, flags);
28980 void mips_tcg_init(void)
28982 int i;
28984 cpu_gpr[0] = NULL;
28985 for (i = 1; i < 32; i++)
28986 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
28987 offsetof(CPUMIPSState, active_tc.gpr[i]),
28988 regnames[i]);
28990 for (i = 0; i < 32; i++) {
28991 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
28992 msa_wr_d[i * 2] =
28993 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
28994 /* The scalar floating-point unit (FPU) registers are mapped on
28995 * the MSA vector registers. */
28996 fpu_f64[i] = msa_wr_d[i * 2];
28997 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
28998 msa_wr_d[i * 2 + 1] =
28999 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
29002 cpu_PC = tcg_global_mem_new(cpu_env,
29003 offsetof(CPUMIPSState, active_tc.PC), "PC");
29004 for (i = 0; i < MIPS_DSP_ACC; i++) {
29005 cpu_HI[i] = tcg_global_mem_new(cpu_env,
29006 offsetof(CPUMIPSState, active_tc.HI[i]),
29007 regnames_HI[i]);
29008 cpu_LO[i] = tcg_global_mem_new(cpu_env,
29009 offsetof(CPUMIPSState, active_tc.LO[i]),
29010 regnames_LO[i]);
29012 cpu_dspctrl = tcg_global_mem_new(cpu_env,
29013 offsetof(CPUMIPSState, active_tc.DSPControl),
29014 "DSPControl");
29015 bcond = tcg_global_mem_new(cpu_env,
29016 offsetof(CPUMIPSState, bcond), "bcond");
29017 btarget = tcg_global_mem_new(cpu_env,
29018 offsetof(CPUMIPSState, btarget), "btarget");
29019 hflags = tcg_global_mem_new_i32(cpu_env,
29020 offsetof(CPUMIPSState, hflags), "hflags");
29022 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
29023 offsetof(CPUMIPSState, active_fpu.fcr0),
29024 "fcr0");
29025 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
29026 offsetof(CPUMIPSState, active_fpu.fcr31),
29027 "fcr31");
29029 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
29030 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
29031 offsetof(CPUMIPSState,
29032 active_tc.mxu_gpr[i]),
29033 mxuregnames[i]);
29036 mxu_CR = tcg_global_mem_new(cpu_env,
29037 offsetof(CPUMIPSState, active_tc.mxu_cr),
29038 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
29041 #include "translate_init.inc.c"
29043 void cpu_mips_realize_env(CPUMIPSState *env)
29045 env->exception_base = (int32_t)0xBFC00000;
29047 #ifndef CONFIG_USER_ONLY
29048 mmu_init(env, env->cpu_model);
29049 #endif
29050 fpu_init(env, env->cpu_model);
29051 mvp_init(env, env->cpu_model);
29054 bool cpu_supports_cps_smp(const char *cpu_type)
29056 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29057 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
29060 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
29062 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
29063 return (mcc->cpu_def->insn_flags & isa) != 0;
29066 void cpu_set_exception_base(int vp_index, target_ulong address)
29068 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
29069 vp->env.exception_base = address;
29072 void cpu_state_reset(CPUMIPSState *env)
29074 MIPSCPU *cpu = mips_env_get_cpu(env);
29075 CPUState *cs = CPU(cpu);
29077 /* Reset registers to their default values */
29078 env->CP0_PRid = env->cpu_model->CP0_PRid;
29079 env->CP0_Config0 = env->cpu_model->CP0_Config0;
29080 #ifdef TARGET_WORDS_BIGENDIAN
29081 env->CP0_Config0 |= (1 << CP0C0_BE);
29082 #endif
29083 env->CP0_Config1 = env->cpu_model->CP0_Config1;
29084 env->CP0_Config2 = env->cpu_model->CP0_Config2;
29085 env->CP0_Config3 = env->cpu_model->CP0_Config3;
29086 env->CP0_Config4 = env->cpu_model->CP0_Config4;
29087 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
29088 env->CP0_Config5 = env->cpu_model->CP0_Config5;
29089 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
29090 env->CP0_Config6 = env->cpu_model->CP0_Config6;
29091 env->CP0_Config7 = env->cpu_model->CP0_Config7;
29092 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
29093 << env->cpu_model->CP0_LLAddr_shift;
29094 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
29095 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
29096 env->CCRes = env->cpu_model->CCRes;
29097 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
29098 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
29099 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
29100 env->current_tc = 0;
29101 env->SEGBITS = env->cpu_model->SEGBITS;
29102 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
29103 #if defined(TARGET_MIPS64)
29104 if (env->cpu_model->insn_flags & ISA_MIPS3) {
29105 env->SEGMask |= 3ULL << 62;
29107 #endif
29108 env->PABITS = env->cpu_model->PABITS;
29109 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
29110 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
29111 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
29112 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
29113 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
29114 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
29115 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
29116 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
29117 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
29118 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
29119 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
29120 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
29121 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
29122 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
29123 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
29124 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
29125 env->msair = env->cpu_model->MSAIR;
29126 env->insn_flags = env->cpu_model->insn_flags;
29128 #if defined(CONFIG_USER_ONLY)
29129 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
29130 # ifdef TARGET_MIPS64
29131 /* Enable 64-bit register mode. */
29132 env->CP0_Status |= (1 << CP0St_PX);
29133 # endif
29134 # ifdef TARGET_ABI_MIPSN64
29135 /* Enable 64-bit address mode. */
29136 env->CP0_Status |= (1 << CP0St_UX);
29137 # endif
29138 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
29139 hardware registers. */
29140 env->CP0_HWREna |= 0x0000000F;
29141 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
29142 env->CP0_Status |= (1 << CP0St_CU1);
29144 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
29145 env->CP0_Status |= (1 << CP0St_MX);
29147 # if defined(TARGET_MIPS64)
29148 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
29149 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
29150 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
29151 env->CP0_Status |= (1 << CP0St_FR);
29153 # endif
29154 #else
29155 if (env->hflags & MIPS_HFLAG_BMASK) {
29156 /* If the exception was raised from a delay slot,
29157 come back to the jump. */
29158 env->CP0_ErrorEPC = (env->active_tc.PC
29159 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
29160 } else {
29161 env->CP0_ErrorEPC = env->active_tc.PC;
29163 env->active_tc.PC = env->exception_base;
29164 env->CP0_Random = env->tlb->nb_tlb - 1;
29165 env->tlb->tlb_in_use = env->tlb->nb_tlb;
29166 env->CP0_Wired = 0;
29167 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
29168 env->CP0_EBase = (cs->cpu_index & 0x3FF);
29169 if (mips_um_ksegs_enabled()) {
29170 env->CP0_EBase |= 0x40000000;
29171 } else {
29172 env->CP0_EBase |= (int32_t)0x80000000;
29174 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
29175 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
29177 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
29178 0x3ff : 0xff;
29179 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
29180 /* vectored interrupts not implemented, timer on int 7,
29181 no performance counters. */
29182 env->CP0_IntCtl = 0xe0000000;
29184 int i;
29186 for (i = 0; i < 7; i++) {
29187 env->CP0_WatchLo[i] = 0;
29188 env->CP0_WatchHi[i] = 0x80000000;
29190 env->CP0_WatchLo[7] = 0;
29191 env->CP0_WatchHi[7] = 0;
29193 /* Count register increments in debug mode, EJTAG version 1 */
29194 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
29196 cpu_mips_store_count(env, 1);
29198 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
29199 int i;
29201 /* Only TC0 on VPE 0 starts as active. */
29202 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
29203 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
29204 env->tcs[i].CP0_TCHalt = 1;
29206 env->active_tc.CP0_TCHalt = 1;
29207 cs->halted = 1;
29209 if (cs->cpu_index == 0) {
29210 /* VPE0 starts up enabled. */
29211 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
29212 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
29214 /* TC0 starts up unhalted. */
29215 cs->halted = 0;
29216 env->active_tc.CP0_TCHalt = 0;
29217 env->tcs[0].CP0_TCHalt = 0;
29218 /* With thread 0 active. */
29219 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
29220 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
29225 * Configure default legacy segmentation control. We use this regardless of
29226 * whether segmentation control is presented to the guest.
29228 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
29229 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
29230 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
29231 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
29232 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
29233 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
29234 (2 << CP0SC_C);
29235 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
29236 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
29237 (3 << CP0SC_C)) << 16;
29238 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
29239 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
29240 (1 << CP0SC_EU) | (2 << CP0SC_C);
29241 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
29242 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
29243 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
29244 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
29245 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
29246 #endif
29247 if ((env->insn_flags & ISA_MIPS32R6) &&
29248 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
29249 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
29250 env->CP0_Status |= (1 << CP0St_FR);
29253 if (env->insn_flags & ISA_MIPS32R6) {
29254 /* PTW = 1 */
29255 env->CP0_PWSize = 0x40;
29256 /* GDI = 12 */
29257 /* UDI = 12 */
29258 /* MDI = 12 */
29259 /* PRI = 12 */
29260 /* PTEI = 2 */
29261 env->CP0_PWField = 0x0C30C302;
29262 } else {
29263 /* GDI = 0 */
29264 /* UDI = 0 */
29265 /* MDI = 0 */
29266 /* PRI = 0 */
29267 /* PTEI = 2 */
29268 env->CP0_PWField = 0x02;
29271 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
29272 /* microMIPS on reset when Config3.ISA is 3 */
29273 env->hflags |= MIPS_HFLAG_M16;
29276 /* MSA */
29277 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
29278 msa_reset(env);
29281 compute_hflags(env);
29282 restore_fp_status(env);
29283 restore_pamask(env);
29284 cs->exception_index = EXCP_NONE;
29286 if (semihosting_get_argc()) {
29287 /* UHI interface can be used to obtain argc and argv */
29288 env->active_tc.gpr[4] = -1;
29292 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
29293 target_ulong *data)
29295 env->active_tc.PC = data[0];
29296 env->hflags &= ~MIPS_HFLAG_BMASK;
29297 env->hflags |= data[1];
29298 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
29299 case MIPS_HFLAG_BR:
29300 break;
29301 case MIPS_HFLAG_BC:
29302 case MIPS_HFLAG_BL:
29303 case MIPS_HFLAG_B:
29304 env->btarget = data[2];
29305 break;