target/ppc: Add support for scv and rfscv instructions
[qemu/ar7.git] / target / mips / translate.c
blob25b595a17ddcd250e7be3f758c42b2dcfda691bb
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/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 "hw/semihosting/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
41 #include "qemu/qemu-print.h"
43 #define MIPS_DEBUG_DISAS 0
45 /* MIPS major opcodes */
46 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
48 enum {
49 /* indirect opcode tables */
50 OPC_SPECIAL = (0x00 << 26),
51 OPC_REGIMM = (0x01 << 26),
52 OPC_CP0 = (0x10 << 26),
53 OPC_CP1 = (0x11 << 26),
54 OPC_CP2 = (0x12 << 26),
55 OPC_CP3 = (0x13 << 26),
56 OPC_SPECIAL2 = (0x1C << 26),
57 OPC_SPECIAL3 = (0x1F << 26),
58 /* arithmetic with immediate */
59 OPC_ADDI = (0x08 << 26),
60 OPC_ADDIU = (0x09 << 26),
61 OPC_SLTI = (0x0A << 26),
62 OPC_SLTIU = (0x0B << 26),
63 /* logic with immediate */
64 OPC_ANDI = (0x0C << 26),
65 OPC_ORI = (0x0D << 26),
66 OPC_XORI = (0x0E << 26),
67 OPC_LUI = (0x0F << 26),
68 /* arithmetic with immediate */
69 OPC_DADDI = (0x18 << 26),
70 OPC_DADDIU = (0x19 << 26),
71 /* Jump and branches */
72 OPC_J = (0x02 << 26),
73 OPC_JAL = (0x03 << 26),
74 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
75 OPC_BEQL = (0x14 << 26),
76 OPC_BNE = (0x05 << 26),
77 OPC_BNEL = (0x15 << 26),
78 OPC_BLEZ = (0x06 << 26),
79 OPC_BLEZL = (0x16 << 26),
80 OPC_BGTZ = (0x07 << 26),
81 OPC_BGTZL = (0x17 << 26),
82 OPC_JALX = (0x1D << 26),
83 OPC_DAUI = (0x1D << 26),
84 /* Load and stores */
85 OPC_LDL = (0x1A << 26),
86 OPC_LDR = (0x1B << 26),
87 OPC_LB = (0x20 << 26),
88 OPC_LH = (0x21 << 26),
89 OPC_LWL = (0x22 << 26),
90 OPC_LW = (0x23 << 26),
91 OPC_LWPC = OPC_LW | 0x5,
92 OPC_LBU = (0x24 << 26),
93 OPC_LHU = (0x25 << 26),
94 OPC_LWR = (0x26 << 26),
95 OPC_LWU = (0x27 << 26),
96 OPC_SB = (0x28 << 26),
97 OPC_SH = (0x29 << 26),
98 OPC_SWL = (0x2A << 26),
99 OPC_SW = (0x2B << 26),
100 OPC_SDL = (0x2C << 26),
101 OPC_SDR = (0x2D << 26),
102 OPC_SWR = (0x2E << 26),
103 OPC_LL = (0x30 << 26),
104 OPC_LLD = (0x34 << 26),
105 OPC_LD = (0x37 << 26),
106 OPC_LDPC = OPC_LD | 0x5,
107 OPC_SC = (0x38 << 26),
108 OPC_SCD = (0x3C << 26),
109 OPC_SD = (0x3F << 26),
110 /* Floating point load/store */
111 OPC_LWC1 = (0x31 << 26),
112 OPC_LWC2 = (0x32 << 26),
113 OPC_LDC1 = (0x35 << 26),
114 OPC_LDC2 = (0x36 << 26),
115 OPC_SWC1 = (0x39 << 26),
116 OPC_SWC2 = (0x3A << 26),
117 OPC_SDC1 = (0x3D << 26),
118 OPC_SDC2 = (0x3E << 26),
119 /* Compact Branches */
120 OPC_BLEZALC = (0x06 << 26),
121 OPC_BGEZALC = (0x06 << 26),
122 OPC_BGEUC = (0x06 << 26),
123 OPC_BGTZALC = (0x07 << 26),
124 OPC_BLTZALC = (0x07 << 26),
125 OPC_BLTUC = (0x07 << 26),
126 OPC_BOVC = (0x08 << 26),
127 OPC_BEQZALC = (0x08 << 26),
128 OPC_BEQC = (0x08 << 26),
129 OPC_BLEZC = (0x16 << 26),
130 OPC_BGEZC = (0x16 << 26),
131 OPC_BGEC = (0x16 << 26),
132 OPC_BGTZC = (0x17 << 26),
133 OPC_BLTZC = (0x17 << 26),
134 OPC_BLTC = (0x17 << 26),
135 OPC_BNVC = (0x18 << 26),
136 OPC_BNEZALC = (0x18 << 26),
137 OPC_BNEC = (0x18 << 26),
138 OPC_BC = (0x32 << 26),
139 OPC_BEQZC = (0x36 << 26),
140 OPC_JIC = (0x36 << 26),
141 OPC_BALC = (0x3A << 26),
142 OPC_BNEZC = (0x3E << 26),
143 OPC_JIALC = (0x3E << 26),
144 /* MDMX ASE specific */
145 OPC_MDMX = (0x1E << 26),
146 /* MSA ASE, same as MDMX */
147 OPC_MSA = OPC_MDMX,
148 /* Cache and prefetch */
149 OPC_CACHE = (0x2F << 26),
150 OPC_PREF = (0x33 << 26),
151 /* PC-relative address computation / loads */
152 OPC_PCREL = (0x3B << 26),
155 /* PC-relative address computation / loads */
156 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
157 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
158 enum {
159 /* Instructions determined by bits 19 and 20 */
160 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
161 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
162 OPC_LWUPC = OPC_PCREL | (2 << 19),
164 /* Instructions determined by bits 16 ... 20 */
165 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
166 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
168 /* Other */
169 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
172 /* MIPS special opcodes */
173 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
175 enum {
176 /* Shifts */
177 OPC_SLL = 0x00 | OPC_SPECIAL,
178 /* NOP is SLL r0, r0, 0 */
179 /* SSNOP is SLL r0, r0, 1 */
180 /* EHB is SLL r0, r0, 3 */
181 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
182 OPC_ROTR = OPC_SRL | (1 << 21),
183 OPC_SRA = 0x03 | OPC_SPECIAL,
184 OPC_SLLV = 0x04 | OPC_SPECIAL,
185 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
186 OPC_ROTRV = OPC_SRLV | (1 << 6),
187 OPC_SRAV = 0x07 | OPC_SPECIAL,
188 OPC_DSLLV = 0x14 | OPC_SPECIAL,
189 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
190 OPC_DROTRV = OPC_DSRLV | (1 << 6),
191 OPC_DSRAV = 0x17 | OPC_SPECIAL,
192 OPC_DSLL = 0x38 | OPC_SPECIAL,
193 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
194 OPC_DROTR = OPC_DSRL | (1 << 21),
195 OPC_DSRA = 0x3B | OPC_SPECIAL,
196 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
197 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
198 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
199 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
200 /* Multiplication / division */
201 OPC_MULT = 0x18 | OPC_SPECIAL,
202 OPC_MULTU = 0x19 | OPC_SPECIAL,
203 OPC_DIV = 0x1A | OPC_SPECIAL,
204 OPC_DIVU = 0x1B | OPC_SPECIAL,
205 OPC_DMULT = 0x1C | OPC_SPECIAL,
206 OPC_DMULTU = 0x1D | OPC_SPECIAL,
207 OPC_DDIV = 0x1E | OPC_SPECIAL,
208 OPC_DDIVU = 0x1F | OPC_SPECIAL,
210 /* 2 registers arithmetic / logic */
211 OPC_ADD = 0x20 | OPC_SPECIAL,
212 OPC_ADDU = 0x21 | OPC_SPECIAL,
213 OPC_SUB = 0x22 | OPC_SPECIAL,
214 OPC_SUBU = 0x23 | OPC_SPECIAL,
215 OPC_AND = 0x24 | OPC_SPECIAL,
216 OPC_OR = 0x25 | OPC_SPECIAL,
217 OPC_XOR = 0x26 | OPC_SPECIAL,
218 OPC_NOR = 0x27 | OPC_SPECIAL,
219 OPC_SLT = 0x2A | OPC_SPECIAL,
220 OPC_SLTU = 0x2B | OPC_SPECIAL,
221 OPC_DADD = 0x2C | OPC_SPECIAL,
222 OPC_DADDU = 0x2D | OPC_SPECIAL,
223 OPC_DSUB = 0x2E | OPC_SPECIAL,
224 OPC_DSUBU = 0x2F | OPC_SPECIAL,
225 /* Jumps */
226 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
227 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
228 /* Traps */
229 OPC_TGE = 0x30 | OPC_SPECIAL,
230 OPC_TGEU = 0x31 | OPC_SPECIAL,
231 OPC_TLT = 0x32 | OPC_SPECIAL,
232 OPC_TLTU = 0x33 | OPC_SPECIAL,
233 OPC_TEQ = 0x34 | OPC_SPECIAL,
234 OPC_TNE = 0x36 | OPC_SPECIAL,
235 /* HI / LO registers load & stores */
236 OPC_MFHI = 0x10 | OPC_SPECIAL,
237 OPC_MTHI = 0x11 | OPC_SPECIAL,
238 OPC_MFLO = 0x12 | OPC_SPECIAL,
239 OPC_MTLO = 0x13 | OPC_SPECIAL,
240 /* Conditional moves */
241 OPC_MOVZ = 0x0A | OPC_SPECIAL,
242 OPC_MOVN = 0x0B | OPC_SPECIAL,
244 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
245 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
247 OPC_MOVCI = 0x01 | OPC_SPECIAL,
249 /* Special */
250 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
251 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
252 OPC_BREAK = 0x0D | OPC_SPECIAL,
253 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
254 OPC_SYNC = 0x0F | OPC_SPECIAL,
256 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
257 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
258 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
259 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
263 * R6 Multiply and Divide instructions have the same opcode
264 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
266 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
268 enum {
269 R6_OPC_MUL = OPC_MULT | (2 << 6),
270 R6_OPC_MUH = OPC_MULT | (3 << 6),
271 R6_OPC_MULU = OPC_MULTU | (2 << 6),
272 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
273 R6_OPC_DIV = OPC_DIV | (2 << 6),
274 R6_OPC_MOD = OPC_DIV | (3 << 6),
275 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
276 R6_OPC_MODU = OPC_DIVU | (3 << 6),
278 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
279 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
280 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
281 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
282 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
283 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
284 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
285 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
287 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
288 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
289 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
290 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
291 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
293 OPC_LSA = 0x05 | OPC_SPECIAL,
294 OPC_DLSA = 0x15 | OPC_SPECIAL,
297 /* Multiplication variants of the vr54xx. */
298 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
300 enum {
301 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
302 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
303 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
304 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
305 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
306 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
307 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
308 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
309 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
310 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
311 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
312 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
313 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
314 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
317 /* REGIMM (rt field) opcodes */
318 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
320 enum {
321 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
322 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
323 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
324 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
325 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
326 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
327 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
328 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
329 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
330 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
331 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
332 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
333 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
334 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
335 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
336 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
338 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
339 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
342 /* Special2 opcodes */
343 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
345 enum {
346 /* Multiply & xxx operations */
347 OPC_MADD = 0x00 | OPC_SPECIAL2,
348 OPC_MADDU = 0x01 | OPC_SPECIAL2,
349 OPC_MUL = 0x02 | OPC_SPECIAL2,
350 OPC_MSUB = 0x04 | OPC_SPECIAL2,
351 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
352 /* Loongson 2F */
353 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
354 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
355 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
356 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
357 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
358 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
359 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
360 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
361 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
362 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
363 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
364 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
365 /* Misc */
366 OPC_CLZ = 0x20 | OPC_SPECIAL2,
367 OPC_CLO = 0x21 | OPC_SPECIAL2,
368 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
369 OPC_DCLO = 0x25 | OPC_SPECIAL2,
370 /* Special */
371 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
374 /* Special3 opcodes */
375 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
377 enum {
378 OPC_EXT = 0x00 | OPC_SPECIAL3,
379 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
380 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
381 OPC_DEXT = 0x03 | OPC_SPECIAL3,
382 OPC_INS = 0x04 | OPC_SPECIAL3,
383 OPC_DINSM = 0x05 | OPC_SPECIAL3,
384 OPC_DINSU = 0x06 | OPC_SPECIAL3,
385 OPC_DINS = 0x07 | OPC_SPECIAL3,
386 OPC_FORK = 0x08 | OPC_SPECIAL3,
387 OPC_YIELD = 0x09 | OPC_SPECIAL3,
388 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
389 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
390 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
391 OPC_GINV = 0x3D | OPC_SPECIAL3,
393 /* Loongson 2E */
394 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
395 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
396 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
397 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
398 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
399 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
400 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
401 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
402 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
403 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
404 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
405 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
407 /* MIPS DSP Load */
408 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
409 /* MIPS DSP Arithmetic */
410 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
411 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
412 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
413 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
414 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
415 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
417 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
418 /* MIPS DSP GPR-Based Shift Sub-class */
419 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
420 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
421 /* MIPS DSP Multiply Sub-class insns */
422 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
423 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
424 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
425 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
426 /* DSP Bit/Manipulation Sub-class */
427 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
428 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
429 /* MIPS DSP Append Sub-class */
430 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
431 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
432 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
433 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
434 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
436 /* EVA */
437 OPC_LWLE = 0x19 | OPC_SPECIAL3,
438 OPC_LWRE = 0x1A | OPC_SPECIAL3,
439 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
440 OPC_SBE = 0x1C | OPC_SPECIAL3,
441 OPC_SHE = 0x1D | OPC_SPECIAL3,
442 OPC_SCE = 0x1E | OPC_SPECIAL3,
443 OPC_SWE = 0x1F | OPC_SPECIAL3,
444 OPC_SWLE = 0x21 | OPC_SPECIAL3,
445 OPC_SWRE = 0x22 | OPC_SPECIAL3,
446 OPC_PREFE = 0x23 | OPC_SPECIAL3,
447 OPC_LBUE = 0x28 | OPC_SPECIAL3,
448 OPC_LHUE = 0x29 | OPC_SPECIAL3,
449 OPC_LBE = 0x2C | OPC_SPECIAL3,
450 OPC_LHE = 0x2D | OPC_SPECIAL3,
451 OPC_LLE = 0x2E | OPC_SPECIAL3,
452 OPC_LWE = 0x2F | OPC_SPECIAL3,
454 /* R6 */
455 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
456 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
457 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
458 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
459 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
460 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
463 /* BSHFL opcodes */
464 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
466 enum {
467 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
468 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
469 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
470 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
471 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
472 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
473 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
474 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
477 /* DBSHFL opcodes */
478 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
480 enum {
481 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
482 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
483 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
484 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
485 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
486 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
487 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
488 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
489 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
490 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
491 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
494 /* MIPS DSP REGIMM opcodes */
495 enum {
496 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
497 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
500 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
501 /* MIPS DSP Load */
502 enum {
503 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
504 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
505 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
506 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
509 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
510 enum {
511 /* MIPS DSP Arithmetic Sub-class */
512 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
516 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
518 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
522 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
523 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
524 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
525 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
526 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
527 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
529 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
530 /* MIPS DSP Multiply Sub-class insns */
531 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
533 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
534 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
535 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
536 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
539 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
540 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
541 enum {
542 /* MIPS DSP Arithmetic Sub-class */
543 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
547 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
551 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
552 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
553 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
554 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
555 /* MIPS DSP Multiply Sub-class insns */
556 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
557 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
558 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
559 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
562 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
563 enum {
564 /* MIPS DSP Arithmetic Sub-class */
565 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
575 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
578 /* DSP Bit/Manipulation Sub-class */
579 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
580 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
581 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
582 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
583 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
586 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
587 enum {
588 /* MIPS DSP Arithmetic Sub-class */
589 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
596 /* DSP Compare-Pick Sub-class */
597 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
608 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
609 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
610 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
611 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
614 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
615 enum {
616 /* MIPS DSP GPR-Based Shift Sub-class */
617 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
635 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
636 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
637 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
638 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
641 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
642 enum {
643 /* MIPS DSP Multiply Sub-class insns */
644 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
657 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
660 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
662 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
663 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
664 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
665 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
668 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669 enum {
670 /* DSP Bit/Manipulation Sub-class */
671 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
674 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
675 enum {
676 /* MIPS DSP Append Sub-class */
677 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
678 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
679 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
682 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
683 enum {
684 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
685 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
693 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
694 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
695 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
696 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
697 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
698 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
699 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
700 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
701 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
704 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* MIPS DSP Arithmetic Sub-class */
707 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
724 /* DSP Bit/Manipulation Sub-class */
725 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
727 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
728 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
729 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
730 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
733 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
734 enum {
735 /* MIPS DSP Multiply Sub-class insns */
736 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
737 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
738 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
739 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
740 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
741 /* MIPS DSP Arithmetic Sub-class */
742 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
749 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
750 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
751 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
752 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
759 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
760 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
761 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
762 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
765 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
766 enum {
767 /* DSP Compare-Pick Sub-class */
768 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
787 /* MIPS DSP Arithmetic Sub-class */
788 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
792 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
793 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
794 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
795 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
798 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
799 enum {
800 /* DSP Append Sub-class */
801 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
802 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
803 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
804 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
807 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
808 enum {
809 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
810 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
811 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
827 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
828 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
829 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
830 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
833 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
834 enum {
835 /* DSP Bit/Manipulation Sub-class */
836 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
839 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
840 enum {
841 /* MIPS DSP Multiply Sub-class insns */
842 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
864 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
865 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
866 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
867 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
870 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
871 enum {
872 /* MIPS DSP GPR-Based Shift Sub-class */
873 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
895 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
896 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
897 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
898 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
901 /* Coprocessor 0 (rs field) */
902 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
904 enum {
905 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
906 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
907 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
908 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
909 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
910 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
911 OPC_MFTR = (0x08 << 21) | OPC_CP0,
912 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
913 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
914 OPC_MTTR = (0x0C << 21) | OPC_CP0,
915 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
916 OPC_C0 = (0x10 << 21) | OPC_CP0,
917 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
918 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
919 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
920 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
921 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
922 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
923 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
924 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
925 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
926 OPC_C0_A = (0x1A << 21) | OPC_CP0,
927 OPC_C0_B = (0x1B << 21) | OPC_CP0,
928 OPC_C0_C = (0x1C << 21) | OPC_CP0,
929 OPC_C0_D = (0x1D << 21) | OPC_CP0,
930 OPC_C0_E = (0x1E << 21) | OPC_CP0,
931 OPC_C0_F = (0x1F << 21) | OPC_CP0,
934 /* MFMC0 opcodes */
935 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
937 enum {
938 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
939 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
940 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
941 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
942 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
943 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
944 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
945 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
948 /* Coprocessor 0 (with rs == C0) */
949 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
951 enum {
952 OPC_TLBR = 0x01 | OPC_C0,
953 OPC_TLBWI = 0x02 | OPC_C0,
954 OPC_TLBINV = 0x03 | OPC_C0,
955 OPC_TLBINVF = 0x04 | OPC_C0,
956 OPC_TLBWR = 0x06 | OPC_C0,
957 OPC_TLBP = 0x08 | OPC_C0,
958 OPC_RFE = 0x10 | OPC_C0,
959 OPC_ERET = 0x18 | OPC_C0,
960 OPC_DERET = 0x1F | OPC_C0,
961 OPC_WAIT = 0x20 | OPC_C0,
964 /* Coprocessor 1 (rs field) */
965 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
967 /* Values for the fmt field in FP instructions */
968 enum {
969 /* 0 - 15 are reserved */
970 FMT_S = 16, /* single fp */
971 FMT_D = 17, /* double fp */
972 FMT_E = 18, /* extended fp */
973 FMT_Q = 19, /* quad fp */
974 FMT_W = 20, /* 32-bit fixed */
975 FMT_L = 21, /* 64-bit fixed */
976 FMT_PS = 22, /* paired single fp */
977 /* 23 - 31 are reserved */
980 enum {
981 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
982 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
983 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
984 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
985 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
986 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
987 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
988 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
989 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
990 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
991 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
992 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
993 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
994 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
995 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
996 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
997 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
998 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
999 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1000 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1001 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1002 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1003 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1004 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1005 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1006 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1007 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1008 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1009 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1010 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1013 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1014 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1016 enum {
1017 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1018 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1019 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1020 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1023 enum {
1024 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1025 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1028 enum {
1029 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1030 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1033 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1035 enum {
1036 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1037 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1038 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1039 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1040 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1041 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1042 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1043 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1044 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1045 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1046 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1049 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1051 enum {
1052 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1056 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1057 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1058 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1059 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1061 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1065 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1067 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1068 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1070 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1071 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1072 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1073 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1074 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1075 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1076 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1077 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1079 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1080 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1081 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1082 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1083 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1084 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1085 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1086 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1088 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1089 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1090 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1091 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1092 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1093 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1095 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1097 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1098 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1099 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1100 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1102 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1104 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1106 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1107 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1109 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1111 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1112 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1113 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1114 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1116 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1117 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1118 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1119 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1120 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1121 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1123 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1124 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1125 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1126 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1127 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1128 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1130 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1131 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1132 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1133 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1134 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1135 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1137 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1138 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1139 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1140 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1141 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1142 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1146 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1148 enum {
1149 OPC_LWXC1 = 0x00 | OPC_CP3,
1150 OPC_LDXC1 = 0x01 | OPC_CP3,
1151 OPC_LUXC1 = 0x05 | OPC_CP3,
1152 OPC_SWXC1 = 0x08 | OPC_CP3,
1153 OPC_SDXC1 = 0x09 | OPC_CP3,
1154 OPC_SUXC1 = 0x0D | OPC_CP3,
1155 OPC_PREFX = 0x0F | OPC_CP3,
1156 OPC_ALNV_PS = 0x1E | OPC_CP3,
1157 OPC_MADD_S = 0x20 | OPC_CP3,
1158 OPC_MADD_D = 0x21 | OPC_CP3,
1159 OPC_MADD_PS = 0x26 | OPC_CP3,
1160 OPC_MSUB_S = 0x28 | OPC_CP3,
1161 OPC_MSUB_D = 0x29 | OPC_CP3,
1162 OPC_MSUB_PS = 0x2E | OPC_CP3,
1163 OPC_NMADD_S = 0x30 | OPC_CP3,
1164 OPC_NMADD_D = 0x31 | OPC_CP3,
1165 OPC_NMADD_PS = 0x36 | OPC_CP3,
1166 OPC_NMSUB_S = 0x38 | OPC_CP3,
1167 OPC_NMSUB_D = 0x39 | OPC_CP3,
1168 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1171 /* MSA Opcodes */
1172 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1173 enum {
1174 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1175 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1176 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1177 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1178 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1179 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1180 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1181 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1182 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1183 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1184 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1185 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1186 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1187 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1188 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1189 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1190 OPC_MSA_ELM = 0x19 | OPC_MSA,
1191 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1192 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1193 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1194 OPC_MSA_VEC = 0x1E | OPC_MSA,
1196 /* MI10 instruction */
1197 OPC_LD_B = (0x20) | OPC_MSA,
1198 OPC_LD_H = (0x21) | OPC_MSA,
1199 OPC_LD_W = (0x22) | OPC_MSA,
1200 OPC_LD_D = (0x23) | OPC_MSA,
1201 OPC_ST_B = (0x24) | OPC_MSA,
1202 OPC_ST_H = (0x25) | OPC_MSA,
1203 OPC_ST_W = (0x26) | OPC_MSA,
1204 OPC_ST_D = (0x27) | OPC_MSA,
1207 enum {
1208 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1209 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1210 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1211 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1212 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1213 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1214 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1215 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1216 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1217 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1218 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1219 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1220 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1222 /* I8 instruction */
1223 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1224 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1225 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1226 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1227 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1228 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1229 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1230 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1231 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1232 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1234 /* VEC/2R/2RF instruction */
1235 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1236 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1237 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1238 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1239 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1240 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1241 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1243 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1244 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1246 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1247 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1248 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1249 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1250 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1252 /* 2RF instruction df(bit 16) = _w, _d */
1253 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1254 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1255 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1256 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1257 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1258 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1259 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1260 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1261 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1262 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1263 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1264 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1265 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1266 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1267 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1268 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1270 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1271 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1272 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1273 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1274 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1275 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1276 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1277 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1278 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1279 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1280 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1281 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1282 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1283 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1284 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1285 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1286 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1287 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1288 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1289 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1290 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1291 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1292 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1293 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1294 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1295 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1296 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1297 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1298 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1299 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1300 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1301 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1302 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1303 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1304 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1305 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1306 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1307 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1308 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1309 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1310 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1311 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1312 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1313 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1314 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1315 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1316 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1317 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1318 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1319 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1320 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1321 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1322 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1323 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1324 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1325 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1326 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1327 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1328 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1329 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1330 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1331 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1332 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1333 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1335 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1336 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1340 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1341 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1342 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1343 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1344 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1346 /* 3RF instruction _df(bit 21) = _w, _d */
1347 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1348 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1349 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1351 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1353 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1354 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1355 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1356 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1357 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1358 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1360 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1361 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1362 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1363 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1364 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1365 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1366 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1368 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1369 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1371 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1372 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1373 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1374 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1375 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1376 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1377 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1378 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1379 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1380 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1381 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1382 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1383 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1384 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1385 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1386 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1387 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1389 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1390 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1391 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1392 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1393 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1394 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1395 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1396 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1397 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1398 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1399 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1400 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1401 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1407 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1408 * ============================================
1411 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1412 * instructions set. It is designed to fit the needs of signal, graphical and
1413 * video processing applications. MXU instruction set is used in Xburst family
1414 * of microprocessors by Ingenic.
1416 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1417 * the control register.
1420 * The notation used in MXU assembler mnemonics
1421 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1423 * Register operands:
1425 * XRa, XRb, XRc, XRd - MXU registers
1426 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1428 * Non-register operands:
1430 * aptn1 - 1-bit accumulate add/subtract pattern
1431 * aptn2 - 2-bit accumulate add/subtract pattern
1432 * eptn2 - 2-bit execute add/subtract pattern
1433 * optn2 - 2-bit operand pattern
1434 * optn3 - 3-bit operand pattern
1435 * sft4 - 4-bit shift amount
1436 * strd2 - 2-bit stride amount
1438 * Prefixes:
1440 * Level of parallelism: Operand size:
1441 * S - single operation at a time 32 - word
1442 * D - two operations in parallel 16 - half word
1443 * Q - four operations in parallel 8 - byte
1445 * Operations:
1447 * ADD - Add or subtract
1448 * ADDC - Add with carry-in
1449 * ACC - Accumulate
1450 * ASUM - Sum together then accumulate (add or subtract)
1451 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1452 * AVG - Average between 2 operands
1453 * ABD - Absolute difference
1454 * ALN - Align data
1455 * AND - Logical bitwise 'and' operation
1456 * CPS - Copy sign
1457 * EXTR - Extract bits
1458 * I2M - Move from GPR register to MXU register
1459 * LDD - Load data from memory to XRF
1460 * LDI - Load data from memory to XRF (and increase the address base)
1461 * LUI - Load unsigned immediate
1462 * MUL - Multiply
1463 * MULU - Unsigned multiply
1464 * MADD - 64-bit operand add 32x32 product
1465 * MSUB - 64-bit operand subtract 32x32 product
1466 * MAC - Multiply and accumulate (add or subtract)
1467 * MAD - Multiply and add or subtract
1468 * MAX - Maximum between 2 operands
1469 * MIN - Minimum between 2 operands
1470 * M2I - Move from MXU register to GPR register
1471 * MOVZ - Move if zero
1472 * MOVN - Move if non-zero
1473 * NOR - Logical bitwise 'nor' operation
1474 * OR - Logical bitwise 'or' operation
1475 * STD - Store data from XRF to memory
1476 * SDI - Store data from XRF to memory (and increase the address base)
1477 * SLT - Set of less than comparison
1478 * SAD - Sum of absolute differences
1479 * SLL - Logical shift left
1480 * SLR - Logical shift right
1481 * SAR - Arithmetic shift right
1482 * SAT - Saturation
1483 * SFL - Shuffle
1484 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1485 * XOR - Logical bitwise 'exclusive or' operation
1487 * Suffixes:
1489 * E - Expand results
1490 * F - Fixed point multiplication
1491 * L - Low part result
1492 * R - Doing rounding
1493 * V - Variable instead of immediate
1494 * W - Combine above L and V
1497 * The list of MXU instructions grouped by functionality
1498 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1500 * Load/Store instructions Multiplication instructions
1501 * ----------------------- ---------------------------
1503 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1504 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1505 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1506 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1507 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1508 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1509 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1510 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1511 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1512 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1513 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1514 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1515 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1516 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1517 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1518 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1519 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1520 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1521 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1522 * S16SDI XRa, Rb, s10, eptn2
1523 * S8LDD XRa, Rb, s8, eptn3
1524 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1525 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1526 * S8SDI XRa, Rb, s8, eptn3
1527 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1528 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1529 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1530 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1531 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1532 * S32CPS XRa, XRb, XRc
1533 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1534 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1535 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1536 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1537 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1538 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1539 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1540 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1541 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1542 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1543 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1544 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1545 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1546 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1547 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1548 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1549 * Q8SLT XRa, XRb, XRc
1550 * Q8SLTU XRa, XRb, XRc
1551 * Q8MOVZ XRa, XRb, XRc Shift instructions
1552 * Q8MOVN XRa, XRb, XRc ------------------
1554 * D32SLL XRa, XRb, XRc, XRd, sft4
1555 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1556 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1557 * D32SARL XRa, XRb, XRc, sft4
1558 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1559 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1560 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1561 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1562 * Q16SLL XRa, XRb, XRc, XRd, sft4
1563 * Q16SLR XRa, XRb, XRc, XRd, sft4
1564 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1565 * ------------------------- Q16SLLV XRa, XRb, Rb
1566 * Q16SLRV XRa, XRb, Rb
1567 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1568 * S32ALN XRa, XRb, XRc, Rb
1569 * S32ALNI XRa, XRb, XRc, s3
1570 * S32LUI XRa, s8, optn3 Move instructions
1571 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1572 * S32EXTRV XRa, XRb, Rs, Rt
1573 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1574 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1577 * The opcode organization of MXU instructions
1578 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1580 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1581 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1582 * other bits up to the instruction level is as follows:
1584 * bits
1585 * 05..00
1587 * ┌─ 000000 ─ OPC_MXU_S32MADD
1588 * ├─ 000001 ─ OPC_MXU_S32MADDU
1589 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1590 * │
1591 * │ 20..18
1592 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1593 * │ ├─ 001 ─ OPC_MXU_S32MIN
1594 * │ ├─ 010 ─ OPC_MXU_D16MAX
1595 * │ ├─ 011 ─ OPC_MXU_D16MIN
1596 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1597 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1598 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1599 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1600 * ├─ 000100 ─ OPC_MXU_S32MSUB
1601 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1602 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1603 * │ ├─ 001 ─ OPC_MXU_D16SLT
1604 * │ ├─ 010 ─ OPC_MXU_D16AVG
1605 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1606 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1607 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1608 * │ └─ 111 ─ OPC_MXU_Q8ADD
1609 * │
1610 * │ 20..18
1611 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1612 * │ ├─ 010 ─ OPC_MXU_D16CPS
1613 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1614 * │ └─ 110 ─ OPC_MXU_Q16SAT
1615 * ├─ 001000 ─ OPC_MXU_D16MUL
1616 * │ 25..24
1617 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1618 * │ └─ 01 ─ OPC_MXU_D16MULE
1619 * ├─ 001010 ─ OPC_MXU_D16MAC
1620 * ├─ 001011 ─ OPC_MXU_D16MACF
1621 * ├─ 001100 ─ OPC_MXU_D16MADL
1622 * ├─ 001101 ─ OPC_MXU_S16MAD
1623 * ├─ 001110 ─ OPC_MXU_Q16ADD
1624 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1625 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1626 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1627 * │
1628 * │ 23
1629 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1630 * │ └─ 1 ─ OPC_MXU_S32STDR
1631 * │
1632 * │ 13..10
1633 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1634 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1635 * │
1636 * │ 13..10
1637 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1638 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1639 * │
1640 * │ 23
1641 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1642 * │ └─ 1 ─ OPC_MXU_S32LDIR
1643 * │
1644 * │ 23
1645 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1646 * │ └─ 1 ─ OPC_MXU_S32SDIR
1647 * │
1648 * │ 13..10
1649 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1650 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1651 * │
1652 * │ 13..10
1653 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1654 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1655 * ├─ 011000 ─ OPC_MXU_D32ADD
1656 * │ 23..22
1657 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1658 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1659 * │ └─ 10 ─ OPC_MXU_D32ASUM
1660 * ├─ 011010 ─ <not assigned>
1661 * │ 23..22
1662 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1663 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1664 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1665 * │
1666 * │ 23..22
1667 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1668 * │ ├─ 01 ─ OPC_MXU_D8SUM
1669 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1670 * ├─ 011110 ─ <not assigned>
1671 * ├─ 011111 ─ <not assigned>
1672 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1673 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1674 * ├─ 100010 ─ OPC_MXU_S8LDD
1675 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1676 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1677 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1678 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1679 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1680 * │
1681 * │ 20..18
1682 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1683 * │ ├─ 001 ─ OPC_MXU_S32ALN
1684 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1685 * │ ├─ 011 ─ OPC_MXU_S32LUI
1686 * │ ├─ 100 ─ OPC_MXU_S32NOR
1687 * │ ├─ 101 ─ OPC_MXU_S32AND
1688 * │ ├─ 110 ─ OPC_MXU_S32OR
1689 * │ └─ 111 ─ OPC_MXU_S32XOR
1690 * │
1691 * │ 7..5
1692 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1693 * │ ├─ 001 ─ OPC_MXU_LXH
1694 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1695 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1696 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1697 * ├─ 101100 ─ OPC_MXU_S16LDI
1698 * ├─ 101101 ─ OPC_MXU_S16SDI
1699 * ├─ 101110 ─ OPC_MXU_S32M2I
1700 * ├─ 101111 ─ OPC_MXU_S32I2M
1701 * ├─ 110000 ─ OPC_MXU_D32SLL
1702 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1703 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1704 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1705 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1706 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1707 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1708 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1709 * │
1710 * ├─ 110111 ─ OPC_MXU_Q16SAR
1711 * │ 23..22
1712 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1713 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1714 * │
1715 * │ 20..18
1716 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1717 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1718 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1719 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1720 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1721 * │ └─ 101 ─ OPC_MXU_S32MOVN
1722 * │
1723 * │ 23..22
1724 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1725 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1726 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1727 * ├─ 111100 ─ OPC_MXU_Q8MADL
1728 * ├─ 111101 ─ OPC_MXU_S32SFL
1729 * ├─ 111110 ─ OPC_MXU_Q8SAD
1730 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1733 * Compiled after:
1735 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1736 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1739 enum {
1740 OPC_MXU_S32MADD = 0x00,
1741 OPC_MXU_S32MADDU = 0x01,
1742 OPC__MXU_MUL = 0x02,
1743 OPC_MXU__POOL00 = 0x03,
1744 OPC_MXU_S32MSUB = 0x04,
1745 OPC_MXU_S32MSUBU = 0x05,
1746 OPC_MXU__POOL01 = 0x06,
1747 OPC_MXU__POOL02 = 0x07,
1748 OPC_MXU_D16MUL = 0x08,
1749 OPC_MXU__POOL03 = 0x09,
1750 OPC_MXU_D16MAC = 0x0A,
1751 OPC_MXU_D16MACF = 0x0B,
1752 OPC_MXU_D16MADL = 0x0C,
1753 OPC_MXU_S16MAD = 0x0D,
1754 OPC_MXU_Q16ADD = 0x0E,
1755 OPC_MXU_D16MACE = 0x0F,
1756 OPC_MXU__POOL04 = 0x10,
1757 OPC_MXU__POOL05 = 0x11,
1758 OPC_MXU__POOL06 = 0x12,
1759 OPC_MXU__POOL07 = 0x13,
1760 OPC_MXU__POOL08 = 0x14,
1761 OPC_MXU__POOL09 = 0x15,
1762 OPC_MXU__POOL10 = 0x16,
1763 OPC_MXU__POOL11 = 0x17,
1764 OPC_MXU_D32ADD = 0x18,
1765 OPC_MXU__POOL12 = 0x19,
1766 /* not assigned 0x1A */
1767 OPC_MXU__POOL13 = 0x1B,
1768 OPC_MXU__POOL14 = 0x1C,
1769 OPC_MXU_Q8ACCE = 0x1D,
1770 /* not assigned 0x1E */
1771 /* not assigned 0x1F */
1772 /* not assigned 0x20 */
1773 /* not assigned 0x21 */
1774 OPC_MXU_S8LDD = 0x22,
1775 OPC_MXU_S8STD = 0x23,
1776 OPC_MXU_S8LDI = 0x24,
1777 OPC_MXU_S8SDI = 0x25,
1778 OPC_MXU__POOL15 = 0x26,
1779 OPC_MXU__POOL16 = 0x27,
1780 OPC_MXU__POOL17 = 0x28,
1781 /* not assigned 0x29 */
1782 OPC_MXU_S16LDD = 0x2A,
1783 OPC_MXU_S16STD = 0x2B,
1784 OPC_MXU_S16LDI = 0x2C,
1785 OPC_MXU_S16SDI = 0x2D,
1786 OPC_MXU_S32M2I = 0x2E,
1787 OPC_MXU_S32I2M = 0x2F,
1788 OPC_MXU_D32SLL = 0x30,
1789 OPC_MXU_D32SLR = 0x31,
1790 OPC_MXU_D32SARL = 0x32,
1791 OPC_MXU_D32SAR = 0x33,
1792 OPC_MXU_Q16SLL = 0x34,
1793 OPC_MXU_Q16SLR = 0x35,
1794 OPC_MXU__POOL18 = 0x36,
1795 OPC_MXU_Q16SAR = 0x37,
1796 OPC_MXU__POOL19 = 0x38,
1797 OPC_MXU__POOL20 = 0x39,
1798 OPC_MXU__POOL21 = 0x3A,
1799 OPC_MXU_Q16SCOP = 0x3B,
1800 OPC_MXU_Q8MADL = 0x3C,
1801 OPC_MXU_S32SFL = 0x3D,
1802 OPC_MXU_Q8SAD = 0x3E,
1803 /* not assigned 0x3F */
1808 * MXU pool 00
1810 enum {
1811 OPC_MXU_S32MAX = 0x00,
1812 OPC_MXU_S32MIN = 0x01,
1813 OPC_MXU_D16MAX = 0x02,
1814 OPC_MXU_D16MIN = 0x03,
1815 OPC_MXU_Q8MAX = 0x04,
1816 OPC_MXU_Q8MIN = 0x05,
1817 OPC_MXU_Q8SLT = 0x06,
1818 OPC_MXU_Q8SLTU = 0x07,
1822 * MXU pool 01
1824 enum {
1825 OPC_MXU_S32SLT = 0x00,
1826 OPC_MXU_D16SLT = 0x01,
1827 OPC_MXU_D16AVG = 0x02,
1828 OPC_MXU_D16AVGR = 0x03,
1829 OPC_MXU_Q8AVG = 0x04,
1830 OPC_MXU_Q8AVGR = 0x05,
1831 OPC_MXU_Q8ADD = 0x07,
1835 * MXU pool 02
1837 enum {
1838 OPC_MXU_S32CPS = 0x00,
1839 OPC_MXU_D16CPS = 0x02,
1840 OPC_MXU_Q8ABD = 0x04,
1841 OPC_MXU_Q16SAT = 0x06,
1845 * MXU pool 03
1847 enum {
1848 OPC_MXU_D16MULF = 0x00,
1849 OPC_MXU_D16MULE = 0x01,
1853 * MXU pool 04
1855 enum {
1856 OPC_MXU_S32LDD = 0x00,
1857 OPC_MXU_S32LDDR = 0x01,
1861 * MXU pool 05
1863 enum {
1864 OPC_MXU_S32STD = 0x00,
1865 OPC_MXU_S32STDR = 0x01,
1869 * MXU pool 06
1871 enum {
1872 OPC_MXU_S32LDDV = 0x00,
1873 OPC_MXU_S32LDDVR = 0x01,
1877 * MXU pool 07
1879 enum {
1880 OPC_MXU_S32STDV = 0x00,
1881 OPC_MXU_S32STDVR = 0x01,
1885 * MXU pool 08
1887 enum {
1888 OPC_MXU_S32LDI = 0x00,
1889 OPC_MXU_S32LDIR = 0x01,
1893 * MXU pool 09
1895 enum {
1896 OPC_MXU_S32SDI = 0x00,
1897 OPC_MXU_S32SDIR = 0x01,
1901 * MXU pool 10
1903 enum {
1904 OPC_MXU_S32LDIV = 0x00,
1905 OPC_MXU_S32LDIVR = 0x01,
1909 * MXU pool 11
1911 enum {
1912 OPC_MXU_S32SDIV = 0x00,
1913 OPC_MXU_S32SDIVR = 0x01,
1917 * MXU pool 12
1919 enum {
1920 OPC_MXU_D32ACC = 0x00,
1921 OPC_MXU_D32ACCM = 0x01,
1922 OPC_MXU_D32ASUM = 0x02,
1926 * MXU pool 13
1928 enum {
1929 OPC_MXU_Q16ACC = 0x00,
1930 OPC_MXU_Q16ACCM = 0x01,
1931 OPC_MXU_Q16ASUM = 0x02,
1935 * MXU pool 14
1937 enum {
1938 OPC_MXU_Q8ADDE = 0x00,
1939 OPC_MXU_D8SUM = 0x01,
1940 OPC_MXU_D8SUMC = 0x02,
1944 * MXU pool 15
1946 enum {
1947 OPC_MXU_S32MUL = 0x00,
1948 OPC_MXU_S32MULU = 0x01,
1949 OPC_MXU_S32EXTR = 0x02,
1950 OPC_MXU_S32EXTRV = 0x03,
1954 * MXU pool 16
1956 enum {
1957 OPC_MXU_D32SARW = 0x00,
1958 OPC_MXU_S32ALN = 0x01,
1959 OPC_MXU_S32ALNI = 0x02,
1960 OPC_MXU_S32LUI = 0x03,
1961 OPC_MXU_S32NOR = 0x04,
1962 OPC_MXU_S32AND = 0x05,
1963 OPC_MXU_S32OR = 0x06,
1964 OPC_MXU_S32XOR = 0x07,
1968 * MXU pool 17
1970 enum {
1971 OPC_MXU_LXB = 0x00,
1972 OPC_MXU_LXH = 0x01,
1973 OPC_MXU_LXW = 0x03,
1974 OPC_MXU_LXBU = 0x04,
1975 OPC_MXU_LXHU = 0x05,
1979 * MXU pool 18
1981 enum {
1982 OPC_MXU_D32SLLV = 0x00,
1983 OPC_MXU_D32SLRV = 0x01,
1984 OPC_MXU_D32SARV = 0x03,
1985 OPC_MXU_Q16SLLV = 0x04,
1986 OPC_MXU_Q16SLRV = 0x05,
1987 OPC_MXU_Q16SARV = 0x07,
1991 * MXU pool 19
1993 enum {
1994 OPC_MXU_Q8MUL = 0x00,
1995 OPC_MXU_Q8MULSU = 0x01,
1999 * MXU pool 20
2001 enum {
2002 OPC_MXU_Q8MOVZ = 0x00,
2003 OPC_MXU_Q8MOVN = 0x01,
2004 OPC_MXU_D16MOVZ = 0x02,
2005 OPC_MXU_D16MOVN = 0x03,
2006 OPC_MXU_S32MOVZ = 0x04,
2007 OPC_MXU_S32MOVN = 0x05,
2011 * MXU pool 21
2013 enum {
2014 OPC_MXU_Q8MAC = 0x00,
2015 OPC_MXU_Q8MACSU = 0x01,
2019 * Overview of the TX79-specific instruction set
2020 * =============================================
2022 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2023 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2024 * instructions and certain multimedia instructions (MMIs). These MMIs
2025 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2026 * or sixteen 8-bit paths.
2028 * Reference:
2030 * The Toshiba TX System RISC TX79 Core Architecture manual,
2031 * https://wiki.qemu.org/File:C790.pdf
2033 * Three-Operand Multiply and Multiply-Add (4 instructions)
2034 * --------------------------------------------------------
2035 * MADD [rd,] rs, rt Multiply/Add
2036 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2037 * MULT [rd,] rs, rt Multiply (3-operand)
2038 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2040 * Multiply Instructions for Pipeline 1 (10 instructions)
2041 * ------------------------------------------------------
2042 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2043 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2044 * DIV1 rs, rt Divide Pipeline 1
2045 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2046 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2047 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2048 * MFHI1 rd Move From HI1 Register
2049 * MFLO1 rd Move From LO1 Register
2050 * MTHI1 rs Move To HI1 Register
2051 * MTLO1 rs Move To LO1 Register
2053 * Arithmetic (19 instructions)
2054 * ----------------------------
2055 * PADDB rd, rs, rt Parallel Add Byte
2056 * PSUBB rd, rs, rt Parallel Subtract Byte
2057 * PADDH rd, rs, rt Parallel Add Halfword
2058 * PSUBH rd, rs, rt Parallel Subtract Halfword
2059 * PADDW rd, rs, rt Parallel Add Word
2060 * PSUBW rd, rs, rt Parallel Subtract Word
2061 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2062 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2063 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2064 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2065 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2066 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2067 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2068 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2069 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2070 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2071 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2072 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2073 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2075 * Min/Max (4 instructions)
2076 * ------------------------
2077 * PMAXH rd, rs, rt Parallel Maximum Halfword
2078 * PMINH rd, rs, rt Parallel Minimum Halfword
2079 * PMAXW rd, rs, rt Parallel Maximum Word
2080 * PMINW rd, rs, rt Parallel Minimum Word
2082 * Absolute (2 instructions)
2083 * -------------------------
2084 * PABSH rd, rt Parallel Absolute Halfword
2085 * PABSW rd, rt Parallel Absolute Word
2087 * Logical (4 instructions)
2088 * ------------------------
2089 * PAND rd, rs, rt Parallel AND
2090 * POR rd, rs, rt Parallel OR
2091 * PXOR rd, rs, rt Parallel XOR
2092 * PNOR rd, rs, rt Parallel NOR
2094 * Shift (9 instructions)
2095 * ----------------------
2096 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2097 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2098 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2099 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2100 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2101 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2102 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2103 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2104 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2106 * Compare (6 instructions)
2107 * ------------------------
2108 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2109 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2110 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2111 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2112 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2113 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2115 * LZC (1 instruction)
2116 * -------------------
2117 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2119 * Quadword Load and Store (2 instructions)
2120 * ----------------------------------------
2121 * LQ rt, offset(base) Load Quadword
2122 * SQ rt, offset(base) Store Quadword
2124 * Multiply and Divide (19 instructions)
2125 * -------------------------------------
2126 * PMULTW rd, rs, rt Parallel Multiply Word
2127 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2128 * PDIVW rs, rt Parallel Divide Word
2129 * PDIVUW rs, rt Parallel Divide Unsigned Word
2130 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2131 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2132 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2133 * PMULTH rd, rs, rt Parallel Multiply Halfword
2134 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2135 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2136 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2137 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2138 * PDIVBW rs, rt Parallel Divide Broadcast Word
2139 * PMFHI rd Parallel Move From HI Register
2140 * PMFLO rd Parallel Move From LO Register
2141 * PMTHI rs Parallel Move To HI Register
2142 * PMTLO rs Parallel Move To LO Register
2143 * PMFHL rd Parallel Move From HI/LO Register
2144 * PMTHL rs Parallel Move To HI/LO Register
2146 * Pack/Extend (11 instructions)
2147 * -----------------------------
2148 * PPAC5 rd, rt Parallel Pack to 5 bits
2149 * PPACB rd, rs, rt Parallel Pack to Byte
2150 * PPACH rd, rs, rt Parallel Pack to Halfword
2151 * PPACW rd, rs, rt Parallel Pack to Word
2152 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2153 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2154 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2155 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2156 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2157 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2158 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2160 * Others (16 instructions)
2161 * ------------------------
2162 * PCPYH rd, rt Parallel Copy Halfword
2163 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2164 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2165 * PREVH rd, rt Parallel Reverse Halfword
2166 * PINTH rd, rs, rt Parallel Interleave Halfword
2167 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2168 * PEXEH rd, rt Parallel Exchange Even Halfword
2169 * PEXCH rd, rt Parallel Exchange Center Halfword
2170 * PEXEW rd, rt Parallel Exchange Even Word
2171 * PEXCW rd, rt Parallel Exchange Center Word
2172 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2173 * MFSA rd Move from Shift Amount Register
2174 * MTSA rs Move to Shift Amount Register
2175 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2176 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2177 * PROT3W rd, rt Parallel Rotate 3 Words
2179 * MMI (MultiMedia Instruction) encodings
2180 * ======================================
2182 * MMI instructions encoding table keys:
2184 * * This code is reserved for future use. An attempt to execute it
2185 * causes a Reserved Instruction exception.
2186 * % This code indicates an instruction class. The instruction word
2187 * must be further decoded by examining additional tables that show
2188 * the values for other instruction fields.
2189 * # This code is reserved for the unsupported instructions DMULT,
2190 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2191 * to execute it causes a Reserved Instruction exception.
2193 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2195 * 31 26 0
2196 * +--------+----------------------------------------+
2197 * | opcode | |
2198 * +--------+----------------------------------------+
2200 * opcode bits 28..26
2201 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2202 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2203 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2204 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2205 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2206 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2207 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2208 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2209 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2210 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2211 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2214 enum {
2215 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2216 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2217 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2221 * MMI instructions with opcode field = MMI:
2223 * 31 26 5 0
2224 * +--------+-------------------------------+--------+
2225 * | MMI | |function|
2226 * +--------+-------------------------------+--------+
2228 * function bits 2..0
2229 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2230 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2231 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2232 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2233 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2234 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2235 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2236 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2237 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2238 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2239 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2242 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2243 enum {
2244 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2245 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2246 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2247 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2248 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2249 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2250 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2251 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2252 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2253 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2254 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2255 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2256 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2257 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2258 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2259 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2260 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2261 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2262 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2263 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2264 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2265 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2266 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2267 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2268 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2272 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2274 * 31 26 10 6 5 0
2275 * +--------+----------------------+--------+--------+
2276 * | MMI | |function| MMI0 |
2277 * +--------+----------------------+--------+--------+
2279 * function bits 7..6
2280 * bits | 0 | 1 | 2 | 3
2281 * 10..8 | 00 | 01 | 10 | 11
2282 * -------+-------+-------+-------+-------
2283 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2284 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2285 * 2 010 | PADDB | PSUBB | PCGTB | *
2286 * 3 011 | * | * | * | *
2287 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2288 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2289 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2290 * 7 111 | * | * | PEXT5 | PPAC5
2293 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2294 enum {
2295 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2296 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2297 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2298 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2299 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2300 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2301 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2302 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2303 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2304 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2305 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2306 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2307 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2308 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2309 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2310 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2311 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2312 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2313 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2314 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2315 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2316 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2317 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2318 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2319 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2323 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2325 * 31 26 10 6 5 0
2326 * +--------+----------------------+--------+--------+
2327 * | MMI | |function| MMI1 |
2328 * +--------+----------------------+--------+--------+
2330 * function bits 7..6
2331 * bits | 0 | 1 | 2 | 3
2332 * 10..8 | 00 | 01 | 10 | 11
2333 * -------+-------+-------+-------+-------
2334 * 0 000 | * | PABSW | PCEQW | PMINW
2335 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2336 * 2 010 | * | * | PCEQB | *
2337 * 3 011 | * | * | * | *
2338 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2339 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2340 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2341 * 7 111 | * | * | * | *
2344 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2345 enum {
2346 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2347 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2348 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2349 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2350 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2351 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2352 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2353 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2354 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2355 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2356 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2357 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2358 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2359 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2360 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2361 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2362 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2363 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2367 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2369 * 31 26 10 6 5 0
2370 * +--------+----------------------+--------+--------+
2371 * | MMI | |function| MMI2 |
2372 * +--------+----------------------+--------+--------+
2374 * function bits 7..6
2375 * bits | 0 | 1 | 2 | 3
2376 * 10..8 | 00 | 01 | 10 | 11
2377 * -------+-------+-------+-------+-------
2378 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2379 * 1 001 | PMSUBW| * | * | *
2380 * 2 010 | PMFHI | PMFLO | PINTH | *
2381 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2382 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2383 * 5 101 | PMSUBH| PHMSBH| * | *
2384 * 6 110 | * | * | PEXEH | PREVH
2385 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2388 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2389 enum {
2390 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2391 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2392 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2393 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2394 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2395 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2396 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2397 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2398 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2399 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2400 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2401 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2402 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2403 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2404 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2405 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2406 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2407 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2408 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2409 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2410 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2411 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2415 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2417 * 31 26 10 6 5 0
2418 * +--------+----------------------+--------+--------+
2419 * | MMI | |function| MMI3 |
2420 * +--------+----------------------+--------+--------+
2422 * function bits 7..6
2423 * bits | 0 | 1 | 2 | 3
2424 * 10..8 | 00 | 01 | 10 | 11
2425 * -------+-------+-------+-------+-------
2426 * 0 000 |PMADDUW| * | * | PSRAVW
2427 * 1 001 | * | * | * | *
2428 * 2 010 | PMTHI | PMTLO | PINTEH| *
2429 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2430 * 4 100 | * | * | POR | PNOR
2431 * 5 101 | * | * | * | *
2432 * 6 110 | * | * | PEXCH | PCPYH
2433 * 7 111 | * | * | PEXCW | *
2436 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2437 enum {
2438 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2439 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2440 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2441 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2442 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2443 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2444 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2445 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2446 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2447 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2448 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2449 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2450 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2453 /* global register indices */
2454 static TCGv cpu_gpr[32], cpu_PC;
2455 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2456 static TCGv cpu_dspctrl, btarget, bcond;
2457 static TCGv cpu_lladdr, cpu_llval;
2458 static TCGv_i32 hflags;
2459 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2460 static TCGv_i64 fpu_f64[32];
2461 static TCGv_i64 msa_wr_d[64];
2463 #if defined(TARGET_MIPS64)
2464 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2465 static TCGv_i64 cpu_mmr[32];
2466 #endif
2468 #if !defined(TARGET_MIPS64)
2469 /* MXU registers */
2470 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2471 static TCGv mxu_CR;
2472 #endif
2474 #include "exec/gen-icount.h"
2476 #define gen_helper_0e0i(name, arg) do { \
2477 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2478 gen_helper_##name(cpu_env, helper_tmp); \
2479 tcg_temp_free_i32(helper_tmp); \
2480 } while (0)
2482 #define gen_helper_0e1i(name, arg1, arg2) do { \
2483 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2484 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2485 tcg_temp_free_i32(helper_tmp); \
2486 } while (0)
2488 #define gen_helper_1e0i(name, ret, arg1) do { \
2489 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2490 gen_helper_##name(ret, cpu_env, helper_tmp); \
2491 tcg_temp_free_i32(helper_tmp); \
2492 } while (0)
2494 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2495 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2496 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2497 tcg_temp_free_i32(helper_tmp); \
2498 } while (0)
2500 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2501 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2502 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2503 tcg_temp_free_i32(helper_tmp); \
2504 } while (0)
2506 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2507 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2508 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2509 tcg_temp_free_i32(helper_tmp); \
2510 } while (0)
2512 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2513 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2514 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2515 tcg_temp_free_i32(helper_tmp); \
2516 } while (0)
2518 typedef struct DisasContext {
2519 DisasContextBase base;
2520 target_ulong saved_pc;
2521 target_ulong page_start;
2522 uint32_t opcode;
2523 uint64_t insn_flags;
2524 int32_t CP0_Config1;
2525 int32_t CP0_Config2;
2526 int32_t CP0_Config3;
2527 int32_t CP0_Config5;
2528 /* Routine used to access memory */
2529 int mem_idx;
2530 MemOp default_tcg_memop_mask;
2531 uint32_t hflags, saved_hflags;
2532 target_ulong btarget;
2533 bool ulri;
2534 int kscrexist;
2535 bool rxi;
2536 int ie;
2537 bool bi;
2538 bool bp;
2539 uint64_t PAMask;
2540 bool mvh;
2541 bool eva;
2542 bool sc;
2543 int CP0_LLAddr_shift;
2544 bool ps;
2545 bool vp;
2546 bool cmgcr;
2547 bool mrp;
2548 bool nan2008;
2549 bool abs2008;
2550 bool saar;
2551 bool mi;
2552 int gi;
2553 } DisasContext;
2555 #define DISAS_STOP DISAS_TARGET_0
2556 #define DISAS_EXIT DISAS_TARGET_1
2558 static const char * const regnames[] = {
2559 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2560 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2561 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2562 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2565 static const char * const regnames_HI[] = {
2566 "HI0", "HI1", "HI2", "HI3",
2569 static const char * const regnames_LO[] = {
2570 "LO0", "LO1", "LO2", "LO3",
2573 static const char * const fregnames[] = {
2574 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2575 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2576 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2577 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2580 static const char * const msaregnames[] = {
2581 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2582 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2583 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2584 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2585 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2586 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2587 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2588 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2589 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2590 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2591 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2592 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2593 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2594 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2595 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2596 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2599 #if !defined(TARGET_MIPS64)
2600 static const char * const mxuregnames[] = {
2601 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2602 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2604 #endif
2606 #define LOG_DISAS(...) \
2607 do { \
2608 if (MIPS_DEBUG_DISAS) { \
2609 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2611 } while (0)
2613 #define MIPS_INVAL(op) \
2614 do { \
2615 if (MIPS_DEBUG_DISAS) { \
2616 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2617 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2618 ctx->base.pc_next, ctx->opcode, op, \
2619 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2620 ((ctx->opcode >> 16) & 0x1F)); \
2622 } while (0)
2624 /* General purpose registers moves. */
2625 static inline void gen_load_gpr(TCGv t, int reg)
2627 if (reg == 0) {
2628 tcg_gen_movi_tl(t, 0);
2629 } else {
2630 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2634 static inline void gen_store_gpr(TCGv t, int reg)
2636 if (reg != 0) {
2637 tcg_gen_mov_tl(cpu_gpr[reg], t);
2641 /* Moves to/from shadow registers. */
2642 static inline void gen_load_srsgpr(int from, int to)
2644 TCGv t0 = tcg_temp_new();
2646 if (from == 0) {
2647 tcg_gen_movi_tl(t0, 0);
2648 } else {
2649 TCGv_i32 t2 = tcg_temp_new_i32();
2650 TCGv_ptr addr = tcg_temp_new_ptr();
2652 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2653 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2654 tcg_gen_andi_i32(t2, t2, 0xf);
2655 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2656 tcg_gen_ext_i32_ptr(addr, t2);
2657 tcg_gen_add_ptr(addr, cpu_env, addr);
2659 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2660 tcg_temp_free_ptr(addr);
2661 tcg_temp_free_i32(t2);
2663 gen_store_gpr(t0, to);
2664 tcg_temp_free(t0);
2667 static inline void gen_store_srsgpr(int from, int to)
2669 if (to != 0) {
2670 TCGv t0 = tcg_temp_new();
2671 TCGv_i32 t2 = tcg_temp_new_i32();
2672 TCGv_ptr addr = tcg_temp_new_ptr();
2674 gen_load_gpr(t0, from);
2675 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2676 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2677 tcg_gen_andi_i32(t2, t2, 0xf);
2678 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2679 tcg_gen_ext_i32_ptr(addr, t2);
2680 tcg_gen_add_ptr(addr, cpu_env, addr);
2682 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2683 tcg_temp_free_ptr(addr);
2684 tcg_temp_free_i32(t2);
2685 tcg_temp_free(t0);
2689 #if !defined(TARGET_MIPS64)
2690 /* MXU General purpose registers moves. */
2691 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2693 if (reg == 0) {
2694 tcg_gen_movi_tl(t, 0);
2695 } else if (reg <= 15) {
2696 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2700 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2702 if (reg > 0 && reg <= 15) {
2703 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2707 /* MXU control register moves. */
2708 static inline void gen_load_mxu_cr(TCGv t)
2710 tcg_gen_mov_tl(t, mxu_CR);
2713 static inline void gen_store_mxu_cr(TCGv t)
2715 /* TODO: Add handling of RW rules for MXU_CR. */
2716 tcg_gen_mov_tl(mxu_CR, t);
2718 #endif
2721 /* Tests */
2722 static inline void gen_save_pc(target_ulong pc)
2724 tcg_gen_movi_tl(cpu_PC, pc);
2727 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2729 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2730 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2731 gen_save_pc(ctx->base.pc_next);
2732 ctx->saved_pc = ctx->base.pc_next;
2734 if (ctx->hflags != ctx->saved_hflags) {
2735 tcg_gen_movi_i32(hflags, ctx->hflags);
2736 ctx->saved_hflags = ctx->hflags;
2737 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2738 case MIPS_HFLAG_BR:
2739 break;
2740 case MIPS_HFLAG_BC:
2741 case MIPS_HFLAG_BL:
2742 case MIPS_HFLAG_B:
2743 tcg_gen_movi_tl(btarget, ctx->btarget);
2744 break;
2749 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2751 ctx->saved_hflags = ctx->hflags;
2752 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2753 case MIPS_HFLAG_BR:
2754 break;
2755 case MIPS_HFLAG_BC:
2756 case MIPS_HFLAG_BL:
2757 case MIPS_HFLAG_B:
2758 ctx->btarget = env->btarget;
2759 break;
2763 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2765 TCGv_i32 texcp = tcg_const_i32(excp);
2766 TCGv_i32 terr = tcg_const_i32(err);
2767 save_cpu_state(ctx, 1);
2768 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2769 tcg_temp_free_i32(terr);
2770 tcg_temp_free_i32(texcp);
2771 ctx->base.is_jmp = DISAS_NORETURN;
2774 static inline void generate_exception(DisasContext *ctx, int excp)
2776 gen_helper_0e0i(raise_exception, excp);
2779 static inline void generate_exception_end(DisasContext *ctx, int excp)
2781 generate_exception_err(ctx, excp, 0);
2784 /* Floating point register moves. */
2785 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2787 if (ctx->hflags & MIPS_HFLAG_FRE) {
2788 generate_exception(ctx, EXCP_RI);
2790 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2793 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2795 TCGv_i64 t64;
2796 if (ctx->hflags & MIPS_HFLAG_FRE) {
2797 generate_exception(ctx, EXCP_RI);
2799 t64 = tcg_temp_new_i64();
2800 tcg_gen_extu_i32_i64(t64, t);
2801 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2802 tcg_temp_free_i64(t64);
2805 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2807 if (ctx->hflags & MIPS_HFLAG_F64) {
2808 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2809 } else {
2810 gen_load_fpr32(ctx, t, reg | 1);
2814 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2816 if (ctx->hflags & MIPS_HFLAG_F64) {
2817 TCGv_i64 t64 = tcg_temp_new_i64();
2818 tcg_gen_extu_i32_i64(t64, t);
2819 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2820 tcg_temp_free_i64(t64);
2821 } else {
2822 gen_store_fpr32(ctx, t, reg | 1);
2826 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2828 if (ctx->hflags & MIPS_HFLAG_F64) {
2829 tcg_gen_mov_i64(t, fpu_f64[reg]);
2830 } else {
2831 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2835 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2837 if (ctx->hflags & MIPS_HFLAG_F64) {
2838 tcg_gen_mov_i64(fpu_f64[reg], t);
2839 } else {
2840 TCGv_i64 t0;
2841 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2842 t0 = tcg_temp_new_i64();
2843 tcg_gen_shri_i64(t0, t, 32);
2844 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2845 tcg_temp_free_i64(t0);
2849 static inline int get_fp_bit(int cc)
2851 if (cc) {
2852 return 24 + cc;
2853 } else {
2854 return 23;
2858 /* Addresses computation */
2859 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2860 TCGv arg1)
2862 tcg_gen_add_tl(ret, arg0, arg1);
2864 #if defined(TARGET_MIPS64)
2865 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2866 tcg_gen_ext32s_i64(ret, ret);
2868 #endif
2871 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2872 target_long ofs)
2874 tcg_gen_addi_tl(ret, base, ofs);
2876 #if defined(TARGET_MIPS64)
2877 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2878 tcg_gen_ext32s_i64(ret, ret);
2880 #endif
2883 /* Addresses computation (translation time) */
2884 static target_long addr_add(DisasContext *ctx, target_long base,
2885 target_long offset)
2887 target_long sum = base + offset;
2889 #if defined(TARGET_MIPS64)
2890 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2891 sum = (int32_t)sum;
2893 #endif
2894 return sum;
2897 /* Sign-extract the low 32-bits to a target_long. */
2898 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2900 #if defined(TARGET_MIPS64)
2901 tcg_gen_ext32s_i64(ret, arg);
2902 #else
2903 tcg_gen_extrl_i64_i32(ret, arg);
2904 #endif
2907 /* Sign-extract the high 32-bits to a target_long. */
2908 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2910 #if defined(TARGET_MIPS64)
2911 tcg_gen_sari_i64(ret, arg, 32);
2912 #else
2913 tcg_gen_extrh_i64_i32(ret, arg);
2914 #endif
2917 static inline void check_cp0_enabled(DisasContext *ctx)
2919 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2920 generate_exception_err(ctx, EXCP_CpU, 0);
2924 static inline void check_cp1_enabled(DisasContext *ctx)
2926 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2927 generate_exception_err(ctx, EXCP_CpU, 1);
2932 * Verify that the processor is running with COP1X instructions enabled.
2933 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2934 * opcode tables.
2936 static inline void check_cop1x(DisasContext *ctx)
2938 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2939 generate_exception_end(ctx, EXCP_RI);
2944 * Verify that the processor is running with 64-bit floating-point
2945 * operations enabled.
2947 static inline void check_cp1_64bitmode(DisasContext *ctx)
2949 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2950 generate_exception_end(ctx, EXCP_RI);
2955 * Verify if floating point register is valid; an operation is not defined
2956 * if bit 0 of any register specification is set and the FR bit in the
2957 * Status register equals zero, since the register numbers specify an
2958 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2959 * in the Status register equals one, both even and odd register numbers
2960 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2962 * Multiple 64 bit wide registers can be checked by calling
2963 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2965 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2967 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2968 generate_exception_end(ctx, EXCP_RI);
2973 * Verify that the processor is running with DSP instructions enabled.
2974 * This is enabled by CP0 Status register MX(24) bit.
2976 static inline void check_dsp(DisasContext *ctx)
2978 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2979 if (ctx->insn_flags & ASE_DSP) {
2980 generate_exception_end(ctx, EXCP_DSPDIS);
2981 } else {
2982 generate_exception_end(ctx, EXCP_RI);
2987 static inline void check_dsp_r2(DisasContext *ctx)
2989 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2990 if (ctx->insn_flags & ASE_DSP) {
2991 generate_exception_end(ctx, EXCP_DSPDIS);
2992 } else {
2993 generate_exception_end(ctx, EXCP_RI);
2998 static inline void check_dsp_r3(DisasContext *ctx)
3000 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
3001 if (ctx->insn_flags & ASE_DSP) {
3002 generate_exception_end(ctx, EXCP_DSPDIS);
3003 } else {
3004 generate_exception_end(ctx, EXCP_RI);
3010 * This code generates a "reserved instruction" exception if the
3011 * CPU does not support the instruction set corresponding to flags.
3013 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3015 if (unlikely(!(ctx->insn_flags & flags))) {
3016 generate_exception_end(ctx, EXCP_RI);
3021 * This code generates a "reserved instruction" exception if the
3022 * CPU has corresponding flag set which indicates that the instruction
3023 * has been removed.
3025 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3027 if (unlikely(ctx->insn_flags & flags)) {
3028 generate_exception_end(ctx, EXCP_RI);
3033 * The Linux kernel traps certain reserved instruction exceptions to
3034 * emulate the corresponding instructions. QEMU is the kernel in user
3035 * mode, so those traps are emulated by accepting the instructions.
3037 * A reserved instruction exception is generated for flagged CPUs if
3038 * QEMU runs in system mode.
3040 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3042 #ifndef CONFIG_USER_ONLY
3043 check_insn_opc_removed(ctx, flags);
3044 #endif
3048 * This code generates a "reserved instruction" exception if the
3049 * CPU does not support 64-bit paired-single (PS) floating point data type.
3051 static inline void check_ps(DisasContext *ctx)
3053 if (unlikely(!ctx->ps)) {
3054 generate_exception(ctx, EXCP_RI);
3056 check_cp1_64bitmode(ctx);
3059 #ifdef TARGET_MIPS64
3061 * This code generates a "reserved instruction" exception if 64-bit
3062 * instructions are not enabled.
3064 static inline void check_mips_64(DisasContext *ctx)
3066 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3067 generate_exception_end(ctx, EXCP_RI);
3070 #endif
3072 #ifndef CONFIG_USER_ONLY
3073 static inline void check_mvh(DisasContext *ctx)
3075 if (unlikely(!ctx->mvh)) {
3076 generate_exception(ctx, EXCP_RI);
3079 #endif
3082 * This code generates a "reserved instruction" exception if the
3083 * Config5 XNP bit is set.
3085 static inline void check_xnp(DisasContext *ctx)
3087 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3088 generate_exception_end(ctx, EXCP_RI);
3092 #ifndef CONFIG_USER_ONLY
3094 * This code generates a "reserved instruction" exception if the
3095 * Config3 PW bit is NOT set.
3097 static inline void check_pw(DisasContext *ctx)
3099 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3100 generate_exception_end(ctx, EXCP_RI);
3103 #endif
3106 * This code generates a "reserved instruction" exception if the
3107 * Config3 MT bit is NOT set.
3109 static inline void check_mt(DisasContext *ctx)
3111 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3112 generate_exception_end(ctx, EXCP_RI);
3116 #ifndef CONFIG_USER_ONLY
3118 * This code generates a "coprocessor unusable" exception if CP0 is not
3119 * available, and, if that is not the case, generates a "reserved instruction"
3120 * exception if the Config5 MT bit is NOT set. This is needed for availability
3121 * control of some of MT ASE instructions.
3123 static inline void check_cp0_mt(DisasContext *ctx)
3125 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3126 generate_exception_err(ctx, EXCP_CpU, 0);
3127 } else {
3128 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3129 generate_exception_err(ctx, EXCP_RI, 0);
3133 #endif
3136 * This code generates a "reserved instruction" exception if the
3137 * Config5 NMS bit is set.
3139 static inline void check_nms(DisasContext *ctx)
3141 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3142 generate_exception_end(ctx, EXCP_RI);
3147 * This code generates a "reserved instruction" exception if the
3148 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3149 * Config2 TL, and Config5 L2C are unset.
3151 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3153 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3154 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3155 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3156 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3157 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3158 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3159 generate_exception_end(ctx, EXCP_RI);
3164 * This code generates a "reserved instruction" exception if the
3165 * Config5 EVA bit is NOT set.
3167 static inline void check_eva(DisasContext *ctx)
3169 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3170 generate_exception_end(ctx, EXCP_RI);
3176 * Define small wrappers for gen_load_fpr* so that we have a uniform
3177 * calling interface for 32 and 64-bit FPRs. No sense in changing
3178 * all callers for gen_load_fpr32 when we need the CTX parameter for
3179 * this one use.
3181 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3182 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3183 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3184 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3185 int ft, int fs, int cc) \
3187 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3188 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3189 switch (ifmt) { \
3190 case FMT_PS: \
3191 check_ps(ctx); \
3192 break; \
3193 case FMT_D: \
3194 if (abs) { \
3195 check_cop1x(ctx); \
3197 check_cp1_registers(ctx, fs | ft); \
3198 break; \
3199 case FMT_S: \
3200 if (abs) { \
3201 check_cop1x(ctx); \
3203 break; \
3205 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3206 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3207 switch (n) { \
3208 case 0: \
3209 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3210 break; \
3211 case 1: \
3212 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3213 break; \
3214 case 2: \
3215 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3216 break; \
3217 case 3: \
3218 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3219 break; \
3220 case 4: \
3221 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3222 break; \
3223 case 5: \
3224 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3225 break; \
3226 case 6: \
3227 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3228 break; \
3229 case 7: \
3230 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3231 break; \
3232 case 8: \
3233 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3234 break; \
3235 case 9: \
3236 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3237 break; \
3238 case 10: \
3239 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3240 break; \
3241 case 11: \
3242 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3243 break; \
3244 case 12: \
3245 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3246 break; \
3247 case 13: \
3248 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3249 break; \
3250 case 14: \
3251 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3252 break; \
3253 case 15: \
3254 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3255 break; \
3256 default: \
3257 abort(); \
3259 tcg_temp_free_i##bits(fp0); \
3260 tcg_temp_free_i##bits(fp1); \
3263 FOP_CONDS(, 0, d, FMT_D, 64)
3264 FOP_CONDS(abs, 1, d, FMT_D, 64)
3265 FOP_CONDS(, 0, s, FMT_S, 32)
3266 FOP_CONDS(abs, 1, s, FMT_S, 32)
3267 FOP_CONDS(, 0, ps, FMT_PS, 64)
3268 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3269 #undef FOP_CONDS
3271 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3272 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3273 int ft, int fs, int fd) \
3275 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3276 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3277 if (ifmt == FMT_D) { \
3278 check_cp1_registers(ctx, fs | ft | fd); \
3280 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3281 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3282 switch (n) { \
3283 case 0: \
3284 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3285 break; \
3286 case 1: \
3287 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3288 break; \
3289 case 2: \
3290 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3291 break; \
3292 case 3: \
3293 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3294 break; \
3295 case 4: \
3296 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3297 break; \
3298 case 5: \
3299 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3300 break; \
3301 case 6: \
3302 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3303 break; \
3304 case 7: \
3305 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3306 break; \
3307 case 8: \
3308 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3309 break; \
3310 case 9: \
3311 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3312 break; \
3313 case 10: \
3314 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3315 break; \
3316 case 11: \
3317 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3318 break; \
3319 case 12: \
3320 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3321 break; \
3322 case 13: \
3323 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3324 break; \
3325 case 14: \
3326 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3327 break; \
3328 case 15: \
3329 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3330 break; \
3331 case 17: \
3332 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3333 break; \
3334 case 18: \
3335 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3336 break; \
3337 case 19: \
3338 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3339 break; \
3340 case 25: \
3341 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3342 break; \
3343 case 26: \
3344 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3345 break; \
3346 case 27: \
3347 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3348 break; \
3349 default: \
3350 abort(); \
3352 STORE; \
3353 tcg_temp_free_i ## bits(fp0); \
3354 tcg_temp_free_i ## bits(fp1); \
3357 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3358 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3359 #undef FOP_CONDNS
3360 #undef gen_ldcmp_fpr32
3361 #undef gen_ldcmp_fpr64
3363 /* load/store instructions. */
3364 #ifdef CONFIG_USER_ONLY
3365 #define OP_LD_ATOMIC(insn, fname) \
3366 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3367 DisasContext *ctx) \
3369 TCGv t0 = tcg_temp_new(); \
3370 tcg_gen_mov_tl(t0, arg1); \
3371 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3372 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3373 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3374 tcg_temp_free(t0); \
3376 #else
3377 #define OP_LD_ATOMIC(insn, fname) \
3378 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3379 DisasContext *ctx) \
3381 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3383 #endif
3384 OP_LD_ATOMIC(ll, ld32s);
3385 #if defined(TARGET_MIPS64)
3386 OP_LD_ATOMIC(lld, ld64);
3387 #endif
3388 #undef OP_LD_ATOMIC
3390 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3391 int base, int offset)
3393 if (base == 0) {
3394 tcg_gen_movi_tl(addr, offset);
3395 } else if (offset == 0) {
3396 gen_load_gpr(addr, base);
3397 } else {
3398 tcg_gen_movi_tl(addr, offset);
3399 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3403 static target_ulong pc_relative_pc(DisasContext *ctx)
3405 target_ulong pc = ctx->base.pc_next;
3407 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3408 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3410 pc -= branch_bytes;
3413 pc &= ~(target_ulong)3;
3414 return pc;
3417 /* Load */
3418 static void gen_ld(DisasContext *ctx, uint32_t opc,
3419 int rt, int base, int offset)
3421 TCGv t0, t1, t2;
3422 int mem_idx = ctx->mem_idx;
3424 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3426 * Loongson CPU uses a load to zero register for prefetch.
3427 * We emulate it as a NOP. On other CPU we must perform the
3428 * actual memory access.
3430 return;
3433 t0 = tcg_temp_new();
3434 gen_base_offset_addr(ctx, t0, base, offset);
3436 switch (opc) {
3437 #if defined(TARGET_MIPS64)
3438 case OPC_LWU:
3439 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3440 ctx->default_tcg_memop_mask);
3441 gen_store_gpr(t0, rt);
3442 break;
3443 case OPC_LD:
3444 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3445 ctx->default_tcg_memop_mask);
3446 gen_store_gpr(t0, rt);
3447 break;
3448 case OPC_LLD:
3449 case R6_OPC_LLD:
3450 op_ld_lld(t0, t0, mem_idx, ctx);
3451 gen_store_gpr(t0, rt);
3452 break;
3453 case OPC_LDL:
3454 t1 = tcg_temp_new();
3456 * Do a byte access to possibly trigger a page
3457 * fault with the unaligned address.
3459 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3460 tcg_gen_andi_tl(t1, t0, 7);
3461 #ifndef TARGET_WORDS_BIGENDIAN
3462 tcg_gen_xori_tl(t1, t1, 7);
3463 #endif
3464 tcg_gen_shli_tl(t1, t1, 3);
3465 tcg_gen_andi_tl(t0, t0, ~7);
3466 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3467 tcg_gen_shl_tl(t0, t0, t1);
3468 t2 = tcg_const_tl(-1);
3469 tcg_gen_shl_tl(t2, t2, t1);
3470 gen_load_gpr(t1, rt);
3471 tcg_gen_andc_tl(t1, t1, t2);
3472 tcg_temp_free(t2);
3473 tcg_gen_or_tl(t0, t0, t1);
3474 tcg_temp_free(t1);
3475 gen_store_gpr(t0, rt);
3476 break;
3477 case OPC_LDR:
3478 t1 = tcg_temp_new();
3480 * Do a byte access to possibly trigger a page
3481 * fault with the unaligned address.
3483 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3484 tcg_gen_andi_tl(t1, t0, 7);
3485 #ifdef TARGET_WORDS_BIGENDIAN
3486 tcg_gen_xori_tl(t1, t1, 7);
3487 #endif
3488 tcg_gen_shli_tl(t1, t1, 3);
3489 tcg_gen_andi_tl(t0, t0, ~7);
3490 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3491 tcg_gen_shr_tl(t0, t0, t1);
3492 tcg_gen_xori_tl(t1, t1, 63);
3493 t2 = tcg_const_tl(0xfffffffffffffffeull);
3494 tcg_gen_shl_tl(t2, t2, t1);
3495 gen_load_gpr(t1, rt);
3496 tcg_gen_and_tl(t1, t1, t2);
3497 tcg_temp_free(t2);
3498 tcg_gen_or_tl(t0, t0, t1);
3499 tcg_temp_free(t1);
3500 gen_store_gpr(t0, rt);
3501 break;
3502 case OPC_LDPC:
3503 t1 = tcg_const_tl(pc_relative_pc(ctx));
3504 gen_op_addr_add(ctx, t0, t0, t1);
3505 tcg_temp_free(t1);
3506 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3507 gen_store_gpr(t0, rt);
3508 break;
3509 #endif
3510 case OPC_LWPC:
3511 t1 = tcg_const_tl(pc_relative_pc(ctx));
3512 gen_op_addr_add(ctx, t0, t0, t1);
3513 tcg_temp_free(t1);
3514 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3515 gen_store_gpr(t0, rt);
3516 break;
3517 case OPC_LWE:
3518 mem_idx = MIPS_HFLAG_UM;
3519 /* fall through */
3520 case OPC_LW:
3521 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3522 ctx->default_tcg_memop_mask);
3523 gen_store_gpr(t0, rt);
3524 break;
3525 case OPC_LHE:
3526 mem_idx = MIPS_HFLAG_UM;
3527 /* fall through */
3528 case OPC_LH:
3529 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3530 ctx->default_tcg_memop_mask);
3531 gen_store_gpr(t0, rt);
3532 break;
3533 case OPC_LHUE:
3534 mem_idx = MIPS_HFLAG_UM;
3535 /* fall through */
3536 case OPC_LHU:
3537 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3538 ctx->default_tcg_memop_mask);
3539 gen_store_gpr(t0, rt);
3540 break;
3541 case OPC_LBE:
3542 mem_idx = MIPS_HFLAG_UM;
3543 /* fall through */
3544 case OPC_LB:
3545 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3546 gen_store_gpr(t0, rt);
3547 break;
3548 case OPC_LBUE:
3549 mem_idx = MIPS_HFLAG_UM;
3550 /* fall through */
3551 case OPC_LBU:
3552 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3553 gen_store_gpr(t0, rt);
3554 break;
3555 case OPC_LWLE:
3556 mem_idx = MIPS_HFLAG_UM;
3557 /* fall through */
3558 case OPC_LWL:
3559 t1 = tcg_temp_new();
3561 * Do a byte access to possibly trigger a page
3562 * fault with the unaligned address.
3564 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3565 tcg_gen_andi_tl(t1, t0, 3);
3566 #ifndef TARGET_WORDS_BIGENDIAN
3567 tcg_gen_xori_tl(t1, t1, 3);
3568 #endif
3569 tcg_gen_shli_tl(t1, t1, 3);
3570 tcg_gen_andi_tl(t0, t0, ~3);
3571 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3572 tcg_gen_shl_tl(t0, t0, t1);
3573 t2 = tcg_const_tl(-1);
3574 tcg_gen_shl_tl(t2, t2, t1);
3575 gen_load_gpr(t1, rt);
3576 tcg_gen_andc_tl(t1, t1, t2);
3577 tcg_temp_free(t2);
3578 tcg_gen_or_tl(t0, t0, t1);
3579 tcg_temp_free(t1);
3580 tcg_gen_ext32s_tl(t0, t0);
3581 gen_store_gpr(t0, rt);
3582 break;
3583 case OPC_LWRE:
3584 mem_idx = MIPS_HFLAG_UM;
3585 /* fall through */
3586 case OPC_LWR:
3587 t1 = tcg_temp_new();
3589 * Do a byte access to possibly trigger a page
3590 * fault with the unaligned address.
3592 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3593 tcg_gen_andi_tl(t1, t0, 3);
3594 #ifdef TARGET_WORDS_BIGENDIAN
3595 tcg_gen_xori_tl(t1, t1, 3);
3596 #endif
3597 tcg_gen_shli_tl(t1, t1, 3);
3598 tcg_gen_andi_tl(t0, t0, ~3);
3599 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3600 tcg_gen_shr_tl(t0, t0, t1);
3601 tcg_gen_xori_tl(t1, t1, 31);
3602 t2 = tcg_const_tl(0xfffffffeull);
3603 tcg_gen_shl_tl(t2, t2, t1);
3604 gen_load_gpr(t1, rt);
3605 tcg_gen_and_tl(t1, t1, t2);
3606 tcg_temp_free(t2);
3607 tcg_gen_or_tl(t0, t0, t1);
3608 tcg_temp_free(t1);
3609 tcg_gen_ext32s_tl(t0, t0);
3610 gen_store_gpr(t0, rt);
3611 break;
3612 case OPC_LLE:
3613 mem_idx = MIPS_HFLAG_UM;
3614 /* fall through */
3615 case OPC_LL:
3616 case R6_OPC_LL:
3617 op_ld_ll(t0, t0, mem_idx, ctx);
3618 gen_store_gpr(t0, rt);
3619 break;
3621 tcg_temp_free(t0);
3624 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3625 uint32_t reg1, uint32_t reg2)
3627 TCGv taddr = tcg_temp_new();
3628 TCGv_i64 tval = tcg_temp_new_i64();
3629 TCGv tmp1 = tcg_temp_new();
3630 TCGv tmp2 = tcg_temp_new();
3632 gen_base_offset_addr(ctx, taddr, base, offset);
3633 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3634 #ifdef TARGET_WORDS_BIGENDIAN
3635 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3636 #else
3637 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3638 #endif
3639 gen_store_gpr(tmp1, reg1);
3640 tcg_temp_free(tmp1);
3641 gen_store_gpr(tmp2, reg2);
3642 tcg_temp_free(tmp2);
3643 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3644 tcg_temp_free_i64(tval);
3645 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3646 tcg_temp_free(taddr);
3649 /* Store */
3650 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3651 int base, int offset)
3653 TCGv t0 = tcg_temp_new();
3654 TCGv t1 = tcg_temp_new();
3655 int mem_idx = ctx->mem_idx;
3657 gen_base_offset_addr(ctx, t0, base, offset);
3658 gen_load_gpr(t1, rt);
3659 switch (opc) {
3660 #if defined(TARGET_MIPS64)
3661 case OPC_SD:
3662 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3663 ctx->default_tcg_memop_mask);
3664 break;
3665 case OPC_SDL:
3666 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3667 break;
3668 case OPC_SDR:
3669 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3670 break;
3671 #endif
3672 case OPC_SWE:
3673 mem_idx = MIPS_HFLAG_UM;
3674 /* fall through */
3675 case OPC_SW:
3676 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3677 ctx->default_tcg_memop_mask);
3678 break;
3679 case OPC_SHE:
3680 mem_idx = MIPS_HFLAG_UM;
3681 /* fall through */
3682 case OPC_SH:
3683 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3684 ctx->default_tcg_memop_mask);
3685 break;
3686 case OPC_SBE:
3687 mem_idx = MIPS_HFLAG_UM;
3688 /* fall through */
3689 case OPC_SB:
3690 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3691 break;
3692 case OPC_SWLE:
3693 mem_idx = MIPS_HFLAG_UM;
3694 /* fall through */
3695 case OPC_SWL:
3696 gen_helper_0e2i(swl, t1, t0, mem_idx);
3697 break;
3698 case OPC_SWRE:
3699 mem_idx = MIPS_HFLAG_UM;
3700 /* fall through */
3701 case OPC_SWR:
3702 gen_helper_0e2i(swr, t1, t0, mem_idx);
3703 break;
3705 tcg_temp_free(t0);
3706 tcg_temp_free(t1);
3710 /* Store conditional */
3711 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3712 MemOp tcg_mo, bool eva)
3714 TCGv addr, t0, val;
3715 TCGLabel *l1 = gen_new_label();
3716 TCGLabel *done = gen_new_label();
3718 t0 = tcg_temp_new();
3719 addr = tcg_temp_new();
3720 /* compare the address against that of the preceeding LL */
3721 gen_base_offset_addr(ctx, addr, base, offset);
3722 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3723 tcg_temp_free(addr);
3724 tcg_gen_movi_tl(t0, 0);
3725 gen_store_gpr(t0, rt);
3726 tcg_gen_br(done);
3728 gen_set_label(l1);
3729 /* generate cmpxchg */
3730 val = tcg_temp_new();
3731 gen_load_gpr(val, rt);
3732 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3733 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3734 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3735 gen_store_gpr(t0, rt);
3736 tcg_temp_free(val);
3738 gen_set_label(done);
3739 tcg_temp_free(t0);
3743 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3744 uint32_t reg1, uint32_t reg2, bool eva)
3746 TCGv taddr = tcg_temp_local_new();
3747 TCGv lladdr = tcg_temp_local_new();
3748 TCGv_i64 tval = tcg_temp_new_i64();
3749 TCGv_i64 llval = tcg_temp_new_i64();
3750 TCGv_i64 val = tcg_temp_new_i64();
3751 TCGv tmp1 = tcg_temp_new();
3752 TCGv tmp2 = tcg_temp_new();
3753 TCGLabel *lab_fail = gen_new_label();
3754 TCGLabel *lab_done = gen_new_label();
3756 gen_base_offset_addr(ctx, taddr, base, offset);
3758 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3759 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3761 gen_load_gpr(tmp1, reg1);
3762 gen_load_gpr(tmp2, reg2);
3764 #ifdef TARGET_WORDS_BIGENDIAN
3765 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3766 #else
3767 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3768 #endif
3770 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3771 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3772 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3773 if (reg1 != 0) {
3774 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3776 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3778 gen_set_label(lab_fail);
3780 if (reg1 != 0) {
3781 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3783 gen_set_label(lab_done);
3784 tcg_gen_movi_tl(lladdr, -1);
3785 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3788 /* Load and store */
3789 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3790 TCGv t0)
3793 * Don't do NOP if destination is zero: we must perform the actual
3794 * memory access.
3796 switch (opc) {
3797 case OPC_LWC1:
3799 TCGv_i32 fp0 = tcg_temp_new_i32();
3800 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3801 ctx->default_tcg_memop_mask);
3802 gen_store_fpr32(ctx, fp0, ft);
3803 tcg_temp_free_i32(fp0);
3805 break;
3806 case OPC_SWC1:
3808 TCGv_i32 fp0 = tcg_temp_new_i32();
3809 gen_load_fpr32(ctx, fp0, ft);
3810 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3811 ctx->default_tcg_memop_mask);
3812 tcg_temp_free_i32(fp0);
3814 break;
3815 case OPC_LDC1:
3817 TCGv_i64 fp0 = tcg_temp_new_i64();
3818 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3819 ctx->default_tcg_memop_mask);
3820 gen_store_fpr64(ctx, fp0, ft);
3821 tcg_temp_free_i64(fp0);
3823 break;
3824 case OPC_SDC1:
3826 TCGv_i64 fp0 = tcg_temp_new_i64();
3827 gen_load_fpr64(ctx, fp0, ft);
3828 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3829 ctx->default_tcg_memop_mask);
3830 tcg_temp_free_i64(fp0);
3832 break;
3833 default:
3834 MIPS_INVAL("flt_ldst");
3835 generate_exception_end(ctx, EXCP_RI);
3836 break;
3840 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3841 int rs, int16_t imm)
3843 TCGv t0 = tcg_temp_new();
3845 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3846 check_cp1_enabled(ctx);
3847 switch (op) {
3848 case OPC_LDC1:
3849 case OPC_SDC1:
3850 check_insn(ctx, ISA_MIPS2);
3851 /* Fallthrough */
3852 default:
3853 gen_base_offset_addr(ctx, t0, rs, imm);
3854 gen_flt_ldst(ctx, op, rt, t0);
3856 } else {
3857 generate_exception_err(ctx, EXCP_CpU, 1);
3859 tcg_temp_free(t0);
3862 /* Arithmetic with immediate operand */
3863 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3864 int rt, int rs, int imm)
3866 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3868 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3870 * If no destination, treat it as a NOP.
3871 * For addi, we must generate the overflow exception when needed.
3873 return;
3875 switch (opc) {
3876 case OPC_ADDI:
3878 TCGv t0 = tcg_temp_local_new();
3879 TCGv t1 = tcg_temp_new();
3880 TCGv t2 = tcg_temp_new();
3881 TCGLabel *l1 = gen_new_label();
3883 gen_load_gpr(t1, rs);
3884 tcg_gen_addi_tl(t0, t1, uimm);
3885 tcg_gen_ext32s_tl(t0, t0);
3887 tcg_gen_xori_tl(t1, t1, ~uimm);
3888 tcg_gen_xori_tl(t2, t0, uimm);
3889 tcg_gen_and_tl(t1, t1, t2);
3890 tcg_temp_free(t2);
3891 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3892 tcg_temp_free(t1);
3893 /* operands of same sign, result different sign */
3894 generate_exception(ctx, EXCP_OVERFLOW);
3895 gen_set_label(l1);
3896 tcg_gen_ext32s_tl(t0, t0);
3897 gen_store_gpr(t0, rt);
3898 tcg_temp_free(t0);
3900 break;
3901 case OPC_ADDIU:
3902 if (rs != 0) {
3903 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3904 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3905 } else {
3906 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3908 break;
3909 #if defined(TARGET_MIPS64)
3910 case OPC_DADDI:
3912 TCGv t0 = tcg_temp_local_new();
3913 TCGv t1 = tcg_temp_new();
3914 TCGv t2 = tcg_temp_new();
3915 TCGLabel *l1 = gen_new_label();
3917 gen_load_gpr(t1, rs);
3918 tcg_gen_addi_tl(t0, t1, uimm);
3920 tcg_gen_xori_tl(t1, t1, ~uimm);
3921 tcg_gen_xori_tl(t2, t0, uimm);
3922 tcg_gen_and_tl(t1, t1, t2);
3923 tcg_temp_free(t2);
3924 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3925 tcg_temp_free(t1);
3926 /* operands of same sign, result different sign */
3927 generate_exception(ctx, EXCP_OVERFLOW);
3928 gen_set_label(l1);
3929 gen_store_gpr(t0, rt);
3930 tcg_temp_free(t0);
3932 break;
3933 case OPC_DADDIU:
3934 if (rs != 0) {
3935 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3936 } else {
3937 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3939 break;
3940 #endif
3944 /* Logic with immediate operand */
3945 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3946 int rt, int rs, int16_t imm)
3948 target_ulong uimm;
3950 if (rt == 0) {
3951 /* If no destination, treat it as a NOP. */
3952 return;
3954 uimm = (uint16_t)imm;
3955 switch (opc) {
3956 case OPC_ANDI:
3957 if (likely(rs != 0)) {
3958 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3959 } else {
3960 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3962 break;
3963 case OPC_ORI:
3964 if (rs != 0) {
3965 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3966 } else {
3967 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3969 break;
3970 case OPC_XORI:
3971 if (likely(rs != 0)) {
3972 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3973 } else {
3974 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3976 break;
3977 case OPC_LUI:
3978 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3979 /* OPC_AUI */
3980 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3981 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3982 } else {
3983 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3985 break;
3987 default:
3988 break;
3992 /* Set on less than with immediate operand */
3993 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3994 int rt, int rs, int16_t imm)
3996 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3997 TCGv t0;
3999 if (rt == 0) {
4000 /* If no destination, treat it as a NOP. */
4001 return;
4003 t0 = tcg_temp_new();
4004 gen_load_gpr(t0, rs);
4005 switch (opc) {
4006 case OPC_SLTI:
4007 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
4008 break;
4009 case OPC_SLTIU:
4010 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
4011 break;
4013 tcg_temp_free(t0);
4016 /* Shifts with immediate operand */
4017 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4018 int rt, int rs, int16_t imm)
4020 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4021 TCGv t0;
4023 if (rt == 0) {
4024 /* If no destination, treat it as a NOP. */
4025 return;
4028 t0 = tcg_temp_new();
4029 gen_load_gpr(t0, rs);
4030 switch (opc) {
4031 case OPC_SLL:
4032 tcg_gen_shli_tl(t0, t0, uimm);
4033 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4034 break;
4035 case OPC_SRA:
4036 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4037 break;
4038 case OPC_SRL:
4039 if (uimm != 0) {
4040 tcg_gen_ext32u_tl(t0, t0);
4041 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4042 } else {
4043 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4045 break;
4046 case OPC_ROTR:
4047 if (uimm != 0) {
4048 TCGv_i32 t1 = tcg_temp_new_i32();
4050 tcg_gen_trunc_tl_i32(t1, t0);
4051 tcg_gen_rotri_i32(t1, t1, uimm);
4052 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4053 tcg_temp_free_i32(t1);
4054 } else {
4055 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4057 break;
4058 #if defined(TARGET_MIPS64)
4059 case OPC_DSLL:
4060 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4061 break;
4062 case OPC_DSRA:
4063 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4064 break;
4065 case OPC_DSRL:
4066 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4067 break;
4068 case OPC_DROTR:
4069 if (uimm != 0) {
4070 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4071 } else {
4072 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4074 break;
4075 case OPC_DSLL32:
4076 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4077 break;
4078 case OPC_DSRA32:
4079 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4080 break;
4081 case OPC_DSRL32:
4082 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4083 break;
4084 case OPC_DROTR32:
4085 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4086 break;
4087 #endif
4089 tcg_temp_free(t0);
4092 /* Arithmetic */
4093 static void gen_arith(DisasContext *ctx, uint32_t opc,
4094 int rd, int rs, int rt)
4096 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4097 && opc != OPC_DADD && opc != OPC_DSUB) {
4099 * If no destination, treat it as a NOP.
4100 * For add & sub, we must generate the overflow exception when needed.
4102 return;
4105 switch (opc) {
4106 case OPC_ADD:
4108 TCGv t0 = tcg_temp_local_new();
4109 TCGv t1 = tcg_temp_new();
4110 TCGv t2 = tcg_temp_new();
4111 TCGLabel *l1 = gen_new_label();
4113 gen_load_gpr(t1, rs);
4114 gen_load_gpr(t2, rt);
4115 tcg_gen_add_tl(t0, t1, t2);
4116 tcg_gen_ext32s_tl(t0, t0);
4117 tcg_gen_xor_tl(t1, t1, t2);
4118 tcg_gen_xor_tl(t2, t0, t2);
4119 tcg_gen_andc_tl(t1, t2, t1);
4120 tcg_temp_free(t2);
4121 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4122 tcg_temp_free(t1);
4123 /* operands of same sign, result different sign */
4124 generate_exception(ctx, EXCP_OVERFLOW);
4125 gen_set_label(l1);
4126 gen_store_gpr(t0, rd);
4127 tcg_temp_free(t0);
4129 break;
4130 case OPC_ADDU:
4131 if (rs != 0 && rt != 0) {
4132 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4133 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4134 } else if (rs == 0 && rt != 0) {
4135 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4136 } else if (rs != 0 && rt == 0) {
4137 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4138 } else {
4139 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4141 break;
4142 case OPC_SUB:
4144 TCGv t0 = tcg_temp_local_new();
4145 TCGv t1 = tcg_temp_new();
4146 TCGv t2 = tcg_temp_new();
4147 TCGLabel *l1 = gen_new_label();
4149 gen_load_gpr(t1, rs);
4150 gen_load_gpr(t2, rt);
4151 tcg_gen_sub_tl(t0, t1, t2);
4152 tcg_gen_ext32s_tl(t0, t0);
4153 tcg_gen_xor_tl(t2, t1, t2);
4154 tcg_gen_xor_tl(t1, t0, t1);
4155 tcg_gen_and_tl(t1, t1, t2);
4156 tcg_temp_free(t2);
4157 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4158 tcg_temp_free(t1);
4160 * operands of different sign, first operand and the result
4161 * of different sign
4163 generate_exception(ctx, EXCP_OVERFLOW);
4164 gen_set_label(l1);
4165 gen_store_gpr(t0, rd);
4166 tcg_temp_free(t0);
4168 break;
4169 case OPC_SUBU:
4170 if (rs != 0 && rt != 0) {
4171 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4173 } else if (rs == 0 && rt != 0) {
4174 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4175 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4176 } else if (rs != 0 && rt == 0) {
4177 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4178 } else {
4179 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4181 break;
4182 #if defined(TARGET_MIPS64)
4183 case OPC_DADD:
4185 TCGv t0 = tcg_temp_local_new();
4186 TCGv t1 = tcg_temp_new();
4187 TCGv t2 = tcg_temp_new();
4188 TCGLabel *l1 = gen_new_label();
4190 gen_load_gpr(t1, rs);
4191 gen_load_gpr(t2, rt);
4192 tcg_gen_add_tl(t0, t1, t2);
4193 tcg_gen_xor_tl(t1, t1, t2);
4194 tcg_gen_xor_tl(t2, t0, t2);
4195 tcg_gen_andc_tl(t1, t2, t1);
4196 tcg_temp_free(t2);
4197 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4198 tcg_temp_free(t1);
4199 /* operands of same sign, result different sign */
4200 generate_exception(ctx, EXCP_OVERFLOW);
4201 gen_set_label(l1);
4202 gen_store_gpr(t0, rd);
4203 tcg_temp_free(t0);
4205 break;
4206 case OPC_DADDU:
4207 if (rs != 0 && rt != 0) {
4208 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4209 } else if (rs == 0 && rt != 0) {
4210 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4211 } else if (rs != 0 && rt == 0) {
4212 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4213 } else {
4214 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4216 break;
4217 case OPC_DSUB:
4219 TCGv t0 = tcg_temp_local_new();
4220 TCGv t1 = tcg_temp_new();
4221 TCGv t2 = tcg_temp_new();
4222 TCGLabel *l1 = gen_new_label();
4224 gen_load_gpr(t1, rs);
4225 gen_load_gpr(t2, rt);
4226 tcg_gen_sub_tl(t0, t1, t2);
4227 tcg_gen_xor_tl(t2, t1, t2);
4228 tcg_gen_xor_tl(t1, t0, t1);
4229 tcg_gen_and_tl(t1, t1, t2);
4230 tcg_temp_free(t2);
4231 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4232 tcg_temp_free(t1);
4234 * Operands of different sign, first operand and result different
4235 * sign.
4237 generate_exception(ctx, EXCP_OVERFLOW);
4238 gen_set_label(l1);
4239 gen_store_gpr(t0, rd);
4240 tcg_temp_free(t0);
4242 break;
4243 case OPC_DSUBU:
4244 if (rs != 0 && rt != 0) {
4245 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4246 } else if (rs == 0 && rt != 0) {
4247 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4248 } else if (rs != 0 && rt == 0) {
4249 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4250 } else {
4251 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4253 break;
4254 #endif
4255 case OPC_MUL:
4256 if (likely(rs != 0 && rt != 0)) {
4257 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4258 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4259 } else {
4260 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4262 break;
4266 /* Conditional move */
4267 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4268 int rd, int rs, int rt)
4270 TCGv t0, t1, t2;
4272 if (rd == 0) {
4273 /* If no destination, treat it as a NOP. */
4274 return;
4277 t0 = tcg_temp_new();
4278 gen_load_gpr(t0, rt);
4279 t1 = tcg_const_tl(0);
4280 t2 = tcg_temp_new();
4281 gen_load_gpr(t2, rs);
4282 switch (opc) {
4283 case OPC_MOVN:
4284 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4285 break;
4286 case OPC_MOVZ:
4287 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4288 break;
4289 case OPC_SELNEZ:
4290 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4291 break;
4292 case OPC_SELEQZ:
4293 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4294 break;
4296 tcg_temp_free(t2);
4297 tcg_temp_free(t1);
4298 tcg_temp_free(t0);
4301 /* Logic */
4302 static void gen_logic(DisasContext *ctx, uint32_t opc,
4303 int rd, int rs, int rt)
4305 if (rd == 0) {
4306 /* If no destination, treat it as a NOP. */
4307 return;
4310 switch (opc) {
4311 case OPC_AND:
4312 if (likely(rs != 0 && rt != 0)) {
4313 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4314 } else {
4315 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4317 break;
4318 case OPC_NOR:
4319 if (rs != 0 && rt != 0) {
4320 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4321 } else if (rs == 0 && rt != 0) {
4322 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4323 } else if (rs != 0 && rt == 0) {
4324 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4325 } else {
4326 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4328 break;
4329 case OPC_OR:
4330 if (likely(rs != 0 && rt != 0)) {
4331 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4332 } else if (rs == 0 && rt != 0) {
4333 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4334 } else if (rs != 0 && rt == 0) {
4335 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4336 } else {
4337 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4339 break;
4340 case OPC_XOR:
4341 if (likely(rs != 0 && rt != 0)) {
4342 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4343 } else if (rs == 0 && rt != 0) {
4344 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4345 } else if (rs != 0 && rt == 0) {
4346 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4347 } else {
4348 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4350 break;
4354 /* Set on lower than */
4355 static void gen_slt(DisasContext *ctx, uint32_t opc,
4356 int rd, int rs, int rt)
4358 TCGv t0, t1;
4360 if (rd == 0) {
4361 /* If no destination, treat it as a NOP. */
4362 return;
4365 t0 = tcg_temp_new();
4366 t1 = tcg_temp_new();
4367 gen_load_gpr(t0, rs);
4368 gen_load_gpr(t1, rt);
4369 switch (opc) {
4370 case OPC_SLT:
4371 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4372 break;
4373 case OPC_SLTU:
4374 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4375 break;
4377 tcg_temp_free(t0);
4378 tcg_temp_free(t1);
4381 /* Shifts */
4382 static void gen_shift(DisasContext *ctx, uint32_t opc,
4383 int rd, int rs, int rt)
4385 TCGv t0, t1;
4387 if (rd == 0) {
4389 * If no destination, treat it as a NOP.
4390 * For add & sub, we must generate the overflow exception when needed.
4392 return;
4395 t0 = tcg_temp_new();
4396 t1 = tcg_temp_new();
4397 gen_load_gpr(t0, rs);
4398 gen_load_gpr(t1, rt);
4399 switch (opc) {
4400 case OPC_SLLV:
4401 tcg_gen_andi_tl(t0, t0, 0x1f);
4402 tcg_gen_shl_tl(t0, t1, t0);
4403 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4404 break;
4405 case OPC_SRAV:
4406 tcg_gen_andi_tl(t0, t0, 0x1f);
4407 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4408 break;
4409 case OPC_SRLV:
4410 tcg_gen_ext32u_tl(t1, t1);
4411 tcg_gen_andi_tl(t0, t0, 0x1f);
4412 tcg_gen_shr_tl(t0, t1, t0);
4413 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4414 break;
4415 case OPC_ROTRV:
4417 TCGv_i32 t2 = tcg_temp_new_i32();
4418 TCGv_i32 t3 = tcg_temp_new_i32();
4420 tcg_gen_trunc_tl_i32(t2, t0);
4421 tcg_gen_trunc_tl_i32(t3, t1);
4422 tcg_gen_andi_i32(t2, t2, 0x1f);
4423 tcg_gen_rotr_i32(t2, t3, t2);
4424 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4425 tcg_temp_free_i32(t2);
4426 tcg_temp_free_i32(t3);
4428 break;
4429 #if defined(TARGET_MIPS64)
4430 case OPC_DSLLV:
4431 tcg_gen_andi_tl(t0, t0, 0x3f);
4432 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4433 break;
4434 case OPC_DSRAV:
4435 tcg_gen_andi_tl(t0, t0, 0x3f);
4436 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4437 break;
4438 case OPC_DSRLV:
4439 tcg_gen_andi_tl(t0, t0, 0x3f);
4440 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4441 break;
4442 case OPC_DROTRV:
4443 tcg_gen_andi_tl(t0, t0, 0x3f);
4444 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4445 break;
4446 #endif
4448 tcg_temp_free(t0);
4449 tcg_temp_free(t1);
4452 #if defined(TARGET_MIPS64)
4453 /* Copy GPR to and from TX79 HI1/LO1 register. */
4454 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4456 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4457 /* Treat as NOP. */
4458 return;
4461 switch (opc) {
4462 case MMI_OPC_MFHI1:
4463 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4464 break;
4465 case MMI_OPC_MFLO1:
4466 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4467 break;
4468 case MMI_OPC_MTHI1:
4469 if (reg != 0) {
4470 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4471 } else {
4472 tcg_gen_movi_tl(cpu_HI[1], 0);
4474 break;
4475 case MMI_OPC_MTLO1:
4476 if (reg != 0) {
4477 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4478 } else {
4479 tcg_gen_movi_tl(cpu_LO[1], 0);
4481 break;
4482 default:
4483 MIPS_INVAL("mfthilo1 TX79");
4484 generate_exception_end(ctx, EXCP_RI);
4485 break;
4488 #endif
4490 /* Arithmetic on HI/LO registers */
4491 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4493 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4494 /* Treat as NOP. */
4495 return;
4498 if (acc != 0) {
4499 check_dsp(ctx);
4502 switch (opc) {
4503 case OPC_MFHI:
4504 #if defined(TARGET_MIPS64)
4505 if (acc != 0) {
4506 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4507 } else
4508 #endif
4510 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4512 break;
4513 case OPC_MFLO:
4514 #if defined(TARGET_MIPS64)
4515 if (acc != 0) {
4516 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4517 } else
4518 #endif
4520 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4522 break;
4523 case OPC_MTHI:
4524 if (reg != 0) {
4525 #if defined(TARGET_MIPS64)
4526 if (acc != 0) {
4527 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4528 } else
4529 #endif
4531 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4533 } else {
4534 tcg_gen_movi_tl(cpu_HI[acc], 0);
4536 break;
4537 case OPC_MTLO:
4538 if (reg != 0) {
4539 #if defined(TARGET_MIPS64)
4540 if (acc != 0) {
4541 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4542 } else
4543 #endif
4545 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4547 } else {
4548 tcg_gen_movi_tl(cpu_LO[acc], 0);
4550 break;
4554 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4555 MemOp memop)
4557 TCGv t0 = tcg_const_tl(addr);
4558 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4559 gen_store_gpr(t0, reg);
4560 tcg_temp_free(t0);
4563 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4564 int rs)
4566 target_long offset;
4567 target_long addr;
4569 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4570 case OPC_ADDIUPC:
4571 if (rs != 0) {
4572 offset = sextract32(ctx->opcode << 2, 0, 21);
4573 addr = addr_add(ctx, pc, offset);
4574 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4576 break;
4577 case R6_OPC_LWPC:
4578 offset = sextract32(ctx->opcode << 2, 0, 21);
4579 addr = addr_add(ctx, pc, offset);
4580 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4581 break;
4582 #if defined(TARGET_MIPS64)
4583 case OPC_LWUPC:
4584 check_mips_64(ctx);
4585 offset = sextract32(ctx->opcode << 2, 0, 21);
4586 addr = addr_add(ctx, pc, offset);
4587 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4588 break;
4589 #endif
4590 default:
4591 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4592 case OPC_AUIPC:
4593 if (rs != 0) {
4594 offset = sextract32(ctx->opcode, 0, 16) << 16;
4595 addr = addr_add(ctx, pc, offset);
4596 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4598 break;
4599 case OPC_ALUIPC:
4600 if (rs != 0) {
4601 offset = sextract32(ctx->opcode, 0, 16) << 16;
4602 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4603 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4605 break;
4606 #if defined(TARGET_MIPS64)
4607 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4608 case R6_OPC_LDPC + (1 << 16):
4609 case R6_OPC_LDPC + (2 << 16):
4610 case R6_OPC_LDPC + (3 << 16):
4611 check_mips_64(ctx);
4612 offset = sextract32(ctx->opcode << 3, 0, 21);
4613 addr = addr_add(ctx, (pc & ~0x7), offset);
4614 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4615 break;
4616 #endif
4617 default:
4618 MIPS_INVAL("OPC_PCREL");
4619 generate_exception_end(ctx, EXCP_RI);
4620 break;
4622 break;
4626 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4628 TCGv t0, t1;
4630 if (rd == 0) {
4631 /* Treat as NOP. */
4632 return;
4635 t0 = tcg_temp_new();
4636 t1 = tcg_temp_new();
4638 gen_load_gpr(t0, rs);
4639 gen_load_gpr(t1, rt);
4641 switch (opc) {
4642 case R6_OPC_DIV:
4644 TCGv t2 = tcg_temp_new();
4645 TCGv t3 = tcg_temp_new();
4646 tcg_gen_ext32s_tl(t0, t0);
4647 tcg_gen_ext32s_tl(t1, t1);
4648 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4649 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4650 tcg_gen_and_tl(t2, t2, t3);
4651 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4652 tcg_gen_or_tl(t2, t2, t3);
4653 tcg_gen_movi_tl(t3, 0);
4654 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4655 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4656 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4657 tcg_temp_free(t3);
4658 tcg_temp_free(t2);
4660 break;
4661 case R6_OPC_MOD:
4663 TCGv t2 = tcg_temp_new();
4664 TCGv t3 = tcg_temp_new();
4665 tcg_gen_ext32s_tl(t0, t0);
4666 tcg_gen_ext32s_tl(t1, t1);
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4668 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
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_rem_tl(cpu_gpr[rd], t0, t1);
4675 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4676 tcg_temp_free(t3);
4677 tcg_temp_free(t2);
4679 break;
4680 case R6_OPC_DIVU:
4682 TCGv t2 = tcg_const_tl(0);
4683 TCGv t3 = tcg_const_tl(1);
4684 tcg_gen_ext32u_tl(t0, t0);
4685 tcg_gen_ext32u_tl(t1, t1);
4686 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4687 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4688 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4689 tcg_temp_free(t3);
4690 tcg_temp_free(t2);
4692 break;
4693 case R6_OPC_MODU:
4695 TCGv t2 = tcg_const_tl(0);
4696 TCGv t3 = tcg_const_tl(1);
4697 tcg_gen_ext32u_tl(t0, t0);
4698 tcg_gen_ext32u_tl(t1, t1);
4699 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4700 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4701 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4702 tcg_temp_free(t3);
4703 tcg_temp_free(t2);
4705 break;
4706 case R6_OPC_MUL:
4708 TCGv_i32 t2 = tcg_temp_new_i32();
4709 TCGv_i32 t3 = tcg_temp_new_i32();
4710 tcg_gen_trunc_tl_i32(t2, t0);
4711 tcg_gen_trunc_tl_i32(t3, t1);
4712 tcg_gen_mul_i32(t2, t2, t3);
4713 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4714 tcg_temp_free_i32(t2);
4715 tcg_temp_free_i32(t3);
4717 break;
4718 case R6_OPC_MUH:
4720 TCGv_i32 t2 = tcg_temp_new_i32();
4721 TCGv_i32 t3 = tcg_temp_new_i32();
4722 tcg_gen_trunc_tl_i32(t2, t0);
4723 tcg_gen_trunc_tl_i32(t3, t1);
4724 tcg_gen_muls2_i32(t2, t3, t2, t3);
4725 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4726 tcg_temp_free_i32(t2);
4727 tcg_temp_free_i32(t3);
4729 break;
4730 case R6_OPC_MULU:
4732 TCGv_i32 t2 = tcg_temp_new_i32();
4733 TCGv_i32 t3 = tcg_temp_new_i32();
4734 tcg_gen_trunc_tl_i32(t2, t0);
4735 tcg_gen_trunc_tl_i32(t3, t1);
4736 tcg_gen_mul_i32(t2, t2, t3);
4737 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4738 tcg_temp_free_i32(t2);
4739 tcg_temp_free_i32(t3);
4741 break;
4742 case R6_OPC_MUHU:
4744 TCGv_i32 t2 = tcg_temp_new_i32();
4745 TCGv_i32 t3 = tcg_temp_new_i32();
4746 tcg_gen_trunc_tl_i32(t2, t0);
4747 tcg_gen_trunc_tl_i32(t3, t1);
4748 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4749 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4750 tcg_temp_free_i32(t2);
4751 tcg_temp_free_i32(t3);
4753 break;
4754 #if defined(TARGET_MIPS64)
4755 case R6_OPC_DDIV:
4757 TCGv t2 = tcg_temp_new();
4758 TCGv t3 = tcg_temp_new();
4759 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4760 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4761 tcg_gen_and_tl(t2, t2, t3);
4762 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4763 tcg_gen_or_tl(t2, t2, t3);
4764 tcg_gen_movi_tl(t3, 0);
4765 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4766 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4767 tcg_temp_free(t3);
4768 tcg_temp_free(t2);
4770 break;
4771 case R6_OPC_DMOD:
4773 TCGv t2 = tcg_temp_new();
4774 TCGv t3 = tcg_temp_new();
4775 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4776 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4777 tcg_gen_and_tl(t2, t2, t3);
4778 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4779 tcg_gen_or_tl(t2, t2, t3);
4780 tcg_gen_movi_tl(t3, 0);
4781 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4782 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4783 tcg_temp_free(t3);
4784 tcg_temp_free(t2);
4786 break;
4787 case R6_OPC_DDIVU:
4789 TCGv t2 = tcg_const_tl(0);
4790 TCGv t3 = tcg_const_tl(1);
4791 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4792 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4793 tcg_temp_free(t3);
4794 tcg_temp_free(t2);
4796 break;
4797 case R6_OPC_DMODU:
4799 TCGv t2 = tcg_const_tl(0);
4800 TCGv t3 = tcg_const_tl(1);
4801 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4802 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4803 tcg_temp_free(t3);
4804 tcg_temp_free(t2);
4806 break;
4807 case R6_OPC_DMUL:
4808 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4809 break;
4810 case R6_OPC_DMUH:
4812 TCGv t2 = tcg_temp_new();
4813 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4814 tcg_temp_free(t2);
4816 break;
4817 case R6_OPC_DMULU:
4818 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4819 break;
4820 case R6_OPC_DMUHU:
4822 TCGv t2 = tcg_temp_new();
4823 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4824 tcg_temp_free(t2);
4826 break;
4827 #endif
4828 default:
4829 MIPS_INVAL("r6 mul/div");
4830 generate_exception_end(ctx, EXCP_RI);
4831 goto out;
4833 out:
4834 tcg_temp_free(t0);
4835 tcg_temp_free(t1);
4838 #if defined(TARGET_MIPS64)
4839 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4841 TCGv t0, t1;
4843 t0 = tcg_temp_new();
4844 t1 = tcg_temp_new();
4846 gen_load_gpr(t0, rs);
4847 gen_load_gpr(t1, rt);
4849 switch (opc) {
4850 case MMI_OPC_DIV1:
4852 TCGv t2 = tcg_temp_new();
4853 TCGv t3 = tcg_temp_new();
4854 tcg_gen_ext32s_tl(t0, t0);
4855 tcg_gen_ext32s_tl(t1, t1);
4856 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4857 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4858 tcg_gen_and_tl(t2, t2, t3);
4859 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4860 tcg_gen_or_tl(t2, t2, t3);
4861 tcg_gen_movi_tl(t3, 0);
4862 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4863 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4864 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4865 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4866 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4867 tcg_temp_free(t3);
4868 tcg_temp_free(t2);
4870 break;
4871 case MMI_OPC_DIVU1:
4873 TCGv t2 = tcg_const_tl(0);
4874 TCGv t3 = tcg_const_tl(1);
4875 tcg_gen_ext32u_tl(t0, t0);
4876 tcg_gen_ext32u_tl(t1, t1);
4877 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4878 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4879 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4880 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4881 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4882 tcg_temp_free(t3);
4883 tcg_temp_free(t2);
4885 break;
4886 default:
4887 MIPS_INVAL("div1 TX79");
4888 generate_exception_end(ctx, EXCP_RI);
4889 goto out;
4891 out:
4892 tcg_temp_free(t0);
4893 tcg_temp_free(t1);
4895 #endif
4897 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4898 int acc, int rs, int rt)
4900 TCGv t0, t1;
4902 t0 = tcg_temp_new();
4903 t1 = tcg_temp_new();
4905 gen_load_gpr(t0, rs);
4906 gen_load_gpr(t1, rt);
4908 if (acc != 0) {
4909 check_dsp(ctx);
4912 switch (opc) {
4913 case OPC_DIV:
4915 TCGv t2 = tcg_temp_new();
4916 TCGv t3 = tcg_temp_new();
4917 tcg_gen_ext32s_tl(t0, t0);
4918 tcg_gen_ext32s_tl(t1, t1);
4919 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4920 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4921 tcg_gen_and_tl(t2, t2, t3);
4922 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4923 tcg_gen_or_tl(t2, t2, t3);
4924 tcg_gen_movi_tl(t3, 0);
4925 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4926 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4927 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4928 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4929 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4930 tcg_temp_free(t3);
4931 tcg_temp_free(t2);
4933 break;
4934 case OPC_DIVU:
4936 TCGv t2 = tcg_const_tl(0);
4937 TCGv t3 = tcg_const_tl(1);
4938 tcg_gen_ext32u_tl(t0, t0);
4939 tcg_gen_ext32u_tl(t1, t1);
4940 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4941 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4942 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4943 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4944 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4945 tcg_temp_free(t3);
4946 tcg_temp_free(t2);
4948 break;
4949 case OPC_MULT:
4951 TCGv_i32 t2 = tcg_temp_new_i32();
4952 TCGv_i32 t3 = tcg_temp_new_i32();
4953 tcg_gen_trunc_tl_i32(t2, t0);
4954 tcg_gen_trunc_tl_i32(t3, t1);
4955 tcg_gen_muls2_i32(t2, t3, t2, t3);
4956 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4957 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4958 tcg_temp_free_i32(t2);
4959 tcg_temp_free_i32(t3);
4961 break;
4962 case OPC_MULTU:
4964 TCGv_i32 t2 = tcg_temp_new_i32();
4965 TCGv_i32 t3 = tcg_temp_new_i32();
4966 tcg_gen_trunc_tl_i32(t2, t0);
4967 tcg_gen_trunc_tl_i32(t3, t1);
4968 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4969 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4970 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4971 tcg_temp_free_i32(t2);
4972 tcg_temp_free_i32(t3);
4974 break;
4975 #if defined(TARGET_MIPS64)
4976 case OPC_DDIV:
4978 TCGv t2 = tcg_temp_new();
4979 TCGv t3 = tcg_temp_new();
4980 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4981 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4982 tcg_gen_and_tl(t2, t2, t3);
4983 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4984 tcg_gen_or_tl(t2, t2, t3);
4985 tcg_gen_movi_tl(t3, 0);
4986 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4987 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4988 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4989 tcg_temp_free(t3);
4990 tcg_temp_free(t2);
4992 break;
4993 case OPC_DDIVU:
4995 TCGv t2 = tcg_const_tl(0);
4996 TCGv t3 = tcg_const_tl(1);
4997 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4998 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4999 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
5000 tcg_temp_free(t3);
5001 tcg_temp_free(t2);
5003 break;
5004 case OPC_DMULT:
5005 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5006 break;
5007 case OPC_DMULTU:
5008 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5009 break;
5010 #endif
5011 case OPC_MADD:
5013 TCGv_i64 t2 = tcg_temp_new_i64();
5014 TCGv_i64 t3 = tcg_temp_new_i64();
5016 tcg_gen_ext_tl_i64(t2, t0);
5017 tcg_gen_ext_tl_i64(t3, t1);
5018 tcg_gen_mul_i64(t2, t2, t3);
5019 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5020 tcg_gen_add_i64(t2, t2, t3);
5021 tcg_temp_free_i64(t3);
5022 gen_move_low32(cpu_LO[acc], t2);
5023 gen_move_high32(cpu_HI[acc], t2);
5024 tcg_temp_free_i64(t2);
5026 break;
5027 case OPC_MADDU:
5029 TCGv_i64 t2 = tcg_temp_new_i64();
5030 TCGv_i64 t3 = tcg_temp_new_i64();
5032 tcg_gen_ext32u_tl(t0, t0);
5033 tcg_gen_ext32u_tl(t1, t1);
5034 tcg_gen_extu_tl_i64(t2, t0);
5035 tcg_gen_extu_tl_i64(t3, t1);
5036 tcg_gen_mul_i64(t2, t2, t3);
5037 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5038 tcg_gen_add_i64(t2, t2, t3);
5039 tcg_temp_free_i64(t3);
5040 gen_move_low32(cpu_LO[acc], t2);
5041 gen_move_high32(cpu_HI[acc], t2);
5042 tcg_temp_free_i64(t2);
5044 break;
5045 case OPC_MSUB:
5047 TCGv_i64 t2 = tcg_temp_new_i64();
5048 TCGv_i64 t3 = tcg_temp_new_i64();
5050 tcg_gen_ext_tl_i64(t2, t0);
5051 tcg_gen_ext_tl_i64(t3, t1);
5052 tcg_gen_mul_i64(t2, t2, t3);
5053 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5054 tcg_gen_sub_i64(t2, t3, t2);
5055 tcg_temp_free_i64(t3);
5056 gen_move_low32(cpu_LO[acc], t2);
5057 gen_move_high32(cpu_HI[acc], t2);
5058 tcg_temp_free_i64(t2);
5060 break;
5061 case OPC_MSUBU:
5063 TCGv_i64 t2 = tcg_temp_new_i64();
5064 TCGv_i64 t3 = tcg_temp_new_i64();
5066 tcg_gen_ext32u_tl(t0, t0);
5067 tcg_gen_ext32u_tl(t1, t1);
5068 tcg_gen_extu_tl_i64(t2, t0);
5069 tcg_gen_extu_tl_i64(t3, t1);
5070 tcg_gen_mul_i64(t2, t2, t3);
5071 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5072 tcg_gen_sub_i64(t2, t3, t2);
5073 tcg_temp_free_i64(t3);
5074 gen_move_low32(cpu_LO[acc], t2);
5075 gen_move_high32(cpu_HI[acc], t2);
5076 tcg_temp_free_i64(t2);
5078 break;
5079 default:
5080 MIPS_INVAL("mul/div");
5081 generate_exception_end(ctx, EXCP_RI);
5082 goto out;
5084 out:
5085 tcg_temp_free(t0);
5086 tcg_temp_free(t1);
5090 * These MULT[U] and MADD[U] instructions implemented in for example
5091 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5092 * architectures are special three-operand variants with the syntax
5094 * MULT[U][1] rd, rs, rt
5096 * such that
5098 * (rd, LO, HI) <- rs * rt
5100 * and
5102 * MADD[U][1] rd, rs, rt
5104 * such that
5106 * (rd, LO, HI) <- (LO, HI) + rs * rt
5108 * where the low-order 32-bits of the result is placed into both the
5109 * GPR rd and the special register LO. The high-order 32-bits of the
5110 * result is placed into the special register HI.
5112 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5113 * which is the zero register that always reads as 0.
5115 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5116 int rd, int rs, int rt)
5118 TCGv t0 = tcg_temp_new();
5119 TCGv t1 = tcg_temp_new();
5120 int acc = 0;
5122 gen_load_gpr(t0, rs);
5123 gen_load_gpr(t1, rt);
5125 switch (opc) {
5126 case MMI_OPC_MULT1:
5127 acc = 1;
5128 /* Fall through */
5129 case OPC_MULT:
5131 TCGv_i32 t2 = tcg_temp_new_i32();
5132 TCGv_i32 t3 = tcg_temp_new_i32();
5133 tcg_gen_trunc_tl_i32(t2, t0);
5134 tcg_gen_trunc_tl_i32(t3, t1);
5135 tcg_gen_muls2_i32(t2, t3, t2, t3);
5136 if (rd) {
5137 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5139 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5140 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5141 tcg_temp_free_i32(t2);
5142 tcg_temp_free_i32(t3);
5144 break;
5145 case MMI_OPC_MULTU1:
5146 acc = 1;
5147 /* Fall through */
5148 case OPC_MULTU:
5150 TCGv_i32 t2 = tcg_temp_new_i32();
5151 TCGv_i32 t3 = tcg_temp_new_i32();
5152 tcg_gen_trunc_tl_i32(t2, t0);
5153 tcg_gen_trunc_tl_i32(t3, t1);
5154 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5155 if (rd) {
5156 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5158 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5159 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5160 tcg_temp_free_i32(t2);
5161 tcg_temp_free_i32(t3);
5163 break;
5164 case MMI_OPC_MADD1:
5165 acc = 1;
5166 /* Fall through */
5167 case MMI_OPC_MADD:
5169 TCGv_i64 t2 = tcg_temp_new_i64();
5170 TCGv_i64 t3 = tcg_temp_new_i64();
5172 tcg_gen_ext_tl_i64(t2, t0);
5173 tcg_gen_ext_tl_i64(t3, t1);
5174 tcg_gen_mul_i64(t2, t2, t3);
5175 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5176 tcg_gen_add_i64(t2, t2, t3);
5177 tcg_temp_free_i64(t3);
5178 gen_move_low32(cpu_LO[acc], t2);
5179 gen_move_high32(cpu_HI[acc], t2);
5180 if (rd) {
5181 gen_move_low32(cpu_gpr[rd], t2);
5183 tcg_temp_free_i64(t2);
5185 break;
5186 case MMI_OPC_MADDU1:
5187 acc = 1;
5188 /* Fall through */
5189 case MMI_OPC_MADDU:
5191 TCGv_i64 t2 = tcg_temp_new_i64();
5192 TCGv_i64 t3 = tcg_temp_new_i64();
5194 tcg_gen_ext32u_tl(t0, t0);
5195 tcg_gen_ext32u_tl(t1, t1);
5196 tcg_gen_extu_tl_i64(t2, t0);
5197 tcg_gen_extu_tl_i64(t3, t1);
5198 tcg_gen_mul_i64(t2, t2, t3);
5199 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5200 tcg_gen_add_i64(t2, t2, t3);
5201 tcg_temp_free_i64(t3);
5202 gen_move_low32(cpu_LO[acc], t2);
5203 gen_move_high32(cpu_HI[acc], t2);
5204 if (rd) {
5205 gen_move_low32(cpu_gpr[rd], t2);
5207 tcg_temp_free_i64(t2);
5209 break;
5210 default:
5211 MIPS_INVAL("mul/madd TXx9");
5212 generate_exception_end(ctx, EXCP_RI);
5213 goto out;
5216 out:
5217 tcg_temp_free(t0);
5218 tcg_temp_free(t1);
5221 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5222 int rd, int rs, int rt)
5224 TCGv t0 = tcg_temp_new();
5225 TCGv t1 = tcg_temp_new();
5227 gen_load_gpr(t0, rs);
5228 gen_load_gpr(t1, rt);
5230 switch (opc) {
5231 case OPC_VR54XX_MULS:
5232 gen_helper_muls(t0, cpu_env, t0, t1);
5233 break;
5234 case OPC_VR54XX_MULSU:
5235 gen_helper_mulsu(t0, cpu_env, t0, t1);
5236 break;
5237 case OPC_VR54XX_MACC:
5238 gen_helper_macc(t0, cpu_env, t0, t1);
5239 break;
5240 case OPC_VR54XX_MACCU:
5241 gen_helper_maccu(t0, cpu_env, t0, t1);
5242 break;
5243 case OPC_VR54XX_MSAC:
5244 gen_helper_msac(t0, cpu_env, t0, t1);
5245 break;
5246 case OPC_VR54XX_MSACU:
5247 gen_helper_msacu(t0, cpu_env, t0, t1);
5248 break;
5249 case OPC_VR54XX_MULHI:
5250 gen_helper_mulhi(t0, cpu_env, t0, t1);
5251 break;
5252 case OPC_VR54XX_MULHIU:
5253 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5254 break;
5255 case OPC_VR54XX_MULSHI:
5256 gen_helper_mulshi(t0, cpu_env, t0, t1);
5257 break;
5258 case OPC_VR54XX_MULSHIU:
5259 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5260 break;
5261 case OPC_VR54XX_MACCHI:
5262 gen_helper_macchi(t0, cpu_env, t0, t1);
5263 break;
5264 case OPC_VR54XX_MACCHIU:
5265 gen_helper_macchiu(t0, cpu_env, t0, t1);
5266 break;
5267 case OPC_VR54XX_MSACHI:
5268 gen_helper_msachi(t0, cpu_env, t0, t1);
5269 break;
5270 case OPC_VR54XX_MSACHIU:
5271 gen_helper_msachiu(t0, cpu_env, t0, t1);
5272 break;
5273 default:
5274 MIPS_INVAL("mul vr54xx");
5275 generate_exception_end(ctx, EXCP_RI);
5276 goto out;
5278 gen_store_gpr(t0, rd);
5280 out:
5281 tcg_temp_free(t0);
5282 tcg_temp_free(t1);
5285 static void gen_cl(DisasContext *ctx, uint32_t opc,
5286 int rd, int rs)
5288 TCGv t0;
5290 if (rd == 0) {
5291 /* Treat as NOP. */
5292 return;
5294 t0 = cpu_gpr[rd];
5295 gen_load_gpr(t0, rs);
5297 switch (opc) {
5298 case OPC_CLO:
5299 case R6_OPC_CLO:
5300 #if defined(TARGET_MIPS64)
5301 case OPC_DCLO:
5302 case R6_OPC_DCLO:
5303 #endif
5304 tcg_gen_not_tl(t0, t0);
5305 break;
5308 switch (opc) {
5309 case OPC_CLO:
5310 case R6_OPC_CLO:
5311 case OPC_CLZ:
5312 case R6_OPC_CLZ:
5313 tcg_gen_ext32u_tl(t0, t0);
5314 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5315 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5316 break;
5317 #if defined(TARGET_MIPS64)
5318 case OPC_DCLO:
5319 case R6_OPC_DCLO:
5320 case OPC_DCLZ:
5321 case R6_OPC_DCLZ:
5322 tcg_gen_clzi_i64(t0, t0, 64);
5323 break;
5324 #endif
5328 /* Godson integer instructions */
5329 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5330 int rd, int rs, int rt)
5332 TCGv t0, t1;
5334 if (rd == 0) {
5335 /* Treat as NOP. */
5336 return;
5339 switch (opc) {
5340 case OPC_MULT_G_2E:
5341 case OPC_MULT_G_2F:
5342 case OPC_MULTU_G_2E:
5343 case OPC_MULTU_G_2F:
5344 #if defined(TARGET_MIPS64)
5345 case OPC_DMULT_G_2E:
5346 case OPC_DMULT_G_2F:
5347 case OPC_DMULTU_G_2E:
5348 case OPC_DMULTU_G_2F:
5349 #endif
5350 t0 = tcg_temp_new();
5351 t1 = tcg_temp_new();
5352 break;
5353 default:
5354 t0 = tcg_temp_local_new();
5355 t1 = tcg_temp_local_new();
5356 break;
5359 gen_load_gpr(t0, rs);
5360 gen_load_gpr(t1, rt);
5362 switch (opc) {
5363 case OPC_MULT_G_2E:
5364 case OPC_MULT_G_2F:
5365 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5366 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5367 break;
5368 case OPC_MULTU_G_2E:
5369 case OPC_MULTU_G_2F:
5370 tcg_gen_ext32u_tl(t0, t0);
5371 tcg_gen_ext32u_tl(t1, t1);
5372 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5373 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5374 break;
5375 case OPC_DIV_G_2E:
5376 case OPC_DIV_G_2F:
5378 TCGLabel *l1 = gen_new_label();
5379 TCGLabel *l2 = gen_new_label();
5380 TCGLabel *l3 = gen_new_label();
5381 tcg_gen_ext32s_tl(t0, t0);
5382 tcg_gen_ext32s_tl(t1, t1);
5383 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5384 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5385 tcg_gen_br(l3);
5386 gen_set_label(l1);
5387 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5388 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5389 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5390 tcg_gen_br(l3);
5391 gen_set_label(l2);
5392 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5393 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5394 gen_set_label(l3);
5396 break;
5397 case OPC_DIVU_G_2E:
5398 case OPC_DIVU_G_2F:
5400 TCGLabel *l1 = gen_new_label();
5401 TCGLabel *l2 = gen_new_label();
5402 tcg_gen_ext32u_tl(t0, t0);
5403 tcg_gen_ext32u_tl(t1, t1);
5404 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5405 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5406 tcg_gen_br(l2);
5407 gen_set_label(l1);
5408 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5409 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5410 gen_set_label(l2);
5412 break;
5413 case OPC_MOD_G_2E:
5414 case OPC_MOD_G_2F:
5416 TCGLabel *l1 = gen_new_label();
5417 TCGLabel *l2 = gen_new_label();
5418 TCGLabel *l3 = gen_new_label();
5419 tcg_gen_ext32u_tl(t0, t0);
5420 tcg_gen_ext32u_tl(t1, t1);
5421 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5422 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5423 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5424 gen_set_label(l1);
5425 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5426 tcg_gen_br(l3);
5427 gen_set_label(l2);
5428 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5429 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5430 gen_set_label(l3);
5432 break;
5433 case OPC_MODU_G_2E:
5434 case OPC_MODU_G_2F:
5436 TCGLabel *l1 = gen_new_label();
5437 TCGLabel *l2 = gen_new_label();
5438 tcg_gen_ext32u_tl(t0, t0);
5439 tcg_gen_ext32u_tl(t1, t1);
5440 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5441 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5442 tcg_gen_br(l2);
5443 gen_set_label(l1);
5444 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5445 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5446 gen_set_label(l2);
5448 break;
5449 #if defined(TARGET_MIPS64)
5450 case OPC_DMULT_G_2E:
5451 case OPC_DMULT_G_2F:
5452 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5453 break;
5454 case OPC_DMULTU_G_2E:
5455 case OPC_DMULTU_G_2F:
5456 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5457 break;
5458 case OPC_DDIV_G_2E:
5459 case OPC_DDIV_G_2F:
5461 TCGLabel *l1 = gen_new_label();
5462 TCGLabel *l2 = gen_new_label();
5463 TCGLabel *l3 = gen_new_label();
5464 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5465 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5466 tcg_gen_br(l3);
5467 gen_set_label(l1);
5468 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5469 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5470 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5471 tcg_gen_br(l3);
5472 gen_set_label(l2);
5473 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5474 gen_set_label(l3);
5476 break;
5477 case OPC_DDIVU_G_2E:
5478 case OPC_DDIVU_G_2F:
5480 TCGLabel *l1 = gen_new_label();
5481 TCGLabel *l2 = gen_new_label();
5482 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5483 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5484 tcg_gen_br(l2);
5485 gen_set_label(l1);
5486 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5487 gen_set_label(l2);
5489 break;
5490 case OPC_DMOD_G_2E:
5491 case OPC_DMOD_G_2F:
5493 TCGLabel *l1 = gen_new_label();
5494 TCGLabel *l2 = gen_new_label();
5495 TCGLabel *l3 = gen_new_label();
5496 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5497 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5498 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5499 gen_set_label(l1);
5500 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5501 tcg_gen_br(l3);
5502 gen_set_label(l2);
5503 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5504 gen_set_label(l3);
5506 break;
5507 case OPC_DMODU_G_2E:
5508 case OPC_DMODU_G_2F:
5510 TCGLabel *l1 = gen_new_label();
5511 TCGLabel *l2 = gen_new_label();
5512 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5513 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5514 tcg_gen_br(l2);
5515 gen_set_label(l1);
5516 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5517 gen_set_label(l2);
5519 break;
5520 #endif
5523 tcg_temp_free(t0);
5524 tcg_temp_free(t1);
5527 /* Loongson multimedia instructions */
5528 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5530 uint32_t opc, shift_max;
5531 TCGv_i64 t0, t1;
5532 TCGCond cond;
5534 opc = MASK_LMI(ctx->opcode);
5535 switch (opc) {
5536 case OPC_ADD_CP2:
5537 case OPC_SUB_CP2:
5538 case OPC_DADD_CP2:
5539 case OPC_DSUB_CP2:
5540 t0 = tcg_temp_local_new_i64();
5541 t1 = tcg_temp_local_new_i64();
5542 break;
5543 default:
5544 t0 = tcg_temp_new_i64();
5545 t1 = tcg_temp_new_i64();
5546 break;
5549 check_cp1_enabled(ctx);
5550 gen_load_fpr64(ctx, t0, rs);
5551 gen_load_fpr64(ctx, t1, rt);
5553 switch (opc) {
5554 case OPC_PADDSH:
5555 gen_helper_paddsh(t0, t0, t1);
5556 break;
5557 case OPC_PADDUSH:
5558 gen_helper_paddush(t0, t0, t1);
5559 break;
5560 case OPC_PADDH:
5561 gen_helper_paddh(t0, t0, t1);
5562 break;
5563 case OPC_PADDW:
5564 gen_helper_paddw(t0, t0, t1);
5565 break;
5566 case OPC_PADDSB:
5567 gen_helper_paddsb(t0, t0, t1);
5568 break;
5569 case OPC_PADDUSB:
5570 gen_helper_paddusb(t0, t0, t1);
5571 break;
5572 case OPC_PADDB:
5573 gen_helper_paddb(t0, t0, t1);
5574 break;
5576 case OPC_PSUBSH:
5577 gen_helper_psubsh(t0, t0, t1);
5578 break;
5579 case OPC_PSUBUSH:
5580 gen_helper_psubush(t0, t0, t1);
5581 break;
5582 case OPC_PSUBH:
5583 gen_helper_psubh(t0, t0, t1);
5584 break;
5585 case OPC_PSUBW:
5586 gen_helper_psubw(t0, t0, t1);
5587 break;
5588 case OPC_PSUBSB:
5589 gen_helper_psubsb(t0, t0, t1);
5590 break;
5591 case OPC_PSUBUSB:
5592 gen_helper_psubusb(t0, t0, t1);
5593 break;
5594 case OPC_PSUBB:
5595 gen_helper_psubb(t0, t0, t1);
5596 break;
5598 case OPC_PSHUFH:
5599 gen_helper_pshufh(t0, t0, t1);
5600 break;
5601 case OPC_PACKSSWH:
5602 gen_helper_packsswh(t0, t0, t1);
5603 break;
5604 case OPC_PACKSSHB:
5605 gen_helper_packsshb(t0, t0, t1);
5606 break;
5607 case OPC_PACKUSHB:
5608 gen_helper_packushb(t0, t0, t1);
5609 break;
5611 case OPC_PUNPCKLHW:
5612 gen_helper_punpcklhw(t0, t0, t1);
5613 break;
5614 case OPC_PUNPCKHHW:
5615 gen_helper_punpckhhw(t0, t0, t1);
5616 break;
5617 case OPC_PUNPCKLBH:
5618 gen_helper_punpcklbh(t0, t0, t1);
5619 break;
5620 case OPC_PUNPCKHBH:
5621 gen_helper_punpckhbh(t0, t0, t1);
5622 break;
5623 case OPC_PUNPCKLWD:
5624 gen_helper_punpcklwd(t0, t0, t1);
5625 break;
5626 case OPC_PUNPCKHWD:
5627 gen_helper_punpckhwd(t0, t0, t1);
5628 break;
5630 case OPC_PAVGH:
5631 gen_helper_pavgh(t0, t0, t1);
5632 break;
5633 case OPC_PAVGB:
5634 gen_helper_pavgb(t0, t0, t1);
5635 break;
5636 case OPC_PMAXSH:
5637 gen_helper_pmaxsh(t0, t0, t1);
5638 break;
5639 case OPC_PMINSH:
5640 gen_helper_pminsh(t0, t0, t1);
5641 break;
5642 case OPC_PMAXUB:
5643 gen_helper_pmaxub(t0, t0, t1);
5644 break;
5645 case OPC_PMINUB:
5646 gen_helper_pminub(t0, t0, t1);
5647 break;
5649 case OPC_PCMPEQW:
5650 gen_helper_pcmpeqw(t0, t0, t1);
5651 break;
5652 case OPC_PCMPGTW:
5653 gen_helper_pcmpgtw(t0, t0, t1);
5654 break;
5655 case OPC_PCMPEQH:
5656 gen_helper_pcmpeqh(t0, t0, t1);
5657 break;
5658 case OPC_PCMPGTH:
5659 gen_helper_pcmpgth(t0, t0, t1);
5660 break;
5661 case OPC_PCMPEQB:
5662 gen_helper_pcmpeqb(t0, t0, t1);
5663 break;
5664 case OPC_PCMPGTB:
5665 gen_helper_pcmpgtb(t0, t0, t1);
5666 break;
5668 case OPC_PSLLW:
5669 gen_helper_psllw(t0, t0, t1);
5670 break;
5671 case OPC_PSLLH:
5672 gen_helper_psllh(t0, t0, t1);
5673 break;
5674 case OPC_PSRLW:
5675 gen_helper_psrlw(t0, t0, t1);
5676 break;
5677 case OPC_PSRLH:
5678 gen_helper_psrlh(t0, t0, t1);
5679 break;
5680 case OPC_PSRAW:
5681 gen_helper_psraw(t0, t0, t1);
5682 break;
5683 case OPC_PSRAH:
5684 gen_helper_psrah(t0, t0, t1);
5685 break;
5687 case OPC_PMULLH:
5688 gen_helper_pmullh(t0, t0, t1);
5689 break;
5690 case OPC_PMULHH:
5691 gen_helper_pmulhh(t0, t0, t1);
5692 break;
5693 case OPC_PMULHUH:
5694 gen_helper_pmulhuh(t0, t0, t1);
5695 break;
5696 case OPC_PMADDHW:
5697 gen_helper_pmaddhw(t0, t0, t1);
5698 break;
5700 case OPC_PASUBUB:
5701 gen_helper_pasubub(t0, t0, t1);
5702 break;
5703 case OPC_BIADD:
5704 gen_helper_biadd(t0, t0);
5705 break;
5706 case OPC_PMOVMSKB:
5707 gen_helper_pmovmskb(t0, t0);
5708 break;
5710 case OPC_PADDD:
5711 tcg_gen_add_i64(t0, t0, t1);
5712 break;
5713 case OPC_PSUBD:
5714 tcg_gen_sub_i64(t0, t0, t1);
5715 break;
5716 case OPC_XOR_CP2:
5717 tcg_gen_xor_i64(t0, t0, t1);
5718 break;
5719 case OPC_NOR_CP2:
5720 tcg_gen_nor_i64(t0, t0, t1);
5721 break;
5722 case OPC_AND_CP2:
5723 tcg_gen_and_i64(t0, t0, t1);
5724 break;
5725 case OPC_OR_CP2:
5726 tcg_gen_or_i64(t0, t0, t1);
5727 break;
5729 case OPC_PANDN:
5730 tcg_gen_andc_i64(t0, t1, t0);
5731 break;
5733 case OPC_PINSRH_0:
5734 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5735 break;
5736 case OPC_PINSRH_1:
5737 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5738 break;
5739 case OPC_PINSRH_2:
5740 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5741 break;
5742 case OPC_PINSRH_3:
5743 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5744 break;
5746 case OPC_PEXTRH:
5747 tcg_gen_andi_i64(t1, t1, 3);
5748 tcg_gen_shli_i64(t1, t1, 4);
5749 tcg_gen_shr_i64(t0, t0, t1);
5750 tcg_gen_ext16u_i64(t0, t0);
5751 break;
5753 case OPC_ADDU_CP2:
5754 tcg_gen_add_i64(t0, t0, t1);
5755 tcg_gen_ext32s_i64(t0, t0);
5756 break;
5757 case OPC_SUBU_CP2:
5758 tcg_gen_sub_i64(t0, t0, t1);
5759 tcg_gen_ext32s_i64(t0, t0);
5760 break;
5762 case OPC_SLL_CP2:
5763 shift_max = 32;
5764 goto do_shift;
5765 case OPC_SRL_CP2:
5766 shift_max = 32;
5767 goto do_shift;
5768 case OPC_SRA_CP2:
5769 shift_max = 32;
5770 goto do_shift;
5771 case OPC_DSLL_CP2:
5772 shift_max = 64;
5773 goto do_shift;
5774 case OPC_DSRL_CP2:
5775 shift_max = 64;
5776 goto do_shift;
5777 case OPC_DSRA_CP2:
5778 shift_max = 64;
5779 goto do_shift;
5780 do_shift:
5781 /* Make sure shift count isn't TCG undefined behaviour. */
5782 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5784 switch (opc) {
5785 case OPC_SLL_CP2:
5786 case OPC_DSLL_CP2:
5787 tcg_gen_shl_i64(t0, t0, t1);
5788 break;
5789 case OPC_SRA_CP2:
5790 case OPC_DSRA_CP2:
5792 * Since SRA is UndefinedResult without sign-extended inputs,
5793 * we can treat SRA and DSRA the same.
5795 tcg_gen_sar_i64(t0, t0, t1);
5796 break;
5797 case OPC_SRL_CP2:
5798 /* We want to shift in zeros for SRL; zero-extend first. */
5799 tcg_gen_ext32u_i64(t0, t0);
5800 /* FALLTHRU */
5801 case OPC_DSRL_CP2:
5802 tcg_gen_shr_i64(t0, t0, t1);
5803 break;
5806 if (shift_max == 32) {
5807 tcg_gen_ext32s_i64(t0, t0);
5810 /* Shifts larger than MAX produce zero. */
5811 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5812 tcg_gen_neg_i64(t1, t1);
5813 tcg_gen_and_i64(t0, t0, t1);
5814 break;
5816 case OPC_ADD_CP2:
5817 case OPC_DADD_CP2:
5819 TCGv_i64 t2 = tcg_temp_new_i64();
5820 TCGLabel *lab = gen_new_label();
5822 tcg_gen_mov_i64(t2, t0);
5823 tcg_gen_add_i64(t0, t1, t2);
5824 if (opc == OPC_ADD_CP2) {
5825 tcg_gen_ext32s_i64(t0, t0);
5827 tcg_gen_xor_i64(t1, t1, t2);
5828 tcg_gen_xor_i64(t2, t2, t0);
5829 tcg_gen_andc_i64(t1, t2, t1);
5830 tcg_temp_free_i64(t2);
5831 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5832 generate_exception(ctx, EXCP_OVERFLOW);
5833 gen_set_label(lab);
5834 break;
5837 case OPC_SUB_CP2:
5838 case OPC_DSUB_CP2:
5840 TCGv_i64 t2 = tcg_temp_new_i64();
5841 TCGLabel *lab = gen_new_label();
5843 tcg_gen_mov_i64(t2, t0);
5844 tcg_gen_sub_i64(t0, t1, t2);
5845 if (opc == OPC_SUB_CP2) {
5846 tcg_gen_ext32s_i64(t0, t0);
5848 tcg_gen_xor_i64(t1, t1, t2);
5849 tcg_gen_xor_i64(t2, t2, t0);
5850 tcg_gen_and_i64(t1, t1, t2);
5851 tcg_temp_free_i64(t2);
5852 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5853 generate_exception(ctx, EXCP_OVERFLOW);
5854 gen_set_label(lab);
5855 break;
5858 case OPC_PMULUW:
5859 tcg_gen_ext32u_i64(t0, t0);
5860 tcg_gen_ext32u_i64(t1, t1);
5861 tcg_gen_mul_i64(t0, t0, t1);
5862 break;
5864 case OPC_SEQU_CP2:
5865 case OPC_SEQ_CP2:
5866 cond = TCG_COND_EQ;
5867 goto do_cc_cond;
5868 break;
5869 case OPC_SLTU_CP2:
5870 cond = TCG_COND_LTU;
5871 goto do_cc_cond;
5872 break;
5873 case OPC_SLT_CP2:
5874 cond = TCG_COND_LT;
5875 goto do_cc_cond;
5876 break;
5877 case OPC_SLEU_CP2:
5878 cond = TCG_COND_LEU;
5879 goto do_cc_cond;
5880 break;
5881 case OPC_SLE_CP2:
5882 cond = TCG_COND_LE;
5883 do_cc_cond:
5885 int cc = (ctx->opcode >> 8) & 0x7;
5886 TCGv_i64 t64 = tcg_temp_new_i64();
5887 TCGv_i32 t32 = tcg_temp_new_i32();
5889 tcg_gen_setcond_i64(cond, t64, t0, t1);
5890 tcg_gen_extrl_i64_i32(t32, t64);
5891 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5892 get_fp_bit(cc), 1);
5894 tcg_temp_free_i32(t32);
5895 tcg_temp_free_i64(t64);
5897 goto no_rd;
5898 break;
5899 default:
5900 MIPS_INVAL("loongson_cp2");
5901 generate_exception_end(ctx, EXCP_RI);
5902 return;
5905 gen_store_fpr64(ctx, t0, rd);
5907 no_rd:
5908 tcg_temp_free_i64(t0);
5909 tcg_temp_free_i64(t1);
5912 /* Traps */
5913 static void gen_trap(DisasContext *ctx, uint32_t opc,
5914 int rs, int rt, int16_t imm)
5916 int cond;
5917 TCGv t0 = tcg_temp_new();
5918 TCGv t1 = tcg_temp_new();
5920 cond = 0;
5921 /* Load needed operands */
5922 switch (opc) {
5923 case OPC_TEQ:
5924 case OPC_TGE:
5925 case OPC_TGEU:
5926 case OPC_TLT:
5927 case OPC_TLTU:
5928 case OPC_TNE:
5929 /* Compare two registers */
5930 if (rs != rt) {
5931 gen_load_gpr(t0, rs);
5932 gen_load_gpr(t1, rt);
5933 cond = 1;
5935 break;
5936 case OPC_TEQI:
5937 case OPC_TGEI:
5938 case OPC_TGEIU:
5939 case OPC_TLTI:
5940 case OPC_TLTIU:
5941 case OPC_TNEI:
5942 /* Compare register to immediate */
5943 if (rs != 0 || imm != 0) {
5944 gen_load_gpr(t0, rs);
5945 tcg_gen_movi_tl(t1, (int32_t)imm);
5946 cond = 1;
5948 break;
5950 if (cond == 0) {
5951 switch (opc) {
5952 case OPC_TEQ: /* rs == rs */
5953 case OPC_TEQI: /* r0 == 0 */
5954 case OPC_TGE: /* rs >= rs */
5955 case OPC_TGEI: /* r0 >= 0 */
5956 case OPC_TGEU: /* rs >= rs unsigned */
5957 case OPC_TGEIU: /* r0 >= 0 unsigned */
5958 /* Always trap */
5959 generate_exception_end(ctx, EXCP_TRAP);
5960 break;
5961 case OPC_TLT: /* rs < rs */
5962 case OPC_TLTI: /* r0 < 0 */
5963 case OPC_TLTU: /* rs < rs unsigned */
5964 case OPC_TLTIU: /* r0 < 0 unsigned */
5965 case OPC_TNE: /* rs != rs */
5966 case OPC_TNEI: /* r0 != 0 */
5967 /* Never trap: treat as NOP. */
5968 break;
5970 } else {
5971 TCGLabel *l1 = gen_new_label();
5973 switch (opc) {
5974 case OPC_TEQ:
5975 case OPC_TEQI:
5976 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5977 break;
5978 case OPC_TGE:
5979 case OPC_TGEI:
5980 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5981 break;
5982 case OPC_TGEU:
5983 case OPC_TGEIU:
5984 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5985 break;
5986 case OPC_TLT:
5987 case OPC_TLTI:
5988 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5989 break;
5990 case OPC_TLTU:
5991 case OPC_TLTIU:
5992 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5993 break;
5994 case OPC_TNE:
5995 case OPC_TNEI:
5996 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5997 break;
5999 generate_exception(ctx, EXCP_TRAP);
6000 gen_set_label(l1);
6002 tcg_temp_free(t0);
6003 tcg_temp_free(t1);
6006 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6008 if (unlikely(ctx->base.singlestep_enabled)) {
6009 return false;
6012 #ifndef CONFIG_USER_ONLY
6013 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6014 #else
6015 return true;
6016 #endif
6019 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6021 if (use_goto_tb(ctx, dest)) {
6022 tcg_gen_goto_tb(n);
6023 gen_save_pc(dest);
6024 tcg_gen_exit_tb(ctx->base.tb, n);
6025 } else {
6026 gen_save_pc(dest);
6027 if (ctx->base.singlestep_enabled) {
6028 save_cpu_state(ctx, 0);
6029 gen_helper_raise_exception_debug(cpu_env);
6031 tcg_gen_lookup_and_goto_ptr();
6035 /* Branches (before delay slot) */
6036 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6037 int insn_bytes,
6038 int rs, int rt, int32_t offset,
6039 int delayslot_size)
6041 target_ulong btgt = -1;
6042 int blink = 0;
6043 int bcond_compute = 0;
6044 TCGv t0 = tcg_temp_new();
6045 TCGv t1 = tcg_temp_new();
6047 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6048 #ifdef MIPS_DEBUG_DISAS
6049 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6050 TARGET_FMT_lx "\n", ctx->base.pc_next);
6051 #endif
6052 generate_exception_end(ctx, EXCP_RI);
6053 goto out;
6056 /* Load needed operands */
6057 switch (opc) {
6058 case OPC_BEQ:
6059 case OPC_BEQL:
6060 case OPC_BNE:
6061 case OPC_BNEL:
6062 /* Compare two registers */
6063 if (rs != rt) {
6064 gen_load_gpr(t0, rs);
6065 gen_load_gpr(t1, rt);
6066 bcond_compute = 1;
6068 btgt = ctx->base.pc_next + insn_bytes + offset;
6069 break;
6070 case OPC_BGEZ:
6071 case OPC_BGEZAL:
6072 case OPC_BGEZALL:
6073 case OPC_BGEZL:
6074 case OPC_BGTZ:
6075 case OPC_BGTZL:
6076 case OPC_BLEZ:
6077 case OPC_BLEZL:
6078 case OPC_BLTZ:
6079 case OPC_BLTZAL:
6080 case OPC_BLTZALL:
6081 case OPC_BLTZL:
6082 /* Compare to zero */
6083 if (rs != 0) {
6084 gen_load_gpr(t0, rs);
6085 bcond_compute = 1;
6087 btgt = ctx->base.pc_next + insn_bytes + offset;
6088 break;
6089 case OPC_BPOSGE32:
6090 #if defined(TARGET_MIPS64)
6091 case OPC_BPOSGE64:
6092 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6093 #else
6094 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6095 #endif
6096 bcond_compute = 1;
6097 btgt = ctx->base.pc_next + insn_bytes + offset;
6098 break;
6099 case OPC_J:
6100 case OPC_JAL:
6101 case OPC_JALX:
6102 /* Jump to immediate */
6103 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6104 (uint32_t)offset;
6105 break;
6106 case OPC_JR:
6107 case OPC_JALR:
6108 /* Jump to register */
6109 if (offset != 0 && offset != 16) {
6111 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6112 * others are reserved.
6114 MIPS_INVAL("jump hint");
6115 generate_exception_end(ctx, EXCP_RI);
6116 goto out;
6118 gen_load_gpr(btarget, rs);
6119 break;
6120 default:
6121 MIPS_INVAL("branch/jump");
6122 generate_exception_end(ctx, EXCP_RI);
6123 goto out;
6125 if (bcond_compute == 0) {
6126 /* No condition to be computed */
6127 switch (opc) {
6128 case OPC_BEQ: /* rx == rx */
6129 case OPC_BEQL: /* rx == rx likely */
6130 case OPC_BGEZ: /* 0 >= 0 */
6131 case OPC_BGEZL: /* 0 >= 0 likely */
6132 case OPC_BLEZ: /* 0 <= 0 */
6133 case OPC_BLEZL: /* 0 <= 0 likely */
6134 /* Always take */
6135 ctx->hflags |= MIPS_HFLAG_B;
6136 break;
6137 case OPC_BGEZAL: /* 0 >= 0 */
6138 case OPC_BGEZALL: /* 0 >= 0 likely */
6139 /* Always take and link */
6140 blink = 31;
6141 ctx->hflags |= MIPS_HFLAG_B;
6142 break;
6143 case OPC_BNE: /* rx != rx */
6144 case OPC_BGTZ: /* 0 > 0 */
6145 case OPC_BLTZ: /* 0 < 0 */
6146 /* Treat as NOP. */
6147 goto out;
6148 case OPC_BLTZAL: /* 0 < 0 */
6150 * Handle as an unconditional branch to get correct delay
6151 * slot checking.
6153 blink = 31;
6154 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6155 ctx->hflags |= MIPS_HFLAG_B;
6156 break;
6157 case OPC_BLTZALL: /* 0 < 0 likely */
6158 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6159 /* Skip the instruction in the delay slot */
6160 ctx->base.pc_next += 4;
6161 goto out;
6162 case OPC_BNEL: /* rx != rx likely */
6163 case OPC_BGTZL: /* 0 > 0 likely */
6164 case OPC_BLTZL: /* 0 < 0 likely */
6165 /* Skip the instruction in the delay slot */
6166 ctx->base.pc_next += 4;
6167 goto out;
6168 case OPC_J:
6169 ctx->hflags |= MIPS_HFLAG_B;
6170 break;
6171 case OPC_JALX:
6172 ctx->hflags |= MIPS_HFLAG_BX;
6173 /* Fallthrough */
6174 case OPC_JAL:
6175 blink = 31;
6176 ctx->hflags |= MIPS_HFLAG_B;
6177 break;
6178 case OPC_JR:
6179 ctx->hflags |= MIPS_HFLAG_BR;
6180 break;
6181 case OPC_JALR:
6182 blink = rt;
6183 ctx->hflags |= MIPS_HFLAG_BR;
6184 break;
6185 default:
6186 MIPS_INVAL("branch/jump");
6187 generate_exception_end(ctx, EXCP_RI);
6188 goto out;
6190 } else {
6191 switch (opc) {
6192 case OPC_BEQ:
6193 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6194 goto not_likely;
6195 case OPC_BEQL:
6196 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6197 goto likely;
6198 case OPC_BNE:
6199 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6200 goto not_likely;
6201 case OPC_BNEL:
6202 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6203 goto likely;
6204 case OPC_BGEZ:
6205 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6206 goto not_likely;
6207 case OPC_BGEZL:
6208 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6209 goto likely;
6210 case OPC_BGEZAL:
6211 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6212 blink = 31;
6213 goto not_likely;
6214 case OPC_BGEZALL:
6215 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6216 blink = 31;
6217 goto likely;
6218 case OPC_BGTZ:
6219 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6220 goto not_likely;
6221 case OPC_BGTZL:
6222 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6223 goto likely;
6224 case OPC_BLEZ:
6225 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6226 goto not_likely;
6227 case OPC_BLEZL:
6228 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6229 goto likely;
6230 case OPC_BLTZ:
6231 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6232 goto not_likely;
6233 case OPC_BLTZL:
6234 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6235 goto likely;
6236 case OPC_BPOSGE32:
6237 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6238 goto not_likely;
6239 #if defined(TARGET_MIPS64)
6240 case OPC_BPOSGE64:
6241 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6242 goto not_likely;
6243 #endif
6244 case OPC_BLTZAL:
6245 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6246 blink = 31;
6247 not_likely:
6248 ctx->hflags |= MIPS_HFLAG_BC;
6249 break;
6250 case OPC_BLTZALL:
6251 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6252 blink = 31;
6253 likely:
6254 ctx->hflags |= MIPS_HFLAG_BL;
6255 break;
6256 default:
6257 MIPS_INVAL("conditional branch/jump");
6258 generate_exception_end(ctx, EXCP_RI);
6259 goto out;
6263 ctx->btarget = btgt;
6265 switch (delayslot_size) {
6266 case 2:
6267 ctx->hflags |= MIPS_HFLAG_BDS16;
6268 break;
6269 case 4:
6270 ctx->hflags |= MIPS_HFLAG_BDS32;
6271 break;
6274 if (blink > 0) {
6275 int post_delay = insn_bytes + delayslot_size;
6276 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6278 tcg_gen_movi_tl(cpu_gpr[blink],
6279 ctx->base.pc_next + post_delay + lowbit);
6282 out:
6283 if (insn_bytes == 2) {
6284 ctx->hflags |= MIPS_HFLAG_B16;
6286 tcg_temp_free(t0);
6287 tcg_temp_free(t1);
6291 /* nanoMIPS Branches */
6292 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6293 int insn_bytes,
6294 int rs, int rt, int32_t offset)
6296 target_ulong btgt = -1;
6297 int bcond_compute = 0;
6298 TCGv t0 = tcg_temp_new();
6299 TCGv t1 = tcg_temp_new();
6301 /* Load needed operands */
6302 switch (opc) {
6303 case OPC_BEQ:
6304 case OPC_BNE:
6305 /* Compare two registers */
6306 if (rs != rt) {
6307 gen_load_gpr(t0, rs);
6308 gen_load_gpr(t1, rt);
6309 bcond_compute = 1;
6311 btgt = ctx->base.pc_next + insn_bytes + offset;
6312 break;
6313 case OPC_BGEZAL:
6314 /* Compare to zero */
6315 if (rs != 0) {
6316 gen_load_gpr(t0, rs);
6317 bcond_compute = 1;
6319 btgt = ctx->base.pc_next + insn_bytes + offset;
6320 break;
6321 case OPC_BPOSGE32:
6322 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6323 bcond_compute = 1;
6324 btgt = ctx->base.pc_next + insn_bytes + offset;
6325 break;
6326 case OPC_JR:
6327 case OPC_JALR:
6328 /* Jump to register */
6329 if (offset != 0 && offset != 16) {
6331 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6332 * others are reserved.
6334 MIPS_INVAL("jump hint");
6335 generate_exception_end(ctx, EXCP_RI);
6336 goto out;
6338 gen_load_gpr(btarget, rs);
6339 break;
6340 default:
6341 MIPS_INVAL("branch/jump");
6342 generate_exception_end(ctx, EXCP_RI);
6343 goto out;
6345 if (bcond_compute == 0) {
6346 /* No condition to be computed */
6347 switch (opc) {
6348 case OPC_BEQ: /* rx == rx */
6349 /* Always take */
6350 ctx->hflags |= MIPS_HFLAG_B;
6351 break;
6352 case OPC_BGEZAL: /* 0 >= 0 */
6353 /* Always take and link */
6354 tcg_gen_movi_tl(cpu_gpr[31],
6355 ctx->base.pc_next + insn_bytes);
6356 ctx->hflags |= MIPS_HFLAG_B;
6357 break;
6358 case OPC_BNE: /* rx != rx */
6359 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6360 /* Skip the instruction in the delay slot */
6361 ctx->base.pc_next += 4;
6362 goto out;
6363 case OPC_JR:
6364 ctx->hflags |= MIPS_HFLAG_BR;
6365 break;
6366 case OPC_JALR:
6367 if (rt > 0) {
6368 tcg_gen_movi_tl(cpu_gpr[rt],
6369 ctx->base.pc_next + insn_bytes);
6371 ctx->hflags |= MIPS_HFLAG_BR;
6372 break;
6373 default:
6374 MIPS_INVAL("branch/jump");
6375 generate_exception_end(ctx, EXCP_RI);
6376 goto out;
6378 } else {
6379 switch (opc) {
6380 case OPC_BEQ:
6381 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6382 goto not_likely;
6383 case OPC_BNE:
6384 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6385 goto not_likely;
6386 case OPC_BGEZAL:
6387 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6388 tcg_gen_movi_tl(cpu_gpr[31],
6389 ctx->base.pc_next + insn_bytes);
6390 goto not_likely;
6391 case OPC_BPOSGE32:
6392 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6393 not_likely:
6394 ctx->hflags |= MIPS_HFLAG_BC;
6395 break;
6396 default:
6397 MIPS_INVAL("conditional branch/jump");
6398 generate_exception_end(ctx, EXCP_RI);
6399 goto out;
6403 ctx->btarget = btgt;
6405 out:
6406 if (insn_bytes == 2) {
6407 ctx->hflags |= MIPS_HFLAG_B16;
6409 tcg_temp_free(t0);
6410 tcg_temp_free(t1);
6414 /* special3 bitfield operations */
6415 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6416 int rs, int lsb, int msb)
6418 TCGv t0 = tcg_temp_new();
6419 TCGv t1 = tcg_temp_new();
6421 gen_load_gpr(t1, rs);
6422 switch (opc) {
6423 case OPC_EXT:
6424 if (lsb + msb > 31) {
6425 goto fail;
6427 if (msb != 31) {
6428 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6429 } else {
6431 * The two checks together imply that lsb == 0,
6432 * so this is a simple sign-extension.
6434 tcg_gen_ext32s_tl(t0, t1);
6436 break;
6437 #if defined(TARGET_MIPS64)
6438 case OPC_DEXTU:
6439 lsb += 32;
6440 goto do_dext;
6441 case OPC_DEXTM:
6442 msb += 32;
6443 goto do_dext;
6444 case OPC_DEXT:
6445 do_dext:
6446 if (lsb + msb > 63) {
6447 goto fail;
6449 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6450 break;
6451 #endif
6452 case OPC_INS:
6453 if (lsb > msb) {
6454 goto fail;
6456 gen_load_gpr(t0, rt);
6457 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6458 tcg_gen_ext32s_tl(t0, t0);
6459 break;
6460 #if defined(TARGET_MIPS64)
6461 case OPC_DINSU:
6462 lsb += 32;
6463 /* FALLTHRU */
6464 case OPC_DINSM:
6465 msb += 32;
6466 /* FALLTHRU */
6467 case OPC_DINS:
6468 if (lsb > msb) {
6469 goto fail;
6471 gen_load_gpr(t0, rt);
6472 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6473 break;
6474 #endif
6475 default:
6476 fail:
6477 MIPS_INVAL("bitops");
6478 generate_exception_end(ctx, EXCP_RI);
6479 tcg_temp_free(t0);
6480 tcg_temp_free(t1);
6481 return;
6483 gen_store_gpr(t0, rt);
6484 tcg_temp_free(t0);
6485 tcg_temp_free(t1);
6488 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6490 TCGv t0;
6492 if (rd == 0) {
6493 /* If no destination, treat it as a NOP. */
6494 return;
6497 t0 = tcg_temp_new();
6498 gen_load_gpr(t0, rt);
6499 switch (op2) {
6500 case OPC_WSBH:
6502 TCGv t1 = tcg_temp_new();
6503 TCGv t2 = tcg_const_tl(0x00FF00FF);
6505 tcg_gen_shri_tl(t1, t0, 8);
6506 tcg_gen_and_tl(t1, t1, t2);
6507 tcg_gen_and_tl(t0, t0, t2);
6508 tcg_gen_shli_tl(t0, t0, 8);
6509 tcg_gen_or_tl(t0, t0, t1);
6510 tcg_temp_free(t2);
6511 tcg_temp_free(t1);
6512 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6514 break;
6515 case OPC_SEB:
6516 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6517 break;
6518 case OPC_SEH:
6519 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6520 break;
6521 #if defined(TARGET_MIPS64)
6522 case OPC_DSBH:
6524 TCGv t1 = tcg_temp_new();
6525 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6527 tcg_gen_shri_tl(t1, t0, 8);
6528 tcg_gen_and_tl(t1, t1, t2);
6529 tcg_gen_and_tl(t0, t0, t2);
6530 tcg_gen_shli_tl(t0, t0, 8);
6531 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6532 tcg_temp_free(t2);
6533 tcg_temp_free(t1);
6535 break;
6536 case OPC_DSHD:
6538 TCGv t1 = tcg_temp_new();
6539 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6541 tcg_gen_shri_tl(t1, t0, 16);
6542 tcg_gen_and_tl(t1, t1, t2);
6543 tcg_gen_and_tl(t0, t0, t2);
6544 tcg_gen_shli_tl(t0, t0, 16);
6545 tcg_gen_or_tl(t0, t0, t1);
6546 tcg_gen_shri_tl(t1, t0, 32);
6547 tcg_gen_shli_tl(t0, t0, 32);
6548 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6549 tcg_temp_free(t2);
6550 tcg_temp_free(t1);
6552 break;
6553 #endif
6554 default:
6555 MIPS_INVAL("bsfhl");
6556 generate_exception_end(ctx, EXCP_RI);
6557 tcg_temp_free(t0);
6558 return;
6560 tcg_temp_free(t0);
6563 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6564 int imm2)
6566 TCGv t0;
6567 TCGv t1;
6568 if (rd == 0) {
6569 /* Treat as NOP. */
6570 return;
6572 t0 = tcg_temp_new();
6573 t1 = tcg_temp_new();
6574 gen_load_gpr(t0, rs);
6575 gen_load_gpr(t1, rt);
6576 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6577 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6578 if (opc == OPC_LSA) {
6579 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6582 tcg_temp_free(t1);
6583 tcg_temp_free(t0);
6585 return;
6588 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6589 int rt, int bits)
6591 TCGv t0;
6592 if (rd == 0) {
6593 /* Treat as NOP. */
6594 return;
6596 t0 = tcg_temp_new();
6597 if (bits == 0 || bits == wordsz) {
6598 if (bits == 0) {
6599 gen_load_gpr(t0, rt);
6600 } else {
6601 gen_load_gpr(t0, rs);
6603 switch (wordsz) {
6604 case 32:
6605 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6606 break;
6607 #if defined(TARGET_MIPS64)
6608 case 64:
6609 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6610 break;
6611 #endif
6613 } else {
6614 TCGv t1 = tcg_temp_new();
6615 gen_load_gpr(t0, rt);
6616 gen_load_gpr(t1, rs);
6617 switch (wordsz) {
6618 case 32:
6620 TCGv_i64 t2 = tcg_temp_new_i64();
6621 tcg_gen_concat_tl_i64(t2, t1, t0);
6622 tcg_gen_shri_i64(t2, t2, 32 - bits);
6623 gen_move_low32(cpu_gpr[rd], t2);
6624 tcg_temp_free_i64(t2);
6626 break;
6627 #if defined(TARGET_MIPS64)
6628 case 64:
6629 tcg_gen_shli_tl(t0, t0, bits);
6630 tcg_gen_shri_tl(t1, t1, 64 - bits);
6631 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6632 break;
6633 #endif
6635 tcg_temp_free(t1);
6638 tcg_temp_free(t0);
6641 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6642 int bp)
6644 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6647 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6648 int shift)
6650 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6653 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6655 TCGv t0;
6656 if (rd == 0) {
6657 /* Treat as NOP. */
6658 return;
6660 t0 = tcg_temp_new();
6661 gen_load_gpr(t0, rt);
6662 switch (opc) {
6663 case OPC_BITSWAP:
6664 gen_helper_bitswap(cpu_gpr[rd], t0);
6665 break;
6666 #if defined(TARGET_MIPS64)
6667 case OPC_DBITSWAP:
6668 gen_helper_dbitswap(cpu_gpr[rd], t0);
6669 break;
6670 #endif
6672 tcg_temp_free(t0);
6675 #ifndef CONFIG_USER_ONLY
6676 /* CP0 (MMU and control) */
6677 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6679 TCGv_i64 t0 = tcg_temp_new_i64();
6680 TCGv_i64 t1 = tcg_temp_new_i64();
6682 tcg_gen_ext_tl_i64(t0, arg);
6683 tcg_gen_ld_i64(t1, cpu_env, off);
6684 #if defined(TARGET_MIPS64)
6685 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6686 #else
6687 tcg_gen_concat32_i64(t1, t1, t0);
6688 #endif
6689 tcg_gen_st_i64(t1, cpu_env, off);
6690 tcg_temp_free_i64(t1);
6691 tcg_temp_free_i64(t0);
6694 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6696 TCGv_i64 t0 = tcg_temp_new_i64();
6697 TCGv_i64 t1 = tcg_temp_new_i64();
6699 tcg_gen_ext_tl_i64(t0, arg);
6700 tcg_gen_ld_i64(t1, cpu_env, off);
6701 tcg_gen_concat32_i64(t1, t1, t0);
6702 tcg_gen_st_i64(t1, cpu_env, off);
6703 tcg_temp_free_i64(t1);
6704 tcg_temp_free_i64(t0);
6707 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6709 TCGv_i64 t0 = tcg_temp_new_i64();
6711 tcg_gen_ld_i64(t0, cpu_env, off);
6712 #if defined(TARGET_MIPS64)
6713 tcg_gen_shri_i64(t0, t0, 30);
6714 #else
6715 tcg_gen_shri_i64(t0, t0, 32);
6716 #endif
6717 gen_move_low32(arg, t0);
6718 tcg_temp_free_i64(t0);
6721 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6723 TCGv_i64 t0 = tcg_temp_new_i64();
6725 tcg_gen_ld_i64(t0, cpu_env, off);
6726 tcg_gen_shri_i64(t0, t0, 32 + shift);
6727 gen_move_low32(arg, t0);
6728 tcg_temp_free_i64(t0);
6731 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
6733 TCGv_i32 t0 = tcg_temp_new_i32();
6735 tcg_gen_ld_i32(t0, cpu_env, off);
6736 tcg_gen_ext_i32_tl(arg, t0);
6737 tcg_temp_free_i32(t0);
6740 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
6742 tcg_gen_ld_tl(arg, cpu_env, off);
6743 tcg_gen_ext32s_tl(arg, arg);
6746 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
6748 TCGv_i32 t0 = tcg_temp_new_i32();
6750 tcg_gen_trunc_tl_i32(t0, arg);
6751 tcg_gen_st_i32(t0, cpu_env, off);
6752 tcg_temp_free_i32(t0);
6755 #define CP0_CHECK(c) \
6756 do { \
6757 if (!(c)) { \
6758 goto cp0_unimplemented; \
6760 } while (0)
6762 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6764 const char *register_name = "invalid";
6766 switch (reg) {
6767 case CP0_REGISTER_02:
6768 switch (sel) {
6769 case 0:
6770 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6771 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6772 register_name = "EntryLo0";
6773 break;
6774 default:
6775 goto cp0_unimplemented;
6777 break;
6778 case CP0_REGISTER_03:
6779 switch (sel) {
6780 case CP0_REG03__ENTRYLO1:
6781 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6782 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6783 register_name = "EntryLo1";
6784 break;
6785 default:
6786 goto cp0_unimplemented;
6788 break;
6789 case CP0_REGISTER_09:
6790 switch (sel) {
6791 case CP0_REG09__SAAR:
6792 CP0_CHECK(ctx->saar);
6793 gen_helper_mfhc0_saar(arg, cpu_env);
6794 register_name = "SAAR";
6795 break;
6796 default:
6797 goto cp0_unimplemented;
6799 break;
6800 case CP0_REGISTER_17:
6801 switch (sel) {
6802 case CP0_REG17__LLADDR:
6803 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
6804 ctx->CP0_LLAddr_shift);
6805 register_name = "LLAddr";
6806 break;
6807 case CP0_REG17__MAAR:
6808 CP0_CHECK(ctx->mrp);
6809 gen_helper_mfhc0_maar(arg, cpu_env);
6810 register_name = "MAAR";
6811 break;
6812 default:
6813 goto cp0_unimplemented;
6815 break;
6816 case CP0_REGISTER_19:
6817 switch (sel) {
6818 case CP0_REG19__WATCHHI0:
6819 case CP0_REG19__WATCHHI1:
6820 case CP0_REG19__WATCHHI2:
6821 case CP0_REG19__WATCHHI3:
6822 case CP0_REG19__WATCHHI4:
6823 case CP0_REG19__WATCHHI5:
6824 case CP0_REG19__WATCHHI6:
6825 case CP0_REG19__WATCHHI7:
6826 /* upper 32 bits are only available when Config5MI != 0 */
6827 CP0_CHECK(ctx->mi);
6828 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
6829 register_name = "WatchHi";
6830 break;
6831 default:
6832 goto cp0_unimplemented;
6834 break;
6835 case CP0_REGISTER_28:
6836 switch (sel) {
6837 case 0:
6838 case 2:
6839 case 4:
6840 case 6:
6841 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6842 register_name = "TagLo";
6843 break;
6844 default:
6845 goto cp0_unimplemented;
6847 break;
6848 default:
6849 goto cp0_unimplemented;
6851 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
6852 return;
6854 cp0_unimplemented:
6855 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
6856 register_name, reg, sel);
6857 tcg_gen_movi_tl(arg, 0);
6860 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6862 const char *register_name = "invalid";
6863 uint64_t mask = ctx->PAMask >> 36;
6865 switch (reg) {
6866 case CP0_REGISTER_02:
6867 switch (sel) {
6868 case 0:
6869 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6870 tcg_gen_andi_tl(arg, arg, mask);
6871 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6872 register_name = "EntryLo0";
6873 break;
6874 default:
6875 goto cp0_unimplemented;
6877 break;
6878 case CP0_REGISTER_03:
6879 switch (sel) {
6880 case CP0_REG03__ENTRYLO1:
6881 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6882 tcg_gen_andi_tl(arg, arg, mask);
6883 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6884 register_name = "EntryLo1";
6885 break;
6886 default:
6887 goto cp0_unimplemented;
6889 break;
6890 case CP0_REGISTER_09:
6891 switch (sel) {
6892 case CP0_REG09__SAAR:
6893 CP0_CHECK(ctx->saar);
6894 gen_helper_mthc0_saar(cpu_env, arg);
6895 register_name = "SAAR";
6896 break;
6897 default:
6898 goto cp0_unimplemented;
6900 break;
6901 case CP0_REGISTER_17:
6902 switch (sel) {
6903 case CP0_REG17__LLADDR:
6905 * LLAddr is read-only (the only exception is bit 0 if LLB is
6906 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
6907 * relevant for modern MIPS cores supporting MTHC0, therefore
6908 * treating MTHC0 to LLAddr as NOP.
6910 register_name = "LLAddr";
6911 break;
6912 case CP0_REG17__MAAR:
6913 CP0_CHECK(ctx->mrp);
6914 gen_helper_mthc0_maar(cpu_env, arg);
6915 register_name = "MAAR";
6916 break;
6917 default:
6918 goto cp0_unimplemented;
6920 break;
6921 case CP0_REGISTER_19:
6922 switch (sel) {
6923 case CP0_REG19__WATCHHI0:
6924 case CP0_REG19__WATCHHI1:
6925 case CP0_REG19__WATCHHI2:
6926 case CP0_REG19__WATCHHI3:
6927 case CP0_REG19__WATCHHI4:
6928 case CP0_REG19__WATCHHI5:
6929 case CP0_REG19__WATCHHI6:
6930 case CP0_REG19__WATCHHI7:
6931 /* upper 32 bits are only available when Config5MI != 0 */
6932 CP0_CHECK(ctx->mi);
6933 gen_helper_0e1i(mthc0_watchhi, arg, sel);
6934 register_name = "WatchHi";
6935 break;
6936 default:
6937 goto cp0_unimplemented;
6939 break;
6940 case CP0_REGISTER_28:
6941 switch (sel) {
6942 case 0:
6943 case 2:
6944 case 4:
6945 case 6:
6946 tcg_gen_andi_tl(arg, arg, mask);
6947 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6948 register_name = "TagLo";
6949 break;
6950 default:
6951 goto cp0_unimplemented;
6953 break;
6954 default:
6955 goto cp0_unimplemented;
6957 trace_mips_translate_c0("mthc0", register_name, reg, sel);
6959 cp0_unimplemented:
6960 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
6961 register_name, reg, sel);
6964 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6966 if (ctx->insn_flags & ISA_MIPS32R6) {
6967 tcg_gen_movi_tl(arg, 0);
6968 } else {
6969 tcg_gen_movi_tl(arg, ~0);
6973 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6975 const char *register_name = "invalid";
6977 if (sel != 0) {
6978 check_insn(ctx, ISA_MIPS32);
6981 switch (reg) {
6982 case CP0_REGISTER_00:
6983 switch (sel) {
6984 case CP0_REG00__INDEX:
6985 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6986 register_name = "Index";
6987 break;
6988 case CP0_REG00__MVPCONTROL:
6989 CP0_CHECK(ctx->insn_flags & ASE_MT);
6990 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6991 register_name = "MVPControl";
6992 break;
6993 case CP0_REG00__MVPCONF0:
6994 CP0_CHECK(ctx->insn_flags & ASE_MT);
6995 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6996 register_name = "MVPConf0";
6997 break;
6998 case CP0_REG00__MVPCONF1:
6999 CP0_CHECK(ctx->insn_flags & ASE_MT);
7000 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7001 register_name = "MVPConf1";
7002 break;
7003 case CP0_REG00__VPCONTROL:
7004 CP0_CHECK(ctx->vp);
7005 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7006 register_name = "VPControl";
7007 break;
7008 default:
7009 goto cp0_unimplemented;
7011 break;
7012 case CP0_REGISTER_01:
7013 switch (sel) {
7014 case CP0_REG01__RANDOM:
7015 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7016 gen_helper_mfc0_random(arg, cpu_env);
7017 register_name = "Random";
7018 break;
7019 case CP0_REG01__VPECONTROL:
7020 CP0_CHECK(ctx->insn_flags & ASE_MT);
7021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7022 register_name = "VPEControl";
7023 break;
7024 case CP0_REG01__VPECONF0:
7025 CP0_CHECK(ctx->insn_flags & ASE_MT);
7026 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7027 register_name = "VPEConf0";
7028 break;
7029 case CP0_REG01__VPECONF1:
7030 CP0_CHECK(ctx->insn_flags & ASE_MT);
7031 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7032 register_name = "VPEConf1";
7033 break;
7034 case CP0_REG01__YQMASK:
7035 CP0_CHECK(ctx->insn_flags & ASE_MT);
7036 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7037 register_name = "YQMask";
7038 break;
7039 case CP0_REG01__VPESCHEDULE:
7040 CP0_CHECK(ctx->insn_flags & ASE_MT);
7041 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7042 register_name = "VPESchedule";
7043 break;
7044 case CP0_REG01__VPESCHEFBACK:
7045 CP0_CHECK(ctx->insn_flags & ASE_MT);
7046 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7047 register_name = "VPEScheFBack";
7048 break;
7049 case CP0_REG01__VPEOPT:
7050 CP0_CHECK(ctx->insn_flags & ASE_MT);
7051 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7052 register_name = "VPEOpt";
7053 break;
7054 default:
7055 goto cp0_unimplemented;
7057 break;
7058 case CP0_REGISTER_02:
7059 switch (sel) {
7060 case CP0_REG02__ENTRYLO0:
7062 TCGv_i64 tmp = tcg_temp_new_i64();
7063 tcg_gen_ld_i64(tmp, cpu_env,
7064 offsetof(CPUMIPSState, CP0_EntryLo0));
7065 #if defined(TARGET_MIPS64)
7066 if (ctx->rxi) {
7067 /* Move RI/XI fields to bits 31:30 */
7068 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7069 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7071 #endif
7072 gen_move_low32(arg, tmp);
7073 tcg_temp_free_i64(tmp);
7075 register_name = "EntryLo0";
7076 break;
7077 case CP0_REG02__TCSTATUS:
7078 CP0_CHECK(ctx->insn_flags & ASE_MT);
7079 gen_helper_mfc0_tcstatus(arg, cpu_env);
7080 register_name = "TCStatus";
7081 break;
7082 case CP0_REG02__TCBIND:
7083 CP0_CHECK(ctx->insn_flags & ASE_MT);
7084 gen_helper_mfc0_tcbind(arg, cpu_env);
7085 register_name = "TCBind";
7086 break;
7087 case CP0_REG02__TCRESTART:
7088 CP0_CHECK(ctx->insn_flags & ASE_MT);
7089 gen_helper_mfc0_tcrestart(arg, cpu_env);
7090 register_name = "TCRestart";
7091 break;
7092 case CP0_REG02__TCHALT:
7093 CP0_CHECK(ctx->insn_flags & ASE_MT);
7094 gen_helper_mfc0_tchalt(arg, cpu_env);
7095 register_name = "TCHalt";
7096 break;
7097 case CP0_REG02__TCCONTEXT:
7098 CP0_CHECK(ctx->insn_flags & ASE_MT);
7099 gen_helper_mfc0_tccontext(arg, cpu_env);
7100 register_name = "TCContext";
7101 break;
7102 case CP0_REG02__TCSCHEDULE:
7103 CP0_CHECK(ctx->insn_flags & ASE_MT);
7104 gen_helper_mfc0_tcschedule(arg, cpu_env);
7105 register_name = "TCSchedule";
7106 break;
7107 case CP0_REG02__TCSCHEFBACK:
7108 CP0_CHECK(ctx->insn_flags & ASE_MT);
7109 gen_helper_mfc0_tcschefback(arg, cpu_env);
7110 register_name = "TCScheFBack";
7111 break;
7112 default:
7113 goto cp0_unimplemented;
7115 break;
7116 case CP0_REGISTER_03:
7117 switch (sel) {
7118 case CP0_REG03__ENTRYLO1:
7120 TCGv_i64 tmp = tcg_temp_new_i64();
7121 tcg_gen_ld_i64(tmp, cpu_env,
7122 offsetof(CPUMIPSState, CP0_EntryLo1));
7123 #if defined(TARGET_MIPS64)
7124 if (ctx->rxi) {
7125 /* Move RI/XI fields to bits 31:30 */
7126 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7127 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7129 #endif
7130 gen_move_low32(arg, tmp);
7131 tcg_temp_free_i64(tmp);
7133 register_name = "EntryLo1";
7134 break;
7135 case CP0_REG03__GLOBALNUM:
7136 CP0_CHECK(ctx->vp);
7137 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7138 register_name = "GlobalNumber";
7139 break;
7140 default:
7141 goto cp0_unimplemented;
7143 break;
7144 case CP0_REGISTER_04:
7145 switch (sel) {
7146 case CP0_REG04__CONTEXT:
7147 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7148 tcg_gen_ext32s_tl(arg, arg);
7149 register_name = "Context";
7150 break;
7151 case CP0_REG04__CONTEXTCONFIG:
7152 /* SmartMIPS ASE */
7153 /* gen_helper_mfc0_contextconfig(arg); */
7154 register_name = "ContextConfig";
7155 goto cp0_unimplemented;
7156 case CP0_REG04__USERLOCAL:
7157 CP0_CHECK(ctx->ulri);
7158 tcg_gen_ld_tl(arg, cpu_env,
7159 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7160 tcg_gen_ext32s_tl(arg, arg);
7161 register_name = "UserLocal";
7162 break;
7163 case CP0_REG04__MMID:
7164 CP0_CHECK(ctx->mi);
7165 gen_helper_mtc0_memorymapid(cpu_env, arg);
7166 register_name = "MMID";
7167 break;
7168 default:
7169 goto cp0_unimplemented;
7171 break;
7172 case CP0_REGISTER_05:
7173 switch (sel) {
7174 case CP0_REG05__PAGEMASK:
7175 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7176 register_name = "PageMask";
7177 break;
7178 case CP0_REG05__PAGEGRAIN:
7179 check_insn(ctx, ISA_MIPS32R2);
7180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7181 register_name = "PageGrain";
7182 break;
7183 case CP0_REG05__SEGCTL0:
7184 CP0_CHECK(ctx->sc);
7185 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7186 tcg_gen_ext32s_tl(arg, arg);
7187 register_name = "SegCtl0";
7188 break;
7189 case CP0_REG05__SEGCTL1:
7190 CP0_CHECK(ctx->sc);
7191 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7192 tcg_gen_ext32s_tl(arg, arg);
7193 register_name = "SegCtl1";
7194 break;
7195 case CP0_REG05__SEGCTL2:
7196 CP0_CHECK(ctx->sc);
7197 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7198 tcg_gen_ext32s_tl(arg, arg);
7199 register_name = "SegCtl2";
7200 break;
7201 case CP0_REG05__PWBASE:
7202 check_pw(ctx);
7203 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7204 register_name = "PWBase";
7205 break;
7206 case CP0_REG05__PWFIELD:
7207 check_pw(ctx);
7208 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7209 register_name = "PWField";
7210 break;
7211 case CP0_REG05__PWSIZE:
7212 check_pw(ctx);
7213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7214 register_name = "PWSize";
7215 break;
7216 default:
7217 goto cp0_unimplemented;
7219 break;
7220 case CP0_REGISTER_06:
7221 switch (sel) {
7222 case CP0_REG06__WIRED:
7223 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7224 register_name = "Wired";
7225 break;
7226 case CP0_REG06__SRSCONF0:
7227 check_insn(ctx, ISA_MIPS32R2);
7228 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7229 register_name = "SRSConf0";
7230 break;
7231 case CP0_REG06__SRSCONF1:
7232 check_insn(ctx, ISA_MIPS32R2);
7233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7234 register_name = "SRSConf1";
7235 break;
7236 case CP0_REG06__SRSCONF2:
7237 check_insn(ctx, ISA_MIPS32R2);
7238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7239 register_name = "SRSConf2";
7240 break;
7241 case CP0_REG06__SRSCONF3:
7242 check_insn(ctx, ISA_MIPS32R2);
7243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7244 register_name = "SRSConf3";
7245 break;
7246 case CP0_REG06__SRSCONF4:
7247 check_insn(ctx, ISA_MIPS32R2);
7248 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7249 register_name = "SRSConf4";
7250 break;
7251 case CP0_REG06__PWCTL:
7252 check_pw(ctx);
7253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7254 register_name = "PWCtl";
7255 break;
7256 default:
7257 goto cp0_unimplemented;
7259 break;
7260 case CP0_REGISTER_07:
7261 switch (sel) {
7262 case CP0_REG07__HWRENA:
7263 check_insn(ctx, ISA_MIPS32R2);
7264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7265 register_name = "HWREna";
7266 break;
7267 default:
7268 goto cp0_unimplemented;
7270 break;
7271 case CP0_REGISTER_08:
7272 switch (sel) {
7273 case CP0_REG08__BADVADDR:
7274 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7275 tcg_gen_ext32s_tl(arg, arg);
7276 register_name = "BadVAddr";
7277 break;
7278 case CP0_REG08__BADINSTR:
7279 CP0_CHECK(ctx->bi);
7280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7281 register_name = "BadInstr";
7282 break;
7283 case CP0_REG08__BADINSTRP:
7284 CP0_CHECK(ctx->bp);
7285 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7286 register_name = "BadInstrP";
7287 break;
7288 case CP0_REG08__BADINSTRX:
7289 CP0_CHECK(ctx->bi);
7290 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7291 tcg_gen_andi_tl(arg, arg, ~0xffff);
7292 register_name = "BadInstrX";
7293 break;
7294 default:
7295 goto cp0_unimplemented;
7297 break;
7298 case CP0_REGISTER_09:
7299 switch (sel) {
7300 case CP0_REG09__COUNT:
7301 /* Mark as an IO operation because we read the time. */
7302 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7303 gen_io_start();
7305 gen_helper_mfc0_count(arg, cpu_env);
7307 * Break the TB to be able to take timer interrupts immediately
7308 * after reading count. DISAS_STOP isn't sufficient, we need to
7309 * ensure we break completely out of translated code.
7311 gen_save_pc(ctx->base.pc_next + 4);
7312 ctx->base.is_jmp = DISAS_EXIT;
7313 register_name = "Count";
7314 break;
7315 case CP0_REG09__SAARI:
7316 CP0_CHECK(ctx->saar);
7317 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7318 register_name = "SAARI";
7319 break;
7320 case CP0_REG09__SAAR:
7321 CP0_CHECK(ctx->saar);
7322 gen_helper_mfc0_saar(arg, cpu_env);
7323 register_name = "SAAR";
7324 break;
7325 default:
7326 goto cp0_unimplemented;
7328 break;
7329 case CP0_REGISTER_10:
7330 switch (sel) {
7331 case CP0_REG10__ENTRYHI:
7332 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7333 tcg_gen_ext32s_tl(arg, arg);
7334 register_name = "EntryHi";
7335 break;
7336 default:
7337 goto cp0_unimplemented;
7339 break;
7340 case CP0_REGISTER_11:
7341 switch (sel) {
7342 case CP0_REG11__COMPARE:
7343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7344 register_name = "Compare";
7345 break;
7346 /* 6,7 are implementation dependent */
7347 default:
7348 goto cp0_unimplemented;
7350 break;
7351 case CP0_REGISTER_12:
7352 switch (sel) {
7353 case CP0_REG12__STATUS:
7354 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7355 register_name = "Status";
7356 break;
7357 case CP0_REG12__INTCTL:
7358 check_insn(ctx, ISA_MIPS32R2);
7359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7360 register_name = "IntCtl";
7361 break;
7362 case CP0_REG12__SRSCTL:
7363 check_insn(ctx, ISA_MIPS32R2);
7364 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7365 register_name = "SRSCtl";
7366 break;
7367 case CP0_REG12__SRSMAP:
7368 check_insn(ctx, ISA_MIPS32R2);
7369 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7370 register_name = "SRSMap";
7371 break;
7372 default:
7373 goto cp0_unimplemented;
7375 break;
7376 case CP0_REGISTER_13:
7377 switch (sel) {
7378 case CP0_REG13__CAUSE:
7379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7380 register_name = "Cause";
7381 break;
7382 default:
7383 goto cp0_unimplemented;
7385 break;
7386 case CP0_REGISTER_14:
7387 switch (sel) {
7388 case CP0_REG14__EPC:
7389 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7390 tcg_gen_ext32s_tl(arg, arg);
7391 register_name = "EPC";
7392 break;
7393 default:
7394 goto cp0_unimplemented;
7396 break;
7397 case CP0_REGISTER_15:
7398 switch (sel) {
7399 case CP0_REG15__PRID:
7400 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7401 register_name = "PRid";
7402 break;
7403 case CP0_REG15__EBASE:
7404 check_insn(ctx, ISA_MIPS32R2);
7405 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7406 tcg_gen_ext32s_tl(arg, arg);
7407 register_name = "EBase";
7408 break;
7409 case CP0_REG15__CMGCRBASE:
7410 check_insn(ctx, ISA_MIPS32R2);
7411 CP0_CHECK(ctx->cmgcr);
7412 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7413 tcg_gen_ext32s_tl(arg, arg);
7414 register_name = "CMGCRBase";
7415 break;
7416 default:
7417 goto cp0_unimplemented;
7419 break;
7420 case CP0_REGISTER_16:
7421 switch (sel) {
7422 case CP0_REG16__CONFIG:
7423 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7424 register_name = "Config";
7425 break;
7426 case CP0_REG16__CONFIG1:
7427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7428 register_name = "Config1";
7429 break;
7430 case CP0_REG16__CONFIG2:
7431 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7432 register_name = "Config2";
7433 break;
7434 case CP0_REG16__CONFIG3:
7435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7436 register_name = "Config3";
7437 break;
7438 case CP0_REG16__CONFIG4:
7439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7440 register_name = "Config4";
7441 break;
7442 case CP0_REG16__CONFIG5:
7443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7444 register_name = "Config5";
7445 break;
7446 /* 6,7 are implementation dependent */
7447 case CP0_REG16__CONFIG6:
7448 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7449 register_name = "Config6";
7450 break;
7451 case CP0_REG16__CONFIG7:
7452 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7453 register_name = "Config7";
7454 break;
7455 default:
7456 goto cp0_unimplemented;
7458 break;
7459 case CP0_REGISTER_17:
7460 switch (sel) {
7461 case CP0_REG17__LLADDR:
7462 gen_helper_mfc0_lladdr(arg, cpu_env);
7463 register_name = "LLAddr";
7464 break;
7465 case CP0_REG17__MAAR:
7466 CP0_CHECK(ctx->mrp);
7467 gen_helper_mfc0_maar(arg, cpu_env);
7468 register_name = "MAAR";
7469 break;
7470 case CP0_REG17__MAARI:
7471 CP0_CHECK(ctx->mrp);
7472 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7473 register_name = "MAARI";
7474 break;
7475 default:
7476 goto cp0_unimplemented;
7478 break;
7479 case CP0_REGISTER_18:
7480 switch (sel) {
7481 case CP0_REG18__WATCHLO0:
7482 case CP0_REG18__WATCHLO1:
7483 case CP0_REG18__WATCHLO2:
7484 case CP0_REG18__WATCHLO3:
7485 case CP0_REG18__WATCHLO4:
7486 case CP0_REG18__WATCHLO5:
7487 case CP0_REG18__WATCHLO6:
7488 case CP0_REG18__WATCHLO7:
7489 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7490 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7491 register_name = "WatchLo";
7492 break;
7493 default:
7494 goto cp0_unimplemented;
7496 break;
7497 case CP0_REGISTER_19:
7498 switch (sel) {
7499 case CP0_REG19__WATCHHI0:
7500 case CP0_REG19__WATCHHI1:
7501 case CP0_REG19__WATCHHI2:
7502 case CP0_REG19__WATCHHI3:
7503 case CP0_REG19__WATCHHI4:
7504 case CP0_REG19__WATCHHI5:
7505 case CP0_REG19__WATCHHI6:
7506 case CP0_REG19__WATCHHI7:
7507 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7508 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7509 register_name = "WatchHi";
7510 break;
7511 default:
7512 goto cp0_unimplemented;
7514 break;
7515 case CP0_REGISTER_20:
7516 switch (sel) {
7517 case CP0_REG20__XCONTEXT:
7518 #if defined(TARGET_MIPS64)
7519 check_insn(ctx, ISA_MIPS3);
7520 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7521 tcg_gen_ext32s_tl(arg, arg);
7522 register_name = "XContext";
7523 break;
7524 #endif
7525 default:
7526 goto cp0_unimplemented;
7528 break;
7529 case CP0_REGISTER_21:
7530 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7531 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7532 switch (sel) {
7533 case 0:
7534 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7535 register_name = "Framemask";
7536 break;
7537 default:
7538 goto cp0_unimplemented;
7540 break;
7541 case CP0_REGISTER_22:
7542 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7543 register_name = "'Diagnostic"; /* implementation dependent */
7544 break;
7545 case CP0_REGISTER_23:
7546 switch (sel) {
7547 case CP0_REG23__DEBUG:
7548 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7549 register_name = "Debug";
7550 break;
7551 case CP0_REG23__TRACECONTROL:
7552 /* PDtrace support */
7553 /* gen_helper_mfc0_tracecontrol(arg); */
7554 register_name = "TraceControl";
7555 goto cp0_unimplemented;
7556 case CP0_REG23__TRACECONTROL2:
7557 /* PDtrace support */
7558 /* gen_helper_mfc0_tracecontrol2(arg); */
7559 register_name = "TraceControl2";
7560 goto cp0_unimplemented;
7561 case CP0_REG23__USERTRACEDATA1:
7562 /* PDtrace support */
7563 /* gen_helper_mfc0_usertracedata1(arg);*/
7564 register_name = "UserTraceData1";
7565 goto cp0_unimplemented;
7566 case CP0_REG23__TRACEIBPC:
7567 /* PDtrace support */
7568 /* gen_helper_mfc0_traceibpc(arg); */
7569 register_name = "TraceIBPC";
7570 goto cp0_unimplemented;
7571 case CP0_REG23__TRACEDBPC:
7572 /* PDtrace support */
7573 /* gen_helper_mfc0_tracedbpc(arg); */
7574 register_name = "TraceDBPC";
7575 goto cp0_unimplemented;
7576 default:
7577 goto cp0_unimplemented;
7579 break;
7580 case CP0_REGISTER_24:
7581 switch (sel) {
7582 case CP0_REG24__DEPC:
7583 /* EJTAG support */
7584 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7585 tcg_gen_ext32s_tl(arg, arg);
7586 register_name = "DEPC";
7587 break;
7588 default:
7589 goto cp0_unimplemented;
7591 break;
7592 case CP0_REGISTER_25:
7593 switch (sel) {
7594 case CP0_REG25__PERFCTL0:
7595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7596 register_name = "Performance0";
7597 break;
7598 case CP0_REG25__PERFCNT0:
7599 /* gen_helper_mfc0_performance1(arg); */
7600 register_name = "Performance1";
7601 goto cp0_unimplemented;
7602 case CP0_REG25__PERFCTL1:
7603 /* gen_helper_mfc0_performance2(arg); */
7604 register_name = "Performance2";
7605 goto cp0_unimplemented;
7606 case CP0_REG25__PERFCNT1:
7607 /* gen_helper_mfc0_performance3(arg); */
7608 register_name = "Performance3";
7609 goto cp0_unimplemented;
7610 case CP0_REG25__PERFCTL2:
7611 /* gen_helper_mfc0_performance4(arg); */
7612 register_name = "Performance4";
7613 goto cp0_unimplemented;
7614 case CP0_REG25__PERFCNT2:
7615 /* gen_helper_mfc0_performance5(arg); */
7616 register_name = "Performance5";
7617 goto cp0_unimplemented;
7618 case CP0_REG25__PERFCTL3:
7619 /* gen_helper_mfc0_performance6(arg); */
7620 register_name = "Performance6";
7621 goto cp0_unimplemented;
7622 case CP0_REG25__PERFCNT3:
7623 /* gen_helper_mfc0_performance7(arg); */
7624 register_name = "Performance7";
7625 goto cp0_unimplemented;
7626 default:
7627 goto cp0_unimplemented;
7629 break;
7630 case CP0_REGISTER_26:
7631 switch (sel) {
7632 case CP0_REG26__ERRCTL:
7633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7634 register_name = "ErrCtl";
7635 break;
7636 default:
7637 goto cp0_unimplemented;
7639 break;
7640 case CP0_REGISTER_27:
7641 switch (sel) {
7642 case CP0_REG27__CACHERR:
7643 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7644 register_name = "CacheErr";
7645 break;
7646 default:
7647 goto cp0_unimplemented;
7649 break;
7650 case CP0_REGISTER_28:
7651 switch (sel) {
7652 case CP0_REG28__TAGLO:
7653 case CP0_REG28__TAGLO1:
7654 case CP0_REG28__TAGLO2:
7655 case CP0_REG28__TAGLO3:
7657 TCGv_i64 tmp = tcg_temp_new_i64();
7658 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7659 gen_move_low32(arg, tmp);
7660 tcg_temp_free_i64(tmp);
7662 register_name = "TagLo";
7663 break;
7664 case CP0_REG28__DATALO:
7665 case CP0_REG28__DATALO1:
7666 case CP0_REG28__DATALO2:
7667 case CP0_REG28__DATALO3:
7668 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7669 register_name = "DataLo";
7670 break;
7671 default:
7672 goto cp0_unimplemented;
7674 break;
7675 case CP0_REGISTER_29:
7676 switch (sel) {
7677 case CP0_REG29__TAGHI:
7678 case CP0_REG29__TAGHI1:
7679 case CP0_REG29__TAGHI2:
7680 case CP0_REG29__TAGHI3:
7681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7682 register_name = "TagHi";
7683 break;
7684 case CP0_REG29__DATAHI:
7685 case CP0_REG29__DATAHI1:
7686 case CP0_REG29__DATAHI2:
7687 case CP0_REG29__DATAHI3:
7688 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7689 register_name = "DataHi";
7690 break;
7691 default:
7692 goto cp0_unimplemented;
7694 break;
7695 case CP0_REGISTER_30:
7696 switch (sel) {
7697 case CP0_REG30__ERROREPC:
7698 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7699 tcg_gen_ext32s_tl(arg, arg);
7700 register_name = "ErrorEPC";
7701 break;
7702 default:
7703 goto cp0_unimplemented;
7705 break;
7706 case CP0_REGISTER_31:
7707 switch (sel) {
7708 case CP0_REG31__DESAVE:
7709 /* EJTAG support */
7710 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7711 register_name = "DESAVE";
7712 break;
7713 case CP0_REG31__KSCRATCH1:
7714 case CP0_REG31__KSCRATCH2:
7715 case CP0_REG31__KSCRATCH3:
7716 case CP0_REG31__KSCRATCH4:
7717 case CP0_REG31__KSCRATCH5:
7718 case CP0_REG31__KSCRATCH6:
7719 CP0_CHECK(ctx->kscrexist & (1 << sel));
7720 tcg_gen_ld_tl(arg, cpu_env,
7721 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7722 tcg_gen_ext32s_tl(arg, arg);
7723 register_name = "KScratch";
7724 break;
7725 default:
7726 goto cp0_unimplemented;
7728 break;
7729 default:
7730 goto cp0_unimplemented;
7732 trace_mips_translate_c0("mfc0", register_name, reg, sel);
7733 return;
7735 cp0_unimplemented:
7736 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
7737 register_name, reg, sel);
7738 gen_mfc0_unimplemented(ctx, arg);
7741 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7743 const char *register_name = "invalid";
7745 if (sel != 0) {
7746 check_insn(ctx, ISA_MIPS32);
7749 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7750 gen_io_start();
7753 switch (reg) {
7754 case CP0_REGISTER_00:
7755 switch (sel) {
7756 case CP0_REG00__INDEX:
7757 gen_helper_mtc0_index(cpu_env, arg);
7758 register_name = "Index";
7759 break;
7760 case CP0_REG00__MVPCONTROL:
7761 CP0_CHECK(ctx->insn_flags & ASE_MT);
7762 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7763 register_name = "MVPControl";
7764 break;
7765 case CP0_REG00__MVPCONF0:
7766 CP0_CHECK(ctx->insn_flags & ASE_MT);
7767 /* ignored */
7768 register_name = "MVPConf0";
7769 break;
7770 case CP0_REG00__MVPCONF1:
7771 CP0_CHECK(ctx->insn_flags & ASE_MT);
7772 /* ignored */
7773 register_name = "MVPConf1";
7774 break;
7775 case CP0_REG00__VPCONTROL:
7776 CP0_CHECK(ctx->vp);
7777 /* ignored */
7778 register_name = "VPControl";
7779 break;
7780 default:
7781 goto cp0_unimplemented;
7783 break;
7784 case CP0_REGISTER_01:
7785 switch (sel) {
7786 case CP0_REG01__RANDOM:
7787 /* ignored */
7788 register_name = "Random";
7789 break;
7790 case CP0_REG01__VPECONTROL:
7791 CP0_CHECK(ctx->insn_flags & ASE_MT);
7792 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7793 register_name = "VPEControl";
7794 break;
7795 case CP0_REG01__VPECONF0:
7796 CP0_CHECK(ctx->insn_flags & ASE_MT);
7797 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7798 register_name = "VPEConf0";
7799 break;
7800 case CP0_REG01__VPECONF1:
7801 CP0_CHECK(ctx->insn_flags & ASE_MT);
7802 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7803 register_name = "VPEConf1";
7804 break;
7805 case CP0_REG01__YQMASK:
7806 CP0_CHECK(ctx->insn_flags & ASE_MT);
7807 gen_helper_mtc0_yqmask(cpu_env, arg);
7808 register_name = "YQMask";
7809 break;
7810 case CP0_REG01__VPESCHEDULE:
7811 CP0_CHECK(ctx->insn_flags & ASE_MT);
7812 tcg_gen_st_tl(arg, cpu_env,
7813 offsetof(CPUMIPSState, CP0_VPESchedule));
7814 register_name = "VPESchedule";
7815 break;
7816 case CP0_REG01__VPESCHEFBACK:
7817 CP0_CHECK(ctx->insn_flags & ASE_MT);
7818 tcg_gen_st_tl(arg, cpu_env,
7819 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7820 register_name = "VPEScheFBack";
7821 break;
7822 case CP0_REG01__VPEOPT:
7823 CP0_CHECK(ctx->insn_flags & ASE_MT);
7824 gen_helper_mtc0_vpeopt(cpu_env, arg);
7825 register_name = "VPEOpt";
7826 break;
7827 default:
7828 goto cp0_unimplemented;
7830 break;
7831 case CP0_REGISTER_02:
7832 switch (sel) {
7833 case CP0_REG02__ENTRYLO0:
7834 gen_helper_mtc0_entrylo0(cpu_env, arg);
7835 register_name = "EntryLo0";
7836 break;
7837 case CP0_REG02__TCSTATUS:
7838 CP0_CHECK(ctx->insn_flags & ASE_MT);
7839 gen_helper_mtc0_tcstatus(cpu_env, arg);
7840 register_name = "TCStatus";
7841 break;
7842 case CP0_REG02__TCBIND:
7843 CP0_CHECK(ctx->insn_flags & ASE_MT);
7844 gen_helper_mtc0_tcbind(cpu_env, arg);
7845 register_name = "TCBind";
7846 break;
7847 case CP0_REG02__TCRESTART:
7848 CP0_CHECK(ctx->insn_flags & ASE_MT);
7849 gen_helper_mtc0_tcrestart(cpu_env, arg);
7850 register_name = "TCRestart";
7851 break;
7852 case CP0_REG02__TCHALT:
7853 CP0_CHECK(ctx->insn_flags & ASE_MT);
7854 gen_helper_mtc0_tchalt(cpu_env, arg);
7855 register_name = "TCHalt";
7856 break;
7857 case CP0_REG02__TCCONTEXT:
7858 CP0_CHECK(ctx->insn_flags & ASE_MT);
7859 gen_helper_mtc0_tccontext(cpu_env, arg);
7860 register_name = "TCContext";
7861 break;
7862 case CP0_REG02__TCSCHEDULE:
7863 CP0_CHECK(ctx->insn_flags & ASE_MT);
7864 gen_helper_mtc0_tcschedule(cpu_env, arg);
7865 register_name = "TCSchedule";
7866 break;
7867 case CP0_REG02__TCSCHEFBACK:
7868 CP0_CHECK(ctx->insn_flags & ASE_MT);
7869 gen_helper_mtc0_tcschefback(cpu_env, arg);
7870 register_name = "TCScheFBack";
7871 break;
7872 default:
7873 goto cp0_unimplemented;
7875 break;
7876 case CP0_REGISTER_03:
7877 switch (sel) {
7878 case CP0_REG03__ENTRYLO1:
7879 gen_helper_mtc0_entrylo1(cpu_env, arg);
7880 register_name = "EntryLo1";
7881 break;
7882 case CP0_REG03__GLOBALNUM:
7883 CP0_CHECK(ctx->vp);
7884 /* ignored */
7885 register_name = "GlobalNumber";
7886 break;
7887 default:
7888 goto cp0_unimplemented;
7890 break;
7891 case CP0_REGISTER_04:
7892 switch (sel) {
7893 case CP0_REG04__CONTEXT:
7894 gen_helper_mtc0_context(cpu_env, arg);
7895 register_name = "Context";
7896 break;
7897 case CP0_REG04__CONTEXTCONFIG:
7898 /* SmartMIPS ASE */
7899 /* gen_helper_mtc0_contextconfig(arg); */
7900 register_name = "ContextConfig";
7901 goto cp0_unimplemented;
7902 case CP0_REG04__USERLOCAL:
7903 CP0_CHECK(ctx->ulri);
7904 tcg_gen_st_tl(arg, cpu_env,
7905 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7906 register_name = "UserLocal";
7907 break;
7908 case CP0_REG04__MMID:
7909 CP0_CHECK(ctx->mi);
7910 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7911 register_name = "MMID";
7912 break;
7913 default:
7914 goto cp0_unimplemented;
7916 break;
7917 case CP0_REGISTER_05:
7918 switch (sel) {
7919 case CP0_REG05__PAGEMASK:
7920 gen_helper_mtc0_pagemask(cpu_env, arg);
7921 register_name = "PageMask";
7922 break;
7923 case CP0_REG05__PAGEGRAIN:
7924 check_insn(ctx, ISA_MIPS32R2);
7925 gen_helper_mtc0_pagegrain(cpu_env, arg);
7926 register_name = "PageGrain";
7927 ctx->base.is_jmp = DISAS_STOP;
7928 break;
7929 case CP0_REG05__SEGCTL0:
7930 CP0_CHECK(ctx->sc);
7931 gen_helper_mtc0_segctl0(cpu_env, arg);
7932 register_name = "SegCtl0";
7933 break;
7934 case CP0_REG05__SEGCTL1:
7935 CP0_CHECK(ctx->sc);
7936 gen_helper_mtc0_segctl1(cpu_env, arg);
7937 register_name = "SegCtl1";
7938 break;
7939 case CP0_REG05__SEGCTL2:
7940 CP0_CHECK(ctx->sc);
7941 gen_helper_mtc0_segctl2(cpu_env, arg);
7942 register_name = "SegCtl2";
7943 break;
7944 case CP0_REG05__PWBASE:
7945 check_pw(ctx);
7946 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7947 register_name = "PWBase";
7948 break;
7949 case CP0_REG05__PWFIELD:
7950 check_pw(ctx);
7951 gen_helper_mtc0_pwfield(cpu_env, arg);
7952 register_name = "PWField";
7953 break;
7954 case CP0_REG05__PWSIZE:
7955 check_pw(ctx);
7956 gen_helper_mtc0_pwsize(cpu_env, arg);
7957 register_name = "PWSize";
7958 break;
7959 default:
7960 goto cp0_unimplemented;
7962 break;
7963 case CP0_REGISTER_06:
7964 switch (sel) {
7965 case CP0_REG06__WIRED:
7966 gen_helper_mtc0_wired(cpu_env, arg);
7967 register_name = "Wired";
7968 break;
7969 case CP0_REG06__SRSCONF0:
7970 check_insn(ctx, ISA_MIPS32R2);
7971 gen_helper_mtc0_srsconf0(cpu_env, arg);
7972 register_name = "SRSConf0";
7973 break;
7974 case CP0_REG06__SRSCONF1:
7975 check_insn(ctx, ISA_MIPS32R2);
7976 gen_helper_mtc0_srsconf1(cpu_env, arg);
7977 register_name = "SRSConf1";
7978 break;
7979 case CP0_REG06__SRSCONF2:
7980 check_insn(ctx, ISA_MIPS32R2);
7981 gen_helper_mtc0_srsconf2(cpu_env, arg);
7982 register_name = "SRSConf2";
7983 break;
7984 case CP0_REG06__SRSCONF3:
7985 check_insn(ctx, ISA_MIPS32R2);
7986 gen_helper_mtc0_srsconf3(cpu_env, arg);
7987 register_name = "SRSConf3";
7988 break;
7989 case CP0_REG06__SRSCONF4:
7990 check_insn(ctx, ISA_MIPS32R2);
7991 gen_helper_mtc0_srsconf4(cpu_env, arg);
7992 register_name = "SRSConf4";
7993 break;
7994 case CP0_REG06__PWCTL:
7995 check_pw(ctx);
7996 gen_helper_mtc0_pwctl(cpu_env, arg);
7997 register_name = "PWCtl";
7998 break;
7999 default:
8000 goto cp0_unimplemented;
8002 break;
8003 case CP0_REGISTER_07:
8004 switch (sel) {
8005 case CP0_REG07__HWRENA:
8006 check_insn(ctx, ISA_MIPS32R2);
8007 gen_helper_mtc0_hwrena(cpu_env, arg);
8008 ctx->base.is_jmp = DISAS_STOP;
8009 register_name = "HWREna";
8010 break;
8011 default:
8012 goto cp0_unimplemented;
8014 break;
8015 case CP0_REGISTER_08:
8016 switch (sel) {
8017 case CP0_REG08__BADVADDR:
8018 /* ignored */
8019 register_name = "BadVAddr";
8020 break;
8021 case CP0_REG08__BADINSTR:
8022 /* ignored */
8023 register_name = "BadInstr";
8024 break;
8025 case CP0_REG08__BADINSTRP:
8026 /* ignored */
8027 register_name = "BadInstrP";
8028 break;
8029 case CP0_REG08__BADINSTRX:
8030 /* ignored */
8031 register_name = "BadInstrX";
8032 break;
8033 default:
8034 goto cp0_unimplemented;
8036 break;
8037 case CP0_REGISTER_09:
8038 switch (sel) {
8039 case CP0_REG09__COUNT:
8040 gen_helper_mtc0_count(cpu_env, arg);
8041 register_name = "Count";
8042 break;
8043 case CP0_REG09__SAARI:
8044 CP0_CHECK(ctx->saar);
8045 gen_helper_mtc0_saari(cpu_env, arg);
8046 register_name = "SAARI";
8047 break;
8048 case CP0_REG09__SAAR:
8049 CP0_CHECK(ctx->saar);
8050 gen_helper_mtc0_saar(cpu_env, arg);
8051 register_name = "SAAR";
8052 break;
8053 default:
8054 goto cp0_unimplemented;
8056 break;
8057 case CP0_REGISTER_10:
8058 switch (sel) {
8059 case CP0_REG10__ENTRYHI:
8060 gen_helper_mtc0_entryhi(cpu_env, arg);
8061 register_name = "EntryHi";
8062 break;
8063 default:
8064 goto cp0_unimplemented;
8066 break;
8067 case CP0_REGISTER_11:
8068 switch (sel) {
8069 case CP0_REG11__COMPARE:
8070 gen_helper_mtc0_compare(cpu_env, arg);
8071 register_name = "Compare";
8072 break;
8073 /* 6,7 are implementation dependent */
8074 default:
8075 goto cp0_unimplemented;
8077 break;
8078 case CP0_REGISTER_12:
8079 switch (sel) {
8080 case CP0_REG12__STATUS:
8081 save_cpu_state(ctx, 1);
8082 gen_helper_mtc0_status(cpu_env, arg);
8083 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8084 gen_save_pc(ctx->base.pc_next + 4);
8085 ctx->base.is_jmp = DISAS_EXIT;
8086 register_name = "Status";
8087 break;
8088 case CP0_REG12__INTCTL:
8089 check_insn(ctx, ISA_MIPS32R2);
8090 gen_helper_mtc0_intctl(cpu_env, arg);
8091 /* Stop translation as we may have switched the execution mode */
8092 ctx->base.is_jmp = DISAS_STOP;
8093 register_name = "IntCtl";
8094 break;
8095 case CP0_REG12__SRSCTL:
8096 check_insn(ctx, ISA_MIPS32R2);
8097 gen_helper_mtc0_srsctl(cpu_env, arg);
8098 /* Stop translation as we may have switched the execution mode */
8099 ctx->base.is_jmp = DISAS_STOP;
8100 register_name = "SRSCtl";
8101 break;
8102 case CP0_REG12__SRSMAP:
8103 check_insn(ctx, ISA_MIPS32R2);
8104 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8105 /* Stop translation as we may have switched the execution mode */
8106 ctx->base.is_jmp = DISAS_STOP;
8107 register_name = "SRSMap";
8108 break;
8109 default:
8110 goto cp0_unimplemented;
8112 break;
8113 case CP0_REGISTER_13:
8114 switch (sel) {
8115 case CP0_REG13__CAUSE:
8116 save_cpu_state(ctx, 1);
8117 gen_helper_mtc0_cause(cpu_env, arg);
8119 * Stop translation as we may have triggered an interrupt.
8120 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8121 * translated code to check for pending interrupts.
8123 gen_save_pc(ctx->base.pc_next + 4);
8124 ctx->base.is_jmp = DISAS_EXIT;
8125 register_name = "Cause";
8126 break;
8127 default:
8128 goto cp0_unimplemented;
8130 break;
8131 case CP0_REGISTER_14:
8132 switch (sel) {
8133 case CP0_REG14__EPC:
8134 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8135 register_name = "EPC";
8136 break;
8137 default:
8138 goto cp0_unimplemented;
8140 break;
8141 case CP0_REGISTER_15:
8142 switch (sel) {
8143 case CP0_REG15__PRID:
8144 /* ignored */
8145 register_name = "PRid";
8146 break;
8147 case CP0_REG15__EBASE:
8148 check_insn(ctx, ISA_MIPS32R2);
8149 gen_helper_mtc0_ebase(cpu_env, arg);
8150 register_name = "EBase";
8151 break;
8152 default:
8153 goto cp0_unimplemented;
8155 break;
8156 case CP0_REGISTER_16:
8157 switch (sel) {
8158 case CP0_REG16__CONFIG:
8159 gen_helper_mtc0_config0(cpu_env, arg);
8160 register_name = "Config";
8161 /* Stop translation as we may have switched the execution mode */
8162 ctx->base.is_jmp = DISAS_STOP;
8163 break;
8164 case CP0_REG16__CONFIG1:
8165 /* ignored, read only */
8166 register_name = "Config1";
8167 break;
8168 case CP0_REG16__CONFIG2:
8169 gen_helper_mtc0_config2(cpu_env, arg);
8170 register_name = "Config2";
8171 /* Stop translation as we may have switched the execution mode */
8172 ctx->base.is_jmp = DISAS_STOP;
8173 break;
8174 case CP0_REG16__CONFIG3:
8175 gen_helper_mtc0_config3(cpu_env, arg);
8176 register_name = "Config3";
8177 /* Stop translation as we may have switched the execution mode */
8178 ctx->base.is_jmp = DISAS_STOP;
8179 break;
8180 case CP0_REG16__CONFIG4:
8181 gen_helper_mtc0_config4(cpu_env, arg);
8182 register_name = "Config4";
8183 ctx->base.is_jmp = DISAS_STOP;
8184 break;
8185 case CP0_REG16__CONFIG5:
8186 gen_helper_mtc0_config5(cpu_env, arg);
8187 register_name = "Config5";
8188 /* Stop translation as we may have switched the execution mode */
8189 ctx->base.is_jmp = DISAS_STOP;
8190 break;
8191 /* 6,7 are implementation dependent */
8192 case CP0_REG16__CONFIG6:
8193 /* ignored */
8194 register_name = "Config6";
8195 break;
8196 case CP0_REG16__CONFIG7:
8197 /* ignored */
8198 register_name = "Config7";
8199 break;
8200 default:
8201 register_name = "Invalid config selector";
8202 goto cp0_unimplemented;
8204 break;
8205 case CP0_REGISTER_17:
8206 switch (sel) {
8207 case CP0_REG17__LLADDR:
8208 gen_helper_mtc0_lladdr(cpu_env, arg);
8209 register_name = "LLAddr";
8210 break;
8211 case CP0_REG17__MAAR:
8212 CP0_CHECK(ctx->mrp);
8213 gen_helper_mtc0_maar(cpu_env, arg);
8214 register_name = "MAAR";
8215 break;
8216 case CP0_REG17__MAARI:
8217 CP0_CHECK(ctx->mrp);
8218 gen_helper_mtc0_maari(cpu_env, arg);
8219 register_name = "MAARI";
8220 break;
8221 default:
8222 goto cp0_unimplemented;
8224 break;
8225 case CP0_REGISTER_18:
8226 switch (sel) {
8227 case CP0_REG18__WATCHLO0:
8228 case CP0_REG18__WATCHLO1:
8229 case CP0_REG18__WATCHLO2:
8230 case CP0_REG18__WATCHLO3:
8231 case CP0_REG18__WATCHLO4:
8232 case CP0_REG18__WATCHLO5:
8233 case CP0_REG18__WATCHLO6:
8234 case CP0_REG18__WATCHLO7:
8235 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8236 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8237 register_name = "WatchLo";
8238 break;
8239 default:
8240 goto cp0_unimplemented;
8242 break;
8243 case CP0_REGISTER_19:
8244 switch (sel) {
8245 case CP0_REG19__WATCHHI0:
8246 case CP0_REG19__WATCHHI1:
8247 case CP0_REG19__WATCHHI2:
8248 case CP0_REG19__WATCHHI3:
8249 case CP0_REG19__WATCHHI4:
8250 case CP0_REG19__WATCHHI5:
8251 case CP0_REG19__WATCHHI6:
8252 case CP0_REG19__WATCHHI7:
8253 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8254 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8255 register_name = "WatchHi";
8256 break;
8257 default:
8258 goto cp0_unimplemented;
8260 break;
8261 case CP0_REGISTER_20:
8262 switch (sel) {
8263 case CP0_REG20__XCONTEXT:
8264 #if defined(TARGET_MIPS64)
8265 check_insn(ctx, ISA_MIPS3);
8266 gen_helper_mtc0_xcontext(cpu_env, arg);
8267 register_name = "XContext";
8268 break;
8269 #endif
8270 default:
8271 goto cp0_unimplemented;
8273 break;
8274 case CP0_REGISTER_21:
8275 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8276 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8277 switch (sel) {
8278 case 0:
8279 gen_helper_mtc0_framemask(cpu_env, arg);
8280 register_name = "Framemask";
8281 break;
8282 default:
8283 goto cp0_unimplemented;
8285 break;
8286 case CP0_REGISTER_22:
8287 /* ignored */
8288 register_name = "Diagnostic"; /* implementation dependent */
8289 break;
8290 case CP0_REGISTER_23:
8291 switch (sel) {
8292 case CP0_REG23__DEBUG:
8293 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8294 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8295 gen_save_pc(ctx->base.pc_next + 4);
8296 ctx->base.is_jmp = DISAS_EXIT;
8297 register_name = "Debug";
8298 break;
8299 case CP0_REG23__TRACECONTROL:
8300 /* PDtrace support */
8301 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8302 register_name = "TraceControl";
8303 /* Stop translation as we may have switched the execution mode */
8304 ctx->base.is_jmp = DISAS_STOP;
8305 goto cp0_unimplemented;
8306 case CP0_REG23__TRACECONTROL2:
8307 /* PDtrace support */
8308 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8309 register_name = "TraceControl2";
8310 /* Stop translation as we may have switched the execution mode */
8311 ctx->base.is_jmp = DISAS_STOP;
8312 goto cp0_unimplemented;
8313 case CP0_REG23__USERTRACEDATA1:
8314 /* Stop translation as we may have switched the execution mode */
8315 ctx->base.is_jmp = DISAS_STOP;
8316 /* PDtrace support */
8317 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8318 register_name = "UserTraceData";
8319 /* Stop translation as we may have switched the execution mode */
8320 ctx->base.is_jmp = DISAS_STOP;
8321 goto cp0_unimplemented;
8322 case CP0_REG23__TRACEIBPC:
8323 /* PDtrace support */
8324 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8325 /* Stop translation as we may have switched the execution mode */
8326 ctx->base.is_jmp = DISAS_STOP;
8327 register_name = "TraceIBPC";
8328 goto cp0_unimplemented;
8329 case CP0_REG23__TRACEDBPC:
8330 /* PDtrace support */
8331 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8332 /* Stop translation as we may have switched the execution mode */
8333 ctx->base.is_jmp = DISAS_STOP;
8334 register_name = "TraceDBPC";
8335 goto cp0_unimplemented;
8336 default:
8337 goto cp0_unimplemented;
8339 break;
8340 case CP0_REGISTER_24:
8341 switch (sel) {
8342 case CP0_REG24__DEPC:
8343 /* EJTAG support */
8344 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8345 register_name = "DEPC";
8346 break;
8347 default:
8348 goto cp0_unimplemented;
8350 break;
8351 case CP0_REGISTER_25:
8352 switch (sel) {
8353 case CP0_REG25__PERFCTL0:
8354 gen_helper_mtc0_performance0(cpu_env, arg);
8355 register_name = "Performance0";
8356 break;
8357 case CP0_REG25__PERFCNT0:
8358 /* gen_helper_mtc0_performance1(arg); */
8359 register_name = "Performance1";
8360 goto cp0_unimplemented;
8361 case CP0_REG25__PERFCTL1:
8362 /* gen_helper_mtc0_performance2(arg); */
8363 register_name = "Performance2";
8364 goto cp0_unimplemented;
8365 case CP0_REG25__PERFCNT1:
8366 /* gen_helper_mtc0_performance3(arg); */
8367 register_name = "Performance3";
8368 goto cp0_unimplemented;
8369 case CP0_REG25__PERFCTL2:
8370 /* gen_helper_mtc0_performance4(arg); */
8371 register_name = "Performance4";
8372 goto cp0_unimplemented;
8373 case CP0_REG25__PERFCNT2:
8374 /* gen_helper_mtc0_performance5(arg); */
8375 register_name = "Performance5";
8376 goto cp0_unimplemented;
8377 case CP0_REG25__PERFCTL3:
8378 /* gen_helper_mtc0_performance6(arg); */
8379 register_name = "Performance6";
8380 goto cp0_unimplemented;
8381 case CP0_REG25__PERFCNT3:
8382 /* gen_helper_mtc0_performance7(arg); */
8383 register_name = "Performance7";
8384 goto cp0_unimplemented;
8385 default:
8386 goto cp0_unimplemented;
8388 break;
8389 case CP0_REGISTER_26:
8390 switch (sel) {
8391 case CP0_REG26__ERRCTL:
8392 gen_helper_mtc0_errctl(cpu_env, arg);
8393 ctx->base.is_jmp = DISAS_STOP;
8394 register_name = "ErrCtl";
8395 break;
8396 default:
8397 goto cp0_unimplemented;
8399 break;
8400 case CP0_REGISTER_27:
8401 switch (sel) {
8402 case CP0_REG27__CACHERR:
8403 /* ignored */
8404 register_name = "CacheErr";
8405 break;
8406 default:
8407 goto cp0_unimplemented;
8409 break;
8410 case CP0_REGISTER_28:
8411 switch (sel) {
8412 case CP0_REG28__TAGLO:
8413 case CP0_REG28__TAGLO1:
8414 case CP0_REG28__TAGLO2:
8415 case CP0_REG28__TAGLO3:
8416 gen_helper_mtc0_taglo(cpu_env, arg);
8417 register_name = "TagLo";
8418 break;
8419 case CP0_REG28__DATALO:
8420 case CP0_REG28__DATALO1:
8421 case CP0_REG28__DATALO2:
8422 case CP0_REG28__DATALO3:
8423 gen_helper_mtc0_datalo(cpu_env, arg);
8424 register_name = "DataLo";
8425 break;
8426 default:
8427 goto cp0_unimplemented;
8429 break;
8430 case CP0_REGISTER_29:
8431 switch (sel) {
8432 case CP0_REG29__TAGHI:
8433 case CP0_REG29__TAGHI1:
8434 case CP0_REG29__TAGHI2:
8435 case CP0_REG29__TAGHI3:
8436 gen_helper_mtc0_taghi(cpu_env, arg);
8437 register_name = "TagHi";
8438 break;
8439 case CP0_REG29__DATAHI:
8440 case CP0_REG29__DATAHI1:
8441 case CP0_REG29__DATAHI2:
8442 case CP0_REG29__DATAHI3:
8443 gen_helper_mtc0_datahi(cpu_env, arg);
8444 register_name = "DataHi";
8445 break;
8446 default:
8447 register_name = "invalid sel";
8448 goto cp0_unimplemented;
8450 break;
8451 case CP0_REGISTER_30:
8452 switch (sel) {
8453 case CP0_REG30__ERROREPC:
8454 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8455 register_name = "ErrorEPC";
8456 break;
8457 default:
8458 goto cp0_unimplemented;
8460 break;
8461 case CP0_REGISTER_31:
8462 switch (sel) {
8463 case CP0_REG31__DESAVE:
8464 /* EJTAG support */
8465 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8466 register_name = "DESAVE";
8467 break;
8468 case CP0_REG31__KSCRATCH1:
8469 case CP0_REG31__KSCRATCH2:
8470 case CP0_REG31__KSCRATCH3:
8471 case CP0_REG31__KSCRATCH4:
8472 case CP0_REG31__KSCRATCH5:
8473 case CP0_REG31__KSCRATCH6:
8474 CP0_CHECK(ctx->kscrexist & (1 << sel));
8475 tcg_gen_st_tl(arg, cpu_env,
8476 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8477 register_name = "KScratch";
8478 break;
8479 default:
8480 goto cp0_unimplemented;
8482 break;
8483 default:
8484 goto cp0_unimplemented;
8486 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8488 /* For simplicity assume that all writes can cause interrupts. */
8489 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8491 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8492 * translated code to check for pending interrupts.
8494 gen_save_pc(ctx->base.pc_next + 4);
8495 ctx->base.is_jmp = DISAS_EXIT;
8497 return;
8499 cp0_unimplemented:
8500 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8501 register_name, reg, sel);
8504 #if defined(TARGET_MIPS64)
8505 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8507 const char *register_name = "invalid";
8509 if (sel != 0) {
8510 check_insn(ctx, ISA_MIPS64);
8513 switch (reg) {
8514 case CP0_REGISTER_00:
8515 switch (sel) {
8516 case CP0_REG00__INDEX:
8517 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8518 register_name = "Index";
8519 break;
8520 case CP0_REG00__MVPCONTROL:
8521 CP0_CHECK(ctx->insn_flags & ASE_MT);
8522 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8523 register_name = "MVPControl";
8524 break;
8525 case CP0_REG00__MVPCONF0:
8526 CP0_CHECK(ctx->insn_flags & ASE_MT);
8527 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8528 register_name = "MVPConf0";
8529 break;
8530 case CP0_REG00__MVPCONF1:
8531 CP0_CHECK(ctx->insn_flags & ASE_MT);
8532 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8533 register_name = "MVPConf1";
8534 break;
8535 case CP0_REG00__VPCONTROL:
8536 CP0_CHECK(ctx->vp);
8537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8538 register_name = "VPControl";
8539 break;
8540 default:
8541 goto cp0_unimplemented;
8543 break;
8544 case CP0_REGISTER_01:
8545 switch (sel) {
8546 case CP0_REG01__RANDOM:
8547 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8548 gen_helper_mfc0_random(arg, cpu_env);
8549 register_name = "Random";
8550 break;
8551 case CP0_REG01__VPECONTROL:
8552 CP0_CHECK(ctx->insn_flags & ASE_MT);
8553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8554 register_name = "VPEControl";
8555 break;
8556 case CP0_REG01__VPECONF0:
8557 CP0_CHECK(ctx->insn_flags & ASE_MT);
8558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8559 register_name = "VPEConf0";
8560 break;
8561 case CP0_REG01__VPECONF1:
8562 CP0_CHECK(ctx->insn_flags & ASE_MT);
8563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8564 register_name = "VPEConf1";
8565 break;
8566 case CP0_REG01__YQMASK:
8567 CP0_CHECK(ctx->insn_flags & ASE_MT);
8568 tcg_gen_ld_tl(arg, cpu_env,
8569 offsetof(CPUMIPSState, CP0_YQMask));
8570 register_name = "YQMask";
8571 break;
8572 case CP0_REG01__VPESCHEDULE:
8573 CP0_CHECK(ctx->insn_flags & ASE_MT);
8574 tcg_gen_ld_tl(arg, cpu_env,
8575 offsetof(CPUMIPSState, CP0_VPESchedule));
8576 register_name = "VPESchedule";
8577 break;
8578 case CP0_REG01__VPESCHEFBACK:
8579 CP0_CHECK(ctx->insn_flags & ASE_MT);
8580 tcg_gen_ld_tl(arg, cpu_env,
8581 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8582 register_name = "VPEScheFBack";
8583 break;
8584 case CP0_REG01__VPEOPT:
8585 CP0_CHECK(ctx->insn_flags & ASE_MT);
8586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8587 register_name = "VPEOpt";
8588 break;
8589 default:
8590 goto cp0_unimplemented;
8592 break;
8593 case CP0_REGISTER_02:
8594 switch (sel) {
8595 case CP0_REG02__ENTRYLO0:
8596 tcg_gen_ld_tl(arg, cpu_env,
8597 offsetof(CPUMIPSState, CP0_EntryLo0));
8598 register_name = "EntryLo0";
8599 break;
8600 case CP0_REG02__TCSTATUS:
8601 CP0_CHECK(ctx->insn_flags & ASE_MT);
8602 gen_helper_mfc0_tcstatus(arg, cpu_env);
8603 register_name = "TCStatus";
8604 break;
8605 case CP0_REG02__TCBIND:
8606 CP0_CHECK(ctx->insn_flags & ASE_MT);
8607 gen_helper_mfc0_tcbind(arg, cpu_env);
8608 register_name = "TCBind";
8609 break;
8610 case CP0_REG02__TCRESTART:
8611 CP0_CHECK(ctx->insn_flags & ASE_MT);
8612 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8613 register_name = "TCRestart";
8614 break;
8615 case CP0_REG02__TCHALT:
8616 CP0_CHECK(ctx->insn_flags & ASE_MT);
8617 gen_helper_dmfc0_tchalt(arg, cpu_env);
8618 register_name = "TCHalt";
8619 break;
8620 case CP0_REG02__TCCONTEXT:
8621 CP0_CHECK(ctx->insn_flags & ASE_MT);
8622 gen_helper_dmfc0_tccontext(arg, cpu_env);
8623 register_name = "TCContext";
8624 break;
8625 case CP0_REG02__TCSCHEDULE:
8626 CP0_CHECK(ctx->insn_flags & ASE_MT);
8627 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8628 register_name = "TCSchedule";
8629 break;
8630 case CP0_REG02__TCSCHEFBACK:
8631 CP0_CHECK(ctx->insn_flags & ASE_MT);
8632 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8633 register_name = "TCScheFBack";
8634 break;
8635 default:
8636 goto cp0_unimplemented;
8638 break;
8639 case CP0_REGISTER_03:
8640 switch (sel) {
8641 case CP0_REG03__ENTRYLO1:
8642 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8643 register_name = "EntryLo1";
8644 break;
8645 case CP0_REG03__GLOBALNUM:
8646 CP0_CHECK(ctx->vp);
8647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8648 register_name = "GlobalNumber";
8649 break;
8650 default:
8651 goto cp0_unimplemented;
8653 break;
8654 case CP0_REGISTER_04:
8655 switch (sel) {
8656 case CP0_REG04__CONTEXT:
8657 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8658 register_name = "Context";
8659 break;
8660 case CP0_REG04__CONTEXTCONFIG:
8661 /* SmartMIPS ASE */
8662 /* gen_helper_dmfc0_contextconfig(arg); */
8663 register_name = "ContextConfig";
8664 goto cp0_unimplemented;
8665 case CP0_REG04__USERLOCAL:
8666 CP0_CHECK(ctx->ulri);
8667 tcg_gen_ld_tl(arg, cpu_env,
8668 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8669 register_name = "UserLocal";
8670 break;
8671 case CP0_REG04__MMID:
8672 CP0_CHECK(ctx->mi);
8673 gen_helper_mtc0_memorymapid(cpu_env, arg);
8674 register_name = "MMID";
8675 break;
8676 default:
8677 goto cp0_unimplemented;
8679 break;
8680 case CP0_REGISTER_05:
8681 switch (sel) {
8682 case CP0_REG05__PAGEMASK:
8683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8684 register_name = "PageMask";
8685 break;
8686 case CP0_REG05__PAGEGRAIN:
8687 check_insn(ctx, ISA_MIPS32R2);
8688 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8689 register_name = "PageGrain";
8690 break;
8691 case CP0_REG05__SEGCTL0:
8692 CP0_CHECK(ctx->sc);
8693 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8694 register_name = "SegCtl0";
8695 break;
8696 case CP0_REG05__SEGCTL1:
8697 CP0_CHECK(ctx->sc);
8698 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8699 register_name = "SegCtl1";
8700 break;
8701 case CP0_REG05__SEGCTL2:
8702 CP0_CHECK(ctx->sc);
8703 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8704 register_name = "SegCtl2";
8705 break;
8706 case CP0_REG05__PWBASE:
8707 check_pw(ctx);
8708 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8709 register_name = "PWBase";
8710 break;
8711 case CP0_REG05__PWFIELD:
8712 check_pw(ctx);
8713 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8714 register_name = "PWField";
8715 break;
8716 case CP0_REG05__PWSIZE:
8717 check_pw(ctx);
8718 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8719 register_name = "PWSize";
8720 break;
8721 default:
8722 goto cp0_unimplemented;
8724 break;
8725 case CP0_REGISTER_06:
8726 switch (sel) {
8727 case CP0_REG06__WIRED:
8728 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8729 register_name = "Wired";
8730 break;
8731 case CP0_REG06__SRSCONF0:
8732 check_insn(ctx, ISA_MIPS32R2);
8733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8734 register_name = "SRSConf0";
8735 break;
8736 case CP0_REG06__SRSCONF1:
8737 check_insn(ctx, ISA_MIPS32R2);
8738 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8739 register_name = "SRSConf1";
8740 break;
8741 case CP0_REG06__SRSCONF2:
8742 check_insn(ctx, ISA_MIPS32R2);
8743 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8744 register_name = "SRSConf2";
8745 break;
8746 case CP0_REG06__SRSCONF3:
8747 check_insn(ctx, ISA_MIPS32R2);
8748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8749 register_name = "SRSConf3";
8750 break;
8751 case CP0_REG06__SRSCONF4:
8752 check_insn(ctx, ISA_MIPS32R2);
8753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8754 register_name = "SRSConf4";
8755 break;
8756 case CP0_REG06__PWCTL:
8757 check_pw(ctx);
8758 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8759 register_name = "PWCtl";
8760 break;
8761 default:
8762 goto cp0_unimplemented;
8764 break;
8765 case CP0_REGISTER_07:
8766 switch (sel) {
8767 case CP0_REG07__HWRENA:
8768 check_insn(ctx, ISA_MIPS32R2);
8769 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8770 register_name = "HWREna";
8771 break;
8772 default:
8773 goto cp0_unimplemented;
8775 break;
8776 case CP0_REGISTER_08:
8777 switch (sel) {
8778 case CP0_REG08__BADVADDR:
8779 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8780 register_name = "BadVAddr";
8781 break;
8782 case CP0_REG08__BADINSTR:
8783 CP0_CHECK(ctx->bi);
8784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8785 register_name = "BadInstr";
8786 break;
8787 case CP0_REG08__BADINSTRP:
8788 CP0_CHECK(ctx->bp);
8789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8790 register_name = "BadInstrP";
8791 break;
8792 case CP0_REG08__BADINSTRX:
8793 CP0_CHECK(ctx->bi);
8794 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8795 tcg_gen_andi_tl(arg, arg, ~0xffff);
8796 register_name = "BadInstrX";
8797 break;
8798 default:
8799 goto cp0_unimplemented;
8801 break;
8802 case CP0_REGISTER_09:
8803 switch (sel) {
8804 case CP0_REG09__COUNT:
8805 /* Mark as an IO operation because we read the time. */
8806 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8807 gen_io_start();
8809 gen_helper_mfc0_count(arg, cpu_env);
8811 * Break the TB to be able to take timer interrupts immediately
8812 * after reading count. DISAS_STOP isn't sufficient, we need to
8813 * ensure we break completely out of translated code.
8815 gen_save_pc(ctx->base.pc_next + 4);
8816 ctx->base.is_jmp = DISAS_EXIT;
8817 register_name = "Count";
8818 break;
8819 case CP0_REG09__SAARI:
8820 CP0_CHECK(ctx->saar);
8821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
8822 register_name = "SAARI";
8823 break;
8824 case CP0_REG09__SAAR:
8825 CP0_CHECK(ctx->saar);
8826 gen_helper_dmfc0_saar(arg, cpu_env);
8827 register_name = "SAAR";
8828 break;
8829 default:
8830 goto cp0_unimplemented;
8832 break;
8833 case CP0_REGISTER_10:
8834 switch (sel) {
8835 case CP0_REG10__ENTRYHI:
8836 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8837 register_name = "EntryHi";
8838 break;
8839 default:
8840 goto cp0_unimplemented;
8842 break;
8843 case CP0_REGISTER_11:
8844 switch (sel) {
8845 case CP0_REG11__COMPARE:
8846 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8847 register_name = "Compare";
8848 break;
8849 /* 6,7 are implementation dependent */
8850 default:
8851 goto cp0_unimplemented;
8853 break;
8854 case CP0_REGISTER_12:
8855 switch (sel) {
8856 case CP0_REG12__STATUS:
8857 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8858 register_name = "Status";
8859 break;
8860 case CP0_REG12__INTCTL:
8861 check_insn(ctx, ISA_MIPS32R2);
8862 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8863 register_name = "IntCtl";
8864 break;
8865 case CP0_REG12__SRSCTL:
8866 check_insn(ctx, ISA_MIPS32R2);
8867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8868 register_name = "SRSCtl";
8869 break;
8870 case CP0_REG12__SRSMAP:
8871 check_insn(ctx, ISA_MIPS32R2);
8872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8873 register_name = "SRSMap";
8874 break;
8875 default:
8876 goto cp0_unimplemented;
8878 break;
8879 case CP0_REGISTER_13:
8880 switch (sel) {
8881 case CP0_REG13__CAUSE:
8882 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8883 register_name = "Cause";
8884 break;
8885 default:
8886 goto cp0_unimplemented;
8888 break;
8889 case CP0_REGISTER_14:
8890 switch (sel) {
8891 case CP0_REG14__EPC:
8892 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8893 register_name = "EPC";
8894 break;
8895 default:
8896 goto cp0_unimplemented;
8898 break;
8899 case CP0_REGISTER_15:
8900 switch (sel) {
8901 case CP0_REG15__PRID:
8902 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8903 register_name = "PRid";
8904 break;
8905 case CP0_REG15__EBASE:
8906 check_insn(ctx, ISA_MIPS32R2);
8907 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8908 register_name = "EBase";
8909 break;
8910 case CP0_REG15__CMGCRBASE:
8911 check_insn(ctx, ISA_MIPS32R2);
8912 CP0_CHECK(ctx->cmgcr);
8913 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8914 register_name = "CMGCRBase";
8915 break;
8916 default:
8917 goto cp0_unimplemented;
8919 break;
8920 case CP0_REGISTER_16:
8921 switch (sel) {
8922 case CP0_REG16__CONFIG:
8923 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8924 register_name = "Config";
8925 break;
8926 case CP0_REG16__CONFIG1:
8927 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8928 register_name = "Config1";
8929 break;
8930 case CP0_REG16__CONFIG2:
8931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8932 register_name = "Config2";
8933 break;
8934 case CP0_REG16__CONFIG3:
8935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8936 register_name = "Config3";
8937 break;
8938 case CP0_REG16__CONFIG4:
8939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8940 register_name = "Config4";
8941 break;
8942 case CP0_REG16__CONFIG5:
8943 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8944 register_name = "Config5";
8945 break;
8946 /* 6,7 are implementation dependent */
8947 case CP0_REG16__CONFIG6:
8948 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8949 register_name = "Config6";
8950 break;
8951 case CP0_REG16__CONFIG7:
8952 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8953 register_name = "Config7";
8954 break;
8955 default:
8956 goto cp0_unimplemented;
8958 break;
8959 case CP0_REGISTER_17:
8960 switch (sel) {
8961 case CP0_REG17__LLADDR:
8962 gen_helper_dmfc0_lladdr(arg, cpu_env);
8963 register_name = "LLAddr";
8964 break;
8965 case CP0_REG17__MAAR:
8966 CP0_CHECK(ctx->mrp);
8967 gen_helper_dmfc0_maar(arg, cpu_env);
8968 register_name = "MAAR";
8969 break;
8970 case CP0_REG17__MAARI:
8971 CP0_CHECK(ctx->mrp);
8972 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8973 register_name = "MAARI";
8974 break;
8975 default:
8976 goto cp0_unimplemented;
8978 break;
8979 case CP0_REGISTER_18:
8980 switch (sel) {
8981 case CP0_REG18__WATCHLO0:
8982 case CP0_REG18__WATCHLO1:
8983 case CP0_REG18__WATCHLO2:
8984 case CP0_REG18__WATCHLO3:
8985 case CP0_REG18__WATCHLO4:
8986 case CP0_REG18__WATCHLO5:
8987 case CP0_REG18__WATCHLO6:
8988 case CP0_REG18__WATCHLO7:
8989 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8990 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8991 register_name = "WatchLo";
8992 break;
8993 default:
8994 goto cp0_unimplemented;
8996 break;
8997 case CP0_REGISTER_19:
8998 switch (sel) {
8999 case CP0_REG19__WATCHHI0:
9000 case CP0_REG19__WATCHHI1:
9001 case CP0_REG19__WATCHHI2:
9002 case CP0_REG19__WATCHHI3:
9003 case CP0_REG19__WATCHHI4:
9004 case CP0_REG19__WATCHHI5:
9005 case CP0_REG19__WATCHHI6:
9006 case CP0_REG19__WATCHHI7:
9007 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9008 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9009 register_name = "WatchHi";
9010 break;
9011 default:
9012 goto cp0_unimplemented;
9014 break;
9015 case CP0_REGISTER_20:
9016 switch (sel) {
9017 case CP0_REG20__XCONTEXT:
9018 check_insn(ctx, ISA_MIPS3);
9019 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9020 register_name = "XContext";
9021 break;
9022 default:
9023 goto cp0_unimplemented;
9025 break;
9026 case CP0_REGISTER_21:
9027 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9028 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9029 switch (sel) {
9030 case 0:
9031 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9032 register_name = "Framemask";
9033 break;
9034 default:
9035 goto cp0_unimplemented;
9037 break;
9038 case CP0_REGISTER_22:
9039 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9040 register_name = "'Diagnostic"; /* implementation dependent */
9041 break;
9042 case CP0_REGISTER_23:
9043 switch (sel) {
9044 case CP0_REG23__DEBUG:
9045 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9046 register_name = "Debug";
9047 break;
9048 case CP0_REG23__TRACECONTROL:
9049 /* PDtrace support */
9050 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9051 register_name = "TraceControl";
9052 goto cp0_unimplemented;
9053 case CP0_REG23__TRACECONTROL2:
9054 /* PDtrace support */
9055 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9056 register_name = "TraceControl2";
9057 goto cp0_unimplemented;
9058 case CP0_REG23__USERTRACEDATA1:
9059 /* PDtrace support */
9060 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9061 register_name = "UserTraceData1";
9062 goto cp0_unimplemented;
9063 case CP0_REG23__TRACEIBPC:
9064 /* PDtrace support */
9065 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9066 register_name = "TraceIBPC";
9067 goto cp0_unimplemented;
9068 case CP0_REG23__TRACEDBPC:
9069 /* PDtrace support */
9070 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9071 register_name = "TraceDBPC";
9072 goto cp0_unimplemented;
9073 default:
9074 goto cp0_unimplemented;
9076 break;
9077 case CP0_REGISTER_24:
9078 switch (sel) {
9079 case CP0_REG24__DEPC:
9080 /* EJTAG support */
9081 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9082 register_name = "DEPC";
9083 break;
9084 default:
9085 goto cp0_unimplemented;
9087 break;
9088 case CP0_REGISTER_25:
9089 switch (sel) {
9090 case CP0_REG25__PERFCTL0:
9091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9092 register_name = "Performance0";
9093 break;
9094 case CP0_REG25__PERFCNT0:
9095 /* gen_helper_dmfc0_performance1(arg); */
9096 register_name = "Performance1";
9097 goto cp0_unimplemented;
9098 case CP0_REG25__PERFCTL1:
9099 /* gen_helper_dmfc0_performance2(arg); */
9100 register_name = "Performance2";
9101 goto cp0_unimplemented;
9102 case CP0_REG25__PERFCNT1:
9103 /* gen_helper_dmfc0_performance3(arg); */
9104 register_name = "Performance3";
9105 goto cp0_unimplemented;
9106 case CP0_REG25__PERFCTL2:
9107 /* gen_helper_dmfc0_performance4(arg); */
9108 register_name = "Performance4";
9109 goto cp0_unimplemented;
9110 case CP0_REG25__PERFCNT2:
9111 /* gen_helper_dmfc0_performance5(arg); */
9112 register_name = "Performance5";
9113 goto cp0_unimplemented;
9114 case CP0_REG25__PERFCTL3:
9115 /* gen_helper_dmfc0_performance6(arg); */
9116 register_name = "Performance6";
9117 goto cp0_unimplemented;
9118 case CP0_REG25__PERFCNT3:
9119 /* gen_helper_dmfc0_performance7(arg); */
9120 register_name = "Performance7";
9121 goto cp0_unimplemented;
9122 default:
9123 goto cp0_unimplemented;
9125 break;
9126 case CP0_REGISTER_26:
9127 switch (sel) {
9128 case CP0_REG26__ERRCTL:
9129 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9130 register_name = "ErrCtl";
9131 break;
9132 default:
9133 goto cp0_unimplemented;
9135 break;
9136 case CP0_REGISTER_27:
9137 switch (sel) {
9138 /* ignored */
9139 case CP0_REG27__CACHERR:
9140 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9141 register_name = "CacheErr";
9142 break;
9143 default:
9144 goto cp0_unimplemented;
9146 break;
9147 case CP0_REGISTER_28:
9148 switch (sel) {
9149 case CP0_REG28__TAGLO:
9150 case CP0_REG28__TAGLO1:
9151 case CP0_REG28__TAGLO2:
9152 case CP0_REG28__TAGLO3:
9153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9154 register_name = "TagLo";
9155 break;
9156 case CP0_REG28__DATALO:
9157 case CP0_REG28__DATALO1:
9158 case CP0_REG28__DATALO2:
9159 case CP0_REG28__DATALO3:
9160 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9161 register_name = "DataLo";
9162 break;
9163 default:
9164 goto cp0_unimplemented;
9166 break;
9167 case CP0_REGISTER_29:
9168 switch (sel) {
9169 case CP0_REG29__TAGHI:
9170 case CP0_REG29__TAGHI1:
9171 case CP0_REG29__TAGHI2:
9172 case CP0_REG29__TAGHI3:
9173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9174 register_name = "TagHi";
9175 break;
9176 case CP0_REG29__DATAHI:
9177 case CP0_REG29__DATAHI1:
9178 case CP0_REG29__DATAHI2:
9179 case CP0_REG29__DATAHI3:
9180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9181 register_name = "DataHi";
9182 break;
9183 default:
9184 goto cp0_unimplemented;
9186 break;
9187 case CP0_REGISTER_30:
9188 switch (sel) {
9189 case CP0_REG30__ERROREPC:
9190 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9191 register_name = "ErrorEPC";
9192 break;
9193 default:
9194 goto cp0_unimplemented;
9196 break;
9197 case CP0_REGISTER_31:
9198 switch (sel) {
9199 case CP0_REG31__DESAVE:
9200 /* EJTAG support */
9201 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9202 register_name = "DESAVE";
9203 break;
9204 case CP0_REG31__KSCRATCH1:
9205 case CP0_REG31__KSCRATCH2:
9206 case CP0_REG31__KSCRATCH3:
9207 case CP0_REG31__KSCRATCH4:
9208 case CP0_REG31__KSCRATCH5:
9209 case CP0_REG31__KSCRATCH6:
9210 CP0_CHECK(ctx->kscrexist & (1 << sel));
9211 tcg_gen_ld_tl(arg, cpu_env,
9212 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9213 register_name = "KScratch";
9214 break;
9215 default:
9216 goto cp0_unimplemented;
9218 break;
9219 default:
9220 goto cp0_unimplemented;
9222 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9223 return;
9225 cp0_unimplemented:
9226 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9227 register_name, reg, sel);
9228 gen_mfc0_unimplemented(ctx, arg);
9231 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9233 const char *register_name = "invalid";
9235 if (sel != 0) {
9236 check_insn(ctx, ISA_MIPS64);
9239 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9240 gen_io_start();
9243 switch (reg) {
9244 case CP0_REGISTER_00:
9245 switch (sel) {
9246 case CP0_REG00__INDEX:
9247 gen_helper_mtc0_index(cpu_env, arg);
9248 register_name = "Index";
9249 break;
9250 case CP0_REG00__MVPCONTROL:
9251 CP0_CHECK(ctx->insn_flags & ASE_MT);
9252 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9253 register_name = "MVPControl";
9254 break;
9255 case CP0_REG00__MVPCONF0:
9256 CP0_CHECK(ctx->insn_flags & ASE_MT);
9257 /* ignored */
9258 register_name = "MVPConf0";
9259 break;
9260 case CP0_REG00__MVPCONF1:
9261 CP0_CHECK(ctx->insn_flags & ASE_MT);
9262 /* ignored */
9263 register_name = "MVPConf1";
9264 break;
9265 case CP0_REG00__VPCONTROL:
9266 CP0_CHECK(ctx->vp);
9267 /* ignored */
9268 register_name = "VPControl";
9269 break;
9270 default:
9271 goto cp0_unimplemented;
9273 break;
9274 case CP0_REGISTER_01:
9275 switch (sel) {
9276 case CP0_REG01__RANDOM:
9277 /* ignored */
9278 register_name = "Random";
9279 break;
9280 case CP0_REG01__VPECONTROL:
9281 CP0_CHECK(ctx->insn_flags & ASE_MT);
9282 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9283 register_name = "VPEControl";
9284 break;
9285 case CP0_REG01__VPECONF0:
9286 CP0_CHECK(ctx->insn_flags & ASE_MT);
9287 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9288 register_name = "VPEConf0";
9289 break;
9290 case CP0_REG01__VPECONF1:
9291 CP0_CHECK(ctx->insn_flags & ASE_MT);
9292 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9293 register_name = "VPEConf1";
9294 break;
9295 case CP0_REG01__YQMASK:
9296 CP0_CHECK(ctx->insn_flags & ASE_MT);
9297 gen_helper_mtc0_yqmask(cpu_env, arg);
9298 register_name = "YQMask";
9299 break;
9300 case CP0_REG01__VPESCHEDULE:
9301 CP0_CHECK(ctx->insn_flags & ASE_MT);
9302 tcg_gen_st_tl(arg, cpu_env,
9303 offsetof(CPUMIPSState, CP0_VPESchedule));
9304 register_name = "VPESchedule";
9305 break;
9306 case CP0_REG01__VPESCHEFBACK:
9307 CP0_CHECK(ctx->insn_flags & ASE_MT);
9308 tcg_gen_st_tl(arg, cpu_env,
9309 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9310 register_name = "VPEScheFBack";
9311 break;
9312 case CP0_REG01__VPEOPT:
9313 CP0_CHECK(ctx->insn_flags & ASE_MT);
9314 gen_helper_mtc0_vpeopt(cpu_env, arg);
9315 register_name = "VPEOpt";
9316 break;
9317 default:
9318 goto cp0_unimplemented;
9320 break;
9321 case CP0_REGISTER_02:
9322 switch (sel) {
9323 case CP0_REG02__ENTRYLO0:
9324 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9325 register_name = "EntryLo0";
9326 break;
9327 case CP0_REG02__TCSTATUS:
9328 CP0_CHECK(ctx->insn_flags & ASE_MT);
9329 gen_helper_mtc0_tcstatus(cpu_env, arg);
9330 register_name = "TCStatus";
9331 break;
9332 case CP0_REG02__TCBIND:
9333 CP0_CHECK(ctx->insn_flags & ASE_MT);
9334 gen_helper_mtc0_tcbind(cpu_env, arg);
9335 register_name = "TCBind";
9336 break;
9337 case CP0_REG02__TCRESTART:
9338 CP0_CHECK(ctx->insn_flags & ASE_MT);
9339 gen_helper_mtc0_tcrestart(cpu_env, arg);
9340 register_name = "TCRestart";
9341 break;
9342 case CP0_REG02__TCHALT:
9343 CP0_CHECK(ctx->insn_flags & ASE_MT);
9344 gen_helper_mtc0_tchalt(cpu_env, arg);
9345 register_name = "TCHalt";
9346 break;
9347 case CP0_REG02__TCCONTEXT:
9348 CP0_CHECK(ctx->insn_flags & ASE_MT);
9349 gen_helper_mtc0_tccontext(cpu_env, arg);
9350 register_name = "TCContext";
9351 break;
9352 case CP0_REG02__TCSCHEDULE:
9353 CP0_CHECK(ctx->insn_flags & ASE_MT);
9354 gen_helper_mtc0_tcschedule(cpu_env, arg);
9355 register_name = "TCSchedule";
9356 break;
9357 case CP0_REG02__TCSCHEFBACK:
9358 CP0_CHECK(ctx->insn_flags & ASE_MT);
9359 gen_helper_mtc0_tcschefback(cpu_env, arg);
9360 register_name = "TCScheFBack";
9361 break;
9362 default:
9363 goto cp0_unimplemented;
9365 break;
9366 case CP0_REGISTER_03:
9367 switch (sel) {
9368 case CP0_REG03__ENTRYLO1:
9369 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9370 register_name = "EntryLo1";
9371 break;
9372 case CP0_REG03__GLOBALNUM:
9373 CP0_CHECK(ctx->vp);
9374 /* ignored */
9375 register_name = "GlobalNumber";
9376 break;
9377 default:
9378 goto cp0_unimplemented;
9380 break;
9381 case CP0_REGISTER_04:
9382 switch (sel) {
9383 case CP0_REG04__CONTEXT:
9384 gen_helper_mtc0_context(cpu_env, arg);
9385 register_name = "Context";
9386 break;
9387 case CP0_REG04__CONTEXTCONFIG:
9388 /* SmartMIPS ASE */
9389 /* gen_helper_dmtc0_contextconfig(arg); */
9390 register_name = "ContextConfig";
9391 goto cp0_unimplemented;
9392 case CP0_REG04__USERLOCAL:
9393 CP0_CHECK(ctx->ulri);
9394 tcg_gen_st_tl(arg, cpu_env,
9395 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9396 register_name = "UserLocal";
9397 break;
9398 case CP0_REG04__MMID:
9399 CP0_CHECK(ctx->mi);
9400 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9401 register_name = "MMID";
9402 break;
9403 default:
9404 goto cp0_unimplemented;
9406 break;
9407 case CP0_REGISTER_05:
9408 switch (sel) {
9409 case CP0_REG05__PAGEMASK:
9410 gen_helper_mtc0_pagemask(cpu_env, arg);
9411 register_name = "PageMask";
9412 break;
9413 case CP0_REG05__PAGEGRAIN:
9414 check_insn(ctx, ISA_MIPS32R2);
9415 gen_helper_mtc0_pagegrain(cpu_env, arg);
9416 register_name = "PageGrain";
9417 break;
9418 case CP0_REG05__SEGCTL0:
9419 CP0_CHECK(ctx->sc);
9420 gen_helper_mtc0_segctl0(cpu_env, arg);
9421 register_name = "SegCtl0";
9422 break;
9423 case CP0_REG05__SEGCTL1:
9424 CP0_CHECK(ctx->sc);
9425 gen_helper_mtc0_segctl1(cpu_env, arg);
9426 register_name = "SegCtl1";
9427 break;
9428 case CP0_REG05__SEGCTL2:
9429 CP0_CHECK(ctx->sc);
9430 gen_helper_mtc0_segctl2(cpu_env, arg);
9431 register_name = "SegCtl2";
9432 break;
9433 case CP0_REG05__PWBASE:
9434 check_pw(ctx);
9435 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9436 register_name = "PWBase";
9437 break;
9438 case CP0_REG05__PWFIELD:
9439 check_pw(ctx);
9440 gen_helper_mtc0_pwfield(cpu_env, arg);
9441 register_name = "PWField";
9442 break;
9443 case CP0_REG05__PWSIZE:
9444 check_pw(ctx);
9445 gen_helper_mtc0_pwsize(cpu_env, arg);
9446 register_name = "PWSize";
9447 break;
9448 default:
9449 goto cp0_unimplemented;
9451 break;
9452 case CP0_REGISTER_06:
9453 switch (sel) {
9454 case CP0_REG06__WIRED:
9455 gen_helper_mtc0_wired(cpu_env, arg);
9456 register_name = "Wired";
9457 break;
9458 case CP0_REG06__SRSCONF0:
9459 check_insn(ctx, ISA_MIPS32R2);
9460 gen_helper_mtc0_srsconf0(cpu_env, arg);
9461 register_name = "SRSConf0";
9462 break;
9463 case CP0_REG06__SRSCONF1:
9464 check_insn(ctx, ISA_MIPS32R2);
9465 gen_helper_mtc0_srsconf1(cpu_env, arg);
9466 register_name = "SRSConf1";
9467 break;
9468 case CP0_REG06__SRSCONF2:
9469 check_insn(ctx, ISA_MIPS32R2);
9470 gen_helper_mtc0_srsconf2(cpu_env, arg);
9471 register_name = "SRSConf2";
9472 break;
9473 case CP0_REG06__SRSCONF3:
9474 check_insn(ctx, ISA_MIPS32R2);
9475 gen_helper_mtc0_srsconf3(cpu_env, arg);
9476 register_name = "SRSConf3";
9477 break;
9478 case CP0_REG06__SRSCONF4:
9479 check_insn(ctx, ISA_MIPS32R2);
9480 gen_helper_mtc0_srsconf4(cpu_env, arg);
9481 register_name = "SRSConf4";
9482 break;
9483 case CP0_REG06__PWCTL:
9484 check_pw(ctx);
9485 gen_helper_mtc0_pwctl(cpu_env, arg);
9486 register_name = "PWCtl";
9487 break;
9488 default:
9489 goto cp0_unimplemented;
9491 break;
9492 case CP0_REGISTER_07:
9493 switch (sel) {
9494 case CP0_REG07__HWRENA:
9495 check_insn(ctx, ISA_MIPS32R2);
9496 gen_helper_mtc0_hwrena(cpu_env, arg);
9497 ctx->base.is_jmp = DISAS_STOP;
9498 register_name = "HWREna";
9499 break;
9500 default:
9501 goto cp0_unimplemented;
9503 break;
9504 case CP0_REGISTER_08:
9505 switch (sel) {
9506 case CP0_REG08__BADVADDR:
9507 /* ignored */
9508 register_name = "BadVAddr";
9509 break;
9510 case CP0_REG08__BADINSTR:
9511 /* ignored */
9512 register_name = "BadInstr";
9513 break;
9514 case CP0_REG08__BADINSTRP:
9515 /* ignored */
9516 register_name = "BadInstrP";
9517 break;
9518 case CP0_REG08__BADINSTRX:
9519 /* ignored */
9520 register_name = "BadInstrX";
9521 break;
9522 default:
9523 goto cp0_unimplemented;
9525 break;
9526 case CP0_REGISTER_09:
9527 switch (sel) {
9528 case CP0_REG09__COUNT:
9529 gen_helper_mtc0_count(cpu_env, arg);
9530 register_name = "Count";
9531 break;
9532 case CP0_REG09__SAARI:
9533 CP0_CHECK(ctx->saar);
9534 gen_helper_mtc0_saari(cpu_env, arg);
9535 register_name = "SAARI";
9536 break;
9537 case CP0_REG09__SAAR:
9538 CP0_CHECK(ctx->saar);
9539 gen_helper_mtc0_saar(cpu_env, arg);
9540 register_name = "SAAR";
9541 break;
9542 default:
9543 goto cp0_unimplemented;
9545 /* Stop translation as we may have switched the execution mode */
9546 ctx->base.is_jmp = DISAS_STOP;
9547 break;
9548 case CP0_REGISTER_10:
9549 switch (sel) {
9550 case CP0_REG10__ENTRYHI:
9551 gen_helper_mtc0_entryhi(cpu_env, arg);
9552 register_name = "EntryHi";
9553 break;
9554 default:
9555 goto cp0_unimplemented;
9557 break;
9558 case CP0_REGISTER_11:
9559 switch (sel) {
9560 case CP0_REG11__COMPARE:
9561 gen_helper_mtc0_compare(cpu_env, arg);
9562 register_name = "Compare";
9563 break;
9564 /* 6,7 are implementation dependent */
9565 default:
9566 goto cp0_unimplemented;
9568 /* Stop translation as we may have switched the execution mode */
9569 ctx->base.is_jmp = DISAS_STOP;
9570 break;
9571 case CP0_REGISTER_12:
9572 switch (sel) {
9573 case CP0_REG12__STATUS:
9574 save_cpu_state(ctx, 1);
9575 gen_helper_mtc0_status(cpu_env, arg);
9576 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9577 gen_save_pc(ctx->base.pc_next + 4);
9578 ctx->base.is_jmp = DISAS_EXIT;
9579 register_name = "Status";
9580 break;
9581 case CP0_REG12__INTCTL:
9582 check_insn(ctx, ISA_MIPS32R2);
9583 gen_helper_mtc0_intctl(cpu_env, arg);
9584 /* Stop translation as we may have switched the execution mode */
9585 ctx->base.is_jmp = DISAS_STOP;
9586 register_name = "IntCtl";
9587 break;
9588 case CP0_REG12__SRSCTL:
9589 check_insn(ctx, ISA_MIPS32R2);
9590 gen_helper_mtc0_srsctl(cpu_env, arg);
9591 /* Stop translation as we may have switched the execution mode */
9592 ctx->base.is_jmp = DISAS_STOP;
9593 register_name = "SRSCtl";
9594 break;
9595 case CP0_REG12__SRSMAP:
9596 check_insn(ctx, ISA_MIPS32R2);
9597 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9598 /* Stop translation as we may have switched the execution mode */
9599 ctx->base.is_jmp = DISAS_STOP;
9600 register_name = "SRSMap";
9601 break;
9602 default:
9603 goto cp0_unimplemented;
9605 break;
9606 case CP0_REGISTER_13:
9607 switch (sel) {
9608 case CP0_REG13__CAUSE:
9609 save_cpu_state(ctx, 1);
9610 gen_helper_mtc0_cause(cpu_env, arg);
9612 * Stop translation as we may have triggered an interrupt.
9613 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9614 * translated code to check for pending interrupts.
9616 gen_save_pc(ctx->base.pc_next + 4);
9617 ctx->base.is_jmp = DISAS_EXIT;
9618 register_name = "Cause";
9619 break;
9620 default:
9621 goto cp0_unimplemented;
9623 break;
9624 case CP0_REGISTER_14:
9625 switch (sel) {
9626 case CP0_REG14__EPC:
9627 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9628 register_name = "EPC";
9629 break;
9630 default:
9631 goto cp0_unimplemented;
9633 break;
9634 case CP0_REGISTER_15:
9635 switch (sel) {
9636 case CP0_REG15__PRID:
9637 /* ignored */
9638 register_name = "PRid";
9639 break;
9640 case CP0_REG15__EBASE:
9641 check_insn(ctx, ISA_MIPS32R2);
9642 gen_helper_mtc0_ebase(cpu_env, arg);
9643 register_name = "EBase";
9644 break;
9645 default:
9646 goto cp0_unimplemented;
9648 break;
9649 case CP0_REGISTER_16:
9650 switch (sel) {
9651 case CP0_REG16__CONFIG:
9652 gen_helper_mtc0_config0(cpu_env, arg);
9653 register_name = "Config";
9654 /* Stop translation as we may have switched the execution mode */
9655 ctx->base.is_jmp = DISAS_STOP;
9656 break;
9657 case CP0_REG16__CONFIG1:
9658 /* ignored, read only */
9659 register_name = "Config1";
9660 break;
9661 case CP0_REG16__CONFIG2:
9662 gen_helper_mtc0_config2(cpu_env, arg);
9663 register_name = "Config2";
9664 /* Stop translation as we may have switched the execution mode */
9665 ctx->base.is_jmp = DISAS_STOP;
9666 break;
9667 case CP0_REG16__CONFIG3:
9668 gen_helper_mtc0_config3(cpu_env, arg);
9669 register_name = "Config3";
9670 /* Stop translation as we may have switched the execution mode */
9671 ctx->base.is_jmp = DISAS_STOP;
9672 break;
9673 case CP0_REG16__CONFIG4:
9674 /* currently ignored */
9675 register_name = "Config4";
9676 break;
9677 case CP0_REG16__CONFIG5:
9678 gen_helper_mtc0_config5(cpu_env, arg);
9679 register_name = "Config5";
9680 /* Stop translation as we may have switched the execution mode */
9681 ctx->base.is_jmp = DISAS_STOP;
9682 break;
9683 /* 6,7 are implementation dependent */
9684 default:
9685 register_name = "Invalid config selector";
9686 goto cp0_unimplemented;
9688 break;
9689 case CP0_REGISTER_17:
9690 switch (sel) {
9691 case CP0_REG17__LLADDR:
9692 gen_helper_mtc0_lladdr(cpu_env, arg);
9693 register_name = "LLAddr";
9694 break;
9695 case CP0_REG17__MAAR:
9696 CP0_CHECK(ctx->mrp);
9697 gen_helper_mtc0_maar(cpu_env, arg);
9698 register_name = "MAAR";
9699 break;
9700 case CP0_REG17__MAARI:
9701 CP0_CHECK(ctx->mrp);
9702 gen_helper_mtc0_maari(cpu_env, arg);
9703 register_name = "MAARI";
9704 break;
9705 default:
9706 goto cp0_unimplemented;
9708 break;
9709 case CP0_REGISTER_18:
9710 switch (sel) {
9711 case CP0_REG18__WATCHLO0:
9712 case CP0_REG18__WATCHLO1:
9713 case CP0_REG18__WATCHLO2:
9714 case CP0_REG18__WATCHLO3:
9715 case CP0_REG18__WATCHLO4:
9716 case CP0_REG18__WATCHLO5:
9717 case CP0_REG18__WATCHLO6:
9718 case CP0_REG18__WATCHLO7:
9719 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9720 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9721 register_name = "WatchLo";
9722 break;
9723 default:
9724 goto cp0_unimplemented;
9726 break;
9727 case CP0_REGISTER_19:
9728 switch (sel) {
9729 case CP0_REG19__WATCHHI0:
9730 case CP0_REG19__WATCHHI1:
9731 case CP0_REG19__WATCHHI2:
9732 case CP0_REG19__WATCHHI3:
9733 case CP0_REG19__WATCHHI4:
9734 case CP0_REG19__WATCHHI5:
9735 case CP0_REG19__WATCHHI6:
9736 case CP0_REG19__WATCHHI7:
9737 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9738 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9739 register_name = "WatchHi";
9740 break;
9741 default:
9742 goto cp0_unimplemented;
9744 break;
9745 case CP0_REGISTER_20:
9746 switch (sel) {
9747 case CP0_REG20__XCONTEXT:
9748 check_insn(ctx, ISA_MIPS3);
9749 gen_helper_mtc0_xcontext(cpu_env, arg);
9750 register_name = "XContext";
9751 break;
9752 default:
9753 goto cp0_unimplemented;
9755 break;
9756 case CP0_REGISTER_21:
9757 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9758 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9759 switch (sel) {
9760 case 0:
9761 gen_helper_mtc0_framemask(cpu_env, arg);
9762 register_name = "Framemask";
9763 break;
9764 default:
9765 goto cp0_unimplemented;
9767 break;
9768 case CP0_REGISTER_22:
9769 /* ignored */
9770 register_name = "Diagnostic"; /* implementation dependent */
9771 break;
9772 case CP0_REGISTER_23:
9773 switch (sel) {
9774 case CP0_REG23__DEBUG:
9775 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9776 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9777 gen_save_pc(ctx->base.pc_next + 4);
9778 ctx->base.is_jmp = DISAS_EXIT;
9779 register_name = "Debug";
9780 break;
9781 case CP0_REG23__TRACECONTROL:
9782 /* PDtrace support */
9783 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
9784 /* Stop translation as we may have switched the execution mode */
9785 ctx->base.is_jmp = DISAS_STOP;
9786 register_name = "TraceControl";
9787 goto cp0_unimplemented;
9788 case CP0_REG23__TRACECONTROL2:
9789 /* PDtrace support */
9790 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
9791 /* Stop translation as we may have switched the execution mode */
9792 ctx->base.is_jmp = DISAS_STOP;
9793 register_name = "TraceControl2";
9794 goto cp0_unimplemented;
9795 case CP0_REG23__USERTRACEDATA1:
9796 /* PDtrace support */
9797 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
9798 /* Stop translation as we may have switched the execution mode */
9799 ctx->base.is_jmp = DISAS_STOP;
9800 register_name = "UserTraceData1";
9801 goto cp0_unimplemented;
9802 case CP0_REG23__TRACEIBPC:
9803 /* PDtrace support */
9804 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
9805 /* Stop translation as we may have switched the execution mode */
9806 ctx->base.is_jmp = DISAS_STOP;
9807 register_name = "TraceIBPC";
9808 goto cp0_unimplemented;
9809 case CP0_REG23__TRACEDBPC:
9810 /* PDtrace support */
9811 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
9812 /* Stop translation as we may have switched the execution mode */
9813 ctx->base.is_jmp = DISAS_STOP;
9814 register_name = "TraceDBPC";
9815 goto cp0_unimplemented;
9816 default:
9817 goto cp0_unimplemented;
9819 break;
9820 case CP0_REGISTER_24:
9821 switch (sel) {
9822 case CP0_REG24__DEPC:
9823 /* EJTAG support */
9824 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9825 register_name = "DEPC";
9826 break;
9827 default:
9828 goto cp0_unimplemented;
9830 break;
9831 case CP0_REGISTER_25:
9832 switch (sel) {
9833 case CP0_REG25__PERFCTL0:
9834 gen_helper_mtc0_performance0(cpu_env, arg);
9835 register_name = "Performance0";
9836 break;
9837 case CP0_REG25__PERFCNT0:
9838 /* gen_helper_mtc0_performance1(cpu_env, arg); */
9839 register_name = "Performance1";
9840 goto cp0_unimplemented;
9841 case CP0_REG25__PERFCTL1:
9842 /* gen_helper_mtc0_performance2(cpu_env, arg); */
9843 register_name = "Performance2";
9844 goto cp0_unimplemented;
9845 case CP0_REG25__PERFCNT1:
9846 /* gen_helper_mtc0_performance3(cpu_env, arg); */
9847 register_name = "Performance3";
9848 goto cp0_unimplemented;
9849 case CP0_REG25__PERFCTL2:
9850 /* gen_helper_mtc0_performance4(cpu_env, arg); */
9851 register_name = "Performance4";
9852 goto cp0_unimplemented;
9853 case CP0_REG25__PERFCNT2:
9854 /* gen_helper_mtc0_performance5(cpu_env, arg); */
9855 register_name = "Performance5";
9856 goto cp0_unimplemented;
9857 case CP0_REG25__PERFCTL3:
9858 /* gen_helper_mtc0_performance6(cpu_env, arg); */
9859 register_name = "Performance6";
9860 goto cp0_unimplemented;
9861 case CP0_REG25__PERFCNT3:
9862 /* gen_helper_mtc0_performance7(cpu_env, arg); */
9863 register_name = "Performance7";
9864 goto cp0_unimplemented;
9865 default:
9866 goto cp0_unimplemented;
9868 break;
9869 case CP0_REGISTER_26:
9870 switch (sel) {
9871 case CP0_REG26__ERRCTL:
9872 gen_helper_mtc0_errctl(cpu_env, arg);
9873 ctx->base.is_jmp = DISAS_STOP;
9874 register_name = "ErrCtl";
9875 break;
9876 default:
9877 goto cp0_unimplemented;
9879 break;
9880 case CP0_REGISTER_27:
9881 switch (sel) {
9882 case CP0_REG27__CACHERR:
9883 /* ignored */
9884 register_name = "CacheErr";
9885 break;
9886 default:
9887 goto cp0_unimplemented;
9889 break;
9890 case CP0_REGISTER_28:
9891 switch (sel) {
9892 case CP0_REG28__TAGLO:
9893 case CP0_REG28__TAGLO1:
9894 case CP0_REG28__TAGLO2:
9895 case CP0_REG28__TAGLO3:
9896 gen_helper_mtc0_taglo(cpu_env, arg);
9897 register_name = "TagLo";
9898 break;
9899 case CP0_REG28__DATALO:
9900 case CP0_REG28__DATALO1:
9901 case CP0_REG28__DATALO2:
9902 case CP0_REG28__DATALO3:
9903 gen_helper_mtc0_datalo(cpu_env, arg);
9904 register_name = "DataLo";
9905 break;
9906 default:
9907 goto cp0_unimplemented;
9909 break;
9910 case CP0_REGISTER_29:
9911 switch (sel) {
9912 case CP0_REG29__TAGHI:
9913 case CP0_REG29__TAGHI1:
9914 case CP0_REG29__TAGHI2:
9915 case CP0_REG29__TAGHI3:
9916 gen_helper_mtc0_taghi(cpu_env, arg);
9917 register_name = "TagHi";
9918 break;
9919 case CP0_REG29__DATAHI:
9920 case CP0_REG29__DATAHI1:
9921 case CP0_REG29__DATAHI2:
9922 case CP0_REG29__DATAHI3:
9923 gen_helper_mtc0_datahi(cpu_env, arg);
9924 register_name = "DataHi";
9925 break;
9926 default:
9927 register_name = "invalid sel";
9928 goto cp0_unimplemented;
9930 break;
9931 case CP0_REGISTER_30:
9932 switch (sel) {
9933 case CP0_REG30__ERROREPC:
9934 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9935 register_name = "ErrorEPC";
9936 break;
9937 default:
9938 goto cp0_unimplemented;
9940 break;
9941 case CP0_REGISTER_31:
9942 switch (sel) {
9943 case CP0_REG31__DESAVE:
9944 /* EJTAG support */
9945 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9946 register_name = "DESAVE";
9947 break;
9948 case CP0_REG31__KSCRATCH1:
9949 case CP0_REG31__KSCRATCH2:
9950 case CP0_REG31__KSCRATCH3:
9951 case CP0_REG31__KSCRATCH4:
9952 case CP0_REG31__KSCRATCH5:
9953 case CP0_REG31__KSCRATCH6:
9954 CP0_CHECK(ctx->kscrexist & (1 << sel));
9955 tcg_gen_st_tl(arg, cpu_env,
9956 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9957 register_name = "KScratch";
9958 break;
9959 default:
9960 goto cp0_unimplemented;
9962 break;
9963 default:
9964 goto cp0_unimplemented;
9966 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
9968 /* For simplicity assume that all writes can cause interrupts. */
9969 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9971 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9972 * translated code to check for pending interrupts.
9974 gen_save_pc(ctx->base.pc_next + 4);
9975 ctx->base.is_jmp = DISAS_EXIT;
9977 return;
9979 cp0_unimplemented:
9980 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
9981 register_name, reg, sel);
9983 #endif /* TARGET_MIPS64 */
9985 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9986 int u, int sel, int h)
9988 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9989 TCGv t0 = tcg_temp_local_new();
9991 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9992 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9993 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9994 tcg_gen_movi_tl(t0, -1);
9995 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9996 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9997 tcg_gen_movi_tl(t0, -1);
9998 } else if (u == 0) {
9999 switch (rt) {
10000 case 1:
10001 switch (sel) {
10002 case 1:
10003 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10004 break;
10005 case 2:
10006 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10007 break;
10008 default:
10009 goto die;
10010 break;
10012 break;
10013 case 2:
10014 switch (sel) {
10015 case 1:
10016 gen_helper_mftc0_tcstatus(t0, cpu_env);
10017 break;
10018 case 2:
10019 gen_helper_mftc0_tcbind(t0, cpu_env);
10020 break;
10021 case 3:
10022 gen_helper_mftc0_tcrestart(t0, cpu_env);
10023 break;
10024 case 4:
10025 gen_helper_mftc0_tchalt(t0, cpu_env);
10026 break;
10027 case 5:
10028 gen_helper_mftc0_tccontext(t0, cpu_env);
10029 break;
10030 case 6:
10031 gen_helper_mftc0_tcschedule(t0, cpu_env);
10032 break;
10033 case 7:
10034 gen_helper_mftc0_tcschefback(t0, cpu_env);
10035 break;
10036 default:
10037 gen_mfc0(ctx, t0, rt, sel);
10038 break;
10040 break;
10041 case 10:
10042 switch (sel) {
10043 case 0:
10044 gen_helper_mftc0_entryhi(t0, cpu_env);
10045 break;
10046 default:
10047 gen_mfc0(ctx, t0, rt, sel);
10048 break;
10050 break;
10051 case 12:
10052 switch (sel) {
10053 case 0:
10054 gen_helper_mftc0_status(t0, cpu_env);
10055 break;
10056 default:
10057 gen_mfc0(ctx, t0, rt, sel);
10058 break;
10060 break;
10061 case 13:
10062 switch (sel) {
10063 case 0:
10064 gen_helper_mftc0_cause(t0, cpu_env);
10065 break;
10066 default:
10067 goto die;
10068 break;
10070 break;
10071 case 14:
10072 switch (sel) {
10073 case 0:
10074 gen_helper_mftc0_epc(t0, cpu_env);
10075 break;
10076 default:
10077 goto die;
10078 break;
10080 break;
10081 case 15:
10082 switch (sel) {
10083 case 1:
10084 gen_helper_mftc0_ebase(t0, cpu_env);
10085 break;
10086 default:
10087 goto die;
10088 break;
10090 break;
10091 case 16:
10092 switch (sel) {
10093 case 0:
10094 case 1:
10095 case 2:
10096 case 3:
10097 case 4:
10098 case 5:
10099 case 6:
10100 case 7:
10101 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10102 break;
10103 default:
10104 goto die;
10105 break;
10107 break;
10108 case 23:
10109 switch (sel) {
10110 case 0:
10111 gen_helper_mftc0_debug(t0, cpu_env);
10112 break;
10113 default:
10114 gen_mfc0(ctx, t0, rt, sel);
10115 break;
10117 break;
10118 default:
10119 gen_mfc0(ctx, t0, rt, sel);
10121 } else {
10122 switch (sel) {
10123 /* GPR registers. */
10124 case 0:
10125 gen_helper_1e0i(mftgpr, t0, rt);
10126 break;
10127 /* Auxiliary CPU registers */
10128 case 1:
10129 switch (rt) {
10130 case 0:
10131 gen_helper_1e0i(mftlo, t0, 0);
10132 break;
10133 case 1:
10134 gen_helper_1e0i(mfthi, t0, 0);
10135 break;
10136 case 2:
10137 gen_helper_1e0i(mftacx, t0, 0);
10138 break;
10139 case 4:
10140 gen_helper_1e0i(mftlo, t0, 1);
10141 break;
10142 case 5:
10143 gen_helper_1e0i(mfthi, t0, 1);
10144 break;
10145 case 6:
10146 gen_helper_1e0i(mftacx, t0, 1);
10147 break;
10148 case 8:
10149 gen_helper_1e0i(mftlo, t0, 2);
10150 break;
10151 case 9:
10152 gen_helper_1e0i(mfthi, t0, 2);
10153 break;
10154 case 10:
10155 gen_helper_1e0i(mftacx, t0, 2);
10156 break;
10157 case 12:
10158 gen_helper_1e0i(mftlo, t0, 3);
10159 break;
10160 case 13:
10161 gen_helper_1e0i(mfthi, t0, 3);
10162 break;
10163 case 14:
10164 gen_helper_1e0i(mftacx, t0, 3);
10165 break;
10166 case 16:
10167 gen_helper_mftdsp(t0, cpu_env);
10168 break;
10169 default:
10170 goto die;
10172 break;
10173 /* Floating point (COP1). */
10174 case 2:
10175 /* XXX: For now we support only a single FPU context. */
10176 if (h == 0) {
10177 TCGv_i32 fp0 = tcg_temp_new_i32();
10179 gen_load_fpr32(ctx, fp0, rt);
10180 tcg_gen_ext_i32_tl(t0, fp0);
10181 tcg_temp_free_i32(fp0);
10182 } else {
10183 TCGv_i32 fp0 = tcg_temp_new_i32();
10185 gen_load_fpr32h(ctx, fp0, rt);
10186 tcg_gen_ext_i32_tl(t0, fp0);
10187 tcg_temp_free_i32(fp0);
10189 break;
10190 case 3:
10191 /* XXX: For now we support only a single FPU context. */
10192 gen_helper_1e0i(cfc1, t0, rt);
10193 break;
10194 /* COP2: Not implemented. */
10195 case 4:
10196 case 5:
10197 /* fall through */
10198 default:
10199 goto die;
10202 trace_mips_translate_tr("mftr", rt, u, sel, h);
10203 gen_store_gpr(t0, rd);
10204 tcg_temp_free(t0);
10205 return;
10207 die:
10208 tcg_temp_free(t0);
10209 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10210 generate_exception_end(ctx, EXCP_RI);
10213 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10214 int u, int sel, int h)
10216 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10217 TCGv t0 = tcg_temp_local_new();
10219 gen_load_gpr(t0, rt);
10220 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10221 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10222 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10223 /* NOP */
10225 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10226 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10227 /* NOP */
10229 } else if (u == 0) {
10230 switch (rd) {
10231 case 1:
10232 switch (sel) {
10233 case 1:
10234 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10235 break;
10236 case 2:
10237 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10238 break;
10239 default:
10240 goto die;
10241 break;
10243 break;
10244 case 2:
10245 switch (sel) {
10246 case 1:
10247 gen_helper_mttc0_tcstatus(cpu_env, t0);
10248 break;
10249 case 2:
10250 gen_helper_mttc0_tcbind(cpu_env, t0);
10251 break;
10252 case 3:
10253 gen_helper_mttc0_tcrestart(cpu_env, t0);
10254 break;
10255 case 4:
10256 gen_helper_mttc0_tchalt(cpu_env, t0);
10257 break;
10258 case 5:
10259 gen_helper_mttc0_tccontext(cpu_env, t0);
10260 break;
10261 case 6:
10262 gen_helper_mttc0_tcschedule(cpu_env, t0);
10263 break;
10264 case 7:
10265 gen_helper_mttc0_tcschefback(cpu_env, t0);
10266 break;
10267 default:
10268 gen_mtc0(ctx, t0, rd, sel);
10269 break;
10271 break;
10272 case 10:
10273 switch (sel) {
10274 case 0:
10275 gen_helper_mttc0_entryhi(cpu_env, t0);
10276 break;
10277 default:
10278 gen_mtc0(ctx, t0, rd, sel);
10279 break;
10281 break;
10282 case 12:
10283 switch (sel) {
10284 case 0:
10285 gen_helper_mttc0_status(cpu_env, t0);
10286 break;
10287 default:
10288 gen_mtc0(ctx, t0, rd, sel);
10289 break;
10291 break;
10292 case 13:
10293 switch (sel) {
10294 case 0:
10295 gen_helper_mttc0_cause(cpu_env, t0);
10296 break;
10297 default:
10298 goto die;
10299 break;
10301 break;
10302 case 15:
10303 switch (sel) {
10304 case 1:
10305 gen_helper_mttc0_ebase(cpu_env, t0);
10306 break;
10307 default:
10308 goto die;
10309 break;
10311 break;
10312 case 23:
10313 switch (sel) {
10314 case 0:
10315 gen_helper_mttc0_debug(cpu_env, t0);
10316 break;
10317 default:
10318 gen_mtc0(ctx, t0, rd, sel);
10319 break;
10321 break;
10322 default:
10323 gen_mtc0(ctx, t0, rd, sel);
10325 } else {
10326 switch (sel) {
10327 /* GPR registers. */
10328 case 0:
10329 gen_helper_0e1i(mttgpr, t0, rd);
10330 break;
10331 /* Auxiliary CPU registers */
10332 case 1:
10333 switch (rd) {
10334 case 0:
10335 gen_helper_0e1i(mttlo, t0, 0);
10336 break;
10337 case 1:
10338 gen_helper_0e1i(mtthi, t0, 0);
10339 break;
10340 case 2:
10341 gen_helper_0e1i(mttacx, t0, 0);
10342 break;
10343 case 4:
10344 gen_helper_0e1i(mttlo, t0, 1);
10345 break;
10346 case 5:
10347 gen_helper_0e1i(mtthi, t0, 1);
10348 break;
10349 case 6:
10350 gen_helper_0e1i(mttacx, t0, 1);
10351 break;
10352 case 8:
10353 gen_helper_0e1i(mttlo, t0, 2);
10354 break;
10355 case 9:
10356 gen_helper_0e1i(mtthi, t0, 2);
10357 break;
10358 case 10:
10359 gen_helper_0e1i(mttacx, t0, 2);
10360 break;
10361 case 12:
10362 gen_helper_0e1i(mttlo, t0, 3);
10363 break;
10364 case 13:
10365 gen_helper_0e1i(mtthi, t0, 3);
10366 break;
10367 case 14:
10368 gen_helper_0e1i(mttacx, t0, 3);
10369 break;
10370 case 16:
10371 gen_helper_mttdsp(cpu_env, t0);
10372 break;
10373 default:
10374 goto die;
10376 break;
10377 /* Floating point (COP1). */
10378 case 2:
10379 /* XXX: For now we support only a single FPU context. */
10380 if (h == 0) {
10381 TCGv_i32 fp0 = tcg_temp_new_i32();
10383 tcg_gen_trunc_tl_i32(fp0, t0);
10384 gen_store_fpr32(ctx, fp0, rd);
10385 tcg_temp_free_i32(fp0);
10386 } else {
10387 TCGv_i32 fp0 = tcg_temp_new_i32();
10389 tcg_gen_trunc_tl_i32(fp0, t0);
10390 gen_store_fpr32h(ctx, fp0, rd);
10391 tcg_temp_free_i32(fp0);
10393 break;
10394 case 3:
10395 /* XXX: For now we support only a single FPU context. */
10397 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10399 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10400 tcg_temp_free_i32(fs_tmp);
10402 /* Stop translation as we may have changed hflags */
10403 ctx->base.is_jmp = DISAS_STOP;
10404 break;
10405 /* COP2: Not implemented. */
10406 case 4:
10407 case 5:
10408 /* fall through */
10409 default:
10410 goto die;
10413 trace_mips_translate_tr("mttr", rd, u, sel, h);
10414 tcg_temp_free(t0);
10415 return;
10417 die:
10418 tcg_temp_free(t0);
10419 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10420 generate_exception_end(ctx, EXCP_RI);
10423 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10424 int rt, int rd)
10426 const char *opn = "ldst";
10428 check_cp0_enabled(ctx);
10429 switch (opc) {
10430 case OPC_MFC0:
10431 if (rt == 0) {
10432 /* Treat as NOP. */
10433 return;
10435 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10436 opn = "mfc0";
10437 break;
10438 case OPC_MTC0:
10440 TCGv t0 = tcg_temp_new();
10442 gen_load_gpr(t0, rt);
10443 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10444 tcg_temp_free(t0);
10446 opn = "mtc0";
10447 break;
10448 #if defined(TARGET_MIPS64)
10449 case OPC_DMFC0:
10450 check_insn(ctx, ISA_MIPS3);
10451 if (rt == 0) {
10452 /* Treat as NOP. */
10453 return;
10455 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10456 opn = "dmfc0";
10457 break;
10458 case OPC_DMTC0:
10459 check_insn(ctx, ISA_MIPS3);
10461 TCGv t0 = tcg_temp_new();
10463 gen_load_gpr(t0, rt);
10464 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10465 tcg_temp_free(t0);
10467 opn = "dmtc0";
10468 break;
10469 #endif
10470 case OPC_MFHC0:
10471 check_mvh(ctx);
10472 if (rt == 0) {
10473 /* Treat as NOP. */
10474 return;
10476 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10477 opn = "mfhc0";
10478 break;
10479 case OPC_MTHC0:
10480 check_mvh(ctx);
10482 TCGv t0 = tcg_temp_new();
10483 gen_load_gpr(t0, rt);
10484 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10485 tcg_temp_free(t0);
10487 opn = "mthc0";
10488 break;
10489 case OPC_MFTR:
10490 check_cp0_enabled(ctx);
10491 if (rd == 0) {
10492 /* Treat as NOP. */
10493 return;
10495 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10496 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10497 opn = "mftr";
10498 break;
10499 case OPC_MTTR:
10500 check_cp0_enabled(ctx);
10501 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10502 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10503 opn = "mttr";
10504 break;
10505 case OPC_TLBWI:
10506 opn = "tlbwi";
10507 if (!env->tlb->helper_tlbwi) {
10508 goto die;
10510 gen_helper_tlbwi(cpu_env);
10511 break;
10512 case OPC_TLBINV:
10513 opn = "tlbinv";
10514 if (ctx->ie >= 2) {
10515 if (!env->tlb->helper_tlbinv) {
10516 goto die;
10518 gen_helper_tlbinv(cpu_env);
10519 } /* treat as nop if TLBINV not supported */
10520 break;
10521 case OPC_TLBINVF:
10522 opn = "tlbinvf";
10523 if (ctx->ie >= 2) {
10524 if (!env->tlb->helper_tlbinvf) {
10525 goto die;
10527 gen_helper_tlbinvf(cpu_env);
10528 } /* treat as nop if TLBINV not supported */
10529 break;
10530 case OPC_TLBWR:
10531 opn = "tlbwr";
10532 if (!env->tlb->helper_tlbwr) {
10533 goto die;
10535 gen_helper_tlbwr(cpu_env);
10536 break;
10537 case OPC_TLBP:
10538 opn = "tlbp";
10539 if (!env->tlb->helper_tlbp) {
10540 goto die;
10542 gen_helper_tlbp(cpu_env);
10543 break;
10544 case OPC_TLBR:
10545 opn = "tlbr";
10546 if (!env->tlb->helper_tlbr) {
10547 goto die;
10549 gen_helper_tlbr(cpu_env);
10550 break;
10551 case OPC_ERET: /* OPC_ERETNC */
10552 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10553 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10554 goto die;
10555 } else {
10556 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10557 if (ctx->opcode & (1 << bit_shift)) {
10558 /* OPC_ERETNC */
10559 opn = "eretnc";
10560 check_insn(ctx, ISA_MIPS32R5);
10561 gen_helper_eretnc(cpu_env);
10562 } else {
10563 /* OPC_ERET */
10564 opn = "eret";
10565 check_insn(ctx, ISA_MIPS2);
10566 gen_helper_eret(cpu_env);
10568 ctx->base.is_jmp = DISAS_EXIT;
10570 break;
10571 case OPC_DERET:
10572 opn = "deret";
10573 check_insn(ctx, ISA_MIPS32);
10574 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10575 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10576 goto die;
10578 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10579 MIPS_INVAL(opn);
10580 generate_exception_end(ctx, EXCP_RI);
10581 } else {
10582 gen_helper_deret(cpu_env);
10583 ctx->base.is_jmp = DISAS_EXIT;
10585 break;
10586 case OPC_WAIT:
10587 opn = "wait";
10588 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
10589 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10590 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10591 goto die;
10593 /* If we get an exception, we want to restart at next instruction */
10594 ctx->base.pc_next += 4;
10595 save_cpu_state(ctx, 1);
10596 ctx->base.pc_next -= 4;
10597 gen_helper_wait(cpu_env);
10598 ctx->base.is_jmp = DISAS_NORETURN;
10599 break;
10600 default:
10601 die:
10602 MIPS_INVAL(opn);
10603 generate_exception_end(ctx, EXCP_RI);
10604 return;
10606 (void)opn; /* avoid a compiler warning */
10608 #endif /* !CONFIG_USER_ONLY */
10610 /* CP1 Branches (before delay slot) */
10611 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10612 int32_t cc, int32_t offset)
10614 target_ulong btarget;
10615 TCGv_i32 t0 = tcg_temp_new_i32();
10617 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10618 generate_exception_end(ctx, EXCP_RI);
10619 goto out;
10622 if (cc != 0) {
10623 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
10626 btarget = ctx->base.pc_next + 4 + offset;
10628 switch (op) {
10629 case OPC_BC1F:
10630 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10631 tcg_gen_not_i32(t0, t0);
10632 tcg_gen_andi_i32(t0, t0, 1);
10633 tcg_gen_extu_i32_tl(bcond, t0);
10634 goto not_likely;
10635 case OPC_BC1FL:
10636 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10637 tcg_gen_not_i32(t0, t0);
10638 tcg_gen_andi_i32(t0, t0, 1);
10639 tcg_gen_extu_i32_tl(bcond, t0);
10640 goto likely;
10641 case OPC_BC1T:
10642 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10643 tcg_gen_andi_i32(t0, t0, 1);
10644 tcg_gen_extu_i32_tl(bcond, t0);
10645 goto not_likely;
10646 case OPC_BC1TL:
10647 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10648 tcg_gen_andi_i32(t0, t0, 1);
10649 tcg_gen_extu_i32_tl(bcond, t0);
10650 likely:
10651 ctx->hflags |= MIPS_HFLAG_BL;
10652 break;
10653 case OPC_BC1FANY2:
10655 TCGv_i32 t1 = tcg_temp_new_i32();
10656 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10657 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10658 tcg_gen_nand_i32(t0, t0, t1);
10659 tcg_temp_free_i32(t1);
10660 tcg_gen_andi_i32(t0, t0, 1);
10661 tcg_gen_extu_i32_tl(bcond, t0);
10663 goto not_likely;
10664 case OPC_BC1TANY2:
10666 TCGv_i32 t1 = tcg_temp_new_i32();
10667 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10668 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10669 tcg_gen_or_i32(t0, t0, t1);
10670 tcg_temp_free_i32(t1);
10671 tcg_gen_andi_i32(t0, t0, 1);
10672 tcg_gen_extu_i32_tl(bcond, t0);
10674 goto not_likely;
10675 case OPC_BC1FANY4:
10677 TCGv_i32 t1 = tcg_temp_new_i32();
10678 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10679 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10680 tcg_gen_and_i32(t0, t0, t1);
10681 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10682 tcg_gen_and_i32(t0, t0, t1);
10683 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10684 tcg_gen_nand_i32(t0, t0, t1);
10685 tcg_temp_free_i32(t1);
10686 tcg_gen_andi_i32(t0, t0, 1);
10687 tcg_gen_extu_i32_tl(bcond, t0);
10689 goto not_likely;
10690 case OPC_BC1TANY4:
10692 TCGv_i32 t1 = tcg_temp_new_i32();
10693 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10694 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10695 tcg_gen_or_i32(t0, t0, t1);
10696 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10697 tcg_gen_or_i32(t0, t0, t1);
10698 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10699 tcg_gen_or_i32(t0, t0, t1);
10700 tcg_temp_free_i32(t1);
10701 tcg_gen_andi_i32(t0, t0, 1);
10702 tcg_gen_extu_i32_tl(bcond, t0);
10704 not_likely:
10705 ctx->hflags |= MIPS_HFLAG_BC;
10706 break;
10707 default:
10708 MIPS_INVAL("cp1 cond branch");
10709 generate_exception_end(ctx, EXCP_RI);
10710 goto out;
10712 ctx->btarget = btarget;
10713 ctx->hflags |= MIPS_HFLAG_BDS32;
10714 out:
10715 tcg_temp_free_i32(t0);
10718 /* R6 CP1 Branches */
10719 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10720 int32_t ft, int32_t offset,
10721 int delayslot_size)
10723 target_ulong btarget;
10724 TCGv_i64 t0 = tcg_temp_new_i64();
10726 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10727 #ifdef MIPS_DEBUG_DISAS
10728 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10729 "\n", ctx->base.pc_next);
10730 #endif
10731 generate_exception_end(ctx, EXCP_RI);
10732 goto out;
10735 gen_load_fpr64(ctx, t0, ft);
10736 tcg_gen_andi_i64(t0, t0, 1);
10738 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10740 switch (op) {
10741 case OPC_BC1EQZ:
10742 tcg_gen_xori_i64(t0, t0, 1);
10743 ctx->hflags |= MIPS_HFLAG_BC;
10744 break;
10745 case OPC_BC1NEZ:
10746 /* t0 already set */
10747 ctx->hflags |= MIPS_HFLAG_BC;
10748 break;
10749 default:
10750 MIPS_INVAL("cp1 cond branch");
10751 generate_exception_end(ctx, EXCP_RI);
10752 goto out;
10755 tcg_gen_trunc_i64_tl(bcond, t0);
10757 ctx->btarget = btarget;
10759 switch (delayslot_size) {
10760 case 2:
10761 ctx->hflags |= MIPS_HFLAG_BDS16;
10762 break;
10763 case 4:
10764 ctx->hflags |= MIPS_HFLAG_BDS32;
10765 break;
10768 out:
10769 tcg_temp_free_i64(t0);
10772 /* Coprocessor 1 (FPU) */
10774 #define FOP(func, fmt) (((fmt) << 21) | (func))
10776 enum fopcode {
10777 OPC_ADD_S = FOP(0, FMT_S),
10778 OPC_SUB_S = FOP(1, FMT_S),
10779 OPC_MUL_S = FOP(2, FMT_S),
10780 OPC_DIV_S = FOP(3, FMT_S),
10781 OPC_SQRT_S = FOP(4, FMT_S),
10782 OPC_ABS_S = FOP(5, FMT_S),
10783 OPC_MOV_S = FOP(6, FMT_S),
10784 OPC_NEG_S = FOP(7, FMT_S),
10785 OPC_ROUND_L_S = FOP(8, FMT_S),
10786 OPC_TRUNC_L_S = FOP(9, FMT_S),
10787 OPC_CEIL_L_S = FOP(10, FMT_S),
10788 OPC_FLOOR_L_S = FOP(11, FMT_S),
10789 OPC_ROUND_W_S = FOP(12, FMT_S),
10790 OPC_TRUNC_W_S = FOP(13, FMT_S),
10791 OPC_CEIL_W_S = FOP(14, FMT_S),
10792 OPC_FLOOR_W_S = FOP(15, FMT_S),
10793 OPC_SEL_S = FOP(16, FMT_S),
10794 OPC_MOVCF_S = FOP(17, FMT_S),
10795 OPC_MOVZ_S = FOP(18, FMT_S),
10796 OPC_MOVN_S = FOP(19, FMT_S),
10797 OPC_SELEQZ_S = FOP(20, FMT_S),
10798 OPC_RECIP_S = FOP(21, FMT_S),
10799 OPC_RSQRT_S = FOP(22, FMT_S),
10800 OPC_SELNEZ_S = FOP(23, FMT_S),
10801 OPC_MADDF_S = FOP(24, FMT_S),
10802 OPC_MSUBF_S = FOP(25, FMT_S),
10803 OPC_RINT_S = FOP(26, FMT_S),
10804 OPC_CLASS_S = FOP(27, FMT_S),
10805 OPC_MIN_S = FOP(28, FMT_S),
10806 OPC_RECIP2_S = FOP(28, FMT_S),
10807 OPC_MINA_S = FOP(29, FMT_S),
10808 OPC_RECIP1_S = FOP(29, FMT_S),
10809 OPC_MAX_S = FOP(30, FMT_S),
10810 OPC_RSQRT1_S = FOP(30, FMT_S),
10811 OPC_MAXA_S = FOP(31, FMT_S),
10812 OPC_RSQRT2_S = FOP(31, FMT_S),
10813 OPC_CVT_D_S = FOP(33, FMT_S),
10814 OPC_CVT_W_S = FOP(36, FMT_S),
10815 OPC_CVT_L_S = FOP(37, FMT_S),
10816 OPC_CVT_PS_S = FOP(38, FMT_S),
10817 OPC_CMP_F_S = FOP(48, FMT_S),
10818 OPC_CMP_UN_S = FOP(49, FMT_S),
10819 OPC_CMP_EQ_S = FOP(50, FMT_S),
10820 OPC_CMP_UEQ_S = FOP(51, FMT_S),
10821 OPC_CMP_OLT_S = FOP(52, FMT_S),
10822 OPC_CMP_ULT_S = FOP(53, FMT_S),
10823 OPC_CMP_OLE_S = FOP(54, FMT_S),
10824 OPC_CMP_ULE_S = FOP(55, FMT_S),
10825 OPC_CMP_SF_S = FOP(56, FMT_S),
10826 OPC_CMP_NGLE_S = FOP(57, FMT_S),
10827 OPC_CMP_SEQ_S = FOP(58, FMT_S),
10828 OPC_CMP_NGL_S = FOP(59, FMT_S),
10829 OPC_CMP_LT_S = FOP(60, FMT_S),
10830 OPC_CMP_NGE_S = FOP(61, FMT_S),
10831 OPC_CMP_LE_S = FOP(62, FMT_S),
10832 OPC_CMP_NGT_S = FOP(63, FMT_S),
10834 OPC_ADD_D = FOP(0, FMT_D),
10835 OPC_SUB_D = FOP(1, FMT_D),
10836 OPC_MUL_D = FOP(2, FMT_D),
10837 OPC_DIV_D = FOP(3, FMT_D),
10838 OPC_SQRT_D = FOP(4, FMT_D),
10839 OPC_ABS_D = FOP(5, FMT_D),
10840 OPC_MOV_D = FOP(6, FMT_D),
10841 OPC_NEG_D = FOP(7, FMT_D),
10842 OPC_ROUND_L_D = FOP(8, FMT_D),
10843 OPC_TRUNC_L_D = FOP(9, FMT_D),
10844 OPC_CEIL_L_D = FOP(10, FMT_D),
10845 OPC_FLOOR_L_D = FOP(11, FMT_D),
10846 OPC_ROUND_W_D = FOP(12, FMT_D),
10847 OPC_TRUNC_W_D = FOP(13, FMT_D),
10848 OPC_CEIL_W_D = FOP(14, FMT_D),
10849 OPC_FLOOR_W_D = FOP(15, FMT_D),
10850 OPC_SEL_D = FOP(16, FMT_D),
10851 OPC_MOVCF_D = FOP(17, FMT_D),
10852 OPC_MOVZ_D = FOP(18, FMT_D),
10853 OPC_MOVN_D = FOP(19, FMT_D),
10854 OPC_SELEQZ_D = FOP(20, FMT_D),
10855 OPC_RECIP_D = FOP(21, FMT_D),
10856 OPC_RSQRT_D = FOP(22, FMT_D),
10857 OPC_SELNEZ_D = FOP(23, FMT_D),
10858 OPC_MADDF_D = FOP(24, FMT_D),
10859 OPC_MSUBF_D = FOP(25, FMT_D),
10860 OPC_RINT_D = FOP(26, FMT_D),
10861 OPC_CLASS_D = FOP(27, FMT_D),
10862 OPC_MIN_D = FOP(28, FMT_D),
10863 OPC_RECIP2_D = FOP(28, FMT_D),
10864 OPC_MINA_D = FOP(29, FMT_D),
10865 OPC_RECIP1_D = FOP(29, FMT_D),
10866 OPC_MAX_D = FOP(30, FMT_D),
10867 OPC_RSQRT1_D = FOP(30, FMT_D),
10868 OPC_MAXA_D = FOP(31, FMT_D),
10869 OPC_RSQRT2_D = FOP(31, FMT_D),
10870 OPC_CVT_S_D = FOP(32, FMT_D),
10871 OPC_CVT_W_D = FOP(36, FMT_D),
10872 OPC_CVT_L_D = FOP(37, FMT_D),
10873 OPC_CMP_F_D = FOP(48, FMT_D),
10874 OPC_CMP_UN_D = FOP(49, FMT_D),
10875 OPC_CMP_EQ_D = FOP(50, FMT_D),
10876 OPC_CMP_UEQ_D = FOP(51, FMT_D),
10877 OPC_CMP_OLT_D = FOP(52, FMT_D),
10878 OPC_CMP_ULT_D = FOP(53, FMT_D),
10879 OPC_CMP_OLE_D = FOP(54, FMT_D),
10880 OPC_CMP_ULE_D = FOP(55, FMT_D),
10881 OPC_CMP_SF_D = FOP(56, FMT_D),
10882 OPC_CMP_NGLE_D = FOP(57, FMT_D),
10883 OPC_CMP_SEQ_D = FOP(58, FMT_D),
10884 OPC_CMP_NGL_D = FOP(59, FMT_D),
10885 OPC_CMP_LT_D = FOP(60, FMT_D),
10886 OPC_CMP_NGE_D = FOP(61, FMT_D),
10887 OPC_CMP_LE_D = FOP(62, FMT_D),
10888 OPC_CMP_NGT_D = FOP(63, FMT_D),
10890 OPC_CVT_S_W = FOP(32, FMT_W),
10891 OPC_CVT_D_W = FOP(33, FMT_W),
10892 OPC_CVT_S_L = FOP(32, FMT_L),
10893 OPC_CVT_D_L = FOP(33, FMT_L),
10894 OPC_CVT_PS_PW = FOP(38, FMT_W),
10896 OPC_ADD_PS = FOP(0, FMT_PS),
10897 OPC_SUB_PS = FOP(1, FMT_PS),
10898 OPC_MUL_PS = FOP(2, FMT_PS),
10899 OPC_DIV_PS = FOP(3, FMT_PS),
10900 OPC_ABS_PS = FOP(5, FMT_PS),
10901 OPC_MOV_PS = FOP(6, FMT_PS),
10902 OPC_NEG_PS = FOP(7, FMT_PS),
10903 OPC_MOVCF_PS = FOP(17, FMT_PS),
10904 OPC_MOVZ_PS = FOP(18, FMT_PS),
10905 OPC_MOVN_PS = FOP(19, FMT_PS),
10906 OPC_ADDR_PS = FOP(24, FMT_PS),
10907 OPC_MULR_PS = FOP(26, FMT_PS),
10908 OPC_RECIP2_PS = FOP(28, FMT_PS),
10909 OPC_RECIP1_PS = FOP(29, FMT_PS),
10910 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10911 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10913 OPC_CVT_S_PU = FOP(32, FMT_PS),
10914 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10915 OPC_CVT_S_PL = FOP(40, FMT_PS),
10916 OPC_PLL_PS = FOP(44, FMT_PS),
10917 OPC_PLU_PS = FOP(45, FMT_PS),
10918 OPC_PUL_PS = FOP(46, FMT_PS),
10919 OPC_PUU_PS = FOP(47, FMT_PS),
10920 OPC_CMP_F_PS = FOP(48, FMT_PS),
10921 OPC_CMP_UN_PS = FOP(49, FMT_PS),
10922 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
10923 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
10924 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
10925 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
10926 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
10927 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
10928 OPC_CMP_SF_PS = FOP(56, FMT_PS),
10929 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
10930 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
10931 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
10932 OPC_CMP_LT_PS = FOP(60, FMT_PS),
10933 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
10934 OPC_CMP_LE_PS = FOP(62, FMT_PS),
10935 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
10938 enum r6_f_cmp_op {
10939 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10940 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10941 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10942 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10943 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10944 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10945 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10946 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10947 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10948 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10949 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10950 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10951 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10952 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10953 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10954 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10955 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10956 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10957 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10958 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10959 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10960 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10962 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10963 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10964 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10965 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10966 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10967 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10968 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10969 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10970 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10971 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10972 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10973 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10974 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10975 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10976 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10977 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10978 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10979 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10980 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10981 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10982 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10983 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10986 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
10988 TCGv t0 = tcg_temp_new();
10990 switch (opc) {
10991 case OPC_MFC1:
10993 TCGv_i32 fp0 = tcg_temp_new_i32();
10995 gen_load_fpr32(ctx, fp0, fs);
10996 tcg_gen_ext_i32_tl(t0, fp0);
10997 tcg_temp_free_i32(fp0);
10999 gen_store_gpr(t0, rt);
11000 break;
11001 case OPC_MTC1:
11002 gen_load_gpr(t0, rt);
11004 TCGv_i32 fp0 = tcg_temp_new_i32();
11006 tcg_gen_trunc_tl_i32(fp0, t0);
11007 gen_store_fpr32(ctx, fp0, fs);
11008 tcg_temp_free_i32(fp0);
11010 break;
11011 case OPC_CFC1:
11012 gen_helper_1e0i(cfc1, t0, fs);
11013 gen_store_gpr(t0, rt);
11014 break;
11015 case OPC_CTC1:
11016 gen_load_gpr(t0, rt);
11017 save_cpu_state(ctx, 0);
11019 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11021 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11022 tcg_temp_free_i32(fs_tmp);
11024 /* Stop translation as we may have changed hflags */
11025 ctx->base.is_jmp = DISAS_STOP;
11026 break;
11027 #if defined(TARGET_MIPS64)
11028 case OPC_DMFC1:
11029 gen_load_fpr64(ctx, t0, fs);
11030 gen_store_gpr(t0, rt);
11031 break;
11032 case OPC_DMTC1:
11033 gen_load_gpr(t0, rt);
11034 gen_store_fpr64(ctx, t0, fs);
11035 break;
11036 #endif
11037 case OPC_MFHC1:
11039 TCGv_i32 fp0 = tcg_temp_new_i32();
11041 gen_load_fpr32h(ctx, fp0, fs);
11042 tcg_gen_ext_i32_tl(t0, fp0);
11043 tcg_temp_free_i32(fp0);
11045 gen_store_gpr(t0, rt);
11046 break;
11047 case OPC_MTHC1:
11048 gen_load_gpr(t0, rt);
11050 TCGv_i32 fp0 = tcg_temp_new_i32();
11052 tcg_gen_trunc_tl_i32(fp0, t0);
11053 gen_store_fpr32h(ctx, fp0, fs);
11054 tcg_temp_free_i32(fp0);
11056 break;
11057 default:
11058 MIPS_INVAL("cp1 move");
11059 generate_exception_end(ctx, EXCP_RI);
11060 goto out;
11063 out:
11064 tcg_temp_free(t0);
11067 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11069 TCGLabel *l1;
11070 TCGCond cond;
11071 TCGv_i32 t0;
11073 if (rd == 0) {
11074 /* Treat as NOP. */
11075 return;
11078 if (tf) {
11079 cond = TCG_COND_EQ;
11080 } else {
11081 cond = TCG_COND_NE;
11084 l1 = gen_new_label();
11085 t0 = tcg_temp_new_i32();
11086 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11087 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11088 tcg_temp_free_i32(t0);
11089 if (rs == 0) {
11090 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11091 } else {
11092 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11094 gen_set_label(l1);
11097 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11098 int tf)
11100 int cond;
11101 TCGv_i32 t0 = tcg_temp_new_i32();
11102 TCGLabel *l1 = gen_new_label();
11104 if (tf) {
11105 cond = TCG_COND_EQ;
11106 } else {
11107 cond = TCG_COND_NE;
11110 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11111 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11112 gen_load_fpr32(ctx, t0, fs);
11113 gen_store_fpr32(ctx, t0, fd);
11114 gen_set_label(l1);
11115 tcg_temp_free_i32(t0);
11118 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11119 int tf)
11121 int cond;
11122 TCGv_i32 t0 = tcg_temp_new_i32();
11123 TCGv_i64 fp0;
11124 TCGLabel *l1 = gen_new_label();
11126 if (tf) {
11127 cond = TCG_COND_EQ;
11128 } else {
11129 cond = TCG_COND_NE;
11132 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11133 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11134 tcg_temp_free_i32(t0);
11135 fp0 = tcg_temp_new_i64();
11136 gen_load_fpr64(ctx, fp0, fs);
11137 gen_store_fpr64(ctx, fp0, fd);
11138 tcg_temp_free_i64(fp0);
11139 gen_set_label(l1);
11142 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11143 int cc, int tf)
11145 int cond;
11146 TCGv_i32 t0 = tcg_temp_new_i32();
11147 TCGLabel *l1 = gen_new_label();
11148 TCGLabel *l2 = gen_new_label();
11150 if (tf) {
11151 cond = TCG_COND_EQ;
11152 } else {
11153 cond = TCG_COND_NE;
11156 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11157 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11158 gen_load_fpr32(ctx, t0, fs);
11159 gen_store_fpr32(ctx, t0, fd);
11160 gen_set_label(l1);
11162 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11163 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11164 gen_load_fpr32h(ctx, t0, fs);
11165 gen_store_fpr32h(ctx, t0, fd);
11166 tcg_temp_free_i32(t0);
11167 gen_set_label(l2);
11170 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11171 int fs)
11173 TCGv_i32 t1 = tcg_const_i32(0);
11174 TCGv_i32 fp0 = tcg_temp_new_i32();
11175 TCGv_i32 fp1 = tcg_temp_new_i32();
11176 TCGv_i32 fp2 = tcg_temp_new_i32();
11177 gen_load_fpr32(ctx, fp0, fd);
11178 gen_load_fpr32(ctx, fp1, ft);
11179 gen_load_fpr32(ctx, fp2, fs);
11181 switch (op1) {
11182 case OPC_SEL_S:
11183 tcg_gen_andi_i32(fp0, fp0, 1);
11184 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11185 break;
11186 case OPC_SELEQZ_S:
11187 tcg_gen_andi_i32(fp1, fp1, 1);
11188 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11189 break;
11190 case OPC_SELNEZ_S:
11191 tcg_gen_andi_i32(fp1, fp1, 1);
11192 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11193 break;
11194 default:
11195 MIPS_INVAL("gen_sel_s");
11196 generate_exception_end(ctx, EXCP_RI);
11197 break;
11200 gen_store_fpr32(ctx, fp0, fd);
11201 tcg_temp_free_i32(fp2);
11202 tcg_temp_free_i32(fp1);
11203 tcg_temp_free_i32(fp0);
11204 tcg_temp_free_i32(t1);
11207 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11208 int fs)
11210 TCGv_i64 t1 = tcg_const_i64(0);
11211 TCGv_i64 fp0 = tcg_temp_new_i64();
11212 TCGv_i64 fp1 = tcg_temp_new_i64();
11213 TCGv_i64 fp2 = tcg_temp_new_i64();
11214 gen_load_fpr64(ctx, fp0, fd);
11215 gen_load_fpr64(ctx, fp1, ft);
11216 gen_load_fpr64(ctx, fp2, fs);
11218 switch (op1) {
11219 case OPC_SEL_D:
11220 tcg_gen_andi_i64(fp0, fp0, 1);
11221 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11222 break;
11223 case OPC_SELEQZ_D:
11224 tcg_gen_andi_i64(fp1, fp1, 1);
11225 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11226 break;
11227 case OPC_SELNEZ_D:
11228 tcg_gen_andi_i64(fp1, fp1, 1);
11229 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11230 break;
11231 default:
11232 MIPS_INVAL("gen_sel_d");
11233 generate_exception_end(ctx, EXCP_RI);
11234 break;
11237 gen_store_fpr64(ctx, fp0, fd);
11238 tcg_temp_free_i64(fp2);
11239 tcg_temp_free_i64(fp1);
11240 tcg_temp_free_i64(fp0);
11241 tcg_temp_free_i64(t1);
11244 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11245 int ft, int fs, int fd, int cc)
11247 uint32_t func = ctx->opcode & 0x3f;
11248 switch (op1) {
11249 case OPC_ADD_S:
11251 TCGv_i32 fp0 = tcg_temp_new_i32();
11252 TCGv_i32 fp1 = tcg_temp_new_i32();
11254 gen_load_fpr32(ctx, fp0, fs);
11255 gen_load_fpr32(ctx, fp1, ft);
11256 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11257 tcg_temp_free_i32(fp1);
11258 gen_store_fpr32(ctx, fp0, fd);
11259 tcg_temp_free_i32(fp0);
11261 break;
11262 case OPC_SUB_S:
11264 TCGv_i32 fp0 = tcg_temp_new_i32();
11265 TCGv_i32 fp1 = tcg_temp_new_i32();
11267 gen_load_fpr32(ctx, fp0, fs);
11268 gen_load_fpr32(ctx, fp1, ft);
11269 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11270 tcg_temp_free_i32(fp1);
11271 gen_store_fpr32(ctx, fp0, fd);
11272 tcg_temp_free_i32(fp0);
11274 break;
11275 case OPC_MUL_S:
11277 TCGv_i32 fp0 = tcg_temp_new_i32();
11278 TCGv_i32 fp1 = tcg_temp_new_i32();
11280 gen_load_fpr32(ctx, fp0, fs);
11281 gen_load_fpr32(ctx, fp1, ft);
11282 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11283 tcg_temp_free_i32(fp1);
11284 gen_store_fpr32(ctx, fp0, fd);
11285 tcg_temp_free_i32(fp0);
11287 break;
11288 case OPC_DIV_S:
11290 TCGv_i32 fp0 = tcg_temp_new_i32();
11291 TCGv_i32 fp1 = tcg_temp_new_i32();
11293 gen_load_fpr32(ctx, fp0, fs);
11294 gen_load_fpr32(ctx, fp1, ft);
11295 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11296 tcg_temp_free_i32(fp1);
11297 gen_store_fpr32(ctx, fp0, fd);
11298 tcg_temp_free_i32(fp0);
11300 break;
11301 case OPC_SQRT_S:
11303 TCGv_i32 fp0 = tcg_temp_new_i32();
11305 gen_load_fpr32(ctx, fp0, fs);
11306 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11307 gen_store_fpr32(ctx, fp0, fd);
11308 tcg_temp_free_i32(fp0);
11310 break;
11311 case OPC_ABS_S:
11313 TCGv_i32 fp0 = tcg_temp_new_i32();
11315 gen_load_fpr32(ctx, fp0, fs);
11316 if (ctx->abs2008) {
11317 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11318 } else {
11319 gen_helper_float_abs_s(fp0, fp0);
11321 gen_store_fpr32(ctx, fp0, fd);
11322 tcg_temp_free_i32(fp0);
11324 break;
11325 case OPC_MOV_S:
11327 TCGv_i32 fp0 = tcg_temp_new_i32();
11329 gen_load_fpr32(ctx, fp0, fs);
11330 gen_store_fpr32(ctx, fp0, fd);
11331 tcg_temp_free_i32(fp0);
11333 break;
11334 case OPC_NEG_S:
11336 TCGv_i32 fp0 = tcg_temp_new_i32();
11338 gen_load_fpr32(ctx, fp0, fs);
11339 if (ctx->abs2008) {
11340 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11341 } else {
11342 gen_helper_float_chs_s(fp0, fp0);
11344 gen_store_fpr32(ctx, fp0, fd);
11345 tcg_temp_free_i32(fp0);
11347 break;
11348 case OPC_ROUND_L_S:
11349 check_cp1_64bitmode(ctx);
11351 TCGv_i32 fp32 = tcg_temp_new_i32();
11352 TCGv_i64 fp64 = tcg_temp_new_i64();
11354 gen_load_fpr32(ctx, fp32, fs);
11355 if (ctx->nan2008) {
11356 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11357 } else {
11358 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11360 tcg_temp_free_i32(fp32);
11361 gen_store_fpr64(ctx, fp64, fd);
11362 tcg_temp_free_i64(fp64);
11364 break;
11365 case OPC_TRUNC_L_S:
11366 check_cp1_64bitmode(ctx);
11368 TCGv_i32 fp32 = tcg_temp_new_i32();
11369 TCGv_i64 fp64 = tcg_temp_new_i64();
11371 gen_load_fpr32(ctx, fp32, fs);
11372 if (ctx->nan2008) {
11373 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11374 } else {
11375 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11377 tcg_temp_free_i32(fp32);
11378 gen_store_fpr64(ctx, fp64, fd);
11379 tcg_temp_free_i64(fp64);
11381 break;
11382 case OPC_CEIL_L_S:
11383 check_cp1_64bitmode(ctx);
11385 TCGv_i32 fp32 = tcg_temp_new_i32();
11386 TCGv_i64 fp64 = tcg_temp_new_i64();
11388 gen_load_fpr32(ctx, fp32, fs);
11389 if (ctx->nan2008) {
11390 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11391 } else {
11392 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11394 tcg_temp_free_i32(fp32);
11395 gen_store_fpr64(ctx, fp64, fd);
11396 tcg_temp_free_i64(fp64);
11398 break;
11399 case OPC_FLOOR_L_S:
11400 check_cp1_64bitmode(ctx);
11402 TCGv_i32 fp32 = tcg_temp_new_i32();
11403 TCGv_i64 fp64 = tcg_temp_new_i64();
11405 gen_load_fpr32(ctx, fp32, fs);
11406 if (ctx->nan2008) {
11407 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11408 } else {
11409 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11411 tcg_temp_free_i32(fp32);
11412 gen_store_fpr64(ctx, fp64, fd);
11413 tcg_temp_free_i64(fp64);
11415 break;
11416 case OPC_ROUND_W_S:
11418 TCGv_i32 fp0 = tcg_temp_new_i32();
11420 gen_load_fpr32(ctx, fp0, fs);
11421 if (ctx->nan2008) {
11422 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11423 } else {
11424 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11426 gen_store_fpr32(ctx, fp0, fd);
11427 tcg_temp_free_i32(fp0);
11429 break;
11430 case OPC_TRUNC_W_S:
11432 TCGv_i32 fp0 = tcg_temp_new_i32();
11434 gen_load_fpr32(ctx, fp0, fs);
11435 if (ctx->nan2008) {
11436 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11437 } else {
11438 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11440 gen_store_fpr32(ctx, fp0, fd);
11441 tcg_temp_free_i32(fp0);
11443 break;
11444 case OPC_CEIL_W_S:
11446 TCGv_i32 fp0 = tcg_temp_new_i32();
11448 gen_load_fpr32(ctx, fp0, fs);
11449 if (ctx->nan2008) {
11450 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11451 } else {
11452 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11454 gen_store_fpr32(ctx, fp0, fd);
11455 tcg_temp_free_i32(fp0);
11457 break;
11458 case OPC_FLOOR_W_S:
11460 TCGv_i32 fp0 = tcg_temp_new_i32();
11462 gen_load_fpr32(ctx, fp0, fs);
11463 if (ctx->nan2008) {
11464 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11465 } else {
11466 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11468 gen_store_fpr32(ctx, fp0, fd);
11469 tcg_temp_free_i32(fp0);
11471 break;
11472 case OPC_SEL_S:
11473 check_insn(ctx, ISA_MIPS32R6);
11474 gen_sel_s(ctx, op1, fd, ft, fs);
11475 break;
11476 case OPC_SELEQZ_S:
11477 check_insn(ctx, ISA_MIPS32R6);
11478 gen_sel_s(ctx, op1, fd, ft, fs);
11479 break;
11480 case OPC_SELNEZ_S:
11481 check_insn(ctx, ISA_MIPS32R6);
11482 gen_sel_s(ctx, op1, fd, ft, fs);
11483 break;
11484 case OPC_MOVCF_S:
11485 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11486 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11487 break;
11488 case OPC_MOVZ_S:
11489 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11491 TCGLabel *l1 = gen_new_label();
11492 TCGv_i32 fp0;
11494 if (ft != 0) {
11495 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11497 fp0 = tcg_temp_new_i32();
11498 gen_load_fpr32(ctx, fp0, fs);
11499 gen_store_fpr32(ctx, fp0, fd);
11500 tcg_temp_free_i32(fp0);
11501 gen_set_label(l1);
11503 break;
11504 case OPC_MOVN_S:
11505 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11507 TCGLabel *l1 = gen_new_label();
11508 TCGv_i32 fp0;
11510 if (ft != 0) {
11511 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11512 fp0 = tcg_temp_new_i32();
11513 gen_load_fpr32(ctx, fp0, fs);
11514 gen_store_fpr32(ctx, fp0, fd);
11515 tcg_temp_free_i32(fp0);
11516 gen_set_label(l1);
11519 break;
11520 case OPC_RECIP_S:
11522 TCGv_i32 fp0 = tcg_temp_new_i32();
11524 gen_load_fpr32(ctx, fp0, fs);
11525 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11526 gen_store_fpr32(ctx, fp0, fd);
11527 tcg_temp_free_i32(fp0);
11529 break;
11530 case OPC_RSQRT_S:
11532 TCGv_i32 fp0 = tcg_temp_new_i32();
11534 gen_load_fpr32(ctx, fp0, fs);
11535 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11536 gen_store_fpr32(ctx, fp0, fd);
11537 tcg_temp_free_i32(fp0);
11539 break;
11540 case OPC_MADDF_S:
11541 check_insn(ctx, ISA_MIPS32R6);
11543 TCGv_i32 fp0 = tcg_temp_new_i32();
11544 TCGv_i32 fp1 = tcg_temp_new_i32();
11545 TCGv_i32 fp2 = tcg_temp_new_i32();
11546 gen_load_fpr32(ctx, fp0, fs);
11547 gen_load_fpr32(ctx, fp1, ft);
11548 gen_load_fpr32(ctx, fp2, fd);
11549 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11550 gen_store_fpr32(ctx, fp2, fd);
11551 tcg_temp_free_i32(fp2);
11552 tcg_temp_free_i32(fp1);
11553 tcg_temp_free_i32(fp0);
11555 break;
11556 case OPC_MSUBF_S:
11557 check_insn(ctx, ISA_MIPS32R6);
11559 TCGv_i32 fp0 = tcg_temp_new_i32();
11560 TCGv_i32 fp1 = tcg_temp_new_i32();
11561 TCGv_i32 fp2 = tcg_temp_new_i32();
11562 gen_load_fpr32(ctx, fp0, fs);
11563 gen_load_fpr32(ctx, fp1, ft);
11564 gen_load_fpr32(ctx, fp2, fd);
11565 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11566 gen_store_fpr32(ctx, fp2, fd);
11567 tcg_temp_free_i32(fp2);
11568 tcg_temp_free_i32(fp1);
11569 tcg_temp_free_i32(fp0);
11571 break;
11572 case OPC_RINT_S:
11573 check_insn(ctx, ISA_MIPS32R6);
11575 TCGv_i32 fp0 = tcg_temp_new_i32();
11576 gen_load_fpr32(ctx, fp0, fs);
11577 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11578 gen_store_fpr32(ctx, fp0, fd);
11579 tcg_temp_free_i32(fp0);
11581 break;
11582 case OPC_CLASS_S:
11583 check_insn(ctx, ISA_MIPS32R6);
11585 TCGv_i32 fp0 = tcg_temp_new_i32();
11586 gen_load_fpr32(ctx, fp0, fs);
11587 gen_helper_float_class_s(fp0, cpu_env, fp0);
11588 gen_store_fpr32(ctx, fp0, fd);
11589 tcg_temp_free_i32(fp0);
11591 break;
11592 case OPC_MIN_S: /* OPC_RECIP2_S */
11593 if (ctx->insn_flags & ISA_MIPS32R6) {
11594 /* OPC_MIN_S */
11595 TCGv_i32 fp0 = tcg_temp_new_i32();
11596 TCGv_i32 fp1 = tcg_temp_new_i32();
11597 TCGv_i32 fp2 = tcg_temp_new_i32();
11598 gen_load_fpr32(ctx, fp0, fs);
11599 gen_load_fpr32(ctx, fp1, ft);
11600 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11601 gen_store_fpr32(ctx, fp2, fd);
11602 tcg_temp_free_i32(fp2);
11603 tcg_temp_free_i32(fp1);
11604 tcg_temp_free_i32(fp0);
11605 } else {
11606 /* OPC_RECIP2_S */
11607 check_cp1_64bitmode(ctx);
11609 TCGv_i32 fp0 = tcg_temp_new_i32();
11610 TCGv_i32 fp1 = tcg_temp_new_i32();
11612 gen_load_fpr32(ctx, fp0, fs);
11613 gen_load_fpr32(ctx, fp1, ft);
11614 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11615 tcg_temp_free_i32(fp1);
11616 gen_store_fpr32(ctx, fp0, fd);
11617 tcg_temp_free_i32(fp0);
11620 break;
11621 case OPC_MINA_S: /* OPC_RECIP1_S */
11622 if (ctx->insn_flags & ISA_MIPS32R6) {
11623 /* OPC_MINA_S */
11624 TCGv_i32 fp0 = tcg_temp_new_i32();
11625 TCGv_i32 fp1 = tcg_temp_new_i32();
11626 TCGv_i32 fp2 = tcg_temp_new_i32();
11627 gen_load_fpr32(ctx, fp0, fs);
11628 gen_load_fpr32(ctx, fp1, ft);
11629 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11630 gen_store_fpr32(ctx, fp2, fd);
11631 tcg_temp_free_i32(fp2);
11632 tcg_temp_free_i32(fp1);
11633 tcg_temp_free_i32(fp0);
11634 } else {
11635 /* OPC_RECIP1_S */
11636 check_cp1_64bitmode(ctx);
11638 TCGv_i32 fp0 = tcg_temp_new_i32();
11640 gen_load_fpr32(ctx, fp0, fs);
11641 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11642 gen_store_fpr32(ctx, fp0, fd);
11643 tcg_temp_free_i32(fp0);
11646 break;
11647 case OPC_MAX_S: /* OPC_RSQRT1_S */
11648 if (ctx->insn_flags & ISA_MIPS32R6) {
11649 /* OPC_MAX_S */
11650 TCGv_i32 fp0 = tcg_temp_new_i32();
11651 TCGv_i32 fp1 = tcg_temp_new_i32();
11652 gen_load_fpr32(ctx, fp0, fs);
11653 gen_load_fpr32(ctx, fp1, ft);
11654 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11655 gen_store_fpr32(ctx, fp1, fd);
11656 tcg_temp_free_i32(fp1);
11657 tcg_temp_free_i32(fp0);
11658 } else {
11659 /* OPC_RSQRT1_S */
11660 check_cp1_64bitmode(ctx);
11662 TCGv_i32 fp0 = tcg_temp_new_i32();
11664 gen_load_fpr32(ctx, fp0, fs);
11665 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11666 gen_store_fpr32(ctx, fp0, fd);
11667 tcg_temp_free_i32(fp0);
11670 break;
11671 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11672 if (ctx->insn_flags & ISA_MIPS32R6) {
11673 /* OPC_MAXA_S */
11674 TCGv_i32 fp0 = tcg_temp_new_i32();
11675 TCGv_i32 fp1 = tcg_temp_new_i32();
11676 gen_load_fpr32(ctx, fp0, fs);
11677 gen_load_fpr32(ctx, fp1, ft);
11678 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11679 gen_store_fpr32(ctx, fp1, fd);
11680 tcg_temp_free_i32(fp1);
11681 tcg_temp_free_i32(fp0);
11682 } else {
11683 /* OPC_RSQRT2_S */
11684 check_cp1_64bitmode(ctx);
11686 TCGv_i32 fp0 = tcg_temp_new_i32();
11687 TCGv_i32 fp1 = tcg_temp_new_i32();
11689 gen_load_fpr32(ctx, fp0, fs);
11690 gen_load_fpr32(ctx, fp1, ft);
11691 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11692 tcg_temp_free_i32(fp1);
11693 gen_store_fpr32(ctx, fp0, fd);
11694 tcg_temp_free_i32(fp0);
11697 break;
11698 case OPC_CVT_D_S:
11699 check_cp1_registers(ctx, fd);
11701 TCGv_i32 fp32 = tcg_temp_new_i32();
11702 TCGv_i64 fp64 = tcg_temp_new_i64();
11704 gen_load_fpr32(ctx, fp32, fs);
11705 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11706 tcg_temp_free_i32(fp32);
11707 gen_store_fpr64(ctx, fp64, fd);
11708 tcg_temp_free_i64(fp64);
11710 break;
11711 case OPC_CVT_W_S:
11713 TCGv_i32 fp0 = tcg_temp_new_i32();
11715 gen_load_fpr32(ctx, fp0, fs);
11716 if (ctx->nan2008) {
11717 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11718 } else {
11719 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11721 gen_store_fpr32(ctx, fp0, fd);
11722 tcg_temp_free_i32(fp0);
11724 break;
11725 case OPC_CVT_L_S:
11726 check_cp1_64bitmode(ctx);
11728 TCGv_i32 fp32 = tcg_temp_new_i32();
11729 TCGv_i64 fp64 = tcg_temp_new_i64();
11731 gen_load_fpr32(ctx, fp32, fs);
11732 if (ctx->nan2008) {
11733 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11734 } else {
11735 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11737 tcg_temp_free_i32(fp32);
11738 gen_store_fpr64(ctx, fp64, fd);
11739 tcg_temp_free_i64(fp64);
11741 break;
11742 case OPC_CVT_PS_S:
11743 check_ps(ctx);
11745 TCGv_i64 fp64 = tcg_temp_new_i64();
11746 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11747 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11749 gen_load_fpr32(ctx, fp32_0, fs);
11750 gen_load_fpr32(ctx, fp32_1, ft);
11751 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11752 tcg_temp_free_i32(fp32_1);
11753 tcg_temp_free_i32(fp32_0);
11754 gen_store_fpr64(ctx, fp64, fd);
11755 tcg_temp_free_i64(fp64);
11757 break;
11758 case OPC_CMP_F_S:
11759 case OPC_CMP_UN_S:
11760 case OPC_CMP_EQ_S:
11761 case OPC_CMP_UEQ_S:
11762 case OPC_CMP_OLT_S:
11763 case OPC_CMP_ULT_S:
11764 case OPC_CMP_OLE_S:
11765 case OPC_CMP_ULE_S:
11766 case OPC_CMP_SF_S:
11767 case OPC_CMP_NGLE_S:
11768 case OPC_CMP_SEQ_S:
11769 case OPC_CMP_NGL_S:
11770 case OPC_CMP_LT_S:
11771 case OPC_CMP_NGE_S:
11772 case OPC_CMP_LE_S:
11773 case OPC_CMP_NGT_S:
11774 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11775 if (ctx->opcode & (1 << 6)) {
11776 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
11777 } else {
11778 gen_cmp_s(ctx, func - 48, ft, fs, cc);
11780 break;
11781 case OPC_ADD_D:
11782 check_cp1_registers(ctx, fs | ft | fd);
11784 TCGv_i64 fp0 = tcg_temp_new_i64();
11785 TCGv_i64 fp1 = tcg_temp_new_i64();
11787 gen_load_fpr64(ctx, fp0, fs);
11788 gen_load_fpr64(ctx, fp1, ft);
11789 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11790 tcg_temp_free_i64(fp1);
11791 gen_store_fpr64(ctx, fp0, fd);
11792 tcg_temp_free_i64(fp0);
11794 break;
11795 case OPC_SUB_D:
11796 check_cp1_registers(ctx, fs | ft | fd);
11798 TCGv_i64 fp0 = tcg_temp_new_i64();
11799 TCGv_i64 fp1 = tcg_temp_new_i64();
11801 gen_load_fpr64(ctx, fp0, fs);
11802 gen_load_fpr64(ctx, fp1, ft);
11803 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11804 tcg_temp_free_i64(fp1);
11805 gen_store_fpr64(ctx, fp0, fd);
11806 tcg_temp_free_i64(fp0);
11808 break;
11809 case OPC_MUL_D:
11810 check_cp1_registers(ctx, fs | ft | fd);
11812 TCGv_i64 fp0 = tcg_temp_new_i64();
11813 TCGv_i64 fp1 = tcg_temp_new_i64();
11815 gen_load_fpr64(ctx, fp0, fs);
11816 gen_load_fpr64(ctx, fp1, ft);
11817 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11818 tcg_temp_free_i64(fp1);
11819 gen_store_fpr64(ctx, fp0, fd);
11820 tcg_temp_free_i64(fp0);
11822 break;
11823 case OPC_DIV_D:
11824 check_cp1_registers(ctx, fs | ft | fd);
11826 TCGv_i64 fp0 = tcg_temp_new_i64();
11827 TCGv_i64 fp1 = tcg_temp_new_i64();
11829 gen_load_fpr64(ctx, fp0, fs);
11830 gen_load_fpr64(ctx, fp1, ft);
11831 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11832 tcg_temp_free_i64(fp1);
11833 gen_store_fpr64(ctx, fp0, fd);
11834 tcg_temp_free_i64(fp0);
11836 break;
11837 case OPC_SQRT_D:
11838 check_cp1_registers(ctx, fs | fd);
11840 TCGv_i64 fp0 = tcg_temp_new_i64();
11842 gen_load_fpr64(ctx, fp0, fs);
11843 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11844 gen_store_fpr64(ctx, fp0, fd);
11845 tcg_temp_free_i64(fp0);
11847 break;
11848 case OPC_ABS_D:
11849 check_cp1_registers(ctx, fs | fd);
11851 TCGv_i64 fp0 = tcg_temp_new_i64();
11853 gen_load_fpr64(ctx, fp0, fs);
11854 if (ctx->abs2008) {
11855 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11856 } else {
11857 gen_helper_float_abs_d(fp0, fp0);
11859 gen_store_fpr64(ctx, fp0, fd);
11860 tcg_temp_free_i64(fp0);
11862 break;
11863 case OPC_MOV_D:
11864 check_cp1_registers(ctx, fs | fd);
11866 TCGv_i64 fp0 = tcg_temp_new_i64();
11868 gen_load_fpr64(ctx, fp0, fs);
11869 gen_store_fpr64(ctx, fp0, fd);
11870 tcg_temp_free_i64(fp0);
11872 break;
11873 case OPC_NEG_D:
11874 check_cp1_registers(ctx, fs | fd);
11876 TCGv_i64 fp0 = tcg_temp_new_i64();
11878 gen_load_fpr64(ctx, fp0, fs);
11879 if (ctx->abs2008) {
11880 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11881 } else {
11882 gen_helper_float_chs_d(fp0, fp0);
11884 gen_store_fpr64(ctx, fp0, fd);
11885 tcg_temp_free_i64(fp0);
11887 break;
11888 case OPC_ROUND_L_D:
11889 check_cp1_64bitmode(ctx);
11891 TCGv_i64 fp0 = tcg_temp_new_i64();
11893 gen_load_fpr64(ctx, fp0, fs);
11894 if (ctx->nan2008) {
11895 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11896 } else {
11897 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11899 gen_store_fpr64(ctx, fp0, fd);
11900 tcg_temp_free_i64(fp0);
11902 break;
11903 case OPC_TRUNC_L_D:
11904 check_cp1_64bitmode(ctx);
11906 TCGv_i64 fp0 = tcg_temp_new_i64();
11908 gen_load_fpr64(ctx, fp0, fs);
11909 if (ctx->nan2008) {
11910 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11911 } else {
11912 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11914 gen_store_fpr64(ctx, fp0, fd);
11915 tcg_temp_free_i64(fp0);
11917 break;
11918 case OPC_CEIL_L_D:
11919 check_cp1_64bitmode(ctx);
11921 TCGv_i64 fp0 = tcg_temp_new_i64();
11923 gen_load_fpr64(ctx, fp0, fs);
11924 if (ctx->nan2008) {
11925 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11926 } else {
11927 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11929 gen_store_fpr64(ctx, fp0, fd);
11930 tcg_temp_free_i64(fp0);
11932 break;
11933 case OPC_FLOOR_L_D:
11934 check_cp1_64bitmode(ctx);
11936 TCGv_i64 fp0 = tcg_temp_new_i64();
11938 gen_load_fpr64(ctx, fp0, fs);
11939 if (ctx->nan2008) {
11940 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11941 } else {
11942 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11944 gen_store_fpr64(ctx, fp0, fd);
11945 tcg_temp_free_i64(fp0);
11947 break;
11948 case OPC_ROUND_W_D:
11949 check_cp1_registers(ctx, fs);
11951 TCGv_i32 fp32 = tcg_temp_new_i32();
11952 TCGv_i64 fp64 = tcg_temp_new_i64();
11954 gen_load_fpr64(ctx, fp64, fs);
11955 if (ctx->nan2008) {
11956 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11957 } else {
11958 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11960 tcg_temp_free_i64(fp64);
11961 gen_store_fpr32(ctx, fp32, fd);
11962 tcg_temp_free_i32(fp32);
11964 break;
11965 case OPC_TRUNC_W_D:
11966 check_cp1_registers(ctx, fs);
11968 TCGv_i32 fp32 = tcg_temp_new_i32();
11969 TCGv_i64 fp64 = tcg_temp_new_i64();
11971 gen_load_fpr64(ctx, fp64, fs);
11972 if (ctx->nan2008) {
11973 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11974 } else {
11975 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11977 tcg_temp_free_i64(fp64);
11978 gen_store_fpr32(ctx, fp32, fd);
11979 tcg_temp_free_i32(fp32);
11981 break;
11982 case OPC_CEIL_W_D:
11983 check_cp1_registers(ctx, fs);
11985 TCGv_i32 fp32 = tcg_temp_new_i32();
11986 TCGv_i64 fp64 = tcg_temp_new_i64();
11988 gen_load_fpr64(ctx, fp64, fs);
11989 if (ctx->nan2008) {
11990 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11991 } else {
11992 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11994 tcg_temp_free_i64(fp64);
11995 gen_store_fpr32(ctx, fp32, fd);
11996 tcg_temp_free_i32(fp32);
11998 break;
11999 case OPC_FLOOR_W_D:
12000 check_cp1_registers(ctx, fs);
12002 TCGv_i32 fp32 = tcg_temp_new_i32();
12003 TCGv_i64 fp64 = tcg_temp_new_i64();
12005 gen_load_fpr64(ctx, fp64, fs);
12006 if (ctx->nan2008) {
12007 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12008 } else {
12009 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12011 tcg_temp_free_i64(fp64);
12012 gen_store_fpr32(ctx, fp32, fd);
12013 tcg_temp_free_i32(fp32);
12015 break;
12016 case OPC_SEL_D:
12017 check_insn(ctx, ISA_MIPS32R6);
12018 gen_sel_d(ctx, op1, fd, ft, fs);
12019 break;
12020 case OPC_SELEQZ_D:
12021 check_insn(ctx, ISA_MIPS32R6);
12022 gen_sel_d(ctx, op1, fd, ft, fs);
12023 break;
12024 case OPC_SELNEZ_D:
12025 check_insn(ctx, ISA_MIPS32R6);
12026 gen_sel_d(ctx, op1, fd, ft, fs);
12027 break;
12028 case OPC_MOVCF_D:
12029 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12030 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12031 break;
12032 case OPC_MOVZ_D:
12033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12035 TCGLabel *l1 = gen_new_label();
12036 TCGv_i64 fp0;
12038 if (ft != 0) {
12039 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12041 fp0 = tcg_temp_new_i64();
12042 gen_load_fpr64(ctx, fp0, fs);
12043 gen_store_fpr64(ctx, fp0, fd);
12044 tcg_temp_free_i64(fp0);
12045 gen_set_label(l1);
12047 break;
12048 case OPC_MOVN_D:
12049 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12051 TCGLabel *l1 = gen_new_label();
12052 TCGv_i64 fp0;
12054 if (ft != 0) {
12055 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12056 fp0 = tcg_temp_new_i64();
12057 gen_load_fpr64(ctx, fp0, fs);
12058 gen_store_fpr64(ctx, fp0, fd);
12059 tcg_temp_free_i64(fp0);
12060 gen_set_label(l1);
12063 break;
12064 case OPC_RECIP_D:
12065 check_cp1_registers(ctx, fs | fd);
12067 TCGv_i64 fp0 = tcg_temp_new_i64();
12069 gen_load_fpr64(ctx, fp0, fs);
12070 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12071 gen_store_fpr64(ctx, fp0, fd);
12072 tcg_temp_free_i64(fp0);
12074 break;
12075 case OPC_RSQRT_D:
12076 check_cp1_registers(ctx, fs | fd);
12078 TCGv_i64 fp0 = tcg_temp_new_i64();
12080 gen_load_fpr64(ctx, fp0, fs);
12081 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12082 gen_store_fpr64(ctx, fp0, fd);
12083 tcg_temp_free_i64(fp0);
12085 break;
12086 case OPC_MADDF_D:
12087 check_insn(ctx, ISA_MIPS32R6);
12089 TCGv_i64 fp0 = tcg_temp_new_i64();
12090 TCGv_i64 fp1 = tcg_temp_new_i64();
12091 TCGv_i64 fp2 = tcg_temp_new_i64();
12092 gen_load_fpr64(ctx, fp0, fs);
12093 gen_load_fpr64(ctx, fp1, ft);
12094 gen_load_fpr64(ctx, fp2, fd);
12095 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12096 gen_store_fpr64(ctx, fp2, fd);
12097 tcg_temp_free_i64(fp2);
12098 tcg_temp_free_i64(fp1);
12099 tcg_temp_free_i64(fp0);
12101 break;
12102 case OPC_MSUBF_D:
12103 check_insn(ctx, ISA_MIPS32R6);
12105 TCGv_i64 fp0 = tcg_temp_new_i64();
12106 TCGv_i64 fp1 = tcg_temp_new_i64();
12107 TCGv_i64 fp2 = tcg_temp_new_i64();
12108 gen_load_fpr64(ctx, fp0, fs);
12109 gen_load_fpr64(ctx, fp1, ft);
12110 gen_load_fpr64(ctx, fp2, fd);
12111 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12112 gen_store_fpr64(ctx, fp2, fd);
12113 tcg_temp_free_i64(fp2);
12114 tcg_temp_free_i64(fp1);
12115 tcg_temp_free_i64(fp0);
12117 break;
12118 case OPC_RINT_D:
12119 check_insn(ctx, ISA_MIPS32R6);
12121 TCGv_i64 fp0 = tcg_temp_new_i64();
12122 gen_load_fpr64(ctx, fp0, fs);
12123 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12124 gen_store_fpr64(ctx, fp0, fd);
12125 tcg_temp_free_i64(fp0);
12127 break;
12128 case OPC_CLASS_D:
12129 check_insn(ctx, ISA_MIPS32R6);
12131 TCGv_i64 fp0 = tcg_temp_new_i64();
12132 gen_load_fpr64(ctx, fp0, fs);
12133 gen_helper_float_class_d(fp0, cpu_env, fp0);
12134 gen_store_fpr64(ctx, fp0, fd);
12135 tcg_temp_free_i64(fp0);
12137 break;
12138 case OPC_MIN_D: /* OPC_RECIP2_D */
12139 if (ctx->insn_flags & ISA_MIPS32R6) {
12140 /* OPC_MIN_D */
12141 TCGv_i64 fp0 = tcg_temp_new_i64();
12142 TCGv_i64 fp1 = tcg_temp_new_i64();
12143 gen_load_fpr64(ctx, fp0, fs);
12144 gen_load_fpr64(ctx, fp1, ft);
12145 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12146 gen_store_fpr64(ctx, fp1, fd);
12147 tcg_temp_free_i64(fp1);
12148 tcg_temp_free_i64(fp0);
12149 } else {
12150 /* OPC_RECIP2_D */
12151 check_cp1_64bitmode(ctx);
12153 TCGv_i64 fp0 = tcg_temp_new_i64();
12154 TCGv_i64 fp1 = tcg_temp_new_i64();
12156 gen_load_fpr64(ctx, fp0, fs);
12157 gen_load_fpr64(ctx, fp1, ft);
12158 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12159 tcg_temp_free_i64(fp1);
12160 gen_store_fpr64(ctx, fp0, fd);
12161 tcg_temp_free_i64(fp0);
12164 break;
12165 case OPC_MINA_D: /* OPC_RECIP1_D */
12166 if (ctx->insn_flags & ISA_MIPS32R6) {
12167 /* OPC_MINA_D */
12168 TCGv_i64 fp0 = tcg_temp_new_i64();
12169 TCGv_i64 fp1 = tcg_temp_new_i64();
12170 gen_load_fpr64(ctx, fp0, fs);
12171 gen_load_fpr64(ctx, fp1, ft);
12172 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12173 gen_store_fpr64(ctx, fp1, fd);
12174 tcg_temp_free_i64(fp1);
12175 tcg_temp_free_i64(fp0);
12176 } else {
12177 /* OPC_RECIP1_D */
12178 check_cp1_64bitmode(ctx);
12180 TCGv_i64 fp0 = tcg_temp_new_i64();
12182 gen_load_fpr64(ctx, fp0, fs);
12183 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12184 gen_store_fpr64(ctx, fp0, fd);
12185 tcg_temp_free_i64(fp0);
12188 break;
12189 case OPC_MAX_D: /* OPC_RSQRT1_D */
12190 if (ctx->insn_flags & ISA_MIPS32R6) {
12191 /* OPC_MAX_D */
12192 TCGv_i64 fp0 = tcg_temp_new_i64();
12193 TCGv_i64 fp1 = tcg_temp_new_i64();
12194 gen_load_fpr64(ctx, fp0, fs);
12195 gen_load_fpr64(ctx, fp1, ft);
12196 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12197 gen_store_fpr64(ctx, fp1, fd);
12198 tcg_temp_free_i64(fp1);
12199 tcg_temp_free_i64(fp0);
12200 } else {
12201 /* OPC_RSQRT1_D */
12202 check_cp1_64bitmode(ctx);
12204 TCGv_i64 fp0 = tcg_temp_new_i64();
12206 gen_load_fpr64(ctx, fp0, fs);
12207 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12208 gen_store_fpr64(ctx, fp0, fd);
12209 tcg_temp_free_i64(fp0);
12212 break;
12213 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12214 if (ctx->insn_flags & ISA_MIPS32R6) {
12215 /* OPC_MAXA_D */
12216 TCGv_i64 fp0 = tcg_temp_new_i64();
12217 TCGv_i64 fp1 = tcg_temp_new_i64();
12218 gen_load_fpr64(ctx, fp0, fs);
12219 gen_load_fpr64(ctx, fp1, ft);
12220 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12221 gen_store_fpr64(ctx, fp1, fd);
12222 tcg_temp_free_i64(fp1);
12223 tcg_temp_free_i64(fp0);
12224 } else {
12225 /* OPC_RSQRT2_D */
12226 check_cp1_64bitmode(ctx);
12228 TCGv_i64 fp0 = tcg_temp_new_i64();
12229 TCGv_i64 fp1 = tcg_temp_new_i64();
12231 gen_load_fpr64(ctx, fp0, fs);
12232 gen_load_fpr64(ctx, fp1, ft);
12233 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12234 tcg_temp_free_i64(fp1);
12235 gen_store_fpr64(ctx, fp0, fd);
12236 tcg_temp_free_i64(fp0);
12239 break;
12240 case OPC_CMP_F_D:
12241 case OPC_CMP_UN_D:
12242 case OPC_CMP_EQ_D:
12243 case OPC_CMP_UEQ_D:
12244 case OPC_CMP_OLT_D:
12245 case OPC_CMP_ULT_D:
12246 case OPC_CMP_OLE_D:
12247 case OPC_CMP_ULE_D:
12248 case OPC_CMP_SF_D:
12249 case OPC_CMP_NGLE_D:
12250 case OPC_CMP_SEQ_D:
12251 case OPC_CMP_NGL_D:
12252 case OPC_CMP_LT_D:
12253 case OPC_CMP_NGE_D:
12254 case OPC_CMP_LE_D:
12255 case OPC_CMP_NGT_D:
12256 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12257 if (ctx->opcode & (1 << 6)) {
12258 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12259 } else {
12260 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12262 break;
12263 case OPC_CVT_S_D:
12264 check_cp1_registers(ctx, fs);
12266 TCGv_i32 fp32 = tcg_temp_new_i32();
12267 TCGv_i64 fp64 = tcg_temp_new_i64();
12269 gen_load_fpr64(ctx, fp64, fs);
12270 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12271 tcg_temp_free_i64(fp64);
12272 gen_store_fpr32(ctx, fp32, fd);
12273 tcg_temp_free_i32(fp32);
12275 break;
12276 case OPC_CVT_W_D:
12277 check_cp1_registers(ctx, fs);
12279 TCGv_i32 fp32 = tcg_temp_new_i32();
12280 TCGv_i64 fp64 = tcg_temp_new_i64();
12282 gen_load_fpr64(ctx, fp64, fs);
12283 if (ctx->nan2008) {
12284 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12285 } else {
12286 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12288 tcg_temp_free_i64(fp64);
12289 gen_store_fpr32(ctx, fp32, fd);
12290 tcg_temp_free_i32(fp32);
12292 break;
12293 case OPC_CVT_L_D:
12294 check_cp1_64bitmode(ctx);
12296 TCGv_i64 fp0 = tcg_temp_new_i64();
12298 gen_load_fpr64(ctx, fp0, fs);
12299 if (ctx->nan2008) {
12300 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12301 } else {
12302 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12304 gen_store_fpr64(ctx, fp0, fd);
12305 tcg_temp_free_i64(fp0);
12307 break;
12308 case OPC_CVT_S_W:
12310 TCGv_i32 fp0 = tcg_temp_new_i32();
12312 gen_load_fpr32(ctx, fp0, fs);
12313 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12314 gen_store_fpr32(ctx, fp0, fd);
12315 tcg_temp_free_i32(fp0);
12317 break;
12318 case OPC_CVT_D_W:
12319 check_cp1_registers(ctx, fd);
12321 TCGv_i32 fp32 = tcg_temp_new_i32();
12322 TCGv_i64 fp64 = tcg_temp_new_i64();
12324 gen_load_fpr32(ctx, fp32, fs);
12325 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12326 tcg_temp_free_i32(fp32);
12327 gen_store_fpr64(ctx, fp64, fd);
12328 tcg_temp_free_i64(fp64);
12330 break;
12331 case OPC_CVT_S_L:
12332 check_cp1_64bitmode(ctx);
12334 TCGv_i32 fp32 = tcg_temp_new_i32();
12335 TCGv_i64 fp64 = tcg_temp_new_i64();
12337 gen_load_fpr64(ctx, fp64, fs);
12338 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12339 tcg_temp_free_i64(fp64);
12340 gen_store_fpr32(ctx, fp32, fd);
12341 tcg_temp_free_i32(fp32);
12343 break;
12344 case OPC_CVT_D_L:
12345 check_cp1_64bitmode(ctx);
12347 TCGv_i64 fp0 = tcg_temp_new_i64();
12349 gen_load_fpr64(ctx, fp0, fs);
12350 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12351 gen_store_fpr64(ctx, fp0, fd);
12352 tcg_temp_free_i64(fp0);
12354 break;
12355 case OPC_CVT_PS_PW:
12356 check_ps(ctx);
12358 TCGv_i64 fp0 = tcg_temp_new_i64();
12360 gen_load_fpr64(ctx, fp0, fs);
12361 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12362 gen_store_fpr64(ctx, fp0, fd);
12363 tcg_temp_free_i64(fp0);
12365 break;
12366 case OPC_ADD_PS:
12367 check_ps(ctx);
12369 TCGv_i64 fp0 = tcg_temp_new_i64();
12370 TCGv_i64 fp1 = tcg_temp_new_i64();
12372 gen_load_fpr64(ctx, fp0, fs);
12373 gen_load_fpr64(ctx, fp1, ft);
12374 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12375 tcg_temp_free_i64(fp1);
12376 gen_store_fpr64(ctx, fp0, fd);
12377 tcg_temp_free_i64(fp0);
12379 break;
12380 case OPC_SUB_PS:
12381 check_ps(ctx);
12383 TCGv_i64 fp0 = tcg_temp_new_i64();
12384 TCGv_i64 fp1 = tcg_temp_new_i64();
12386 gen_load_fpr64(ctx, fp0, fs);
12387 gen_load_fpr64(ctx, fp1, ft);
12388 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12389 tcg_temp_free_i64(fp1);
12390 gen_store_fpr64(ctx, fp0, fd);
12391 tcg_temp_free_i64(fp0);
12393 break;
12394 case OPC_MUL_PS:
12395 check_ps(ctx);
12397 TCGv_i64 fp0 = tcg_temp_new_i64();
12398 TCGv_i64 fp1 = tcg_temp_new_i64();
12400 gen_load_fpr64(ctx, fp0, fs);
12401 gen_load_fpr64(ctx, fp1, ft);
12402 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12403 tcg_temp_free_i64(fp1);
12404 gen_store_fpr64(ctx, fp0, fd);
12405 tcg_temp_free_i64(fp0);
12407 break;
12408 case OPC_ABS_PS:
12409 check_ps(ctx);
12411 TCGv_i64 fp0 = tcg_temp_new_i64();
12413 gen_load_fpr64(ctx, fp0, fs);
12414 gen_helper_float_abs_ps(fp0, fp0);
12415 gen_store_fpr64(ctx, fp0, fd);
12416 tcg_temp_free_i64(fp0);
12418 break;
12419 case OPC_MOV_PS:
12420 check_ps(ctx);
12422 TCGv_i64 fp0 = tcg_temp_new_i64();
12424 gen_load_fpr64(ctx, fp0, fs);
12425 gen_store_fpr64(ctx, fp0, fd);
12426 tcg_temp_free_i64(fp0);
12428 break;
12429 case OPC_NEG_PS:
12430 check_ps(ctx);
12432 TCGv_i64 fp0 = tcg_temp_new_i64();
12434 gen_load_fpr64(ctx, fp0, fs);
12435 gen_helper_float_chs_ps(fp0, fp0);
12436 gen_store_fpr64(ctx, fp0, fd);
12437 tcg_temp_free_i64(fp0);
12439 break;
12440 case OPC_MOVCF_PS:
12441 check_ps(ctx);
12442 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12443 break;
12444 case OPC_MOVZ_PS:
12445 check_ps(ctx);
12447 TCGLabel *l1 = gen_new_label();
12448 TCGv_i64 fp0;
12450 if (ft != 0) {
12451 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12453 fp0 = tcg_temp_new_i64();
12454 gen_load_fpr64(ctx, fp0, fs);
12455 gen_store_fpr64(ctx, fp0, fd);
12456 tcg_temp_free_i64(fp0);
12457 gen_set_label(l1);
12459 break;
12460 case OPC_MOVN_PS:
12461 check_ps(ctx);
12463 TCGLabel *l1 = gen_new_label();
12464 TCGv_i64 fp0;
12466 if (ft != 0) {
12467 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12468 fp0 = tcg_temp_new_i64();
12469 gen_load_fpr64(ctx, fp0, fs);
12470 gen_store_fpr64(ctx, fp0, fd);
12471 tcg_temp_free_i64(fp0);
12472 gen_set_label(l1);
12475 break;
12476 case OPC_ADDR_PS:
12477 check_ps(ctx);
12479 TCGv_i64 fp0 = tcg_temp_new_i64();
12480 TCGv_i64 fp1 = tcg_temp_new_i64();
12482 gen_load_fpr64(ctx, fp0, ft);
12483 gen_load_fpr64(ctx, fp1, fs);
12484 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12485 tcg_temp_free_i64(fp1);
12486 gen_store_fpr64(ctx, fp0, fd);
12487 tcg_temp_free_i64(fp0);
12489 break;
12490 case OPC_MULR_PS:
12491 check_ps(ctx);
12493 TCGv_i64 fp0 = tcg_temp_new_i64();
12494 TCGv_i64 fp1 = tcg_temp_new_i64();
12496 gen_load_fpr64(ctx, fp0, ft);
12497 gen_load_fpr64(ctx, fp1, fs);
12498 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12499 tcg_temp_free_i64(fp1);
12500 gen_store_fpr64(ctx, fp0, fd);
12501 tcg_temp_free_i64(fp0);
12503 break;
12504 case OPC_RECIP2_PS:
12505 check_ps(ctx);
12507 TCGv_i64 fp0 = tcg_temp_new_i64();
12508 TCGv_i64 fp1 = tcg_temp_new_i64();
12510 gen_load_fpr64(ctx, fp0, fs);
12511 gen_load_fpr64(ctx, fp1, ft);
12512 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12513 tcg_temp_free_i64(fp1);
12514 gen_store_fpr64(ctx, fp0, fd);
12515 tcg_temp_free_i64(fp0);
12517 break;
12518 case OPC_RECIP1_PS:
12519 check_ps(ctx);
12521 TCGv_i64 fp0 = tcg_temp_new_i64();
12523 gen_load_fpr64(ctx, fp0, fs);
12524 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12525 gen_store_fpr64(ctx, fp0, fd);
12526 tcg_temp_free_i64(fp0);
12528 break;
12529 case OPC_RSQRT1_PS:
12530 check_ps(ctx);
12532 TCGv_i64 fp0 = tcg_temp_new_i64();
12534 gen_load_fpr64(ctx, fp0, fs);
12535 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12536 gen_store_fpr64(ctx, fp0, fd);
12537 tcg_temp_free_i64(fp0);
12539 break;
12540 case OPC_RSQRT2_PS:
12541 check_ps(ctx);
12543 TCGv_i64 fp0 = tcg_temp_new_i64();
12544 TCGv_i64 fp1 = tcg_temp_new_i64();
12546 gen_load_fpr64(ctx, fp0, fs);
12547 gen_load_fpr64(ctx, fp1, ft);
12548 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12549 tcg_temp_free_i64(fp1);
12550 gen_store_fpr64(ctx, fp0, fd);
12551 tcg_temp_free_i64(fp0);
12553 break;
12554 case OPC_CVT_S_PU:
12555 check_cp1_64bitmode(ctx);
12557 TCGv_i32 fp0 = tcg_temp_new_i32();
12559 gen_load_fpr32h(ctx, fp0, fs);
12560 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12561 gen_store_fpr32(ctx, fp0, fd);
12562 tcg_temp_free_i32(fp0);
12564 break;
12565 case OPC_CVT_PW_PS:
12566 check_ps(ctx);
12568 TCGv_i64 fp0 = tcg_temp_new_i64();
12570 gen_load_fpr64(ctx, fp0, fs);
12571 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12572 gen_store_fpr64(ctx, fp0, fd);
12573 tcg_temp_free_i64(fp0);
12575 break;
12576 case OPC_CVT_S_PL:
12577 check_cp1_64bitmode(ctx);
12579 TCGv_i32 fp0 = tcg_temp_new_i32();
12581 gen_load_fpr32(ctx, fp0, fs);
12582 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12583 gen_store_fpr32(ctx, fp0, fd);
12584 tcg_temp_free_i32(fp0);
12586 break;
12587 case OPC_PLL_PS:
12588 check_ps(ctx);
12590 TCGv_i32 fp0 = tcg_temp_new_i32();
12591 TCGv_i32 fp1 = tcg_temp_new_i32();
12593 gen_load_fpr32(ctx, fp0, fs);
12594 gen_load_fpr32(ctx, fp1, ft);
12595 gen_store_fpr32h(ctx, fp0, fd);
12596 gen_store_fpr32(ctx, fp1, fd);
12597 tcg_temp_free_i32(fp0);
12598 tcg_temp_free_i32(fp1);
12600 break;
12601 case OPC_PLU_PS:
12602 check_ps(ctx);
12604 TCGv_i32 fp0 = tcg_temp_new_i32();
12605 TCGv_i32 fp1 = tcg_temp_new_i32();
12607 gen_load_fpr32(ctx, fp0, fs);
12608 gen_load_fpr32h(ctx, fp1, ft);
12609 gen_store_fpr32(ctx, fp1, fd);
12610 gen_store_fpr32h(ctx, fp0, fd);
12611 tcg_temp_free_i32(fp0);
12612 tcg_temp_free_i32(fp1);
12614 break;
12615 case OPC_PUL_PS:
12616 check_ps(ctx);
12618 TCGv_i32 fp0 = tcg_temp_new_i32();
12619 TCGv_i32 fp1 = tcg_temp_new_i32();
12621 gen_load_fpr32h(ctx, fp0, fs);
12622 gen_load_fpr32(ctx, fp1, ft);
12623 gen_store_fpr32(ctx, fp1, fd);
12624 gen_store_fpr32h(ctx, fp0, fd);
12625 tcg_temp_free_i32(fp0);
12626 tcg_temp_free_i32(fp1);
12628 break;
12629 case OPC_PUU_PS:
12630 check_ps(ctx);
12632 TCGv_i32 fp0 = tcg_temp_new_i32();
12633 TCGv_i32 fp1 = tcg_temp_new_i32();
12635 gen_load_fpr32h(ctx, fp0, fs);
12636 gen_load_fpr32h(ctx, fp1, ft);
12637 gen_store_fpr32(ctx, fp1, fd);
12638 gen_store_fpr32h(ctx, fp0, fd);
12639 tcg_temp_free_i32(fp0);
12640 tcg_temp_free_i32(fp1);
12642 break;
12643 case OPC_CMP_F_PS:
12644 case OPC_CMP_UN_PS:
12645 case OPC_CMP_EQ_PS:
12646 case OPC_CMP_UEQ_PS:
12647 case OPC_CMP_OLT_PS:
12648 case OPC_CMP_ULT_PS:
12649 case OPC_CMP_OLE_PS:
12650 case OPC_CMP_ULE_PS:
12651 case OPC_CMP_SF_PS:
12652 case OPC_CMP_NGLE_PS:
12653 case OPC_CMP_SEQ_PS:
12654 case OPC_CMP_NGL_PS:
12655 case OPC_CMP_LT_PS:
12656 case OPC_CMP_NGE_PS:
12657 case OPC_CMP_LE_PS:
12658 case OPC_CMP_NGT_PS:
12659 if (ctx->opcode & (1 << 6)) {
12660 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12661 } else {
12662 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12664 break;
12665 default:
12666 MIPS_INVAL("farith");
12667 generate_exception_end(ctx, EXCP_RI);
12668 return;
12672 /* Coprocessor 3 (FPU) */
12673 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12674 int fd, int fs, int base, int index)
12676 TCGv t0 = tcg_temp_new();
12678 if (base == 0) {
12679 gen_load_gpr(t0, index);
12680 } else if (index == 0) {
12681 gen_load_gpr(t0, base);
12682 } else {
12683 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12686 * Don't do NOP if destination is zero: we must perform the actual
12687 * memory access.
12689 switch (opc) {
12690 case OPC_LWXC1:
12691 check_cop1x(ctx);
12693 TCGv_i32 fp0 = tcg_temp_new_i32();
12695 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12696 tcg_gen_trunc_tl_i32(fp0, t0);
12697 gen_store_fpr32(ctx, fp0, fd);
12698 tcg_temp_free_i32(fp0);
12700 break;
12701 case OPC_LDXC1:
12702 check_cop1x(ctx);
12703 check_cp1_registers(ctx, fd);
12705 TCGv_i64 fp0 = tcg_temp_new_i64();
12706 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12707 gen_store_fpr64(ctx, fp0, fd);
12708 tcg_temp_free_i64(fp0);
12710 break;
12711 case OPC_LUXC1:
12712 check_cp1_64bitmode(ctx);
12713 tcg_gen_andi_tl(t0, t0, ~0x7);
12715 TCGv_i64 fp0 = tcg_temp_new_i64();
12717 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12718 gen_store_fpr64(ctx, fp0, fd);
12719 tcg_temp_free_i64(fp0);
12721 break;
12722 case OPC_SWXC1:
12723 check_cop1x(ctx);
12725 TCGv_i32 fp0 = tcg_temp_new_i32();
12726 gen_load_fpr32(ctx, fp0, fs);
12727 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12728 tcg_temp_free_i32(fp0);
12730 break;
12731 case OPC_SDXC1:
12732 check_cop1x(ctx);
12733 check_cp1_registers(ctx, fs);
12735 TCGv_i64 fp0 = tcg_temp_new_i64();
12736 gen_load_fpr64(ctx, fp0, fs);
12737 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12738 tcg_temp_free_i64(fp0);
12740 break;
12741 case OPC_SUXC1:
12742 check_cp1_64bitmode(ctx);
12743 tcg_gen_andi_tl(t0, t0, ~0x7);
12745 TCGv_i64 fp0 = tcg_temp_new_i64();
12746 gen_load_fpr64(ctx, fp0, fs);
12747 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12748 tcg_temp_free_i64(fp0);
12750 break;
12752 tcg_temp_free(t0);
12755 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
12756 int fd, int fr, int fs, int ft)
12758 switch (opc) {
12759 case OPC_ALNV_PS:
12760 check_ps(ctx);
12762 TCGv t0 = tcg_temp_local_new();
12763 TCGv_i32 fp = tcg_temp_new_i32();
12764 TCGv_i32 fph = tcg_temp_new_i32();
12765 TCGLabel *l1 = gen_new_label();
12766 TCGLabel *l2 = gen_new_label();
12768 gen_load_gpr(t0, fr);
12769 tcg_gen_andi_tl(t0, t0, 0x7);
12771 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12772 gen_load_fpr32(ctx, fp, fs);
12773 gen_load_fpr32h(ctx, fph, fs);
12774 gen_store_fpr32(ctx, fp, fd);
12775 gen_store_fpr32h(ctx, fph, fd);
12776 tcg_gen_br(l2);
12777 gen_set_label(l1);
12778 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12779 tcg_temp_free(t0);
12780 #ifdef TARGET_WORDS_BIGENDIAN
12781 gen_load_fpr32(ctx, fp, fs);
12782 gen_load_fpr32h(ctx, fph, ft);
12783 gen_store_fpr32h(ctx, fp, fd);
12784 gen_store_fpr32(ctx, fph, fd);
12785 #else
12786 gen_load_fpr32h(ctx, fph, fs);
12787 gen_load_fpr32(ctx, fp, ft);
12788 gen_store_fpr32(ctx, fph, fd);
12789 gen_store_fpr32h(ctx, fp, fd);
12790 #endif
12791 gen_set_label(l2);
12792 tcg_temp_free_i32(fp);
12793 tcg_temp_free_i32(fph);
12795 break;
12796 case OPC_MADD_S:
12797 check_cop1x(ctx);
12799 TCGv_i32 fp0 = tcg_temp_new_i32();
12800 TCGv_i32 fp1 = tcg_temp_new_i32();
12801 TCGv_i32 fp2 = tcg_temp_new_i32();
12803 gen_load_fpr32(ctx, fp0, fs);
12804 gen_load_fpr32(ctx, fp1, ft);
12805 gen_load_fpr32(ctx, fp2, fr);
12806 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12807 tcg_temp_free_i32(fp0);
12808 tcg_temp_free_i32(fp1);
12809 gen_store_fpr32(ctx, fp2, fd);
12810 tcg_temp_free_i32(fp2);
12812 break;
12813 case OPC_MADD_D:
12814 check_cop1x(ctx);
12815 check_cp1_registers(ctx, fd | fs | ft | fr);
12817 TCGv_i64 fp0 = tcg_temp_new_i64();
12818 TCGv_i64 fp1 = tcg_temp_new_i64();
12819 TCGv_i64 fp2 = tcg_temp_new_i64();
12821 gen_load_fpr64(ctx, fp0, fs);
12822 gen_load_fpr64(ctx, fp1, ft);
12823 gen_load_fpr64(ctx, fp2, fr);
12824 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12825 tcg_temp_free_i64(fp0);
12826 tcg_temp_free_i64(fp1);
12827 gen_store_fpr64(ctx, fp2, fd);
12828 tcg_temp_free_i64(fp2);
12830 break;
12831 case OPC_MADD_PS:
12832 check_ps(ctx);
12834 TCGv_i64 fp0 = tcg_temp_new_i64();
12835 TCGv_i64 fp1 = tcg_temp_new_i64();
12836 TCGv_i64 fp2 = tcg_temp_new_i64();
12838 gen_load_fpr64(ctx, fp0, fs);
12839 gen_load_fpr64(ctx, fp1, ft);
12840 gen_load_fpr64(ctx, fp2, fr);
12841 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12842 tcg_temp_free_i64(fp0);
12843 tcg_temp_free_i64(fp1);
12844 gen_store_fpr64(ctx, fp2, fd);
12845 tcg_temp_free_i64(fp2);
12847 break;
12848 case OPC_MSUB_S:
12849 check_cop1x(ctx);
12851 TCGv_i32 fp0 = tcg_temp_new_i32();
12852 TCGv_i32 fp1 = tcg_temp_new_i32();
12853 TCGv_i32 fp2 = tcg_temp_new_i32();
12855 gen_load_fpr32(ctx, fp0, fs);
12856 gen_load_fpr32(ctx, fp1, ft);
12857 gen_load_fpr32(ctx, fp2, fr);
12858 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12859 tcg_temp_free_i32(fp0);
12860 tcg_temp_free_i32(fp1);
12861 gen_store_fpr32(ctx, fp2, fd);
12862 tcg_temp_free_i32(fp2);
12864 break;
12865 case OPC_MSUB_D:
12866 check_cop1x(ctx);
12867 check_cp1_registers(ctx, fd | fs | ft | fr);
12869 TCGv_i64 fp0 = tcg_temp_new_i64();
12870 TCGv_i64 fp1 = tcg_temp_new_i64();
12871 TCGv_i64 fp2 = tcg_temp_new_i64();
12873 gen_load_fpr64(ctx, fp0, fs);
12874 gen_load_fpr64(ctx, fp1, ft);
12875 gen_load_fpr64(ctx, fp2, fr);
12876 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12877 tcg_temp_free_i64(fp0);
12878 tcg_temp_free_i64(fp1);
12879 gen_store_fpr64(ctx, fp2, fd);
12880 tcg_temp_free_i64(fp2);
12882 break;
12883 case OPC_MSUB_PS:
12884 check_ps(ctx);
12886 TCGv_i64 fp0 = tcg_temp_new_i64();
12887 TCGv_i64 fp1 = tcg_temp_new_i64();
12888 TCGv_i64 fp2 = tcg_temp_new_i64();
12890 gen_load_fpr64(ctx, fp0, fs);
12891 gen_load_fpr64(ctx, fp1, ft);
12892 gen_load_fpr64(ctx, fp2, fr);
12893 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12894 tcg_temp_free_i64(fp0);
12895 tcg_temp_free_i64(fp1);
12896 gen_store_fpr64(ctx, fp2, fd);
12897 tcg_temp_free_i64(fp2);
12899 break;
12900 case OPC_NMADD_S:
12901 check_cop1x(ctx);
12903 TCGv_i32 fp0 = tcg_temp_new_i32();
12904 TCGv_i32 fp1 = tcg_temp_new_i32();
12905 TCGv_i32 fp2 = tcg_temp_new_i32();
12907 gen_load_fpr32(ctx, fp0, fs);
12908 gen_load_fpr32(ctx, fp1, ft);
12909 gen_load_fpr32(ctx, fp2, fr);
12910 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12911 tcg_temp_free_i32(fp0);
12912 tcg_temp_free_i32(fp1);
12913 gen_store_fpr32(ctx, fp2, fd);
12914 tcg_temp_free_i32(fp2);
12916 break;
12917 case OPC_NMADD_D:
12918 check_cop1x(ctx);
12919 check_cp1_registers(ctx, fd | fs | ft | fr);
12921 TCGv_i64 fp0 = tcg_temp_new_i64();
12922 TCGv_i64 fp1 = tcg_temp_new_i64();
12923 TCGv_i64 fp2 = tcg_temp_new_i64();
12925 gen_load_fpr64(ctx, fp0, fs);
12926 gen_load_fpr64(ctx, fp1, ft);
12927 gen_load_fpr64(ctx, fp2, fr);
12928 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12929 tcg_temp_free_i64(fp0);
12930 tcg_temp_free_i64(fp1);
12931 gen_store_fpr64(ctx, fp2, fd);
12932 tcg_temp_free_i64(fp2);
12934 break;
12935 case OPC_NMADD_PS:
12936 check_ps(ctx);
12938 TCGv_i64 fp0 = tcg_temp_new_i64();
12939 TCGv_i64 fp1 = tcg_temp_new_i64();
12940 TCGv_i64 fp2 = tcg_temp_new_i64();
12942 gen_load_fpr64(ctx, fp0, fs);
12943 gen_load_fpr64(ctx, fp1, ft);
12944 gen_load_fpr64(ctx, fp2, fr);
12945 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12946 tcg_temp_free_i64(fp0);
12947 tcg_temp_free_i64(fp1);
12948 gen_store_fpr64(ctx, fp2, fd);
12949 tcg_temp_free_i64(fp2);
12951 break;
12952 case OPC_NMSUB_S:
12953 check_cop1x(ctx);
12955 TCGv_i32 fp0 = tcg_temp_new_i32();
12956 TCGv_i32 fp1 = tcg_temp_new_i32();
12957 TCGv_i32 fp2 = tcg_temp_new_i32();
12959 gen_load_fpr32(ctx, fp0, fs);
12960 gen_load_fpr32(ctx, fp1, ft);
12961 gen_load_fpr32(ctx, fp2, fr);
12962 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12963 tcg_temp_free_i32(fp0);
12964 tcg_temp_free_i32(fp1);
12965 gen_store_fpr32(ctx, fp2, fd);
12966 tcg_temp_free_i32(fp2);
12968 break;
12969 case OPC_NMSUB_D:
12970 check_cop1x(ctx);
12971 check_cp1_registers(ctx, fd | fs | ft | fr);
12973 TCGv_i64 fp0 = tcg_temp_new_i64();
12974 TCGv_i64 fp1 = tcg_temp_new_i64();
12975 TCGv_i64 fp2 = tcg_temp_new_i64();
12977 gen_load_fpr64(ctx, fp0, fs);
12978 gen_load_fpr64(ctx, fp1, ft);
12979 gen_load_fpr64(ctx, fp2, fr);
12980 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12981 tcg_temp_free_i64(fp0);
12982 tcg_temp_free_i64(fp1);
12983 gen_store_fpr64(ctx, fp2, fd);
12984 tcg_temp_free_i64(fp2);
12986 break;
12987 case OPC_NMSUB_PS:
12988 check_ps(ctx);
12990 TCGv_i64 fp0 = tcg_temp_new_i64();
12991 TCGv_i64 fp1 = tcg_temp_new_i64();
12992 TCGv_i64 fp2 = tcg_temp_new_i64();
12994 gen_load_fpr64(ctx, fp0, fs);
12995 gen_load_fpr64(ctx, fp1, ft);
12996 gen_load_fpr64(ctx, fp2, fr);
12997 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12998 tcg_temp_free_i64(fp0);
12999 tcg_temp_free_i64(fp1);
13000 gen_store_fpr64(ctx, fp2, fd);
13001 tcg_temp_free_i64(fp2);
13003 break;
13004 default:
13005 MIPS_INVAL("flt3_arith");
13006 generate_exception_end(ctx, EXCP_RI);
13007 return;
13011 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13013 TCGv t0;
13015 #if !defined(CONFIG_USER_ONLY)
13017 * The Linux kernel will emulate rdhwr if it's not supported natively.
13018 * Therefore only check the ISA in system mode.
13020 check_insn(ctx, ISA_MIPS32R2);
13021 #endif
13022 t0 = tcg_temp_new();
13024 switch (rd) {
13025 case 0:
13026 gen_helper_rdhwr_cpunum(t0, cpu_env);
13027 gen_store_gpr(t0, rt);
13028 break;
13029 case 1:
13030 gen_helper_rdhwr_synci_step(t0, cpu_env);
13031 gen_store_gpr(t0, rt);
13032 break;
13033 case 2:
13034 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13035 gen_io_start();
13037 gen_helper_rdhwr_cc(t0, cpu_env);
13038 gen_store_gpr(t0, rt);
13040 * Break the TB to be able to take timer interrupts immediately
13041 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13042 * we break completely out of translated code.
13044 gen_save_pc(ctx->base.pc_next + 4);
13045 ctx->base.is_jmp = DISAS_EXIT;
13046 break;
13047 case 3:
13048 gen_helper_rdhwr_ccres(t0, cpu_env);
13049 gen_store_gpr(t0, rt);
13050 break;
13051 case 4:
13052 check_insn(ctx, ISA_MIPS32R6);
13053 if (sel != 0) {
13055 * Performance counter registers are not implemented other than
13056 * control register 0.
13058 generate_exception(ctx, EXCP_RI);
13060 gen_helper_rdhwr_performance(t0, cpu_env);
13061 gen_store_gpr(t0, rt);
13062 break;
13063 case 5:
13064 check_insn(ctx, ISA_MIPS32R6);
13065 gen_helper_rdhwr_xnp(t0, cpu_env);
13066 gen_store_gpr(t0, rt);
13067 break;
13068 case 29:
13069 #if defined(CONFIG_USER_ONLY)
13070 tcg_gen_ld_tl(t0, cpu_env,
13071 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13072 gen_store_gpr(t0, rt);
13073 break;
13074 #else
13075 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13076 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13077 tcg_gen_ld_tl(t0, cpu_env,
13078 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13079 gen_store_gpr(t0, rt);
13080 } else {
13081 generate_exception_end(ctx, EXCP_RI);
13083 break;
13084 #endif
13085 default: /* Invalid */
13086 MIPS_INVAL("rdhwr");
13087 generate_exception_end(ctx, EXCP_RI);
13088 break;
13090 tcg_temp_free(t0);
13093 static inline void clear_branch_hflags(DisasContext *ctx)
13095 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13096 if (ctx->base.is_jmp == DISAS_NEXT) {
13097 save_cpu_state(ctx, 0);
13098 } else {
13100 * It is not safe to save ctx->hflags as hflags may be changed
13101 * in execution time by the instruction in delay / forbidden slot.
13103 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13107 static void gen_branch(DisasContext *ctx, int insn_bytes)
13109 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13110 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13111 /* Branches completion */
13112 clear_branch_hflags(ctx);
13113 ctx->base.is_jmp = DISAS_NORETURN;
13114 /* FIXME: Need to clear can_do_io. */
13115 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13116 case MIPS_HFLAG_FBNSLOT:
13117 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13118 break;
13119 case MIPS_HFLAG_B:
13120 /* unconditional branch */
13121 if (proc_hflags & MIPS_HFLAG_BX) {
13122 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13124 gen_goto_tb(ctx, 0, ctx->btarget);
13125 break;
13126 case MIPS_HFLAG_BL:
13127 /* blikely taken case */
13128 gen_goto_tb(ctx, 0, ctx->btarget);
13129 break;
13130 case MIPS_HFLAG_BC:
13131 /* Conditional branch */
13133 TCGLabel *l1 = gen_new_label();
13135 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13136 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13137 gen_set_label(l1);
13138 gen_goto_tb(ctx, 0, ctx->btarget);
13140 break;
13141 case MIPS_HFLAG_BR:
13142 /* unconditional branch to register */
13143 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13144 TCGv t0 = tcg_temp_new();
13145 TCGv_i32 t1 = tcg_temp_new_i32();
13147 tcg_gen_andi_tl(t0, btarget, 0x1);
13148 tcg_gen_trunc_tl_i32(t1, t0);
13149 tcg_temp_free(t0);
13150 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13151 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13152 tcg_gen_or_i32(hflags, hflags, t1);
13153 tcg_temp_free_i32(t1);
13155 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13156 } else {
13157 tcg_gen_mov_tl(cpu_PC, btarget);
13159 if (ctx->base.singlestep_enabled) {
13160 save_cpu_state(ctx, 0);
13161 gen_helper_raise_exception_debug(cpu_env);
13163 tcg_gen_lookup_and_goto_ptr();
13164 break;
13165 default:
13166 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13167 abort();
13172 /* Compact Branches */
13173 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13174 int rs, int rt, int32_t offset)
13176 int bcond_compute = 0;
13177 TCGv t0 = tcg_temp_new();
13178 TCGv t1 = tcg_temp_new();
13179 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13181 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13182 #ifdef MIPS_DEBUG_DISAS
13183 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13184 "\n", ctx->base.pc_next);
13185 #endif
13186 generate_exception_end(ctx, EXCP_RI);
13187 goto out;
13190 /* Load needed operands and calculate btarget */
13191 switch (opc) {
13192 /* compact branch */
13193 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13194 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13195 gen_load_gpr(t0, rs);
13196 gen_load_gpr(t1, rt);
13197 bcond_compute = 1;
13198 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13199 if (rs <= rt && rs == 0) {
13200 /* OPC_BEQZALC, OPC_BNEZALC */
13201 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13203 break;
13204 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13205 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13206 gen_load_gpr(t0, rs);
13207 gen_load_gpr(t1, rt);
13208 bcond_compute = 1;
13209 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13210 break;
13211 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13212 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13213 if (rs == 0 || rs == rt) {
13214 /* OPC_BLEZALC, OPC_BGEZALC */
13215 /* OPC_BGTZALC, OPC_BLTZALC */
13216 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13218 gen_load_gpr(t0, rs);
13219 gen_load_gpr(t1, rt);
13220 bcond_compute = 1;
13221 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13222 break;
13223 case OPC_BC:
13224 case OPC_BALC:
13225 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13226 break;
13227 case OPC_BEQZC:
13228 case OPC_BNEZC:
13229 if (rs != 0) {
13230 /* OPC_BEQZC, OPC_BNEZC */
13231 gen_load_gpr(t0, rs);
13232 bcond_compute = 1;
13233 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13234 } else {
13235 /* OPC_JIC, OPC_JIALC */
13236 TCGv tbase = tcg_temp_new();
13237 TCGv toffset = tcg_temp_new();
13239 gen_load_gpr(tbase, rt);
13240 tcg_gen_movi_tl(toffset, offset);
13241 gen_op_addr_add(ctx, btarget, tbase, toffset);
13242 tcg_temp_free(tbase);
13243 tcg_temp_free(toffset);
13245 break;
13246 default:
13247 MIPS_INVAL("Compact branch/jump");
13248 generate_exception_end(ctx, EXCP_RI);
13249 goto out;
13252 if (bcond_compute == 0) {
13253 /* Uncoditional compact branch */
13254 switch (opc) {
13255 case OPC_JIALC:
13256 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13257 /* Fallthrough */
13258 case OPC_JIC:
13259 ctx->hflags |= MIPS_HFLAG_BR;
13260 break;
13261 case OPC_BALC:
13262 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13263 /* Fallthrough */
13264 case OPC_BC:
13265 ctx->hflags |= MIPS_HFLAG_B;
13266 break;
13267 default:
13268 MIPS_INVAL("Compact branch/jump");
13269 generate_exception_end(ctx, EXCP_RI);
13270 goto out;
13273 /* Generating branch here as compact branches don't have delay slot */
13274 gen_branch(ctx, 4);
13275 } else {
13276 /* Conditional compact branch */
13277 TCGLabel *fs = gen_new_label();
13278 save_cpu_state(ctx, 0);
13280 switch (opc) {
13281 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13282 if (rs == 0 && rt != 0) {
13283 /* OPC_BLEZALC */
13284 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13285 } else if (rs != 0 && rt != 0 && rs == rt) {
13286 /* OPC_BGEZALC */
13287 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13288 } else {
13289 /* OPC_BGEUC */
13290 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13292 break;
13293 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13294 if (rs == 0 && rt != 0) {
13295 /* OPC_BGTZALC */
13296 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13297 } else if (rs != 0 && rt != 0 && rs == rt) {
13298 /* OPC_BLTZALC */
13299 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13300 } else {
13301 /* OPC_BLTUC */
13302 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13304 break;
13305 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13306 if (rs == 0 && rt != 0) {
13307 /* OPC_BLEZC */
13308 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13309 } else if (rs != 0 && rt != 0 && rs == rt) {
13310 /* OPC_BGEZC */
13311 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13312 } else {
13313 /* OPC_BGEC */
13314 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13316 break;
13317 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13318 if (rs == 0 && rt != 0) {
13319 /* OPC_BGTZC */
13320 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13321 } else if (rs != 0 && rt != 0 && rs == rt) {
13322 /* OPC_BLTZC */
13323 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13324 } else {
13325 /* OPC_BLTC */
13326 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13328 break;
13329 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13330 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13331 if (rs >= rt) {
13332 /* OPC_BOVC, OPC_BNVC */
13333 TCGv t2 = tcg_temp_new();
13334 TCGv t3 = tcg_temp_new();
13335 TCGv t4 = tcg_temp_new();
13336 TCGv input_overflow = tcg_temp_new();
13338 gen_load_gpr(t0, rs);
13339 gen_load_gpr(t1, rt);
13340 tcg_gen_ext32s_tl(t2, t0);
13341 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13342 tcg_gen_ext32s_tl(t3, t1);
13343 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13344 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13346 tcg_gen_add_tl(t4, t2, t3);
13347 tcg_gen_ext32s_tl(t4, t4);
13348 tcg_gen_xor_tl(t2, t2, t3);
13349 tcg_gen_xor_tl(t3, t4, t3);
13350 tcg_gen_andc_tl(t2, t3, t2);
13351 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13352 tcg_gen_or_tl(t4, t4, input_overflow);
13353 if (opc == OPC_BOVC) {
13354 /* OPC_BOVC */
13355 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13356 } else {
13357 /* OPC_BNVC */
13358 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13360 tcg_temp_free(input_overflow);
13361 tcg_temp_free(t4);
13362 tcg_temp_free(t3);
13363 tcg_temp_free(t2);
13364 } else if (rs < rt && rs == 0) {
13365 /* OPC_BEQZALC, OPC_BNEZALC */
13366 if (opc == OPC_BEQZALC) {
13367 /* OPC_BEQZALC */
13368 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13369 } else {
13370 /* OPC_BNEZALC */
13371 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13373 } else {
13374 /* OPC_BEQC, OPC_BNEC */
13375 if (opc == OPC_BEQC) {
13376 /* OPC_BEQC */
13377 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13378 } else {
13379 /* OPC_BNEC */
13380 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13383 break;
13384 case OPC_BEQZC:
13385 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13386 break;
13387 case OPC_BNEZC:
13388 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13389 break;
13390 default:
13391 MIPS_INVAL("Compact conditional branch/jump");
13392 generate_exception_end(ctx, EXCP_RI);
13393 goto out;
13396 /* Generating branch here as compact branches don't have delay slot */
13397 gen_goto_tb(ctx, 1, ctx->btarget);
13398 gen_set_label(fs);
13400 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13403 out:
13404 tcg_temp_free(t0);
13405 tcg_temp_free(t1);
13408 /* ISA extensions (ASEs) */
13409 /* MIPS16 extension to MIPS32 */
13411 /* MIPS16 major opcodes */
13412 enum {
13413 M16_OPC_ADDIUSP = 0x00,
13414 M16_OPC_ADDIUPC = 0x01,
13415 M16_OPC_B = 0x02,
13416 M16_OPC_JAL = 0x03,
13417 M16_OPC_BEQZ = 0x04,
13418 M16_OPC_BNEQZ = 0x05,
13419 M16_OPC_SHIFT = 0x06,
13420 M16_OPC_LD = 0x07,
13421 M16_OPC_RRIA = 0x08,
13422 M16_OPC_ADDIU8 = 0x09,
13423 M16_OPC_SLTI = 0x0a,
13424 M16_OPC_SLTIU = 0x0b,
13425 M16_OPC_I8 = 0x0c,
13426 M16_OPC_LI = 0x0d,
13427 M16_OPC_CMPI = 0x0e,
13428 M16_OPC_SD = 0x0f,
13429 M16_OPC_LB = 0x10,
13430 M16_OPC_LH = 0x11,
13431 M16_OPC_LWSP = 0x12,
13432 M16_OPC_LW = 0x13,
13433 M16_OPC_LBU = 0x14,
13434 M16_OPC_LHU = 0x15,
13435 M16_OPC_LWPC = 0x16,
13436 M16_OPC_LWU = 0x17,
13437 M16_OPC_SB = 0x18,
13438 M16_OPC_SH = 0x19,
13439 M16_OPC_SWSP = 0x1a,
13440 M16_OPC_SW = 0x1b,
13441 M16_OPC_RRR = 0x1c,
13442 M16_OPC_RR = 0x1d,
13443 M16_OPC_EXTEND = 0x1e,
13444 M16_OPC_I64 = 0x1f
13447 /* I8 funct field */
13448 enum {
13449 I8_BTEQZ = 0x0,
13450 I8_BTNEZ = 0x1,
13451 I8_SWRASP = 0x2,
13452 I8_ADJSP = 0x3,
13453 I8_SVRS = 0x4,
13454 I8_MOV32R = 0x5,
13455 I8_MOVR32 = 0x7
13458 /* RRR f field */
13459 enum {
13460 RRR_DADDU = 0x0,
13461 RRR_ADDU = 0x1,
13462 RRR_DSUBU = 0x2,
13463 RRR_SUBU = 0x3
13466 /* RR funct field */
13467 enum {
13468 RR_JR = 0x00,
13469 RR_SDBBP = 0x01,
13470 RR_SLT = 0x02,
13471 RR_SLTU = 0x03,
13472 RR_SLLV = 0x04,
13473 RR_BREAK = 0x05,
13474 RR_SRLV = 0x06,
13475 RR_SRAV = 0x07,
13476 RR_DSRL = 0x08,
13477 RR_CMP = 0x0a,
13478 RR_NEG = 0x0b,
13479 RR_AND = 0x0c,
13480 RR_OR = 0x0d,
13481 RR_XOR = 0x0e,
13482 RR_NOT = 0x0f,
13483 RR_MFHI = 0x10,
13484 RR_CNVT = 0x11,
13485 RR_MFLO = 0x12,
13486 RR_DSRA = 0x13,
13487 RR_DSLLV = 0x14,
13488 RR_DSRLV = 0x16,
13489 RR_DSRAV = 0x17,
13490 RR_MULT = 0x18,
13491 RR_MULTU = 0x19,
13492 RR_DIV = 0x1a,
13493 RR_DIVU = 0x1b,
13494 RR_DMULT = 0x1c,
13495 RR_DMULTU = 0x1d,
13496 RR_DDIV = 0x1e,
13497 RR_DDIVU = 0x1f
13500 /* I64 funct field */
13501 enum {
13502 I64_LDSP = 0x0,
13503 I64_SDSP = 0x1,
13504 I64_SDRASP = 0x2,
13505 I64_DADJSP = 0x3,
13506 I64_LDPC = 0x4,
13507 I64_DADDIU5 = 0x5,
13508 I64_DADDIUPC = 0x6,
13509 I64_DADDIUSP = 0x7
13512 /* RR ry field for CNVT */
13513 enum {
13514 RR_RY_CNVT_ZEB = 0x0,
13515 RR_RY_CNVT_ZEH = 0x1,
13516 RR_RY_CNVT_ZEW = 0x2,
13517 RR_RY_CNVT_SEB = 0x4,
13518 RR_RY_CNVT_SEH = 0x5,
13519 RR_RY_CNVT_SEW = 0x6,
13522 static int xlat(int r)
13524 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13526 return map[r];
13529 static void gen_mips16_save(DisasContext *ctx,
13530 int xsregs, int aregs,
13531 int do_ra, int do_s0, int do_s1,
13532 int framesize)
13534 TCGv t0 = tcg_temp_new();
13535 TCGv t1 = tcg_temp_new();
13536 TCGv t2 = tcg_temp_new();
13537 int args, astatic;
13539 switch (aregs) {
13540 case 0:
13541 case 1:
13542 case 2:
13543 case 3:
13544 case 11:
13545 args = 0;
13546 break;
13547 case 4:
13548 case 5:
13549 case 6:
13550 case 7:
13551 args = 1;
13552 break;
13553 case 8:
13554 case 9:
13555 case 10:
13556 args = 2;
13557 break;
13558 case 12:
13559 case 13:
13560 args = 3;
13561 break;
13562 case 14:
13563 args = 4;
13564 break;
13565 default:
13566 generate_exception_end(ctx, EXCP_RI);
13567 return;
13570 switch (args) {
13571 case 4:
13572 gen_base_offset_addr(ctx, t0, 29, 12);
13573 gen_load_gpr(t1, 7);
13574 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13575 /* Fall through */
13576 case 3:
13577 gen_base_offset_addr(ctx, t0, 29, 8);
13578 gen_load_gpr(t1, 6);
13579 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13580 /* Fall through */
13581 case 2:
13582 gen_base_offset_addr(ctx, t0, 29, 4);
13583 gen_load_gpr(t1, 5);
13584 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13585 /* Fall through */
13586 case 1:
13587 gen_base_offset_addr(ctx, t0, 29, 0);
13588 gen_load_gpr(t1, 4);
13589 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13592 gen_load_gpr(t0, 29);
13594 #define DECR_AND_STORE(reg) do { \
13595 tcg_gen_movi_tl(t2, -4); \
13596 gen_op_addr_add(ctx, t0, t0, t2); \
13597 gen_load_gpr(t1, reg); \
13598 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13599 } while (0)
13601 if (do_ra) {
13602 DECR_AND_STORE(31);
13605 switch (xsregs) {
13606 case 7:
13607 DECR_AND_STORE(30);
13608 /* Fall through */
13609 case 6:
13610 DECR_AND_STORE(23);
13611 /* Fall through */
13612 case 5:
13613 DECR_AND_STORE(22);
13614 /* Fall through */
13615 case 4:
13616 DECR_AND_STORE(21);
13617 /* Fall through */
13618 case 3:
13619 DECR_AND_STORE(20);
13620 /* Fall through */
13621 case 2:
13622 DECR_AND_STORE(19);
13623 /* Fall through */
13624 case 1:
13625 DECR_AND_STORE(18);
13628 if (do_s1) {
13629 DECR_AND_STORE(17);
13631 if (do_s0) {
13632 DECR_AND_STORE(16);
13635 switch (aregs) {
13636 case 0:
13637 case 4:
13638 case 8:
13639 case 12:
13640 case 14:
13641 astatic = 0;
13642 break;
13643 case 1:
13644 case 5:
13645 case 9:
13646 case 13:
13647 astatic = 1;
13648 break;
13649 case 2:
13650 case 6:
13651 case 10:
13652 astatic = 2;
13653 break;
13654 case 3:
13655 case 7:
13656 astatic = 3;
13657 break;
13658 case 11:
13659 astatic = 4;
13660 break;
13661 default:
13662 generate_exception_end(ctx, EXCP_RI);
13663 return;
13666 if (astatic > 0) {
13667 DECR_AND_STORE(7);
13668 if (astatic > 1) {
13669 DECR_AND_STORE(6);
13670 if (astatic > 2) {
13671 DECR_AND_STORE(5);
13672 if (astatic > 3) {
13673 DECR_AND_STORE(4);
13678 #undef DECR_AND_STORE
13680 tcg_gen_movi_tl(t2, -framesize);
13681 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13682 tcg_temp_free(t0);
13683 tcg_temp_free(t1);
13684 tcg_temp_free(t2);
13687 static void gen_mips16_restore(DisasContext *ctx,
13688 int xsregs, int aregs,
13689 int do_ra, int do_s0, int do_s1,
13690 int framesize)
13692 int astatic;
13693 TCGv t0 = tcg_temp_new();
13694 TCGv t1 = tcg_temp_new();
13695 TCGv t2 = tcg_temp_new();
13697 tcg_gen_movi_tl(t2, framesize);
13698 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13700 #define DECR_AND_LOAD(reg) do { \
13701 tcg_gen_movi_tl(t2, -4); \
13702 gen_op_addr_add(ctx, t0, t0, t2); \
13703 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13704 gen_store_gpr(t1, reg); \
13705 } while (0)
13707 if (do_ra) {
13708 DECR_AND_LOAD(31);
13711 switch (xsregs) {
13712 case 7:
13713 DECR_AND_LOAD(30);
13714 /* Fall through */
13715 case 6:
13716 DECR_AND_LOAD(23);
13717 /* Fall through */
13718 case 5:
13719 DECR_AND_LOAD(22);
13720 /* Fall through */
13721 case 4:
13722 DECR_AND_LOAD(21);
13723 /* Fall through */
13724 case 3:
13725 DECR_AND_LOAD(20);
13726 /* Fall through */
13727 case 2:
13728 DECR_AND_LOAD(19);
13729 /* Fall through */
13730 case 1:
13731 DECR_AND_LOAD(18);
13734 if (do_s1) {
13735 DECR_AND_LOAD(17);
13737 if (do_s0) {
13738 DECR_AND_LOAD(16);
13741 switch (aregs) {
13742 case 0:
13743 case 4:
13744 case 8:
13745 case 12:
13746 case 14:
13747 astatic = 0;
13748 break;
13749 case 1:
13750 case 5:
13751 case 9:
13752 case 13:
13753 astatic = 1;
13754 break;
13755 case 2:
13756 case 6:
13757 case 10:
13758 astatic = 2;
13759 break;
13760 case 3:
13761 case 7:
13762 astatic = 3;
13763 break;
13764 case 11:
13765 astatic = 4;
13766 break;
13767 default:
13768 generate_exception_end(ctx, EXCP_RI);
13769 return;
13772 if (astatic > 0) {
13773 DECR_AND_LOAD(7);
13774 if (astatic > 1) {
13775 DECR_AND_LOAD(6);
13776 if (astatic > 2) {
13777 DECR_AND_LOAD(5);
13778 if (astatic > 3) {
13779 DECR_AND_LOAD(4);
13784 #undef DECR_AND_LOAD
13786 tcg_gen_movi_tl(t2, framesize);
13787 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13788 tcg_temp_free(t0);
13789 tcg_temp_free(t1);
13790 tcg_temp_free(t2);
13793 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
13794 int is_64_bit, int extended)
13796 TCGv t0;
13798 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13799 generate_exception_end(ctx, EXCP_RI);
13800 return;
13803 t0 = tcg_temp_new();
13805 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13806 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13807 if (!is_64_bit) {
13808 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13811 tcg_temp_free(t0);
13814 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13815 int16_t offset)
13817 TCGv_i32 t0 = tcg_const_i32(op);
13818 TCGv t1 = tcg_temp_new();
13819 gen_base_offset_addr(ctx, t1, base, offset);
13820 gen_helper_cache(cpu_env, t1, t0);
13823 #if defined(TARGET_MIPS64)
13824 static void decode_i64_mips16(DisasContext *ctx,
13825 int ry, int funct, int16_t offset,
13826 int extended)
13828 switch (funct) {
13829 case I64_LDSP:
13830 check_insn(ctx, ISA_MIPS3);
13831 check_mips_64(ctx);
13832 offset = extended ? offset : offset << 3;
13833 gen_ld(ctx, OPC_LD, ry, 29, offset);
13834 break;
13835 case I64_SDSP:
13836 check_insn(ctx, ISA_MIPS3);
13837 check_mips_64(ctx);
13838 offset = extended ? offset : offset << 3;
13839 gen_st(ctx, OPC_SD, ry, 29, offset);
13840 break;
13841 case I64_SDRASP:
13842 check_insn(ctx, ISA_MIPS3);
13843 check_mips_64(ctx);
13844 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13845 gen_st(ctx, OPC_SD, 31, 29, offset);
13846 break;
13847 case I64_DADJSP:
13848 check_insn(ctx, ISA_MIPS3);
13849 check_mips_64(ctx);
13850 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13851 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13852 break;
13853 case I64_LDPC:
13854 check_insn(ctx, ISA_MIPS3);
13855 check_mips_64(ctx);
13856 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13857 generate_exception_end(ctx, EXCP_RI);
13858 } else {
13859 offset = extended ? offset : offset << 3;
13860 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13862 break;
13863 case I64_DADDIU5:
13864 check_insn(ctx, ISA_MIPS3);
13865 check_mips_64(ctx);
13866 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13867 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13868 break;
13869 case I64_DADDIUPC:
13870 check_insn(ctx, ISA_MIPS3);
13871 check_mips_64(ctx);
13872 offset = extended ? offset : offset << 2;
13873 gen_addiupc(ctx, ry, offset, 1, extended);
13874 break;
13875 case I64_DADDIUSP:
13876 check_insn(ctx, ISA_MIPS3);
13877 check_mips_64(ctx);
13878 offset = extended ? offset : offset << 2;
13879 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13880 break;
13883 #endif
13885 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13887 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13888 int op, rx, ry, funct, sa;
13889 int16_t imm, offset;
13891 ctx->opcode = (ctx->opcode << 16) | extend;
13892 op = (ctx->opcode >> 11) & 0x1f;
13893 sa = (ctx->opcode >> 22) & 0x1f;
13894 funct = (ctx->opcode >> 8) & 0x7;
13895 rx = xlat((ctx->opcode >> 8) & 0x7);
13896 ry = xlat((ctx->opcode >> 5) & 0x7);
13897 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13898 | ((ctx->opcode >> 21) & 0x3f) << 5
13899 | (ctx->opcode & 0x1f));
13902 * The extended opcodes cleverly reuse the opcodes from their 16-bit
13903 * counterparts.
13905 switch (op) {
13906 case M16_OPC_ADDIUSP:
13907 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13908 break;
13909 case M16_OPC_ADDIUPC:
13910 gen_addiupc(ctx, rx, imm, 0, 1);
13911 break;
13912 case M16_OPC_B:
13913 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13914 /* No delay slot, so just process as a normal instruction */
13915 break;
13916 case M16_OPC_BEQZ:
13917 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13918 /* No delay slot, so just process as a normal instruction */
13919 break;
13920 case M16_OPC_BNEQZ:
13921 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13922 /* No delay slot, so just process as a normal instruction */
13923 break;
13924 case M16_OPC_SHIFT:
13925 switch (ctx->opcode & 0x3) {
13926 case 0x0:
13927 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13928 break;
13929 case 0x1:
13930 #if defined(TARGET_MIPS64)
13931 check_mips_64(ctx);
13932 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13933 #else
13934 generate_exception_end(ctx, EXCP_RI);
13935 #endif
13936 break;
13937 case 0x2:
13938 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13939 break;
13940 case 0x3:
13941 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13942 break;
13944 break;
13945 #if defined(TARGET_MIPS64)
13946 case M16_OPC_LD:
13947 check_insn(ctx, ISA_MIPS3);
13948 check_mips_64(ctx);
13949 gen_ld(ctx, OPC_LD, ry, rx, offset);
13950 break;
13951 #endif
13952 case M16_OPC_RRIA:
13953 imm = ctx->opcode & 0xf;
13954 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13955 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13956 imm = (int16_t) (imm << 1) >> 1;
13957 if ((ctx->opcode >> 4) & 0x1) {
13958 #if defined(TARGET_MIPS64)
13959 check_mips_64(ctx);
13960 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13961 #else
13962 generate_exception_end(ctx, EXCP_RI);
13963 #endif
13964 } else {
13965 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13967 break;
13968 case M16_OPC_ADDIU8:
13969 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13970 break;
13971 case M16_OPC_SLTI:
13972 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13973 break;
13974 case M16_OPC_SLTIU:
13975 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13976 break;
13977 case M16_OPC_I8:
13978 switch (funct) {
13979 case I8_BTEQZ:
13980 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13981 break;
13982 case I8_BTNEZ:
13983 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13984 break;
13985 case I8_SWRASP:
13986 gen_st(ctx, OPC_SW, 31, 29, imm);
13987 break;
13988 case I8_ADJSP:
13989 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13990 break;
13991 case I8_SVRS:
13992 check_insn(ctx, ISA_MIPS32);
13994 int xsregs = (ctx->opcode >> 24) & 0x7;
13995 int aregs = (ctx->opcode >> 16) & 0xf;
13996 int do_ra = (ctx->opcode >> 6) & 0x1;
13997 int do_s0 = (ctx->opcode >> 5) & 0x1;
13998 int do_s1 = (ctx->opcode >> 4) & 0x1;
13999 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14000 | (ctx->opcode & 0xf)) << 3;
14002 if (ctx->opcode & (1 << 7)) {
14003 gen_mips16_save(ctx, xsregs, aregs,
14004 do_ra, do_s0, do_s1,
14005 framesize);
14006 } else {
14007 gen_mips16_restore(ctx, xsregs, aregs,
14008 do_ra, do_s0, do_s1,
14009 framesize);
14012 break;
14013 default:
14014 generate_exception_end(ctx, EXCP_RI);
14015 break;
14017 break;
14018 case M16_OPC_LI:
14019 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14020 break;
14021 case M16_OPC_CMPI:
14022 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14023 break;
14024 #if defined(TARGET_MIPS64)
14025 case M16_OPC_SD:
14026 check_insn(ctx, ISA_MIPS3);
14027 check_mips_64(ctx);
14028 gen_st(ctx, OPC_SD, ry, rx, offset);
14029 break;
14030 #endif
14031 case M16_OPC_LB:
14032 gen_ld(ctx, OPC_LB, ry, rx, offset);
14033 break;
14034 case M16_OPC_LH:
14035 gen_ld(ctx, OPC_LH, ry, rx, offset);
14036 break;
14037 case M16_OPC_LWSP:
14038 gen_ld(ctx, OPC_LW, rx, 29, offset);
14039 break;
14040 case M16_OPC_LW:
14041 gen_ld(ctx, OPC_LW, ry, rx, offset);
14042 break;
14043 case M16_OPC_LBU:
14044 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14045 break;
14046 case M16_OPC_LHU:
14047 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14048 break;
14049 case M16_OPC_LWPC:
14050 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14051 break;
14052 #if defined(TARGET_MIPS64)
14053 case M16_OPC_LWU:
14054 check_insn(ctx, ISA_MIPS3);
14055 check_mips_64(ctx);
14056 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14057 break;
14058 #endif
14059 case M16_OPC_SB:
14060 gen_st(ctx, OPC_SB, ry, rx, offset);
14061 break;
14062 case M16_OPC_SH:
14063 gen_st(ctx, OPC_SH, ry, rx, offset);
14064 break;
14065 case M16_OPC_SWSP:
14066 gen_st(ctx, OPC_SW, rx, 29, offset);
14067 break;
14068 case M16_OPC_SW:
14069 gen_st(ctx, OPC_SW, ry, rx, offset);
14070 break;
14071 #if defined(TARGET_MIPS64)
14072 case M16_OPC_I64:
14073 decode_i64_mips16(ctx, ry, funct, offset, 1);
14074 break;
14075 #endif
14076 default:
14077 generate_exception_end(ctx, EXCP_RI);
14078 break;
14081 return 4;
14084 static inline bool is_uhi(int sdbbp_code)
14086 #ifdef CONFIG_USER_ONLY
14087 return false;
14088 #else
14089 return semihosting_enabled() && sdbbp_code == 1;
14090 #endif
14093 #ifdef CONFIG_USER_ONLY
14094 /* The above should dead-code away any calls to this..*/
14095 static inline void gen_helper_do_semihosting(void *env)
14097 g_assert_not_reached();
14099 #endif
14101 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14103 int rx, ry;
14104 int sa;
14105 int op, cnvt_op, op1, offset;
14106 int funct;
14107 int n_bytes;
14109 op = (ctx->opcode >> 11) & 0x1f;
14110 sa = (ctx->opcode >> 2) & 0x7;
14111 sa = sa == 0 ? 8 : sa;
14112 rx = xlat((ctx->opcode >> 8) & 0x7);
14113 cnvt_op = (ctx->opcode >> 5) & 0x7;
14114 ry = xlat((ctx->opcode >> 5) & 0x7);
14115 op1 = offset = ctx->opcode & 0x1f;
14117 n_bytes = 2;
14119 switch (op) {
14120 case M16_OPC_ADDIUSP:
14122 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14124 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14126 break;
14127 case M16_OPC_ADDIUPC:
14128 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14129 break;
14130 case M16_OPC_B:
14131 offset = (ctx->opcode & 0x7ff) << 1;
14132 offset = (int16_t)(offset << 4) >> 4;
14133 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14134 /* No delay slot, so just process as a normal instruction */
14135 break;
14136 case M16_OPC_JAL:
14137 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14138 offset = (((ctx->opcode & 0x1f) << 21)
14139 | ((ctx->opcode >> 5) & 0x1f) << 16
14140 | offset) << 2;
14141 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14142 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14143 n_bytes = 4;
14144 break;
14145 case M16_OPC_BEQZ:
14146 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14147 ((int8_t)ctx->opcode) << 1, 0);
14148 /* No delay slot, so just process as a normal instruction */
14149 break;
14150 case M16_OPC_BNEQZ:
14151 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14152 ((int8_t)ctx->opcode) << 1, 0);
14153 /* No delay slot, so just process as a normal instruction */
14154 break;
14155 case M16_OPC_SHIFT:
14156 switch (ctx->opcode & 0x3) {
14157 case 0x0:
14158 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14159 break;
14160 case 0x1:
14161 #if defined(TARGET_MIPS64)
14162 check_insn(ctx, ISA_MIPS3);
14163 check_mips_64(ctx);
14164 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14165 #else
14166 generate_exception_end(ctx, EXCP_RI);
14167 #endif
14168 break;
14169 case 0x2:
14170 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14171 break;
14172 case 0x3:
14173 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14174 break;
14176 break;
14177 #if defined(TARGET_MIPS64)
14178 case M16_OPC_LD:
14179 check_insn(ctx, ISA_MIPS3);
14180 check_mips_64(ctx);
14181 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14182 break;
14183 #endif
14184 case M16_OPC_RRIA:
14186 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14188 if ((ctx->opcode >> 4) & 1) {
14189 #if defined(TARGET_MIPS64)
14190 check_insn(ctx, ISA_MIPS3);
14191 check_mips_64(ctx);
14192 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14193 #else
14194 generate_exception_end(ctx, EXCP_RI);
14195 #endif
14196 } else {
14197 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14200 break;
14201 case M16_OPC_ADDIU8:
14203 int16_t imm = (int8_t) ctx->opcode;
14205 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14207 break;
14208 case M16_OPC_SLTI:
14210 int16_t imm = (uint8_t) ctx->opcode;
14211 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14213 break;
14214 case M16_OPC_SLTIU:
14216 int16_t imm = (uint8_t) ctx->opcode;
14217 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14219 break;
14220 case M16_OPC_I8:
14222 int reg32;
14224 funct = (ctx->opcode >> 8) & 0x7;
14225 switch (funct) {
14226 case I8_BTEQZ:
14227 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14228 ((int8_t)ctx->opcode) << 1, 0);
14229 break;
14230 case I8_BTNEZ:
14231 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14232 ((int8_t)ctx->opcode) << 1, 0);
14233 break;
14234 case I8_SWRASP:
14235 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14236 break;
14237 case I8_ADJSP:
14238 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14239 ((int8_t)ctx->opcode) << 3);
14240 break;
14241 case I8_SVRS:
14242 check_insn(ctx, ISA_MIPS32);
14244 int do_ra = ctx->opcode & (1 << 6);
14245 int do_s0 = ctx->opcode & (1 << 5);
14246 int do_s1 = ctx->opcode & (1 << 4);
14247 int framesize = ctx->opcode & 0xf;
14249 if (framesize == 0) {
14250 framesize = 128;
14251 } else {
14252 framesize = framesize << 3;
14255 if (ctx->opcode & (1 << 7)) {
14256 gen_mips16_save(ctx, 0, 0,
14257 do_ra, do_s0, do_s1, framesize);
14258 } else {
14259 gen_mips16_restore(ctx, 0, 0,
14260 do_ra, do_s0, do_s1, framesize);
14263 break;
14264 case I8_MOV32R:
14266 int rz = xlat(ctx->opcode & 0x7);
14268 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14269 ((ctx->opcode >> 5) & 0x7);
14270 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14272 break;
14273 case I8_MOVR32:
14274 reg32 = ctx->opcode & 0x1f;
14275 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14276 break;
14277 default:
14278 generate_exception_end(ctx, EXCP_RI);
14279 break;
14282 break;
14283 case M16_OPC_LI:
14285 int16_t imm = (uint8_t) ctx->opcode;
14287 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14289 break;
14290 case M16_OPC_CMPI:
14292 int16_t imm = (uint8_t) ctx->opcode;
14293 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14295 break;
14296 #if defined(TARGET_MIPS64)
14297 case M16_OPC_SD:
14298 check_insn(ctx, ISA_MIPS3);
14299 check_mips_64(ctx);
14300 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14301 break;
14302 #endif
14303 case M16_OPC_LB:
14304 gen_ld(ctx, OPC_LB, ry, rx, offset);
14305 break;
14306 case M16_OPC_LH:
14307 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14308 break;
14309 case M16_OPC_LWSP:
14310 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14311 break;
14312 case M16_OPC_LW:
14313 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14314 break;
14315 case M16_OPC_LBU:
14316 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14317 break;
14318 case M16_OPC_LHU:
14319 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14320 break;
14321 case M16_OPC_LWPC:
14322 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14323 break;
14324 #if defined(TARGET_MIPS64)
14325 case M16_OPC_LWU:
14326 check_insn(ctx, ISA_MIPS3);
14327 check_mips_64(ctx);
14328 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14329 break;
14330 #endif
14331 case M16_OPC_SB:
14332 gen_st(ctx, OPC_SB, ry, rx, offset);
14333 break;
14334 case M16_OPC_SH:
14335 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14336 break;
14337 case M16_OPC_SWSP:
14338 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14339 break;
14340 case M16_OPC_SW:
14341 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14342 break;
14343 case M16_OPC_RRR:
14345 int rz = xlat((ctx->opcode >> 2) & 0x7);
14346 int mips32_op;
14348 switch (ctx->opcode & 0x3) {
14349 case RRR_ADDU:
14350 mips32_op = OPC_ADDU;
14351 break;
14352 case RRR_SUBU:
14353 mips32_op = OPC_SUBU;
14354 break;
14355 #if defined(TARGET_MIPS64)
14356 case RRR_DADDU:
14357 mips32_op = OPC_DADDU;
14358 check_insn(ctx, ISA_MIPS3);
14359 check_mips_64(ctx);
14360 break;
14361 case RRR_DSUBU:
14362 mips32_op = OPC_DSUBU;
14363 check_insn(ctx, ISA_MIPS3);
14364 check_mips_64(ctx);
14365 break;
14366 #endif
14367 default:
14368 generate_exception_end(ctx, EXCP_RI);
14369 goto done;
14372 gen_arith(ctx, mips32_op, rz, rx, ry);
14373 done:
14376 break;
14377 case M16_OPC_RR:
14378 switch (op1) {
14379 case RR_JR:
14381 int nd = (ctx->opcode >> 7) & 0x1;
14382 int link = (ctx->opcode >> 6) & 0x1;
14383 int ra = (ctx->opcode >> 5) & 0x1;
14385 if (nd) {
14386 check_insn(ctx, ISA_MIPS32);
14389 if (link) {
14390 op = OPC_JALR;
14391 } else {
14392 op = OPC_JR;
14395 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14396 (nd ? 0 : 2));
14398 break;
14399 case RR_SDBBP:
14400 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14401 gen_helper_do_semihosting(cpu_env);
14402 } else {
14404 * XXX: not clear which exception should be raised
14405 * when in debug mode...
14407 check_insn(ctx, ISA_MIPS32);
14408 generate_exception_end(ctx, EXCP_DBp);
14410 break;
14411 case RR_SLT:
14412 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14413 break;
14414 case RR_SLTU:
14415 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14416 break;
14417 case RR_BREAK:
14418 generate_exception_end(ctx, EXCP_BREAK);
14419 break;
14420 case RR_SLLV:
14421 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14422 break;
14423 case RR_SRLV:
14424 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14425 break;
14426 case RR_SRAV:
14427 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14428 break;
14429 #if defined(TARGET_MIPS64)
14430 case RR_DSRL:
14431 check_insn(ctx, ISA_MIPS3);
14432 check_mips_64(ctx);
14433 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14434 break;
14435 #endif
14436 case RR_CMP:
14437 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14438 break;
14439 case RR_NEG:
14440 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14441 break;
14442 case RR_AND:
14443 gen_logic(ctx, OPC_AND, rx, rx, ry);
14444 break;
14445 case RR_OR:
14446 gen_logic(ctx, OPC_OR, rx, rx, ry);
14447 break;
14448 case RR_XOR:
14449 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14450 break;
14451 case RR_NOT:
14452 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14453 break;
14454 case RR_MFHI:
14455 gen_HILO(ctx, OPC_MFHI, 0, rx);
14456 break;
14457 case RR_CNVT:
14458 check_insn(ctx, ISA_MIPS32);
14459 switch (cnvt_op) {
14460 case RR_RY_CNVT_ZEB:
14461 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14462 break;
14463 case RR_RY_CNVT_ZEH:
14464 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14465 break;
14466 case RR_RY_CNVT_SEB:
14467 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14468 break;
14469 case RR_RY_CNVT_SEH:
14470 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14471 break;
14472 #if defined(TARGET_MIPS64)
14473 case RR_RY_CNVT_ZEW:
14474 check_insn(ctx, ISA_MIPS64);
14475 check_mips_64(ctx);
14476 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14477 break;
14478 case RR_RY_CNVT_SEW:
14479 check_insn(ctx, ISA_MIPS64);
14480 check_mips_64(ctx);
14481 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14482 break;
14483 #endif
14484 default:
14485 generate_exception_end(ctx, EXCP_RI);
14486 break;
14488 break;
14489 case RR_MFLO:
14490 gen_HILO(ctx, OPC_MFLO, 0, rx);
14491 break;
14492 #if defined(TARGET_MIPS64)
14493 case RR_DSRA:
14494 check_insn(ctx, ISA_MIPS3);
14495 check_mips_64(ctx);
14496 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14497 break;
14498 case RR_DSLLV:
14499 check_insn(ctx, ISA_MIPS3);
14500 check_mips_64(ctx);
14501 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14502 break;
14503 case RR_DSRLV:
14504 check_insn(ctx, ISA_MIPS3);
14505 check_mips_64(ctx);
14506 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14507 break;
14508 case RR_DSRAV:
14509 check_insn(ctx, ISA_MIPS3);
14510 check_mips_64(ctx);
14511 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14512 break;
14513 #endif
14514 case RR_MULT:
14515 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14516 break;
14517 case RR_MULTU:
14518 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14519 break;
14520 case RR_DIV:
14521 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14522 break;
14523 case RR_DIVU:
14524 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14525 break;
14526 #if defined(TARGET_MIPS64)
14527 case RR_DMULT:
14528 check_insn(ctx, ISA_MIPS3);
14529 check_mips_64(ctx);
14530 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14531 break;
14532 case RR_DMULTU:
14533 check_insn(ctx, ISA_MIPS3);
14534 check_mips_64(ctx);
14535 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14536 break;
14537 case RR_DDIV:
14538 check_insn(ctx, ISA_MIPS3);
14539 check_mips_64(ctx);
14540 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14541 break;
14542 case RR_DDIVU:
14543 check_insn(ctx, ISA_MIPS3);
14544 check_mips_64(ctx);
14545 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14546 break;
14547 #endif
14548 default:
14549 generate_exception_end(ctx, EXCP_RI);
14550 break;
14552 break;
14553 case M16_OPC_EXTEND:
14554 decode_extended_mips16_opc(env, ctx);
14555 n_bytes = 4;
14556 break;
14557 #if defined(TARGET_MIPS64)
14558 case M16_OPC_I64:
14559 funct = (ctx->opcode >> 8) & 0x7;
14560 decode_i64_mips16(ctx, ry, funct, offset, 0);
14561 break;
14562 #endif
14563 default:
14564 generate_exception_end(ctx, EXCP_RI);
14565 break;
14568 return n_bytes;
14571 /* microMIPS extension to MIPS32/MIPS64 */
14574 * microMIPS32/microMIPS64 major opcodes
14576 * 1. MIPS Architecture for Programmers Volume II-B:
14577 * The microMIPS32 Instruction Set (Revision 3.05)
14579 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14581 * 2. MIPS Architecture For Programmers Volume II-A:
14582 * The MIPS64 Instruction Set (Revision 3.51)
14585 enum {
14586 POOL32A = 0x00,
14587 POOL16A = 0x01,
14588 LBU16 = 0x02,
14589 MOVE16 = 0x03,
14590 ADDI32 = 0x04,
14591 R6_LUI = 0x04,
14592 AUI = 0x04,
14593 LBU32 = 0x05,
14594 SB32 = 0x06,
14595 LB32 = 0x07,
14597 POOL32B = 0x08,
14598 POOL16B = 0x09,
14599 LHU16 = 0x0a,
14600 ANDI16 = 0x0b,
14601 ADDIU32 = 0x0c,
14602 LHU32 = 0x0d,
14603 SH32 = 0x0e,
14604 LH32 = 0x0f,
14606 POOL32I = 0x10,
14607 POOL16C = 0x11,
14608 LWSP16 = 0x12,
14609 POOL16D = 0x13,
14610 ORI32 = 0x14,
14611 POOL32F = 0x15,
14612 POOL32S = 0x16, /* MIPS64 */
14613 DADDIU32 = 0x17, /* MIPS64 */
14615 POOL32C = 0x18,
14616 LWGP16 = 0x19,
14617 LW16 = 0x1a,
14618 POOL16E = 0x1b,
14619 XORI32 = 0x1c,
14620 JALS32 = 0x1d,
14621 BOVC = 0x1d,
14622 BEQC = 0x1d,
14623 BEQZALC = 0x1d,
14624 ADDIUPC = 0x1e,
14625 PCREL = 0x1e,
14626 BNVC = 0x1f,
14627 BNEC = 0x1f,
14628 BNEZALC = 0x1f,
14630 R6_BEQZC = 0x20,
14631 JIC = 0x20,
14632 POOL16F = 0x21,
14633 SB16 = 0x22,
14634 BEQZ16 = 0x23,
14635 BEQZC16 = 0x23,
14636 SLTI32 = 0x24,
14637 BEQ32 = 0x25,
14638 BC = 0x25,
14639 SWC132 = 0x26,
14640 LWC132 = 0x27,
14642 /* 0x29 is reserved */
14643 RES_29 = 0x29,
14644 R6_BNEZC = 0x28,
14645 JIALC = 0x28,
14646 SH16 = 0x2a,
14647 BNEZ16 = 0x2b,
14648 BNEZC16 = 0x2b,
14649 SLTIU32 = 0x2c,
14650 BNE32 = 0x2d,
14651 BALC = 0x2d,
14652 SDC132 = 0x2e,
14653 LDC132 = 0x2f,
14655 /* 0x31 is reserved */
14656 RES_31 = 0x31,
14657 BLEZALC = 0x30,
14658 BGEZALC = 0x30,
14659 BGEUC = 0x30,
14660 SWSP16 = 0x32,
14661 B16 = 0x33,
14662 BC16 = 0x33,
14663 ANDI32 = 0x34,
14664 J32 = 0x35,
14665 BGTZC = 0x35,
14666 BLTZC = 0x35,
14667 BLTC = 0x35,
14668 SD32 = 0x36, /* MIPS64 */
14669 LD32 = 0x37, /* MIPS64 */
14671 /* 0x39 is reserved */
14672 RES_39 = 0x39,
14673 BGTZALC = 0x38,
14674 BLTZALC = 0x38,
14675 BLTUC = 0x38,
14676 SW16 = 0x3a,
14677 LI16 = 0x3b,
14678 JALX32 = 0x3c,
14679 JAL32 = 0x3d,
14680 BLEZC = 0x3d,
14681 BGEZC = 0x3d,
14682 BGEC = 0x3d,
14683 SW32 = 0x3e,
14684 LW32 = 0x3f
14687 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14688 enum {
14689 ADDIUPC_00 = 0x00,
14690 ADDIUPC_01 = 0x01,
14691 ADDIUPC_02 = 0x02,
14692 ADDIUPC_03 = 0x03,
14693 ADDIUPC_04 = 0x04,
14694 ADDIUPC_05 = 0x05,
14695 ADDIUPC_06 = 0x06,
14696 ADDIUPC_07 = 0x07,
14697 AUIPC = 0x1e,
14698 ALUIPC = 0x1f,
14699 LWPC_08 = 0x08,
14700 LWPC_09 = 0x09,
14701 LWPC_0A = 0x0A,
14702 LWPC_0B = 0x0B,
14703 LWPC_0C = 0x0C,
14704 LWPC_0D = 0x0D,
14705 LWPC_0E = 0x0E,
14706 LWPC_0F = 0x0F,
14709 /* POOL32A encoding of minor opcode field */
14711 enum {
14713 * These opcodes are distinguished only by bits 9..6; those bits are
14714 * what are recorded below.
14716 SLL32 = 0x0,
14717 SRL32 = 0x1,
14718 SRA = 0x2,
14719 ROTR = 0x3,
14720 SELEQZ = 0x5,
14721 SELNEZ = 0x6,
14722 R6_RDHWR = 0x7,
14724 SLLV = 0x0,
14725 SRLV = 0x1,
14726 SRAV = 0x2,
14727 ROTRV = 0x3,
14728 ADD = 0x4,
14729 ADDU32 = 0x5,
14730 SUB = 0x6,
14731 SUBU32 = 0x7,
14732 MUL = 0x8,
14733 AND = 0x9,
14734 OR32 = 0xa,
14735 NOR = 0xb,
14736 XOR32 = 0xc,
14737 SLT = 0xd,
14738 SLTU = 0xe,
14740 MOVN = 0x0,
14741 R6_MUL = 0x0,
14742 MOVZ = 0x1,
14743 MUH = 0x1,
14744 MULU = 0x2,
14745 MUHU = 0x3,
14746 LWXS = 0x4,
14747 R6_DIV = 0x4,
14748 MOD = 0x5,
14749 R6_DIVU = 0x6,
14750 MODU = 0x7,
14752 /* The following can be distinguished by their lower 6 bits. */
14753 BREAK32 = 0x07,
14754 INS = 0x0c,
14755 LSA = 0x0f,
14756 ALIGN = 0x1f,
14757 EXT = 0x2c,
14758 POOL32AXF = 0x3c,
14759 SIGRIE = 0x3f
14762 /* POOL32AXF encoding of minor opcode field extension */
14765 * 1. MIPS Architecture for Programmers Volume II-B:
14766 * The microMIPS32 Instruction Set (Revision 3.05)
14768 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14770 * 2. MIPS Architecture for Programmers VolumeIV-e:
14771 * The MIPS DSP Application-Specific Extension
14772 * to the microMIPS32 Architecture (Revision 2.34)
14774 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14777 enum {
14778 /* bits 11..6 */
14779 TEQ = 0x00,
14780 TGE = 0x08,
14781 TGEU = 0x10,
14782 TLT = 0x20,
14783 TLTU = 0x28,
14784 TNE = 0x30,
14786 MFC0 = 0x03,
14787 MTC0 = 0x0b,
14789 /* begin of microMIPS32 DSP */
14791 /* bits 13..12 for 0x01 */
14792 MFHI_ACC = 0x0,
14793 MFLO_ACC = 0x1,
14794 MTHI_ACC = 0x2,
14795 MTLO_ACC = 0x3,
14797 /* bits 13..12 for 0x2a */
14798 MADD_ACC = 0x0,
14799 MADDU_ACC = 0x1,
14800 MSUB_ACC = 0x2,
14801 MSUBU_ACC = 0x3,
14803 /* bits 13..12 for 0x32 */
14804 MULT_ACC = 0x0,
14805 MULTU_ACC = 0x1,
14807 /* end of microMIPS32 DSP */
14809 /* bits 15..12 for 0x2c */
14810 BITSWAP = 0x0,
14811 SEB = 0x2,
14812 SEH = 0x3,
14813 CLO = 0x4,
14814 CLZ = 0x5,
14815 RDHWR = 0x6,
14816 WSBH = 0x7,
14817 MULT = 0x8,
14818 MULTU = 0x9,
14819 DIV = 0xa,
14820 DIVU = 0xb,
14821 MADD = 0xc,
14822 MADDU = 0xd,
14823 MSUB = 0xe,
14824 MSUBU = 0xf,
14826 /* bits 15..12 for 0x34 */
14827 MFC2 = 0x4,
14828 MTC2 = 0x5,
14829 MFHC2 = 0x8,
14830 MTHC2 = 0x9,
14831 CFC2 = 0xc,
14832 CTC2 = 0xd,
14834 /* bits 15..12 for 0x3c */
14835 JALR = 0x0,
14836 JR = 0x0, /* alias */
14837 JALRC = 0x0,
14838 JRC = 0x0,
14839 JALR_HB = 0x1,
14840 JALRC_HB = 0x1,
14841 JALRS = 0x4,
14842 JALRS_HB = 0x5,
14844 /* bits 15..12 for 0x05 */
14845 RDPGPR = 0xe,
14846 WRPGPR = 0xf,
14848 /* bits 15..12 for 0x0d */
14849 TLBP = 0x0,
14850 TLBR = 0x1,
14851 TLBWI = 0x2,
14852 TLBWR = 0x3,
14853 TLBINV = 0x4,
14854 TLBINVF = 0x5,
14855 WAIT = 0x9,
14856 IRET = 0xd,
14857 DERET = 0xe,
14858 ERET = 0xf,
14860 /* bits 15..12 for 0x15 */
14861 DMT = 0x0,
14862 DVPE = 0x1,
14863 EMT = 0x2,
14864 EVPE = 0x3,
14866 /* bits 15..12 for 0x1d */
14867 DI = 0x4,
14868 EI = 0x5,
14870 /* bits 15..12 for 0x2d */
14871 SYNC = 0x6,
14872 SYSCALL = 0x8,
14873 SDBBP = 0xd,
14875 /* bits 15..12 for 0x35 */
14876 MFHI32 = 0x0,
14877 MFLO32 = 0x1,
14878 MTHI32 = 0x2,
14879 MTLO32 = 0x3,
14882 /* POOL32B encoding of minor opcode field (bits 15..12) */
14884 enum {
14885 LWC2 = 0x0,
14886 LWP = 0x1,
14887 LDP = 0x4,
14888 LWM32 = 0x5,
14889 CACHE = 0x6,
14890 LDM = 0x7,
14891 SWC2 = 0x8,
14892 SWP = 0x9,
14893 SDP = 0xc,
14894 SWM32 = 0xd,
14895 SDM = 0xf
14898 /* POOL32C encoding of minor opcode field (bits 15..12) */
14900 enum {
14901 LWL = 0x0,
14902 SWL = 0x8,
14903 LWR = 0x1,
14904 SWR = 0x9,
14905 PREF = 0x2,
14906 ST_EVA = 0xa,
14907 LL = 0x3,
14908 SC = 0xb,
14909 LDL = 0x4,
14910 SDL = 0xc,
14911 LDR = 0x5,
14912 SDR = 0xd,
14913 LD_EVA = 0x6,
14914 LWU = 0xe,
14915 LLD = 0x7,
14916 SCD = 0xf
14919 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14921 enum {
14922 LBUE = 0x0,
14923 LHUE = 0x1,
14924 LWLE = 0x2,
14925 LWRE = 0x3,
14926 LBE = 0x4,
14927 LHE = 0x5,
14928 LLE = 0x6,
14929 LWE = 0x7,
14932 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14934 enum {
14935 SWLE = 0x0,
14936 SWRE = 0x1,
14937 PREFE = 0x2,
14938 CACHEE = 0x3,
14939 SBE = 0x4,
14940 SHE = 0x5,
14941 SCE = 0x6,
14942 SWE = 0x7,
14945 /* POOL32F encoding of minor opcode field (bits 5..0) */
14947 enum {
14948 /* These are the bit 7..6 values */
14949 ADD_FMT = 0x0,
14951 SUB_FMT = 0x1,
14953 MUL_FMT = 0x2,
14955 DIV_FMT = 0x3,
14957 /* These are the bit 8..6 values */
14958 MOVN_FMT = 0x0,
14959 RSQRT2_FMT = 0x0,
14960 MOVF_FMT = 0x0,
14961 RINT_FMT = 0x0,
14962 SELNEZ_FMT = 0x0,
14964 MOVZ_FMT = 0x1,
14965 LWXC1 = 0x1,
14966 MOVT_FMT = 0x1,
14967 CLASS_FMT = 0x1,
14968 SELEQZ_FMT = 0x1,
14970 PLL_PS = 0x2,
14971 SWXC1 = 0x2,
14972 SEL_FMT = 0x2,
14974 PLU_PS = 0x3,
14975 LDXC1 = 0x3,
14977 MOVN_FMT_04 = 0x4,
14978 PUL_PS = 0x4,
14979 SDXC1 = 0x4,
14980 RECIP2_FMT = 0x4,
14982 MOVZ_FMT_05 = 0x05,
14983 PUU_PS = 0x5,
14984 LUXC1 = 0x5,
14986 CVT_PS_S = 0x6,
14987 SUXC1 = 0x6,
14988 ADDR_PS = 0x6,
14989 PREFX = 0x6,
14990 MADDF_FMT = 0x6,
14992 MULR_PS = 0x7,
14993 MSUBF_FMT = 0x7,
14995 MADD_S = 0x01,
14996 MADD_D = 0x09,
14997 MADD_PS = 0x11,
14998 ALNV_PS = 0x19,
14999 MSUB_S = 0x21,
15000 MSUB_D = 0x29,
15001 MSUB_PS = 0x31,
15003 NMADD_S = 0x02,
15004 NMADD_D = 0x0a,
15005 NMADD_PS = 0x12,
15006 NMSUB_S = 0x22,
15007 NMSUB_D = 0x2a,
15008 NMSUB_PS = 0x32,
15010 MIN_FMT = 0x3,
15011 MAX_FMT = 0xb,
15012 MINA_FMT = 0x23,
15013 MAXA_FMT = 0x2b,
15014 POOL32FXF = 0x3b,
15016 CABS_COND_FMT = 0x1c, /* MIPS3D */
15017 C_COND_FMT = 0x3c,
15019 CMP_CONDN_S = 0x5,
15020 CMP_CONDN_D = 0x15
15023 /* POOL32Fxf encoding of minor opcode extension field */
15025 enum {
15026 CVT_L = 0x04,
15027 RSQRT_FMT = 0x08,
15028 FLOOR_L = 0x0c,
15029 CVT_PW_PS = 0x1c,
15030 CVT_W = 0x24,
15031 SQRT_FMT = 0x28,
15032 FLOOR_W = 0x2c,
15033 CVT_PS_PW = 0x3c,
15034 CFC1 = 0x40,
15035 RECIP_FMT = 0x48,
15036 CEIL_L = 0x4c,
15037 CTC1 = 0x60,
15038 CEIL_W = 0x6c,
15039 MFC1 = 0x80,
15040 CVT_S_PL = 0x84,
15041 TRUNC_L = 0x8c,
15042 MTC1 = 0xa0,
15043 CVT_S_PU = 0xa4,
15044 TRUNC_W = 0xac,
15045 MFHC1 = 0xc0,
15046 ROUND_L = 0xcc,
15047 MTHC1 = 0xe0,
15048 ROUND_W = 0xec,
15050 MOV_FMT = 0x01,
15051 MOVF = 0x05,
15052 ABS_FMT = 0x0d,
15053 RSQRT1_FMT = 0x1d,
15054 MOVT = 0x25,
15055 NEG_FMT = 0x2d,
15056 CVT_D = 0x4d,
15057 RECIP1_FMT = 0x5d,
15058 CVT_S = 0x6d
15061 /* POOL32I encoding of minor opcode field (bits 25..21) */
15063 enum {
15064 BLTZ = 0x00,
15065 BLTZAL = 0x01,
15066 BGEZ = 0x02,
15067 BGEZAL = 0x03,
15068 BLEZ = 0x04,
15069 BNEZC = 0x05,
15070 BGTZ = 0x06,
15071 BEQZC = 0x07,
15072 TLTI = 0x08,
15073 BC1EQZC = 0x08,
15074 TGEI = 0x09,
15075 BC1NEZC = 0x09,
15076 TLTIU = 0x0a,
15077 BC2EQZC = 0x0a,
15078 TGEIU = 0x0b,
15079 BC2NEZC = 0x0a,
15080 TNEI = 0x0c,
15081 R6_SYNCI = 0x0c,
15082 LUI = 0x0d,
15083 TEQI = 0x0e,
15084 SYNCI = 0x10,
15085 BLTZALS = 0x11,
15086 BGEZALS = 0x13,
15087 BC2F = 0x14,
15088 BC2T = 0x15,
15089 BPOSGE64 = 0x1a,
15090 BPOSGE32 = 0x1b,
15091 /* These overlap and are distinguished by bit16 of the instruction */
15092 BC1F = 0x1c,
15093 BC1T = 0x1d,
15094 BC1ANY2F = 0x1c,
15095 BC1ANY2T = 0x1d,
15096 BC1ANY4F = 0x1e,
15097 BC1ANY4T = 0x1f
15100 /* POOL16A encoding of minor opcode field */
15102 enum {
15103 ADDU16 = 0x0,
15104 SUBU16 = 0x1
15107 /* POOL16B encoding of minor opcode field */
15109 enum {
15110 SLL16 = 0x0,
15111 SRL16 = 0x1
15114 /* POOL16C encoding of minor opcode field */
15116 enum {
15117 NOT16 = 0x00,
15118 XOR16 = 0x04,
15119 AND16 = 0x08,
15120 OR16 = 0x0c,
15121 LWM16 = 0x10,
15122 SWM16 = 0x14,
15123 JR16 = 0x18,
15124 JRC16 = 0x1a,
15125 JALR16 = 0x1c,
15126 JALR16S = 0x1e,
15127 MFHI16 = 0x20,
15128 MFLO16 = 0x24,
15129 BREAK16 = 0x28,
15130 SDBBP16 = 0x2c,
15131 JRADDIUSP = 0x30
15134 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15136 enum {
15137 R6_NOT16 = 0x00,
15138 R6_AND16 = 0x01,
15139 R6_LWM16 = 0x02,
15140 R6_JRC16 = 0x03,
15141 MOVEP = 0x04,
15142 MOVEP_05 = 0x05,
15143 MOVEP_06 = 0x06,
15144 MOVEP_07 = 0x07,
15145 R6_XOR16 = 0x08,
15146 R6_OR16 = 0x09,
15147 R6_SWM16 = 0x0a,
15148 JALRC16 = 0x0b,
15149 MOVEP_0C = 0x0c,
15150 MOVEP_0D = 0x0d,
15151 MOVEP_0E = 0x0e,
15152 MOVEP_0F = 0x0f,
15153 JRCADDIUSP = 0x13,
15154 R6_BREAK16 = 0x1b,
15155 R6_SDBBP16 = 0x3b
15158 /* POOL16D encoding of minor opcode field */
15160 enum {
15161 ADDIUS5 = 0x0,
15162 ADDIUSP = 0x1
15165 /* POOL16E encoding of minor opcode field */
15167 enum {
15168 ADDIUR2 = 0x0,
15169 ADDIUR1SP = 0x1
15172 static int mmreg(int r)
15174 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15176 return map[r];
15179 /* Used for 16-bit store instructions. */
15180 static int mmreg2(int r)
15182 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15184 return map[r];
15187 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15188 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15189 #define uMIPS_RS2(op) uMIPS_RS(op)
15190 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15191 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15192 #define uMIPS_RS5(op) (op & 0x1f)
15194 /* Signed immediate */
15195 #define SIMM(op, start, width) \
15196 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15197 << (32 - width)) \
15198 >> (32 - width))
15199 /* Zero-extended immediate */
15200 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15202 static void gen_addiur1sp(DisasContext *ctx)
15204 int rd = mmreg(uMIPS_RD(ctx->opcode));
15206 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15209 static void gen_addiur2(DisasContext *ctx)
15211 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15212 int rd = mmreg(uMIPS_RD(ctx->opcode));
15213 int rs = mmreg(uMIPS_RS(ctx->opcode));
15215 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15218 static void gen_addiusp(DisasContext *ctx)
15220 int encoded = ZIMM(ctx->opcode, 1, 9);
15221 int decoded;
15223 if (encoded <= 1) {
15224 decoded = 256 + encoded;
15225 } else if (encoded <= 255) {
15226 decoded = encoded;
15227 } else if (encoded <= 509) {
15228 decoded = encoded - 512;
15229 } else {
15230 decoded = encoded - 768;
15233 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15236 static void gen_addius5(DisasContext *ctx)
15238 int imm = SIMM(ctx->opcode, 1, 4);
15239 int rd = (ctx->opcode >> 5) & 0x1f;
15241 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15244 static void gen_andi16(DisasContext *ctx)
15246 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15247 31, 32, 63, 64, 255, 32768, 65535 };
15248 int rd = mmreg(uMIPS_RD(ctx->opcode));
15249 int rs = mmreg(uMIPS_RS(ctx->opcode));
15250 int encoded = ZIMM(ctx->opcode, 0, 4);
15252 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15255 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15256 int base, int16_t offset)
15258 TCGv t0, t1;
15259 TCGv_i32 t2;
15261 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15262 generate_exception_end(ctx, EXCP_RI);
15263 return;
15266 t0 = tcg_temp_new();
15268 gen_base_offset_addr(ctx, t0, base, offset);
15270 t1 = tcg_const_tl(reglist);
15271 t2 = tcg_const_i32(ctx->mem_idx);
15273 save_cpu_state(ctx, 1);
15274 switch (opc) {
15275 case LWM32:
15276 gen_helper_lwm(cpu_env, t0, t1, t2);
15277 break;
15278 case SWM32:
15279 gen_helper_swm(cpu_env, t0, t1, t2);
15280 break;
15281 #ifdef TARGET_MIPS64
15282 case LDM:
15283 gen_helper_ldm(cpu_env, t0, t1, t2);
15284 break;
15285 case SDM:
15286 gen_helper_sdm(cpu_env, t0, t1, t2);
15287 break;
15288 #endif
15290 tcg_temp_free(t0);
15291 tcg_temp_free(t1);
15292 tcg_temp_free_i32(t2);
15296 static void gen_pool16c_insn(DisasContext *ctx)
15298 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15299 int rs = mmreg(ctx->opcode & 0x7);
15301 switch (((ctx->opcode) >> 4) & 0x3f) {
15302 case NOT16 + 0:
15303 case NOT16 + 1:
15304 case NOT16 + 2:
15305 case NOT16 + 3:
15306 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15307 break;
15308 case XOR16 + 0:
15309 case XOR16 + 1:
15310 case XOR16 + 2:
15311 case XOR16 + 3:
15312 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15313 break;
15314 case AND16 + 0:
15315 case AND16 + 1:
15316 case AND16 + 2:
15317 case AND16 + 3:
15318 gen_logic(ctx, OPC_AND, rd, rd, rs);
15319 break;
15320 case OR16 + 0:
15321 case OR16 + 1:
15322 case OR16 + 2:
15323 case OR16 + 3:
15324 gen_logic(ctx, OPC_OR, rd, rd, rs);
15325 break;
15326 case LWM16 + 0:
15327 case LWM16 + 1:
15328 case LWM16 + 2:
15329 case LWM16 + 3:
15331 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15332 int offset = ZIMM(ctx->opcode, 0, 4);
15334 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15335 29, offset << 2);
15337 break;
15338 case SWM16 + 0:
15339 case SWM16 + 1:
15340 case SWM16 + 2:
15341 case SWM16 + 3:
15343 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15344 int offset = ZIMM(ctx->opcode, 0, 4);
15346 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15347 29, offset << 2);
15349 break;
15350 case JR16 + 0:
15351 case JR16 + 1:
15353 int reg = ctx->opcode & 0x1f;
15355 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15357 break;
15358 case JRC16 + 0:
15359 case JRC16 + 1:
15361 int reg = ctx->opcode & 0x1f;
15362 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15364 * Let normal delay slot handling in our caller take us
15365 * to the branch target.
15368 break;
15369 case JALR16 + 0:
15370 case JALR16 + 1:
15371 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15372 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15373 break;
15374 case JALR16S + 0:
15375 case JALR16S + 1:
15376 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15377 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15378 break;
15379 case MFHI16 + 0:
15380 case MFHI16 + 1:
15381 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15382 break;
15383 case MFLO16 + 0:
15384 case MFLO16 + 1:
15385 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15386 break;
15387 case BREAK16:
15388 generate_exception_end(ctx, EXCP_BREAK);
15389 break;
15390 case SDBBP16:
15391 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15392 gen_helper_do_semihosting(cpu_env);
15393 } else {
15395 * XXX: not clear which exception should be raised
15396 * when in debug mode...
15398 check_insn(ctx, ISA_MIPS32);
15399 generate_exception_end(ctx, EXCP_DBp);
15401 break;
15402 case JRADDIUSP + 0:
15403 case JRADDIUSP + 1:
15405 int imm = ZIMM(ctx->opcode, 0, 5);
15406 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15407 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15409 * Let normal delay slot handling in our caller take us
15410 * to the branch target.
15413 break;
15414 default:
15415 generate_exception_end(ctx, EXCP_RI);
15416 break;
15420 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15421 int enc_rs)
15423 int rd, rs, re, rt;
15424 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15425 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15426 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15427 rd = rd_enc[enc_dest];
15428 re = re_enc[enc_dest];
15429 rs = rs_rt_enc[enc_rs];
15430 rt = rs_rt_enc[enc_rt];
15431 if (rs) {
15432 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15433 } else {
15434 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15436 if (rt) {
15437 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15438 } else {
15439 tcg_gen_movi_tl(cpu_gpr[re], 0);
15443 static void gen_pool16c_r6_insn(DisasContext *ctx)
15445 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15446 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15448 switch (ctx->opcode & 0xf) {
15449 case R6_NOT16:
15450 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15451 break;
15452 case R6_AND16:
15453 gen_logic(ctx, OPC_AND, rt, rt, rs);
15454 break;
15455 case R6_LWM16:
15457 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15458 int offset = extract32(ctx->opcode, 4, 4);
15459 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15461 break;
15462 case R6_JRC16: /* JRCADDIUSP */
15463 if ((ctx->opcode >> 4) & 1) {
15464 /* JRCADDIUSP */
15465 int imm = extract32(ctx->opcode, 5, 5);
15466 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15467 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15468 } else {
15469 /* JRC16 */
15470 rs = extract32(ctx->opcode, 5, 5);
15471 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15473 break;
15474 case MOVEP:
15475 case MOVEP_05:
15476 case MOVEP_06:
15477 case MOVEP_07:
15478 case MOVEP_0C:
15479 case MOVEP_0D:
15480 case MOVEP_0E:
15481 case MOVEP_0F:
15483 int enc_dest = uMIPS_RD(ctx->opcode);
15484 int enc_rt = uMIPS_RS2(ctx->opcode);
15485 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15486 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15488 break;
15489 case R6_XOR16:
15490 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15491 break;
15492 case R6_OR16:
15493 gen_logic(ctx, OPC_OR, rt, rt, rs);
15494 break;
15495 case R6_SWM16:
15497 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15498 int offset = extract32(ctx->opcode, 4, 4);
15499 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15501 break;
15502 case JALRC16: /* BREAK16, SDBBP16 */
15503 switch (ctx->opcode & 0x3f) {
15504 case JALRC16:
15505 case JALRC16 + 0x20:
15506 /* JALRC16 */
15507 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15508 31, 0, 0);
15509 break;
15510 case R6_BREAK16:
15511 /* BREAK16 */
15512 generate_exception(ctx, EXCP_BREAK);
15513 break;
15514 case R6_SDBBP16:
15515 /* SDBBP16 */
15516 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15517 gen_helper_do_semihosting(cpu_env);
15518 } else {
15519 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15520 generate_exception(ctx, EXCP_RI);
15521 } else {
15522 generate_exception(ctx, EXCP_DBp);
15525 break;
15527 break;
15528 default:
15529 generate_exception(ctx, EXCP_RI);
15530 break;
15534 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15536 TCGv t0 = tcg_temp_new();
15537 TCGv t1 = tcg_temp_new();
15539 gen_load_gpr(t0, base);
15541 if (index != 0) {
15542 gen_load_gpr(t1, index);
15543 tcg_gen_shli_tl(t1, t1, 2);
15544 gen_op_addr_add(ctx, t0, t1, t0);
15547 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15548 gen_store_gpr(t1, rd);
15550 tcg_temp_free(t0);
15551 tcg_temp_free(t1);
15554 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15555 int base, int16_t offset)
15557 TCGv t0, t1;
15559 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15560 generate_exception_end(ctx, EXCP_RI);
15561 return;
15564 t0 = tcg_temp_new();
15565 t1 = tcg_temp_new();
15567 gen_base_offset_addr(ctx, t0, base, offset);
15569 switch (opc) {
15570 case LWP:
15571 if (rd == base) {
15572 generate_exception_end(ctx, EXCP_RI);
15573 return;
15575 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15576 gen_store_gpr(t1, rd);
15577 tcg_gen_movi_tl(t1, 4);
15578 gen_op_addr_add(ctx, t0, t0, t1);
15579 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15580 gen_store_gpr(t1, rd + 1);
15581 break;
15582 case SWP:
15583 gen_load_gpr(t1, rd);
15584 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15585 tcg_gen_movi_tl(t1, 4);
15586 gen_op_addr_add(ctx, t0, t0, t1);
15587 gen_load_gpr(t1, rd + 1);
15588 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15589 break;
15590 #ifdef TARGET_MIPS64
15591 case LDP:
15592 if (rd == base) {
15593 generate_exception_end(ctx, EXCP_RI);
15594 return;
15596 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15597 gen_store_gpr(t1, rd);
15598 tcg_gen_movi_tl(t1, 8);
15599 gen_op_addr_add(ctx, t0, t0, t1);
15600 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15601 gen_store_gpr(t1, rd + 1);
15602 break;
15603 case SDP:
15604 gen_load_gpr(t1, rd);
15605 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15606 tcg_gen_movi_tl(t1, 8);
15607 gen_op_addr_add(ctx, t0, t0, t1);
15608 gen_load_gpr(t1, rd + 1);
15609 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15610 break;
15611 #endif
15613 tcg_temp_free(t0);
15614 tcg_temp_free(t1);
15617 static void gen_sync(int stype)
15619 TCGBar tcg_mo = TCG_BAR_SC;
15621 switch (stype) {
15622 case 0x4: /* SYNC_WMB */
15623 tcg_mo |= TCG_MO_ST_ST;
15624 break;
15625 case 0x10: /* SYNC_MB */
15626 tcg_mo |= TCG_MO_ALL;
15627 break;
15628 case 0x11: /* SYNC_ACQUIRE */
15629 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15630 break;
15631 case 0x12: /* SYNC_RELEASE */
15632 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15633 break;
15634 case 0x13: /* SYNC_RMB */
15635 tcg_mo |= TCG_MO_LD_LD;
15636 break;
15637 default:
15638 tcg_mo |= TCG_MO_ALL;
15639 break;
15642 tcg_gen_mb(tcg_mo);
15645 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15647 int extension = (ctx->opcode >> 6) & 0x3f;
15648 int minor = (ctx->opcode >> 12) & 0xf;
15649 uint32_t mips32_op;
15651 switch (extension) {
15652 case TEQ:
15653 mips32_op = OPC_TEQ;
15654 goto do_trap;
15655 case TGE:
15656 mips32_op = OPC_TGE;
15657 goto do_trap;
15658 case TGEU:
15659 mips32_op = OPC_TGEU;
15660 goto do_trap;
15661 case TLT:
15662 mips32_op = OPC_TLT;
15663 goto do_trap;
15664 case TLTU:
15665 mips32_op = OPC_TLTU;
15666 goto do_trap;
15667 case TNE:
15668 mips32_op = OPC_TNE;
15669 do_trap:
15670 gen_trap(ctx, mips32_op, rs, rt, -1);
15671 break;
15672 #ifndef CONFIG_USER_ONLY
15673 case MFC0:
15674 case MFC0 + 32:
15675 check_cp0_enabled(ctx);
15676 if (rt == 0) {
15677 /* Treat as NOP. */
15678 break;
15680 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15681 break;
15682 case MTC0:
15683 case MTC0 + 32:
15684 check_cp0_enabled(ctx);
15686 TCGv t0 = tcg_temp_new();
15688 gen_load_gpr(t0, rt);
15689 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
15690 tcg_temp_free(t0);
15692 break;
15693 #endif
15694 case 0x2a:
15695 switch (minor & 3) {
15696 case MADD_ACC:
15697 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15698 break;
15699 case MADDU_ACC:
15700 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15701 break;
15702 case MSUB_ACC:
15703 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15704 break;
15705 case MSUBU_ACC:
15706 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15707 break;
15708 default:
15709 goto pool32axf_invalid;
15711 break;
15712 case 0x32:
15713 switch (minor & 3) {
15714 case MULT_ACC:
15715 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15716 break;
15717 case MULTU_ACC:
15718 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15719 break;
15720 default:
15721 goto pool32axf_invalid;
15723 break;
15724 case 0x2c:
15725 switch (minor) {
15726 case BITSWAP:
15727 check_insn(ctx, ISA_MIPS32R6);
15728 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15729 break;
15730 case SEB:
15731 gen_bshfl(ctx, OPC_SEB, rs, rt);
15732 break;
15733 case SEH:
15734 gen_bshfl(ctx, OPC_SEH, rs, rt);
15735 break;
15736 case CLO:
15737 mips32_op = OPC_CLO;
15738 goto do_cl;
15739 case CLZ:
15740 mips32_op = OPC_CLZ;
15741 do_cl:
15742 check_insn(ctx, ISA_MIPS32);
15743 gen_cl(ctx, mips32_op, rt, rs);
15744 break;
15745 case RDHWR:
15746 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15747 gen_rdhwr(ctx, rt, rs, 0);
15748 break;
15749 case WSBH:
15750 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15751 break;
15752 case MULT:
15753 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15754 mips32_op = OPC_MULT;
15755 goto do_mul;
15756 case MULTU:
15757 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15758 mips32_op = OPC_MULTU;
15759 goto do_mul;
15760 case DIV:
15761 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15762 mips32_op = OPC_DIV;
15763 goto do_div;
15764 case DIVU:
15765 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15766 mips32_op = OPC_DIVU;
15767 goto do_div;
15768 do_div:
15769 check_insn(ctx, ISA_MIPS32);
15770 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15771 break;
15772 case MADD:
15773 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15774 mips32_op = OPC_MADD;
15775 goto do_mul;
15776 case MADDU:
15777 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15778 mips32_op = OPC_MADDU;
15779 goto do_mul;
15780 case MSUB:
15781 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15782 mips32_op = OPC_MSUB;
15783 goto do_mul;
15784 case MSUBU:
15785 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15786 mips32_op = OPC_MSUBU;
15787 do_mul:
15788 check_insn(ctx, ISA_MIPS32);
15789 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15790 break;
15791 default:
15792 goto pool32axf_invalid;
15794 break;
15795 case 0x34:
15796 switch (minor) {
15797 case MFC2:
15798 case MTC2:
15799 case MFHC2:
15800 case MTHC2:
15801 case CFC2:
15802 case CTC2:
15803 generate_exception_err(ctx, EXCP_CpU, 2);
15804 break;
15805 default:
15806 goto pool32axf_invalid;
15808 break;
15809 case 0x3c:
15810 switch (minor) {
15811 case JALR: /* JALRC */
15812 case JALR_HB: /* JALRC_HB */
15813 if (ctx->insn_flags & ISA_MIPS32R6) {
15814 /* JALRC, JALRC_HB */
15815 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15816 } else {
15817 /* JALR, JALR_HB */
15818 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15819 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15821 break;
15822 case JALRS:
15823 case JALRS_HB:
15824 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15825 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15826 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15827 break;
15828 default:
15829 goto pool32axf_invalid;
15831 break;
15832 case 0x05:
15833 switch (minor) {
15834 case RDPGPR:
15835 check_cp0_enabled(ctx);
15836 check_insn(ctx, ISA_MIPS32R2);
15837 gen_load_srsgpr(rs, rt);
15838 break;
15839 case WRPGPR:
15840 check_cp0_enabled(ctx);
15841 check_insn(ctx, ISA_MIPS32R2);
15842 gen_store_srsgpr(rs, rt);
15843 break;
15844 default:
15845 goto pool32axf_invalid;
15847 break;
15848 #ifndef CONFIG_USER_ONLY
15849 case 0x0d:
15850 switch (minor) {
15851 case TLBP:
15852 mips32_op = OPC_TLBP;
15853 goto do_cp0;
15854 case TLBR:
15855 mips32_op = OPC_TLBR;
15856 goto do_cp0;
15857 case TLBWI:
15858 mips32_op = OPC_TLBWI;
15859 goto do_cp0;
15860 case TLBWR:
15861 mips32_op = OPC_TLBWR;
15862 goto do_cp0;
15863 case TLBINV:
15864 mips32_op = OPC_TLBINV;
15865 goto do_cp0;
15866 case TLBINVF:
15867 mips32_op = OPC_TLBINVF;
15868 goto do_cp0;
15869 case WAIT:
15870 mips32_op = OPC_WAIT;
15871 goto do_cp0;
15872 case DERET:
15873 mips32_op = OPC_DERET;
15874 goto do_cp0;
15875 case ERET:
15876 mips32_op = OPC_ERET;
15877 do_cp0:
15878 gen_cp0(env, ctx, mips32_op, rt, rs);
15879 break;
15880 default:
15881 goto pool32axf_invalid;
15883 break;
15884 case 0x1d:
15885 switch (minor) {
15886 case DI:
15887 check_cp0_enabled(ctx);
15889 TCGv t0 = tcg_temp_new();
15891 save_cpu_state(ctx, 1);
15892 gen_helper_di(t0, cpu_env);
15893 gen_store_gpr(t0, rs);
15895 * Stop translation as we may have switched the execution
15896 * mode.
15898 ctx->base.is_jmp = DISAS_STOP;
15899 tcg_temp_free(t0);
15901 break;
15902 case EI:
15903 check_cp0_enabled(ctx);
15905 TCGv t0 = tcg_temp_new();
15907 save_cpu_state(ctx, 1);
15908 gen_helper_ei(t0, cpu_env);
15909 gen_store_gpr(t0, rs);
15911 * DISAS_STOP isn't sufficient, we need to ensure we break out
15912 * of translated code to check for pending interrupts.
15914 gen_save_pc(ctx->base.pc_next + 4);
15915 ctx->base.is_jmp = DISAS_EXIT;
15916 tcg_temp_free(t0);
15918 break;
15919 default:
15920 goto pool32axf_invalid;
15922 break;
15923 #endif
15924 case 0x2d:
15925 switch (minor) {
15926 case SYNC:
15927 gen_sync(extract32(ctx->opcode, 16, 5));
15928 break;
15929 case SYSCALL:
15930 generate_exception_end(ctx, EXCP_SYSCALL);
15931 break;
15932 case SDBBP:
15933 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15934 gen_helper_do_semihosting(cpu_env);
15935 } else {
15936 check_insn(ctx, ISA_MIPS32);
15937 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15938 generate_exception_end(ctx, EXCP_RI);
15939 } else {
15940 generate_exception_end(ctx, EXCP_DBp);
15943 break;
15944 default:
15945 goto pool32axf_invalid;
15947 break;
15948 case 0x01:
15949 switch (minor & 3) {
15950 case MFHI_ACC:
15951 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15952 break;
15953 case MFLO_ACC:
15954 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15955 break;
15956 case MTHI_ACC:
15957 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15958 break;
15959 case MTLO_ACC:
15960 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15961 break;
15962 default:
15963 goto pool32axf_invalid;
15965 break;
15966 case 0x35:
15967 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15968 switch (minor) {
15969 case MFHI32:
15970 gen_HILO(ctx, OPC_MFHI, 0, rs);
15971 break;
15972 case MFLO32:
15973 gen_HILO(ctx, OPC_MFLO, 0, rs);
15974 break;
15975 case MTHI32:
15976 gen_HILO(ctx, OPC_MTHI, 0, rs);
15977 break;
15978 case MTLO32:
15979 gen_HILO(ctx, OPC_MTLO, 0, rs);
15980 break;
15981 default:
15982 goto pool32axf_invalid;
15984 break;
15985 default:
15986 pool32axf_invalid:
15987 MIPS_INVAL("pool32axf");
15988 generate_exception_end(ctx, EXCP_RI);
15989 break;
15994 * Values for microMIPS fmt field. Variable-width, depending on which
15995 * formats the instruction supports.
15997 enum {
15998 FMT_SD_S = 0,
15999 FMT_SD_D = 1,
16001 FMT_SDPS_S = 0,
16002 FMT_SDPS_D = 1,
16003 FMT_SDPS_PS = 2,
16005 FMT_SWL_S = 0,
16006 FMT_SWL_W = 1,
16007 FMT_SWL_L = 2,
16009 FMT_DWL_D = 0,
16010 FMT_DWL_W = 1,
16011 FMT_DWL_L = 2
16014 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16016 int extension = (ctx->opcode >> 6) & 0x3ff;
16017 uint32_t mips32_op;
16019 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16020 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16021 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16023 switch (extension) {
16024 case FLOAT_1BIT_FMT(CFC1, 0):
16025 mips32_op = OPC_CFC1;
16026 goto do_cp1;
16027 case FLOAT_1BIT_FMT(CTC1, 0):
16028 mips32_op = OPC_CTC1;
16029 goto do_cp1;
16030 case FLOAT_1BIT_FMT(MFC1, 0):
16031 mips32_op = OPC_MFC1;
16032 goto do_cp1;
16033 case FLOAT_1BIT_FMT(MTC1, 0):
16034 mips32_op = OPC_MTC1;
16035 goto do_cp1;
16036 case FLOAT_1BIT_FMT(MFHC1, 0):
16037 mips32_op = OPC_MFHC1;
16038 goto do_cp1;
16039 case FLOAT_1BIT_FMT(MTHC1, 0):
16040 mips32_op = OPC_MTHC1;
16041 do_cp1:
16042 gen_cp1(ctx, mips32_op, rt, rs);
16043 break;
16045 /* Reciprocal square root */
16046 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16047 mips32_op = OPC_RSQRT_S;
16048 goto do_unaryfp;
16049 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16050 mips32_op = OPC_RSQRT_D;
16051 goto do_unaryfp;
16053 /* Square root */
16054 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16055 mips32_op = OPC_SQRT_S;
16056 goto do_unaryfp;
16057 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16058 mips32_op = OPC_SQRT_D;
16059 goto do_unaryfp;
16061 /* Reciprocal */
16062 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16063 mips32_op = OPC_RECIP_S;
16064 goto do_unaryfp;
16065 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16066 mips32_op = OPC_RECIP_D;
16067 goto do_unaryfp;
16069 /* Floor */
16070 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16071 mips32_op = OPC_FLOOR_L_S;
16072 goto do_unaryfp;
16073 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16074 mips32_op = OPC_FLOOR_L_D;
16075 goto do_unaryfp;
16076 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16077 mips32_op = OPC_FLOOR_W_S;
16078 goto do_unaryfp;
16079 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16080 mips32_op = OPC_FLOOR_W_D;
16081 goto do_unaryfp;
16083 /* Ceiling */
16084 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16085 mips32_op = OPC_CEIL_L_S;
16086 goto do_unaryfp;
16087 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16088 mips32_op = OPC_CEIL_L_D;
16089 goto do_unaryfp;
16090 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16091 mips32_op = OPC_CEIL_W_S;
16092 goto do_unaryfp;
16093 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16094 mips32_op = OPC_CEIL_W_D;
16095 goto do_unaryfp;
16097 /* Truncation */
16098 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16099 mips32_op = OPC_TRUNC_L_S;
16100 goto do_unaryfp;
16101 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16102 mips32_op = OPC_TRUNC_L_D;
16103 goto do_unaryfp;
16104 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16105 mips32_op = OPC_TRUNC_W_S;
16106 goto do_unaryfp;
16107 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16108 mips32_op = OPC_TRUNC_W_D;
16109 goto do_unaryfp;
16111 /* Round */
16112 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16113 mips32_op = OPC_ROUND_L_S;
16114 goto do_unaryfp;
16115 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16116 mips32_op = OPC_ROUND_L_D;
16117 goto do_unaryfp;
16118 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16119 mips32_op = OPC_ROUND_W_S;
16120 goto do_unaryfp;
16121 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16122 mips32_op = OPC_ROUND_W_D;
16123 goto do_unaryfp;
16125 /* Integer to floating-point conversion */
16126 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16127 mips32_op = OPC_CVT_L_S;
16128 goto do_unaryfp;
16129 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16130 mips32_op = OPC_CVT_L_D;
16131 goto do_unaryfp;
16132 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16133 mips32_op = OPC_CVT_W_S;
16134 goto do_unaryfp;
16135 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16136 mips32_op = OPC_CVT_W_D;
16137 goto do_unaryfp;
16139 /* Paired-foo conversions */
16140 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16141 mips32_op = OPC_CVT_S_PL;
16142 goto do_unaryfp;
16143 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16144 mips32_op = OPC_CVT_S_PU;
16145 goto do_unaryfp;
16146 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16147 mips32_op = OPC_CVT_PW_PS;
16148 goto do_unaryfp;
16149 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16150 mips32_op = OPC_CVT_PS_PW;
16151 goto do_unaryfp;
16153 /* Floating-point moves */
16154 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16155 mips32_op = OPC_MOV_S;
16156 goto do_unaryfp;
16157 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16158 mips32_op = OPC_MOV_D;
16159 goto do_unaryfp;
16160 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16161 mips32_op = OPC_MOV_PS;
16162 goto do_unaryfp;
16164 /* Absolute value */
16165 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16166 mips32_op = OPC_ABS_S;
16167 goto do_unaryfp;
16168 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16169 mips32_op = OPC_ABS_D;
16170 goto do_unaryfp;
16171 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16172 mips32_op = OPC_ABS_PS;
16173 goto do_unaryfp;
16175 /* Negation */
16176 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16177 mips32_op = OPC_NEG_S;
16178 goto do_unaryfp;
16179 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16180 mips32_op = OPC_NEG_D;
16181 goto do_unaryfp;
16182 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16183 mips32_op = OPC_NEG_PS;
16184 goto do_unaryfp;
16186 /* Reciprocal square root step */
16187 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16188 mips32_op = OPC_RSQRT1_S;
16189 goto do_unaryfp;
16190 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16191 mips32_op = OPC_RSQRT1_D;
16192 goto do_unaryfp;
16193 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16194 mips32_op = OPC_RSQRT1_PS;
16195 goto do_unaryfp;
16197 /* Reciprocal step */
16198 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16199 mips32_op = OPC_RECIP1_S;
16200 goto do_unaryfp;
16201 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16202 mips32_op = OPC_RECIP1_S;
16203 goto do_unaryfp;
16204 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16205 mips32_op = OPC_RECIP1_PS;
16206 goto do_unaryfp;
16208 /* Conversions from double */
16209 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16210 mips32_op = OPC_CVT_D_S;
16211 goto do_unaryfp;
16212 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16213 mips32_op = OPC_CVT_D_W;
16214 goto do_unaryfp;
16215 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16216 mips32_op = OPC_CVT_D_L;
16217 goto do_unaryfp;
16219 /* Conversions from single */
16220 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16221 mips32_op = OPC_CVT_S_D;
16222 goto do_unaryfp;
16223 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16224 mips32_op = OPC_CVT_S_W;
16225 goto do_unaryfp;
16226 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16227 mips32_op = OPC_CVT_S_L;
16228 do_unaryfp:
16229 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16230 break;
16232 /* Conditional moves on floating-point codes */
16233 case COND_FLOAT_MOV(MOVT, 0):
16234 case COND_FLOAT_MOV(MOVT, 1):
16235 case COND_FLOAT_MOV(MOVT, 2):
16236 case COND_FLOAT_MOV(MOVT, 3):
16237 case COND_FLOAT_MOV(MOVT, 4):
16238 case COND_FLOAT_MOV(MOVT, 5):
16239 case COND_FLOAT_MOV(MOVT, 6):
16240 case COND_FLOAT_MOV(MOVT, 7):
16241 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16242 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16243 break;
16244 case COND_FLOAT_MOV(MOVF, 0):
16245 case COND_FLOAT_MOV(MOVF, 1):
16246 case COND_FLOAT_MOV(MOVF, 2):
16247 case COND_FLOAT_MOV(MOVF, 3):
16248 case COND_FLOAT_MOV(MOVF, 4):
16249 case COND_FLOAT_MOV(MOVF, 5):
16250 case COND_FLOAT_MOV(MOVF, 6):
16251 case COND_FLOAT_MOV(MOVF, 7):
16252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16253 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16254 break;
16255 default:
16256 MIPS_INVAL("pool32fxf");
16257 generate_exception_end(ctx, EXCP_RI);
16258 break;
16262 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16264 int32_t offset;
16265 uint16_t insn;
16266 int rt, rs, rd, rr;
16267 int16_t imm;
16268 uint32_t op, minor, minor2, mips32_op;
16269 uint32_t cond, fmt, cc;
16271 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16272 ctx->opcode = (ctx->opcode << 16) | insn;
16274 rt = (ctx->opcode >> 21) & 0x1f;
16275 rs = (ctx->opcode >> 16) & 0x1f;
16276 rd = (ctx->opcode >> 11) & 0x1f;
16277 rr = (ctx->opcode >> 6) & 0x1f;
16278 imm = (int16_t) ctx->opcode;
16280 op = (ctx->opcode >> 26) & 0x3f;
16281 switch (op) {
16282 case POOL32A:
16283 minor = ctx->opcode & 0x3f;
16284 switch (minor) {
16285 case 0x00:
16286 minor = (ctx->opcode >> 6) & 0xf;
16287 switch (minor) {
16288 case SLL32:
16289 mips32_op = OPC_SLL;
16290 goto do_shifti;
16291 case SRA:
16292 mips32_op = OPC_SRA;
16293 goto do_shifti;
16294 case SRL32:
16295 mips32_op = OPC_SRL;
16296 goto do_shifti;
16297 case ROTR:
16298 mips32_op = OPC_ROTR;
16299 do_shifti:
16300 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16301 break;
16302 case SELEQZ:
16303 check_insn(ctx, ISA_MIPS32R6);
16304 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16305 break;
16306 case SELNEZ:
16307 check_insn(ctx, ISA_MIPS32R6);
16308 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16309 break;
16310 case R6_RDHWR:
16311 check_insn(ctx, ISA_MIPS32R6);
16312 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16313 break;
16314 default:
16315 goto pool32a_invalid;
16317 break;
16318 case 0x10:
16319 minor = (ctx->opcode >> 6) & 0xf;
16320 switch (minor) {
16321 /* Arithmetic */
16322 case ADD:
16323 mips32_op = OPC_ADD;
16324 goto do_arith;
16325 case ADDU32:
16326 mips32_op = OPC_ADDU;
16327 goto do_arith;
16328 case SUB:
16329 mips32_op = OPC_SUB;
16330 goto do_arith;
16331 case SUBU32:
16332 mips32_op = OPC_SUBU;
16333 goto do_arith;
16334 case MUL:
16335 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16336 mips32_op = OPC_MUL;
16337 do_arith:
16338 gen_arith(ctx, mips32_op, rd, rs, rt);
16339 break;
16340 /* Shifts */
16341 case SLLV:
16342 mips32_op = OPC_SLLV;
16343 goto do_shift;
16344 case SRLV:
16345 mips32_op = OPC_SRLV;
16346 goto do_shift;
16347 case SRAV:
16348 mips32_op = OPC_SRAV;
16349 goto do_shift;
16350 case ROTRV:
16351 mips32_op = OPC_ROTRV;
16352 do_shift:
16353 gen_shift(ctx, mips32_op, rd, rs, rt);
16354 break;
16355 /* Logical operations */
16356 case AND:
16357 mips32_op = OPC_AND;
16358 goto do_logic;
16359 case OR32:
16360 mips32_op = OPC_OR;
16361 goto do_logic;
16362 case NOR:
16363 mips32_op = OPC_NOR;
16364 goto do_logic;
16365 case XOR32:
16366 mips32_op = OPC_XOR;
16367 do_logic:
16368 gen_logic(ctx, mips32_op, rd, rs, rt);
16369 break;
16370 /* Set less than */
16371 case SLT:
16372 mips32_op = OPC_SLT;
16373 goto do_slt;
16374 case SLTU:
16375 mips32_op = OPC_SLTU;
16376 do_slt:
16377 gen_slt(ctx, mips32_op, rd, rs, rt);
16378 break;
16379 default:
16380 goto pool32a_invalid;
16382 break;
16383 case 0x18:
16384 minor = (ctx->opcode >> 6) & 0xf;
16385 switch (minor) {
16386 /* Conditional moves */
16387 case MOVN: /* MUL */
16388 if (ctx->insn_flags & ISA_MIPS32R6) {
16389 /* MUL */
16390 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16391 } else {
16392 /* MOVN */
16393 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16395 break;
16396 case MOVZ: /* MUH */
16397 if (ctx->insn_flags & ISA_MIPS32R6) {
16398 /* MUH */
16399 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16400 } else {
16401 /* MOVZ */
16402 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16404 break;
16405 case MULU:
16406 check_insn(ctx, ISA_MIPS32R6);
16407 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16408 break;
16409 case MUHU:
16410 check_insn(ctx, ISA_MIPS32R6);
16411 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16412 break;
16413 case LWXS: /* DIV */
16414 if (ctx->insn_flags & ISA_MIPS32R6) {
16415 /* DIV */
16416 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16417 } else {
16418 /* LWXS */
16419 gen_ldxs(ctx, rs, rt, rd);
16421 break;
16422 case MOD:
16423 check_insn(ctx, ISA_MIPS32R6);
16424 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16425 break;
16426 case R6_DIVU:
16427 check_insn(ctx, ISA_MIPS32R6);
16428 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16429 break;
16430 case MODU:
16431 check_insn(ctx, ISA_MIPS32R6);
16432 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16433 break;
16434 default:
16435 goto pool32a_invalid;
16437 break;
16438 case INS:
16439 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16440 return;
16441 case LSA:
16442 check_insn(ctx, ISA_MIPS32R6);
16443 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16444 extract32(ctx->opcode, 9, 2));
16445 break;
16446 case ALIGN:
16447 check_insn(ctx, ISA_MIPS32R6);
16448 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16449 break;
16450 case EXT:
16451 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16452 return;
16453 case POOL32AXF:
16454 gen_pool32axf(env, ctx, rt, rs);
16455 break;
16456 case BREAK32:
16457 generate_exception_end(ctx, EXCP_BREAK);
16458 break;
16459 case SIGRIE:
16460 check_insn(ctx, ISA_MIPS32R6);
16461 generate_exception_end(ctx, EXCP_RI);
16462 break;
16463 default:
16464 pool32a_invalid:
16465 MIPS_INVAL("pool32a");
16466 generate_exception_end(ctx, EXCP_RI);
16467 break;
16469 break;
16470 case POOL32B:
16471 minor = (ctx->opcode >> 12) & 0xf;
16472 switch (minor) {
16473 case CACHE:
16474 check_cp0_enabled(ctx);
16475 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16476 gen_cache_operation(ctx, rt, rs, imm);
16478 break;
16479 case LWC2:
16480 case SWC2:
16481 /* COP2: Not implemented. */
16482 generate_exception_err(ctx, EXCP_CpU, 2);
16483 break;
16484 #ifdef TARGET_MIPS64
16485 case LDP:
16486 case SDP:
16487 check_insn(ctx, ISA_MIPS3);
16488 check_mips_64(ctx);
16489 #endif
16490 /* fall through */
16491 case LWP:
16492 case SWP:
16493 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16494 break;
16495 #ifdef TARGET_MIPS64
16496 case LDM:
16497 case SDM:
16498 check_insn(ctx, ISA_MIPS3);
16499 check_mips_64(ctx);
16500 #endif
16501 /* fall through */
16502 case LWM32:
16503 case SWM32:
16504 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16505 break;
16506 default:
16507 MIPS_INVAL("pool32b");
16508 generate_exception_end(ctx, EXCP_RI);
16509 break;
16511 break;
16512 case POOL32F:
16513 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16514 minor = ctx->opcode & 0x3f;
16515 check_cp1_enabled(ctx);
16516 switch (minor) {
16517 case ALNV_PS:
16518 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16519 mips32_op = OPC_ALNV_PS;
16520 goto do_madd;
16521 case MADD_S:
16522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16523 mips32_op = OPC_MADD_S;
16524 goto do_madd;
16525 case MADD_D:
16526 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16527 mips32_op = OPC_MADD_D;
16528 goto do_madd;
16529 case MADD_PS:
16530 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16531 mips32_op = OPC_MADD_PS;
16532 goto do_madd;
16533 case MSUB_S:
16534 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16535 mips32_op = OPC_MSUB_S;
16536 goto do_madd;
16537 case MSUB_D:
16538 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16539 mips32_op = OPC_MSUB_D;
16540 goto do_madd;
16541 case MSUB_PS:
16542 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16543 mips32_op = OPC_MSUB_PS;
16544 goto do_madd;
16545 case NMADD_S:
16546 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16547 mips32_op = OPC_NMADD_S;
16548 goto do_madd;
16549 case NMADD_D:
16550 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16551 mips32_op = OPC_NMADD_D;
16552 goto do_madd;
16553 case NMADD_PS:
16554 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16555 mips32_op = OPC_NMADD_PS;
16556 goto do_madd;
16557 case NMSUB_S:
16558 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16559 mips32_op = OPC_NMSUB_S;
16560 goto do_madd;
16561 case NMSUB_D:
16562 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16563 mips32_op = OPC_NMSUB_D;
16564 goto do_madd;
16565 case NMSUB_PS:
16566 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16567 mips32_op = OPC_NMSUB_PS;
16568 do_madd:
16569 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16570 break;
16571 case CABS_COND_FMT:
16572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16573 cond = (ctx->opcode >> 6) & 0xf;
16574 cc = (ctx->opcode >> 13) & 0x7;
16575 fmt = (ctx->opcode >> 10) & 0x3;
16576 switch (fmt) {
16577 case 0x0:
16578 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16579 break;
16580 case 0x1:
16581 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16582 break;
16583 case 0x2:
16584 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16585 break;
16586 default:
16587 goto pool32f_invalid;
16589 break;
16590 case C_COND_FMT:
16591 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16592 cond = (ctx->opcode >> 6) & 0xf;
16593 cc = (ctx->opcode >> 13) & 0x7;
16594 fmt = (ctx->opcode >> 10) & 0x3;
16595 switch (fmt) {
16596 case 0x0:
16597 gen_cmp_s(ctx, cond, rt, rs, cc);
16598 break;
16599 case 0x1:
16600 gen_cmp_d(ctx, cond, rt, rs, cc);
16601 break;
16602 case 0x2:
16603 gen_cmp_ps(ctx, cond, rt, rs, cc);
16604 break;
16605 default:
16606 goto pool32f_invalid;
16608 break;
16609 case CMP_CONDN_S:
16610 check_insn(ctx, ISA_MIPS32R6);
16611 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16612 break;
16613 case CMP_CONDN_D:
16614 check_insn(ctx, ISA_MIPS32R6);
16615 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16616 break;
16617 case POOL32FXF:
16618 gen_pool32fxf(ctx, rt, rs);
16619 break;
16620 case 0x00:
16621 /* PLL foo */
16622 switch ((ctx->opcode >> 6) & 0x7) {
16623 case PLL_PS:
16624 mips32_op = OPC_PLL_PS;
16625 goto do_ps;
16626 case PLU_PS:
16627 mips32_op = OPC_PLU_PS;
16628 goto do_ps;
16629 case PUL_PS:
16630 mips32_op = OPC_PUL_PS;
16631 goto do_ps;
16632 case PUU_PS:
16633 mips32_op = OPC_PUU_PS;
16634 goto do_ps;
16635 case CVT_PS_S:
16636 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16637 mips32_op = OPC_CVT_PS_S;
16638 do_ps:
16639 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16640 break;
16641 default:
16642 goto pool32f_invalid;
16644 break;
16645 case MIN_FMT:
16646 check_insn(ctx, ISA_MIPS32R6);
16647 switch ((ctx->opcode >> 9) & 0x3) {
16648 case FMT_SDPS_S:
16649 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16650 break;
16651 case FMT_SDPS_D:
16652 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16653 break;
16654 default:
16655 goto pool32f_invalid;
16657 break;
16658 case 0x08:
16659 /* [LS][WDU]XC1 */
16660 switch ((ctx->opcode >> 6) & 0x7) {
16661 case LWXC1:
16662 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16663 mips32_op = OPC_LWXC1;
16664 goto do_ldst_cp1;
16665 case SWXC1:
16666 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16667 mips32_op = OPC_SWXC1;
16668 goto do_ldst_cp1;
16669 case LDXC1:
16670 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16671 mips32_op = OPC_LDXC1;
16672 goto do_ldst_cp1;
16673 case SDXC1:
16674 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16675 mips32_op = OPC_SDXC1;
16676 goto do_ldst_cp1;
16677 case LUXC1:
16678 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16679 mips32_op = OPC_LUXC1;
16680 goto do_ldst_cp1;
16681 case SUXC1:
16682 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16683 mips32_op = OPC_SUXC1;
16684 do_ldst_cp1:
16685 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16686 break;
16687 default:
16688 goto pool32f_invalid;
16690 break;
16691 case MAX_FMT:
16692 check_insn(ctx, ISA_MIPS32R6);
16693 switch ((ctx->opcode >> 9) & 0x3) {
16694 case FMT_SDPS_S:
16695 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
16696 break;
16697 case FMT_SDPS_D:
16698 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
16699 break;
16700 default:
16701 goto pool32f_invalid;
16703 break;
16704 case 0x18:
16705 /* 3D insns */
16706 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16707 fmt = (ctx->opcode >> 9) & 0x3;
16708 switch ((ctx->opcode >> 6) & 0x7) {
16709 case RSQRT2_FMT:
16710 switch (fmt) {
16711 case FMT_SDPS_S:
16712 mips32_op = OPC_RSQRT2_S;
16713 goto do_3d;
16714 case FMT_SDPS_D:
16715 mips32_op = OPC_RSQRT2_D;
16716 goto do_3d;
16717 case FMT_SDPS_PS:
16718 mips32_op = OPC_RSQRT2_PS;
16719 goto do_3d;
16720 default:
16721 goto pool32f_invalid;
16723 break;
16724 case RECIP2_FMT:
16725 switch (fmt) {
16726 case FMT_SDPS_S:
16727 mips32_op = OPC_RECIP2_S;
16728 goto do_3d;
16729 case FMT_SDPS_D:
16730 mips32_op = OPC_RECIP2_D;
16731 goto do_3d;
16732 case FMT_SDPS_PS:
16733 mips32_op = OPC_RECIP2_PS;
16734 goto do_3d;
16735 default:
16736 goto pool32f_invalid;
16738 break;
16739 case ADDR_PS:
16740 mips32_op = OPC_ADDR_PS;
16741 goto do_3d;
16742 case MULR_PS:
16743 mips32_op = OPC_MULR_PS;
16744 do_3d:
16745 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16746 break;
16747 default:
16748 goto pool32f_invalid;
16750 break;
16751 case 0x20:
16752 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16753 cc = (ctx->opcode >> 13) & 0x7;
16754 fmt = (ctx->opcode >> 9) & 0x3;
16755 switch ((ctx->opcode >> 6) & 0x7) {
16756 case MOVF_FMT: /* RINT_FMT */
16757 if (ctx->insn_flags & ISA_MIPS32R6) {
16758 /* RINT_FMT */
16759 switch (fmt) {
16760 case FMT_SDPS_S:
16761 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16762 break;
16763 case FMT_SDPS_D:
16764 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16765 break;
16766 default:
16767 goto pool32f_invalid;
16769 } else {
16770 /* MOVF_FMT */
16771 switch (fmt) {
16772 case FMT_SDPS_S:
16773 gen_movcf_s(ctx, rs, rt, cc, 0);
16774 break;
16775 case FMT_SDPS_D:
16776 gen_movcf_d(ctx, rs, rt, cc, 0);
16777 break;
16778 case FMT_SDPS_PS:
16779 check_ps(ctx);
16780 gen_movcf_ps(ctx, rs, rt, cc, 0);
16781 break;
16782 default:
16783 goto pool32f_invalid;
16786 break;
16787 case MOVT_FMT: /* CLASS_FMT */
16788 if (ctx->insn_flags & ISA_MIPS32R6) {
16789 /* CLASS_FMT */
16790 switch (fmt) {
16791 case FMT_SDPS_S:
16792 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16793 break;
16794 case FMT_SDPS_D:
16795 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16796 break;
16797 default:
16798 goto pool32f_invalid;
16800 } else {
16801 /* MOVT_FMT */
16802 switch (fmt) {
16803 case FMT_SDPS_S:
16804 gen_movcf_s(ctx, rs, rt, cc, 1);
16805 break;
16806 case FMT_SDPS_D:
16807 gen_movcf_d(ctx, rs, rt, cc, 1);
16808 break;
16809 case FMT_SDPS_PS:
16810 check_ps(ctx);
16811 gen_movcf_ps(ctx, rs, rt, cc, 1);
16812 break;
16813 default:
16814 goto pool32f_invalid;
16817 break;
16818 case PREFX:
16819 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16820 break;
16821 default:
16822 goto pool32f_invalid;
16824 break;
16825 #define FINSN_3ARG_SDPS(prfx) \
16826 switch ((ctx->opcode >> 8) & 0x3) { \
16827 case FMT_SDPS_S: \
16828 mips32_op = OPC_##prfx##_S; \
16829 goto do_fpop; \
16830 case FMT_SDPS_D: \
16831 mips32_op = OPC_##prfx##_D; \
16832 goto do_fpop; \
16833 case FMT_SDPS_PS: \
16834 check_ps(ctx); \
16835 mips32_op = OPC_##prfx##_PS; \
16836 goto do_fpop; \
16837 default: \
16838 goto pool32f_invalid; \
16840 case MINA_FMT:
16841 check_insn(ctx, ISA_MIPS32R6);
16842 switch ((ctx->opcode >> 9) & 0x3) {
16843 case FMT_SDPS_S:
16844 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16845 break;
16846 case FMT_SDPS_D:
16847 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16848 break;
16849 default:
16850 goto pool32f_invalid;
16852 break;
16853 case MAXA_FMT:
16854 check_insn(ctx, ISA_MIPS32R6);
16855 switch ((ctx->opcode >> 9) & 0x3) {
16856 case FMT_SDPS_S:
16857 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16858 break;
16859 case FMT_SDPS_D:
16860 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16861 break;
16862 default:
16863 goto pool32f_invalid;
16865 break;
16866 case 0x30:
16867 /* regular FP ops */
16868 switch ((ctx->opcode >> 6) & 0x3) {
16869 case ADD_FMT:
16870 FINSN_3ARG_SDPS(ADD);
16871 break;
16872 case SUB_FMT:
16873 FINSN_3ARG_SDPS(SUB);
16874 break;
16875 case MUL_FMT:
16876 FINSN_3ARG_SDPS(MUL);
16877 break;
16878 case DIV_FMT:
16879 fmt = (ctx->opcode >> 8) & 0x3;
16880 if (fmt == 1) {
16881 mips32_op = OPC_DIV_D;
16882 } else if (fmt == 0) {
16883 mips32_op = OPC_DIV_S;
16884 } else {
16885 goto pool32f_invalid;
16887 goto do_fpop;
16888 default:
16889 goto pool32f_invalid;
16891 break;
16892 case 0x38:
16893 /* cmovs */
16894 switch ((ctx->opcode >> 6) & 0x7) {
16895 case MOVN_FMT: /* SELEQZ_FMT */
16896 if (ctx->insn_flags & ISA_MIPS32R6) {
16897 /* SELEQZ_FMT */
16898 switch ((ctx->opcode >> 9) & 0x3) {
16899 case FMT_SDPS_S:
16900 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16901 break;
16902 case FMT_SDPS_D:
16903 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16904 break;
16905 default:
16906 goto pool32f_invalid;
16908 } else {
16909 /* MOVN_FMT */
16910 FINSN_3ARG_SDPS(MOVN);
16912 break;
16913 case MOVN_FMT_04:
16914 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16915 FINSN_3ARG_SDPS(MOVN);
16916 break;
16917 case MOVZ_FMT: /* SELNEZ_FMT */
16918 if (ctx->insn_flags & ISA_MIPS32R6) {
16919 /* SELNEZ_FMT */
16920 switch ((ctx->opcode >> 9) & 0x3) {
16921 case FMT_SDPS_S:
16922 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16923 break;
16924 case FMT_SDPS_D:
16925 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16926 break;
16927 default:
16928 goto pool32f_invalid;
16930 } else {
16931 /* MOVZ_FMT */
16932 FINSN_3ARG_SDPS(MOVZ);
16934 break;
16935 case MOVZ_FMT_05:
16936 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16937 FINSN_3ARG_SDPS(MOVZ);
16938 break;
16939 case SEL_FMT:
16940 check_insn(ctx, ISA_MIPS32R6);
16941 switch ((ctx->opcode >> 9) & 0x3) {
16942 case FMT_SDPS_S:
16943 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16944 break;
16945 case FMT_SDPS_D:
16946 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16947 break;
16948 default:
16949 goto pool32f_invalid;
16951 break;
16952 case MADDF_FMT:
16953 check_insn(ctx, ISA_MIPS32R6);
16954 switch ((ctx->opcode >> 9) & 0x3) {
16955 case FMT_SDPS_S:
16956 mips32_op = OPC_MADDF_S;
16957 goto do_fpop;
16958 case FMT_SDPS_D:
16959 mips32_op = OPC_MADDF_D;
16960 goto do_fpop;
16961 default:
16962 goto pool32f_invalid;
16964 break;
16965 case MSUBF_FMT:
16966 check_insn(ctx, ISA_MIPS32R6);
16967 switch ((ctx->opcode >> 9) & 0x3) {
16968 case FMT_SDPS_S:
16969 mips32_op = OPC_MSUBF_S;
16970 goto do_fpop;
16971 case FMT_SDPS_D:
16972 mips32_op = OPC_MSUBF_D;
16973 goto do_fpop;
16974 default:
16975 goto pool32f_invalid;
16977 break;
16978 default:
16979 goto pool32f_invalid;
16981 break;
16982 do_fpop:
16983 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16984 break;
16985 default:
16986 pool32f_invalid:
16987 MIPS_INVAL("pool32f");
16988 generate_exception_end(ctx, EXCP_RI);
16989 break;
16991 } else {
16992 generate_exception_err(ctx, EXCP_CpU, 1);
16994 break;
16995 case POOL32I:
16996 minor = (ctx->opcode >> 21) & 0x1f;
16997 switch (minor) {
16998 case BLTZ:
16999 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17000 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17001 break;
17002 case BLTZAL:
17003 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17004 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17005 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17006 break;
17007 case BLTZALS:
17008 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17009 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17010 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17011 break;
17012 case BGEZ:
17013 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17014 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17015 break;
17016 case BGEZAL:
17017 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17018 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17019 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17020 break;
17021 case BGEZALS:
17022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17023 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17024 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17025 break;
17026 case BLEZ:
17027 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17028 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17029 break;
17030 case BGTZ:
17031 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17032 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17033 break;
17035 /* Traps */
17036 case TLTI: /* BC1EQZC */
17037 if (ctx->insn_flags & ISA_MIPS32R6) {
17038 /* BC1EQZC */
17039 check_cp1_enabled(ctx);
17040 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17041 } else {
17042 /* TLTI */
17043 mips32_op = OPC_TLTI;
17044 goto do_trapi;
17046 break;
17047 case TGEI: /* BC1NEZC */
17048 if (ctx->insn_flags & ISA_MIPS32R6) {
17049 /* BC1NEZC */
17050 check_cp1_enabled(ctx);
17051 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17052 } else {
17053 /* TGEI */
17054 mips32_op = OPC_TGEI;
17055 goto do_trapi;
17057 break;
17058 case TLTIU:
17059 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17060 mips32_op = OPC_TLTIU;
17061 goto do_trapi;
17062 case TGEIU:
17063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17064 mips32_op = OPC_TGEIU;
17065 goto do_trapi;
17066 case TNEI: /* SYNCI */
17067 if (ctx->insn_flags & ISA_MIPS32R6) {
17068 /* SYNCI */
17070 * Break the TB to be able to sync copied instructions
17071 * immediately.
17073 ctx->base.is_jmp = DISAS_STOP;
17074 } else {
17075 /* TNEI */
17076 mips32_op = OPC_TNEI;
17077 goto do_trapi;
17079 break;
17080 case TEQI:
17081 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17082 mips32_op = OPC_TEQI;
17083 do_trapi:
17084 gen_trap(ctx, mips32_op, rs, -1, imm);
17085 break;
17087 case BNEZC:
17088 case BEQZC:
17089 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17090 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17091 4, rs, 0, imm << 1, 0);
17093 * Compact branches don't have a delay slot, so just let
17094 * the normal delay slot handling take us to the branch
17095 * target.
17097 break;
17098 case LUI:
17099 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17100 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17101 break;
17102 case SYNCI:
17103 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17105 * Break the TB to be able to sync copied instructions
17106 * immediately.
17108 ctx->base.is_jmp = DISAS_STOP;
17109 break;
17110 case BC2F:
17111 case BC2T:
17112 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17113 /* COP2: Not implemented. */
17114 generate_exception_err(ctx, EXCP_CpU, 2);
17115 break;
17116 case BC1F:
17117 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17118 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17119 goto do_cp1branch;
17120 case BC1T:
17121 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17122 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17123 goto do_cp1branch;
17124 case BC1ANY4F:
17125 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17126 mips32_op = OPC_BC1FANY4;
17127 goto do_cp1mips3d;
17128 case BC1ANY4T:
17129 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17130 mips32_op = OPC_BC1TANY4;
17131 do_cp1mips3d:
17132 check_cop1x(ctx);
17133 check_insn(ctx, ASE_MIPS3D);
17134 /* Fall through */
17135 do_cp1branch:
17136 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17137 check_cp1_enabled(ctx);
17138 gen_compute_branch1(ctx, mips32_op,
17139 (ctx->opcode >> 18) & 0x7, imm << 1);
17140 } else {
17141 generate_exception_err(ctx, EXCP_CpU, 1);
17143 break;
17144 case BPOSGE64:
17145 case BPOSGE32:
17146 /* MIPS DSP: not implemented */
17147 /* Fall through */
17148 default:
17149 MIPS_INVAL("pool32i");
17150 generate_exception_end(ctx, EXCP_RI);
17151 break;
17153 break;
17154 case POOL32C:
17155 minor = (ctx->opcode >> 12) & 0xf;
17156 offset = sextract32(ctx->opcode, 0,
17157 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
17158 switch (minor) {
17159 case LWL:
17160 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17161 mips32_op = OPC_LWL;
17162 goto do_ld_lr;
17163 case SWL:
17164 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17165 mips32_op = OPC_SWL;
17166 goto do_st_lr;
17167 case LWR:
17168 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17169 mips32_op = OPC_LWR;
17170 goto do_ld_lr;
17171 case SWR:
17172 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17173 mips32_op = OPC_SWR;
17174 goto do_st_lr;
17175 #if defined(TARGET_MIPS64)
17176 case LDL:
17177 check_insn(ctx, ISA_MIPS3);
17178 check_mips_64(ctx);
17179 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17180 mips32_op = OPC_LDL;
17181 goto do_ld_lr;
17182 case SDL:
17183 check_insn(ctx, ISA_MIPS3);
17184 check_mips_64(ctx);
17185 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17186 mips32_op = OPC_SDL;
17187 goto do_st_lr;
17188 case LDR:
17189 check_insn(ctx, ISA_MIPS3);
17190 check_mips_64(ctx);
17191 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17192 mips32_op = OPC_LDR;
17193 goto do_ld_lr;
17194 case SDR:
17195 check_insn(ctx, ISA_MIPS3);
17196 check_mips_64(ctx);
17197 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17198 mips32_op = OPC_SDR;
17199 goto do_st_lr;
17200 case LWU:
17201 check_insn(ctx, ISA_MIPS3);
17202 check_mips_64(ctx);
17203 mips32_op = OPC_LWU;
17204 goto do_ld_lr;
17205 case LLD:
17206 check_insn(ctx, ISA_MIPS3);
17207 check_mips_64(ctx);
17208 mips32_op = OPC_LLD;
17209 goto do_ld_lr;
17210 #endif
17211 case LL:
17212 mips32_op = OPC_LL;
17213 goto do_ld_lr;
17214 do_ld_lr:
17215 gen_ld(ctx, mips32_op, rt, rs, offset);
17216 break;
17217 do_st_lr:
17218 gen_st(ctx, mips32_op, rt, rs, offset);
17219 break;
17220 case SC:
17221 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17222 break;
17223 #if defined(TARGET_MIPS64)
17224 case SCD:
17225 check_insn(ctx, ISA_MIPS3);
17226 check_mips_64(ctx);
17227 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17228 break;
17229 #endif
17230 case LD_EVA:
17231 if (!ctx->eva) {
17232 MIPS_INVAL("pool32c ld-eva");
17233 generate_exception_end(ctx, EXCP_RI);
17234 break;
17236 check_cp0_enabled(ctx);
17238 minor2 = (ctx->opcode >> 9) & 0x7;
17239 offset = sextract32(ctx->opcode, 0, 9);
17240 switch (minor2) {
17241 case LBUE:
17242 mips32_op = OPC_LBUE;
17243 goto do_ld_lr;
17244 case LHUE:
17245 mips32_op = OPC_LHUE;
17246 goto do_ld_lr;
17247 case LWLE:
17248 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17249 mips32_op = OPC_LWLE;
17250 goto do_ld_lr;
17251 case LWRE:
17252 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17253 mips32_op = OPC_LWRE;
17254 goto do_ld_lr;
17255 case LBE:
17256 mips32_op = OPC_LBE;
17257 goto do_ld_lr;
17258 case LHE:
17259 mips32_op = OPC_LHE;
17260 goto do_ld_lr;
17261 case LLE:
17262 mips32_op = OPC_LLE;
17263 goto do_ld_lr;
17264 case LWE:
17265 mips32_op = OPC_LWE;
17266 goto do_ld_lr;
17268 break;
17269 case ST_EVA:
17270 if (!ctx->eva) {
17271 MIPS_INVAL("pool32c st-eva");
17272 generate_exception_end(ctx, EXCP_RI);
17273 break;
17275 check_cp0_enabled(ctx);
17277 minor2 = (ctx->opcode >> 9) & 0x7;
17278 offset = sextract32(ctx->opcode, 0, 9);
17279 switch (minor2) {
17280 case SWLE:
17281 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17282 mips32_op = OPC_SWLE;
17283 goto do_st_lr;
17284 case SWRE:
17285 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17286 mips32_op = OPC_SWRE;
17287 goto do_st_lr;
17288 case PREFE:
17289 /* Treat as no-op */
17290 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17291 /* hint codes 24-31 are reserved and signal RI */
17292 generate_exception(ctx, EXCP_RI);
17294 break;
17295 case CACHEE:
17296 /* Treat as no-op */
17297 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17298 gen_cache_operation(ctx, rt, rs, offset);
17300 break;
17301 case SBE:
17302 mips32_op = OPC_SBE;
17303 goto do_st_lr;
17304 case SHE:
17305 mips32_op = OPC_SHE;
17306 goto do_st_lr;
17307 case SCE:
17308 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17309 break;
17310 case SWE:
17311 mips32_op = OPC_SWE;
17312 goto do_st_lr;
17314 break;
17315 case PREF:
17316 /* Treat as no-op */
17317 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17318 /* hint codes 24-31 are reserved and signal RI */
17319 generate_exception(ctx, EXCP_RI);
17321 break;
17322 default:
17323 MIPS_INVAL("pool32c");
17324 generate_exception_end(ctx, EXCP_RI);
17325 break;
17327 break;
17328 case ADDI32: /* AUI, LUI */
17329 if (ctx->insn_flags & ISA_MIPS32R6) {
17330 /* AUI, LUI */
17331 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17332 } else {
17333 /* ADDI32 */
17334 mips32_op = OPC_ADDI;
17335 goto do_addi;
17337 break;
17338 case ADDIU32:
17339 mips32_op = OPC_ADDIU;
17340 do_addi:
17341 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17342 break;
17344 /* Logical operations */
17345 case ORI32:
17346 mips32_op = OPC_ORI;
17347 goto do_logici;
17348 case XORI32:
17349 mips32_op = OPC_XORI;
17350 goto do_logici;
17351 case ANDI32:
17352 mips32_op = OPC_ANDI;
17353 do_logici:
17354 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17355 break;
17357 /* Set less than immediate */
17358 case SLTI32:
17359 mips32_op = OPC_SLTI;
17360 goto do_slti;
17361 case SLTIU32:
17362 mips32_op = OPC_SLTIU;
17363 do_slti:
17364 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17365 break;
17366 case JALX32:
17367 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17368 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17369 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17370 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17371 break;
17372 case JALS32: /* BOVC, BEQC, BEQZALC */
17373 if (ctx->insn_flags & ISA_MIPS32R6) {
17374 if (rs >= rt) {
17375 /* BOVC */
17376 mips32_op = OPC_BOVC;
17377 } else if (rs < rt && rs == 0) {
17378 /* BEQZALC */
17379 mips32_op = OPC_BEQZALC;
17380 } else {
17381 /* BEQC */
17382 mips32_op = OPC_BEQC;
17384 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17385 } else {
17386 /* JALS32 */
17387 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17388 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17389 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17391 break;
17392 case BEQ32: /* BC */
17393 if (ctx->insn_flags & ISA_MIPS32R6) {
17394 /* BC */
17395 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17396 sextract32(ctx->opcode << 1, 0, 27));
17397 } else {
17398 /* BEQ32 */
17399 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17401 break;
17402 case BNE32: /* BALC */
17403 if (ctx->insn_flags & ISA_MIPS32R6) {
17404 /* BALC */
17405 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17406 sextract32(ctx->opcode << 1, 0, 27));
17407 } else {
17408 /* BNE32 */
17409 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17411 break;
17412 case J32: /* BGTZC, BLTZC, BLTC */
17413 if (ctx->insn_flags & ISA_MIPS32R6) {
17414 if (rs == 0 && rt != 0) {
17415 /* BGTZC */
17416 mips32_op = OPC_BGTZC;
17417 } else if (rs != 0 && rt != 0 && rs == rt) {
17418 /* BLTZC */
17419 mips32_op = OPC_BLTZC;
17420 } else {
17421 /* BLTC */
17422 mips32_op = OPC_BLTC;
17424 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17425 } else {
17426 /* J32 */
17427 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17428 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17430 break;
17431 case JAL32: /* BLEZC, BGEZC, BGEC */
17432 if (ctx->insn_flags & ISA_MIPS32R6) {
17433 if (rs == 0 && rt != 0) {
17434 /* BLEZC */
17435 mips32_op = OPC_BLEZC;
17436 } else if (rs != 0 && rt != 0 && rs == rt) {
17437 /* BGEZC */
17438 mips32_op = OPC_BGEZC;
17439 } else {
17440 /* BGEC */
17441 mips32_op = OPC_BGEC;
17443 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17444 } else {
17445 /* JAL32 */
17446 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17447 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17448 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17450 break;
17451 /* Floating point (COP1) */
17452 case LWC132:
17453 mips32_op = OPC_LWC1;
17454 goto do_cop1;
17455 case LDC132:
17456 mips32_op = OPC_LDC1;
17457 goto do_cop1;
17458 case SWC132:
17459 mips32_op = OPC_SWC1;
17460 goto do_cop1;
17461 case SDC132:
17462 mips32_op = OPC_SDC1;
17463 do_cop1:
17464 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17465 break;
17466 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17467 if (ctx->insn_flags & ISA_MIPS32R6) {
17468 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17469 switch ((ctx->opcode >> 16) & 0x1f) {
17470 case ADDIUPC_00:
17471 case ADDIUPC_01:
17472 case ADDIUPC_02:
17473 case ADDIUPC_03:
17474 case ADDIUPC_04:
17475 case ADDIUPC_05:
17476 case ADDIUPC_06:
17477 case ADDIUPC_07:
17478 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17479 break;
17480 case AUIPC:
17481 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17482 break;
17483 case ALUIPC:
17484 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17485 break;
17486 case LWPC_08:
17487 case LWPC_09:
17488 case LWPC_0A:
17489 case LWPC_0B:
17490 case LWPC_0C:
17491 case LWPC_0D:
17492 case LWPC_0E:
17493 case LWPC_0F:
17494 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17495 break;
17496 default:
17497 generate_exception(ctx, EXCP_RI);
17498 break;
17500 } else {
17501 /* ADDIUPC */
17502 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17503 offset = SIMM(ctx->opcode, 0, 23) << 2;
17505 gen_addiupc(ctx, reg, offset, 0, 0);
17507 break;
17508 case BNVC: /* BNEC, BNEZALC */
17509 check_insn(ctx, ISA_MIPS32R6);
17510 if (rs >= rt) {
17511 /* BNVC */
17512 mips32_op = OPC_BNVC;
17513 } else if (rs < rt && rs == 0) {
17514 /* BNEZALC */
17515 mips32_op = OPC_BNEZALC;
17516 } else {
17517 /* BNEC */
17518 mips32_op = OPC_BNEC;
17520 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17521 break;
17522 case R6_BNEZC: /* JIALC */
17523 check_insn(ctx, ISA_MIPS32R6);
17524 if (rt != 0) {
17525 /* BNEZC */
17526 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17527 sextract32(ctx->opcode << 1, 0, 22));
17528 } else {
17529 /* JIALC */
17530 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17532 break;
17533 case R6_BEQZC: /* JIC */
17534 check_insn(ctx, ISA_MIPS32R6);
17535 if (rt != 0) {
17536 /* BEQZC */
17537 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17538 sextract32(ctx->opcode << 1, 0, 22));
17539 } else {
17540 /* JIC */
17541 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17543 break;
17544 case BLEZALC: /* BGEZALC, BGEUC */
17545 check_insn(ctx, ISA_MIPS32R6);
17546 if (rs == 0 && rt != 0) {
17547 /* BLEZALC */
17548 mips32_op = OPC_BLEZALC;
17549 } else if (rs != 0 && rt != 0 && rs == rt) {
17550 /* BGEZALC */
17551 mips32_op = OPC_BGEZALC;
17552 } else {
17553 /* BGEUC */
17554 mips32_op = OPC_BGEUC;
17556 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17557 break;
17558 case BGTZALC: /* BLTZALC, BLTUC */
17559 check_insn(ctx, ISA_MIPS32R6);
17560 if (rs == 0 && rt != 0) {
17561 /* BGTZALC */
17562 mips32_op = OPC_BGTZALC;
17563 } else if (rs != 0 && rt != 0 && rs == rt) {
17564 /* BLTZALC */
17565 mips32_op = OPC_BLTZALC;
17566 } else {
17567 /* BLTUC */
17568 mips32_op = OPC_BLTUC;
17570 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17571 break;
17572 /* Loads and stores */
17573 case LB32:
17574 mips32_op = OPC_LB;
17575 goto do_ld;
17576 case LBU32:
17577 mips32_op = OPC_LBU;
17578 goto do_ld;
17579 case LH32:
17580 mips32_op = OPC_LH;
17581 goto do_ld;
17582 case LHU32:
17583 mips32_op = OPC_LHU;
17584 goto do_ld;
17585 case LW32:
17586 mips32_op = OPC_LW;
17587 goto do_ld;
17588 #ifdef TARGET_MIPS64
17589 case LD32:
17590 check_insn(ctx, ISA_MIPS3);
17591 check_mips_64(ctx);
17592 mips32_op = OPC_LD;
17593 goto do_ld;
17594 case SD32:
17595 check_insn(ctx, ISA_MIPS3);
17596 check_mips_64(ctx);
17597 mips32_op = OPC_SD;
17598 goto do_st;
17599 #endif
17600 case SB32:
17601 mips32_op = OPC_SB;
17602 goto do_st;
17603 case SH32:
17604 mips32_op = OPC_SH;
17605 goto do_st;
17606 case SW32:
17607 mips32_op = OPC_SW;
17608 goto do_st;
17609 do_ld:
17610 gen_ld(ctx, mips32_op, rt, rs, imm);
17611 break;
17612 do_st:
17613 gen_st(ctx, mips32_op, rt, rs, imm);
17614 break;
17615 default:
17616 generate_exception_end(ctx, EXCP_RI);
17617 break;
17621 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17623 uint32_t op;
17625 /* make sure instructions are on a halfword boundary */
17626 if (ctx->base.pc_next & 0x1) {
17627 env->CP0_BadVAddr = ctx->base.pc_next;
17628 generate_exception_end(ctx, EXCP_AdEL);
17629 return 2;
17632 op = (ctx->opcode >> 10) & 0x3f;
17633 /* Enforce properly-sized instructions in a delay slot */
17634 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17635 switch (op & 0x7) { /* MSB-3..MSB-5 */
17636 case 0:
17637 /* POOL32A, POOL32B, POOL32I, POOL32C */
17638 case 4:
17639 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17640 case 5:
17641 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17642 case 6:
17643 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17644 case 7:
17645 /* LB32, LH32, LWC132, LDC132, LW32 */
17646 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17647 generate_exception_end(ctx, EXCP_RI);
17648 return 2;
17650 break;
17651 case 1:
17652 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17653 case 2:
17654 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17655 case 3:
17656 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17657 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17658 generate_exception_end(ctx, EXCP_RI);
17659 return 2;
17661 break;
17665 switch (op) {
17666 case POOL16A:
17668 int rd = mmreg(uMIPS_RD(ctx->opcode));
17669 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17670 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17671 uint32_t opc = 0;
17673 switch (ctx->opcode & 0x1) {
17674 case ADDU16:
17675 opc = OPC_ADDU;
17676 break;
17677 case SUBU16:
17678 opc = OPC_SUBU;
17679 break;
17681 if (ctx->insn_flags & ISA_MIPS32R6) {
17683 * In the Release 6, the register number location in
17684 * the instruction encoding has changed.
17686 gen_arith(ctx, opc, rs1, rd, rs2);
17687 } else {
17688 gen_arith(ctx, opc, rd, rs1, rs2);
17691 break;
17692 case POOL16B:
17694 int rd = mmreg(uMIPS_RD(ctx->opcode));
17695 int rs = mmreg(uMIPS_RS(ctx->opcode));
17696 int amount = (ctx->opcode >> 1) & 0x7;
17697 uint32_t opc = 0;
17698 amount = amount == 0 ? 8 : amount;
17700 switch (ctx->opcode & 0x1) {
17701 case SLL16:
17702 opc = OPC_SLL;
17703 break;
17704 case SRL16:
17705 opc = OPC_SRL;
17706 break;
17709 gen_shift_imm(ctx, opc, rd, rs, amount);
17711 break;
17712 case POOL16C:
17713 if (ctx->insn_flags & ISA_MIPS32R6) {
17714 gen_pool16c_r6_insn(ctx);
17715 } else {
17716 gen_pool16c_insn(ctx);
17718 break;
17719 case LWGP16:
17721 int rd = mmreg(uMIPS_RD(ctx->opcode));
17722 int rb = 28; /* GP */
17723 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17725 gen_ld(ctx, OPC_LW, rd, rb, offset);
17727 break;
17728 case POOL16F:
17729 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17730 if (ctx->opcode & 1) {
17731 generate_exception_end(ctx, EXCP_RI);
17732 } else {
17733 /* MOVEP */
17734 int enc_dest = uMIPS_RD(ctx->opcode);
17735 int enc_rt = uMIPS_RS2(ctx->opcode);
17736 int enc_rs = uMIPS_RS1(ctx->opcode);
17737 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17739 break;
17740 case LBU16:
17742 int rd = mmreg(uMIPS_RD(ctx->opcode));
17743 int rb = mmreg(uMIPS_RS(ctx->opcode));
17744 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17745 offset = (offset == 0xf ? -1 : offset);
17747 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17749 break;
17750 case LHU16:
17752 int rd = mmreg(uMIPS_RD(ctx->opcode));
17753 int rb = mmreg(uMIPS_RS(ctx->opcode));
17754 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17756 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17758 break;
17759 case LWSP16:
17761 int rd = (ctx->opcode >> 5) & 0x1f;
17762 int rb = 29; /* SP */
17763 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17765 gen_ld(ctx, OPC_LW, rd, rb, offset);
17767 break;
17768 case LW16:
17770 int rd = mmreg(uMIPS_RD(ctx->opcode));
17771 int rb = mmreg(uMIPS_RS(ctx->opcode));
17772 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17774 gen_ld(ctx, OPC_LW, rd, rb, offset);
17776 break;
17777 case SB16:
17779 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17780 int rb = mmreg(uMIPS_RS(ctx->opcode));
17781 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17783 gen_st(ctx, OPC_SB, rd, rb, offset);
17785 break;
17786 case SH16:
17788 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17789 int rb = mmreg(uMIPS_RS(ctx->opcode));
17790 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17792 gen_st(ctx, OPC_SH, rd, rb, offset);
17794 break;
17795 case SWSP16:
17797 int rd = (ctx->opcode >> 5) & 0x1f;
17798 int rb = 29; /* SP */
17799 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17801 gen_st(ctx, OPC_SW, rd, rb, offset);
17803 break;
17804 case SW16:
17806 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17807 int rb = mmreg(uMIPS_RS(ctx->opcode));
17808 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17810 gen_st(ctx, OPC_SW, rd, rb, offset);
17812 break;
17813 case MOVE16:
17815 int rd = uMIPS_RD5(ctx->opcode);
17816 int rs = uMIPS_RS5(ctx->opcode);
17818 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17820 break;
17821 case ANDI16:
17822 gen_andi16(ctx);
17823 break;
17824 case POOL16D:
17825 switch (ctx->opcode & 0x1) {
17826 case ADDIUS5:
17827 gen_addius5(ctx);
17828 break;
17829 case ADDIUSP:
17830 gen_addiusp(ctx);
17831 break;
17833 break;
17834 case POOL16E:
17835 switch (ctx->opcode & 0x1) {
17836 case ADDIUR2:
17837 gen_addiur2(ctx);
17838 break;
17839 case ADDIUR1SP:
17840 gen_addiur1sp(ctx);
17841 break;
17843 break;
17844 case B16: /* BC16 */
17845 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17846 sextract32(ctx->opcode, 0, 10) << 1,
17847 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17848 break;
17849 case BNEZ16: /* BNEZC16 */
17850 case BEQZ16: /* BEQZC16 */
17851 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17852 mmreg(uMIPS_RD(ctx->opcode)),
17853 0, sextract32(ctx->opcode, 0, 7) << 1,
17854 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17856 break;
17857 case LI16:
17859 int reg = mmreg(uMIPS_RD(ctx->opcode));
17860 int imm = ZIMM(ctx->opcode, 0, 7);
17862 imm = (imm == 0x7f ? -1 : imm);
17863 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17865 break;
17866 case RES_29:
17867 case RES_31:
17868 case RES_39:
17869 generate_exception_end(ctx, EXCP_RI);
17870 break;
17871 default:
17872 decode_micromips32_opc(env, ctx);
17873 return 4;
17876 return 2;
17881 * nanoMIPS opcodes
17885 /* MAJOR, P16, and P32 pools opcodes */
17886 enum {
17887 NM_P_ADDIU = 0x00,
17888 NM_ADDIUPC = 0x01,
17889 NM_MOVE_BALC = 0x02,
17890 NM_P16_MV = 0x04,
17891 NM_LW16 = 0x05,
17892 NM_BC16 = 0x06,
17893 NM_P16_SR = 0x07,
17895 NM_POOL32A = 0x08,
17896 NM_P_BAL = 0x0a,
17897 NM_P16_SHIFT = 0x0c,
17898 NM_LWSP16 = 0x0d,
17899 NM_BALC16 = 0x0e,
17900 NM_P16_4X4 = 0x0f,
17902 NM_P_GP_W = 0x10,
17903 NM_P_GP_BH = 0x11,
17904 NM_P_J = 0x12,
17905 NM_P16C = 0x14,
17906 NM_LWGP16 = 0x15,
17907 NM_P16_LB = 0x17,
17909 NM_P48I = 0x18,
17910 NM_P16_A1 = 0x1c,
17911 NM_LW4X4 = 0x1d,
17912 NM_P16_LH = 0x1f,
17914 NM_P_U12 = 0x20,
17915 NM_P_LS_U12 = 0x21,
17916 NM_P_BR1 = 0x22,
17917 NM_P16_A2 = 0x24,
17918 NM_SW16 = 0x25,
17919 NM_BEQZC16 = 0x26,
17921 NM_POOL32F = 0x28,
17922 NM_P_LS_S9 = 0x29,
17923 NM_P_BR2 = 0x2a,
17925 NM_P16_ADDU = 0x2c,
17926 NM_SWSP16 = 0x2d,
17927 NM_BNEZC16 = 0x2e,
17928 NM_MOVEP = 0x2f,
17930 NM_POOL32S = 0x30,
17931 NM_P_BRI = 0x32,
17932 NM_LI16 = 0x34,
17933 NM_SWGP16 = 0x35,
17934 NM_P16_BR = 0x36,
17936 NM_P_LUI = 0x38,
17937 NM_ANDI16 = 0x3c,
17938 NM_SW4X4 = 0x3d,
17939 NM_MOVEPREV = 0x3f,
17942 /* POOL32A instruction pool */
17943 enum {
17944 NM_POOL32A0 = 0x00,
17945 NM_SPECIAL2 = 0x01,
17946 NM_COP2_1 = 0x02,
17947 NM_UDI = 0x03,
17948 NM_POOL32A5 = 0x05,
17949 NM_POOL32A7 = 0x07,
17952 /* P.GP.W instruction pool */
17953 enum {
17954 NM_ADDIUGP_W = 0x00,
17955 NM_LWGP = 0x02,
17956 NM_SWGP = 0x03,
17959 /* P48I instruction pool */
17960 enum {
17961 NM_LI48 = 0x00,
17962 NM_ADDIU48 = 0x01,
17963 NM_ADDIUGP48 = 0x02,
17964 NM_ADDIUPC48 = 0x03,
17965 NM_LWPC48 = 0x0b,
17966 NM_SWPC48 = 0x0f,
17969 /* P.U12 instruction pool */
17970 enum {
17971 NM_ORI = 0x00,
17972 NM_XORI = 0x01,
17973 NM_ANDI = 0x02,
17974 NM_P_SR = 0x03,
17975 NM_SLTI = 0x04,
17976 NM_SLTIU = 0x05,
17977 NM_SEQI = 0x06,
17978 NM_ADDIUNEG = 0x08,
17979 NM_P_SHIFT = 0x0c,
17980 NM_P_ROTX = 0x0d,
17981 NM_P_INS = 0x0e,
17982 NM_P_EXT = 0x0f,
17985 /* POOL32F instruction pool */
17986 enum {
17987 NM_POOL32F_0 = 0x00,
17988 NM_POOL32F_3 = 0x03,
17989 NM_POOL32F_5 = 0x05,
17992 /* POOL32S instruction pool */
17993 enum {
17994 NM_POOL32S_0 = 0x00,
17995 NM_POOL32S_4 = 0x04,
17998 /* P.LUI instruction pool */
17999 enum {
18000 NM_LUI = 0x00,
18001 NM_ALUIPC = 0x01,
18004 /* P.GP.BH instruction pool */
18005 enum {
18006 NM_LBGP = 0x00,
18007 NM_SBGP = 0x01,
18008 NM_LBUGP = 0x02,
18009 NM_ADDIUGP_B = 0x03,
18010 NM_P_GP_LH = 0x04,
18011 NM_P_GP_SH = 0x05,
18012 NM_P_GP_CP1 = 0x06,
18015 /* P.LS.U12 instruction pool */
18016 enum {
18017 NM_LB = 0x00,
18018 NM_SB = 0x01,
18019 NM_LBU = 0x02,
18020 NM_P_PREFU12 = 0x03,
18021 NM_LH = 0x04,
18022 NM_SH = 0x05,
18023 NM_LHU = 0x06,
18024 NM_LWU = 0x07,
18025 NM_LW = 0x08,
18026 NM_SW = 0x09,
18027 NM_LWC1 = 0x0a,
18028 NM_SWC1 = 0x0b,
18029 NM_LDC1 = 0x0e,
18030 NM_SDC1 = 0x0f,
18033 /* P.LS.S9 instruction pool */
18034 enum {
18035 NM_P_LS_S0 = 0x00,
18036 NM_P_LS_S1 = 0x01,
18037 NM_P_LS_E0 = 0x02,
18038 NM_P_LS_WM = 0x04,
18039 NM_P_LS_UAWM = 0x05,
18042 /* P.BAL instruction pool */
18043 enum {
18044 NM_BC = 0x00,
18045 NM_BALC = 0x01,
18048 /* P.J instruction pool */
18049 enum {
18050 NM_JALRC = 0x00,
18051 NM_JALRC_HB = 0x01,
18052 NM_P_BALRSC = 0x08,
18055 /* P.BR1 instruction pool */
18056 enum {
18057 NM_BEQC = 0x00,
18058 NM_P_BR3A = 0x01,
18059 NM_BGEC = 0x02,
18060 NM_BGEUC = 0x03,
18063 /* P.BR2 instruction pool */
18064 enum {
18065 NM_BNEC = 0x00,
18066 NM_BLTC = 0x02,
18067 NM_BLTUC = 0x03,
18070 /* P.BRI instruction pool */
18071 enum {
18072 NM_BEQIC = 0x00,
18073 NM_BBEQZC = 0x01,
18074 NM_BGEIC = 0x02,
18075 NM_BGEIUC = 0x03,
18076 NM_BNEIC = 0x04,
18077 NM_BBNEZC = 0x05,
18078 NM_BLTIC = 0x06,
18079 NM_BLTIUC = 0x07,
18082 /* P16.SHIFT instruction pool */
18083 enum {
18084 NM_SLL16 = 0x00,
18085 NM_SRL16 = 0x01,
18088 /* POOL16C instruction pool */
18089 enum {
18090 NM_POOL16C_0 = 0x00,
18091 NM_LWXS16 = 0x01,
18094 /* P16.A1 instruction pool */
18095 enum {
18096 NM_ADDIUR1SP = 0x01,
18099 /* P16.A2 instruction pool */
18100 enum {
18101 NM_ADDIUR2 = 0x00,
18102 NM_P_ADDIURS5 = 0x01,
18105 /* P16.ADDU instruction pool */
18106 enum {
18107 NM_ADDU16 = 0x00,
18108 NM_SUBU16 = 0x01,
18111 /* P16.SR instruction pool */
18112 enum {
18113 NM_SAVE16 = 0x00,
18114 NM_RESTORE_JRC16 = 0x01,
18117 /* P16.4X4 instruction pool */
18118 enum {
18119 NM_ADDU4X4 = 0x00,
18120 NM_MUL4X4 = 0x01,
18123 /* P16.LB instruction pool */
18124 enum {
18125 NM_LB16 = 0x00,
18126 NM_SB16 = 0x01,
18127 NM_LBU16 = 0x02,
18130 /* P16.LH instruction pool */
18131 enum {
18132 NM_LH16 = 0x00,
18133 NM_SH16 = 0x01,
18134 NM_LHU16 = 0x02,
18137 /* P.RI instruction pool */
18138 enum {
18139 NM_SIGRIE = 0x00,
18140 NM_P_SYSCALL = 0x01,
18141 NM_BREAK = 0x02,
18142 NM_SDBBP = 0x03,
18145 /* POOL32A0 instruction pool */
18146 enum {
18147 NM_P_TRAP = 0x00,
18148 NM_SEB = 0x01,
18149 NM_SLLV = 0x02,
18150 NM_MUL = 0x03,
18151 NM_MFC0 = 0x06,
18152 NM_MFHC0 = 0x07,
18153 NM_SEH = 0x09,
18154 NM_SRLV = 0x0a,
18155 NM_MUH = 0x0b,
18156 NM_MTC0 = 0x0e,
18157 NM_MTHC0 = 0x0f,
18158 NM_SRAV = 0x12,
18159 NM_MULU = 0x13,
18160 NM_ROTRV = 0x1a,
18161 NM_MUHU = 0x1b,
18162 NM_ADD = 0x22,
18163 NM_DIV = 0x23,
18164 NM_ADDU = 0x2a,
18165 NM_MOD = 0x2b,
18166 NM_SUB = 0x32,
18167 NM_DIVU = 0x33,
18168 NM_RDHWR = 0x38,
18169 NM_SUBU = 0x3a,
18170 NM_MODU = 0x3b,
18171 NM_P_CMOVE = 0x42,
18172 NM_FORK = 0x45,
18173 NM_MFTR = 0x46,
18174 NM_MFHTR = 0x47,
18175 NM_AND = 0x4a,
18176 NM_YIELD = 0x4d,
18177 NM_MTTR = 0x4e,
18178 NM_MTHTR = 0x4f,
18179 NM_OR = 0x52,
18180 NM_D_E_MT_VPE = 0x56,
18181 NM_NOR = 0x5a,
18182 NM_XOR = 0x62,
18183 NM_SLT = 0x6a,
18184 NM_P_SLTU = 0x72,
18185 NM_SOV = 0x7a,
18188 /* CRC32 instruction pool */
18189 enum {
18190 NM_CRC32B = 0x00,
18191 NM_CRC32H = 0x01,
18192 NM_CRC32W = 0x02,
18193 NM_CRC32CB = 0x04,
18194 NM_CRC32CH = 0x05,
18195 NM_CRC32CW = 0x06,
18198 /* POOL32A5 instruction pool */
18199 enum {
18200 NM_CMP_EQ_PH = 0x00,
18201 NM_CMP_LT_PH = 0x08,
18202 NM_CMP_LE_PH = 0x10,
18203 NM_CMPGU_EQ_QB = 0x18,
18204 NM_CMPGU_LT_QB = 0x20,
18205 NM_CMPGU_LE_QB = 0x28,
18206 NM_CMPGDU_EQ_QB = 0x30,
18207 NM_CMPGDU_LT_QB = 0x38,
18208 NM_CMPGDU_LE_QB = 0x40,
18209 NM_CMPU_EQ_QB = 0x48,
18210 NM_CMPU_LT_QB = 0x50,
18211 NM_CMPU_LE_QB = 0x58,
18212 NM_ADDQ_S_W = 0x60,
18213 NM_SUBQ_S_W = 0x68,
18214 NM_ADDSC = 0x70,
18215 NM_ADDWC = 0x78,
18217 NM_ADDQ_S_PH = 0x01,
18218 NM_ADDQH_R_PH = 0x09,
18219 NM_ADDQH_R_W = 0x11,
18220 NM_ADDU_S_QB = 0x19,
18221 NM_ADDU_S_PH = 0x21,
18222 NM_ADDUH_R_QB = 0x29,
18223 NM_SHRAV_R_PH = 0x31,
18224 NM_SHRAV_R_QB = 0x39,
18225 NM_SUBQ_S_PH = 0x41,
18226 NM_SUBQH_R_PH = 0x49,
18227 NM_SUBQH_R_W = 0x51,
18228 NM_SUBU_S_QB = 0x59,
18229 NM_SUBU_S_PH = 0x61,
18230 NM_SUBUH_R_QB = 0x69,
18231 NM_SHLLV_S_PH = 0x71,
18232 NM_PRECR_SRA_R_PH_W = 0x79,
18234 NM_MULEU_S_PH_QBL = 0x12,
18235 NM_MULEU_S_PH_QBR = 0x1a,
18236 NM_MULQ_RS_PH = 0x22,
18237 NM_MULQ_S_PH = 0x2a,
18238 NM_MULQ_RS_W = 0x32,
18239 NM_MULQ_S_W = 0x3a,
18240 NM_APPEND = 0x42,
18241 NM_MODSUB = 0x52,
18242 NM_SHRAV_R_W = 0x5a,
18243 NM_SHRLV_PH = 0x62,
18244 NM_SHRLV_QB = 0x6a,
18245 NM_SHLLV_QB = 0x72,
18246 NM_SHLLV_S_W = 0x7a,
18248 NM_SHILO = 0x03,
18250 NM_MULEQ_S_W_PHL = 0x04,
18251 NM_MULEQ_S_W_PHR = 0x0c,
18253 NM_MUL_S_PH = 0x05,
18254 NM_PRECR_QB_PH = 0x0d,
18255 NM_PRECRQ_QB_PH = 0x15,
18256 NM_PRECRQ_PH_W = 0x1d,
18257 NM_PRECRQ_RS_PH_W = 0x25,
18258 NM_PRECRQU_S_QB_PH = 0x2d,
18259 NM_PACKRL_PH = 0x35,
18260 NM_PICK_QB = 0x3d,
18261 NM_PICK_PH = 0x45,
18263 NM_SHRA_R_W = 0x5e,
18264 NM_SHRA_R_PH = 0x66,
18265 NM_SHLL_S_PH = 0x76,
18266 NM_SHLL_S_W = 0x7e,
18268 NM_REPL_PH = 0x07
18271 /* POOL32A7 instruction pool */
18272 enum {
18273 NM_P_LSX = 0x00,
18274 NM_LSA = 0x01,
18275 NM_EXTW = 0x03,
18276 NM_POOL32AXF = 0x07,
18279 /* P.SR instruction pool */
18280 enum {
18281 NM_PP_SR = 0x00,
18282 NM_P_SR_F = 0x01,
18285 /* P.SHIFT instruction pool */
18286 enum {
18287 NM_P_SLL = 0x00,
18288 NM_SRL = 0x02,
18289 NM_SRA = 0x04,
18290 NM_ROTR = 0x06,
18293 /* P.ROTX instruction pool */
18294 enum {
18295 NM_ROTX = 0x00,
18298 /* P.INS instruction pool */
18299 enum {
18300 NM_INS = 0x00,
18303 /* P.EXT instruction pool */
18304 enum {
18305 NM_EXT = 0x00,
18308 /* POOL32F_0 (fmt) instruction pool */
18309 enum {
18310 NM_RINT_S = 0x04,
18311 NM_RINT_D = 0x44,
18312 NM_ADD_S = 0x06,
18313 NM_SELEQZ_S = 0x07,
18314 NM_SELEQZ_D = 0x47,
18315 NM_CLASS_S = 0x0c,
18316 NM_CLASS_D = 0x4c,
18317 NM_SUB_S = 0x0e,
18318 NM_SELNEZ_S = 0x0f,
18319 NM_SELNEZ_D = 0x4f,
18320 NM_MUL_S = 0x16,
18321 NM_SEL_S = 0x17,
18322 NM_SEL_D = 0x57,
18323 NM_DIV_S = 0x1e,
18324 NM_ADD_D = 0x26,
18325 NM_SUB_D = 0x2e,
18326 NM_MUL_D = 0x36,
18327 NM_MADDF_S = 0x37,
18328 NM_MADDF_D = 0x77,
18329 NM_DIV_D = 0x3e,
18330 NM_MSUBF_S = 0x3f,
18331 NM_MSUBF_D = 0x7f,
18334 /* POOL32F_3 instruction pool */
18335 enum {
18336 NM_MIN_FMT = 0x00,
18337 NM_MAX_FMT = 0x01,
18338 NM_MINA_FMT = 0x04,
18339 NM_MAXA_FMT = 0x05,
18340 NM_POOL32FXF = 0x07,
18343 /* POOL32F_5 instruction pool */
18344 enum {
18345 NM_CMP_CONDN_S = 0x00,
18346 NM_CMP_CONDN_D = 0x02,
18349 /* P.GP.LH instruction pool */
18350 enum {
18351 NM_LHGP = 0x00,
18352 NM_LHUGP = 0x01,
18355 /* P.GP.SH instruction pool */
18356 enum {
18357 NM_SHGP = 0x00,
18360 /* P.GP.CP1 instruction pool */
18361 enum {
18362 NM_LWC1GP = 0x00,
18363 NM_SWC1GP = 0x01,
18364 NM_LDC1GP = 0x02,
18365 NM_SDC1GP = 0x03,
18368 /* P.LS.S0 instruction pool */
18369 enum {
18370 NM_LBS9 = 0x00,
18371 NM_LHS9 = 0x04,
18372 NM_LWS9 = 0x08,
18373 NM_LDS9 = 0x0c,
18375 NM_SBS9 = 0x01,
18376 NM_SHS9 = 0x05,
18377 NM_SWS9 = 0x09,
18378 NM_SDS9 = 0x0d,
18380 NM_LBUS9 = 0x02,
18381 NM_LHUS9 = 0x06,
18382 NM_LWC1S9 = 0x0a,
18383 NM_LDC1S9 = 0x0e,
18385 NM_P_PREFS9 = 0x03,
18386 NM_LWUS9 = 0x07,
18387 NM_SWC1S9 = 0x0b,
18388 NM_SDC1S9 = 0x0f,
18391 /* P.LS.S1 instruction pool */
18392 enum {
18393 NM_ASET_ACLR = 0x02,
18394 NM_UALH = 0x04,
18395 NM_UASH = 0x05,
18396 NM_CACHE = 0x07,
18397 NM_P_LL = 0x0a,
18398 NM_P_SC = 0x0b,
18401 /* P.LS.E0 instruction pool */
18402 enum {
18403 NM_LBE = 0x00,
18404 NM_SBE = 0x01,
18405 NM_LBUE = 0x02,
18406 NM_P_PREFE = 0x03,
18407 NM_LHE = 0x04,
18408 NM_SHE = 0x05,
18409 NM_LHUE = 0x06,
18410 NM_CACHEE = 0x07,
18411 NM_LWE = 0x08,
18412 NM_SWE = 0x09,
18413 NM_P_LLE = 0x0a,
18414 NM_P_SCE = 0x0b,
18417 /* P.PREFE instruction pool */
18418 enum {
18419 NM_SYNCIE = 0x00,
18420 NM_PREFE = 0x01,
18423 /* P.LLE instruction pool */
18424 enum {
18425 NM_LLE = 0x00,
18426 NM_LLWPE = 0x01,
18429 /* P.SCE instruction pool */
18430 enum {
18431 NM_SCE = 0x00,
18432 NM_SCWPE = 0x01,
18435 /* P.LS.WM instruction pool */
18436 enum {
18437 NM_LWM = 0x00,
18438 NM_SWM = 0x01,
18441 /* P.LS.UAWM instruction pool */
18442 enum {
18443 NM_UALWM = 0x00,
18444 NM_UASWM = 0x01,
18447 /* P.BR3A instruction pool */
18448 enum {
18449 NM_BC1EQZC = 0x00,
18450 NM_BC1NEZC = 0x01,
18451 NM_BC2EQZC = 0x02,
18452 NM_BC2NEZC = 0x03,
18453 NM_BPOSGE32C = 0x04,
18456 /* P16.RI instruction pool */
18457 enum {
18458 NM_P16_SYSCALL = 0x01,
18459 NM_BREAK16 = 0x02,
18460 NM_SDBBP16 = 0x03,
18463 /* POOL16C_0 instruction pool */
18464 enum {
18465 NM_POOL16C_00 = 0x00,
18468 /* P16.JRC instruction pool */
18469 enum {
18470 NM_JRC = 0x00,
18471 NM_JALRC16 = 0x01,
18474 /* P.SYSCALL instruction pool */
18475 enum {
18476 NM_SYSCALL = 0x00,
18477 NM_HYPCALL = 0x01,
18480 /* P.TRAP instruction pool */
18481 enum {
18482 NM_TEQ = 0x00,
18483 NM_TNE = 0x01,
18486 /* P.CMOVE instruction pool */
18487 enum {
18488 NM_MOVZ = 0x00,
18489 NM_MOVN = 0x01,
18492 /* POOL32Axf instruction pool */
18493 enum {
18494 NM_POOL32AXF_1 = 0x01,
18495 NM_POOL32AXF_2 = 0x02,
18496 NM_POOL32AXF_4 = 0x04,
18497 NM_POOL32AXF_5 = 0x05,
18498 NM_POOL32AXF_7 = 0x07,
18501 /* POOL32Axf_1 instruction pool */
18502 enum {
18503 NM_POOL32AXF_1_0 = 0x00,
18504 NM_POOL32AXF_1_1 = 0x01,
18505 NM_POOL32AXF_1_3 = 0x03,
18506 NM_POOL32AXF_1_4 = 0x04,
18507 NM_POOL32AXF_1_5 = 0x05,
18508 NM_POOL32AXF_1_7 = 0x07,
18511 /* POOL32Axf_2 instruction pool */
18512 enum {
18513 NM_POOL32AXF_2_0_7 = 0x00,
18514 NM_POOL32AXF_2_8_15 = 0x01,
18515 NM_POOL32AXF_2_16_23 = 0x02,
18516 NM_POOL32AXF_2_24_31 = 0x03,
18519 /* POOL32Axf_7 instruction pool */
18520 enum {
18521 NM_SHRA_R_QB = 0x0,
18522 NM_SHRL_PH = 0x1,
18523 NM_REPL_QB = 0x2,
18526 /* POOL32Axf_1_0 instruction pool */
18527 enum {
18528 NM_MFHI = 0x0,
18529 NM_MFLO = 0x1,
18530 NM_MTHI = 0x2,
18531 NM_MTLO = 0x3,
18534 /* POOL32Axf_1_1 instruction pool */
18535 enum {
18536 NM_MTHLIP = 0x0,
18537 NM_SHILOV = 0x1,
18540 /* POOL32Axf_1_3 instruction pool */
18541 enum {
18542 NM_RDDSP = 0x0,
18543 NM_WRDSP = 0x1,
18544 NM_EXTP = 0x2,
18545 NM_EXTPDP = 0x3,
18548 /* POOL32Axf_1_4 instruction pool */
18549 enum {
18550 NM_SHLL_QB = 0x0,
18551 NM_SHRL_QB = 0x1,
18554 /* POOL32Axf_1_5 instruction pool */
18555 enum {
18556 NM_MAQ_S_W_PHR = 0x0,
18557 NM_MAQ_S_W_PHL = 0x1,
18558 NM_MAQ_SA_W_PHR = 0x2,
18559 NM_MAQ_SA_W_PHL = 0x3,
18562 /* POOL32Axf_1_7 instruction pool */
18563 enum {
18564 NM_EXTR_W = 0x0,
18565 NM_EXTR_R_W = 0x1,
18566 NM_EXTR_RS_W = 0x2,
18567 NM_EXTR_S_H = 0x3,
18570 /* POOL32Axf_2_0_7 instruction pool */
18571 enum {
18572 NM_DPA_W_PH = 0x0,
18573 NM_DPAQ_S_W_PH = 0x1,
18574 NM_DPS_W_PH = 0x2,
18575 NM_DPSQ_S_W_PH = 0x3,
18576 NM_BALIGN = 0x4,
18577 NM_MADD = 0x5,
18578 NM_MULT = 0x6,
18579 NM_EXTRV_W = 0x7,
18582 /* POOL32Axf_2_8_15 instruction pool */
18583 enum {
18584 NM_DPAX_W_PH = 0x0,
18585 NM_DPAQ_SA_L_W = 0x1,
18586 NM_DPSX_W_PH = 0x2,
18587 NM_DPSQ_SA_L_W = 0x3,
18588 NM_MADDU = 0x5,
18589 NM_MULTU = 0x6,
18590 NM_EXTRV_R_W = 0x7,
18593 /* POOL32Axf_2_16_23 instruction pool */
18594 enum {
18595 NM_DPAU_H_QBL = 0x0,
18596 NM_DPAQX_S_W_PH = 0x1,
18597 NM_DPSU_H_QBL = 0x2,
18598 NM_DPSQX_S_W_PH = 0x3,
18599 NM_EXTPV = 0x4,
18600 NM_MSUB = 0x5,
18601 NM_MULSA_W_PH = 0x6,
18602 NM_EXTRV_RS_W = 0x7,
18605 /* POOL32Axf_2_24_31 instruction pool */
18606 enum {
18607 NM_DPAU_H_QBR = 0x0,
18608 NM_DPAQX_SA_W_PH = 0x1,
18609 NM_DPSU_H_QBR = 0x2,
18610 NM_DPSQX_SA_W_PH = 0x3,
18611 NM_EXTPDPV = 0x4,
18612 NM_MSUBU = 0x5,
18613 NM_MULSAQ_S_W_PH = 0x6,
18614 NM_EXTRV_S_H = 0x7,
18617 /* POOL32Axf_{4, 5} instruction pool */
18618 enum {
18619 NM_CLO = 0x25,
18620 NM_CLZ = 0x2d,
18622 NM_TLBP = 0x01,
18623 NM_TLBR = 0x09,
18624 NM_TLBWI = 0x11,
18625 NM_TLBWR = 0x19,
18626 NM_TLBINV = 0x03,
18627 NM_TLBINVF = 0x0b,
18628 NM_DI = 0x23,
18629 NM_EI = 0x2b,
18630 NM_RDPGPR = 0x70,
18631 NM_WRPGPR = 0x78,
18632 NM_WAIT = 0x61,
18633 NM_DERET = 0x71,
18634 NM_ERETX = 0x79,
18636 /* nanoMIPS DSP instructions */
18637 NM_ABSQ_S_QB = 0x00,
18638 NM_ABSQ_S_PH = 0x08,
18639 NM_ABSQ_S_W = 0x10,
18640 NM_PRECEQ_W_PHL = 0x28,
18641 NM_PRECEQ_W_PHR = 0x30,
18642 NM_PRECEQU_PH_QBL = 0x38,
18643 NM_PRECEQU_PH_QBR = 0x48,
18644 NM_PRECEU_PH_QBL = 0x58,
18645 NM_PRECEU_PH_QBR = 0x68,
18646 NM_PRECEQU_PH_QBLA = 0x39,
18647 NM_PRECEQU_PH_QBRA = 0x49,
18648 NM_PRECEU_PH_QBLA = 0x59,
18649 NM_PRECEU_PH_QBRA = 0x69,
18650 NM_REPLV_PH = 0x01,
18651 NM_REPLV_QB = 0x09,
18652 NM_BITREV = 0x18,
18653 NM_INSV = 0x20,
18654 NM_RADDU_W_QB = 0x78,
18656 NM_BITSWAP = 0x05,
18657 NM_WSBH = 0x3d,
18660 /* PP.SR instruction pool */
18661 enum {
18662 NM_SAVE = 0x00,
18663 NM_RESTORE = 0x02,
18664 NM_RESTORE_JRC = 0x03,
18667 /* P.SR.F instruction pool */
18668 enum {
18669 NM_SAVEF = 0x00,
18670 NM_RESTOREF = 0x01,
18673 /* P16.SYSCALL instruction pool */
18674 enum {
18675 NM_SYSCALL16 = 0x00,
18676 NM_HYPCALL16 = 0x01,
18679 /* POOL16C_00 instruction pool */
18680 enum {
18681 NM_NOT16 = 0x00,
18682 NM_XOR16 = 0x01,
18683 NM_AND16 = 0x02,
18684 NM_OR16 = 0x03,
18687 /* PP.LSX and PP.LSXS instruction pool */
18688 enum {
18689 NM_LBX = 0x00,
18690 NM_LHX = 0x04,
18691 NM_LWX = 0x08,
18692 NM_LDX = 0x0c,
18694 NM_SBX = 0x01,
18695 NM_SHX = 0x05,
18696 NM_SWX = 0x09,
18697 NM_SDX = 0x0d,
18699 NM_LBUX = 0x02,
18700 NM_LHUX = 0x06,
18701 NM_LWC1X = 0x0a,
18702 NM_LDC1X = 0x0e,
18704 NM_LWUX = 0x07,
18705 NM_SWC1X = 0x0b,
18706 NM_SDC1X = 0x0f,
18708 NM_LHXS = 0x04,
18709 NM_LWXS = 0x08,
18710 NM_LDXS = 0x0c,
18712 NM_SHXS = 0x05,
18713 NM_SWXS = 0x09,
18714 NM_SDXS = 0x0d,
18716 NM_LHUXS = 0x06,
18717 NM_LWC1XS = 0x0a,
18718 NM_LDC1XS = 0x0e,
18720 NM_LWUXS = 0x07,
18721 NM_SWC1XS = 0x0b,
18722 NM_SDC1XS = 0x0f,
18725 /* ERETx instruction pool */
18726 enum {
18727 NM_ERET = 0x00,
18728 NM_ERETNC = 0x01,
18731 /* POOL32FxF_{0, 1} insturction pool */
18732 enum {
18733 NM_CFC1 = 0x40,
18734 NM_CTC1 = 0x60,
18735 NM_MFC1 = 0x80,
18736 NM_MTC1 = 0xa0,
18737 NM_MFHC1 = 0xc0,
18738 NM_MTHC1 = 0xe0,
18740 NM_CVT_S_PL = 0x84,
18741 NM_CVT_S_PU = 0xa4,
18743 NM_CVT_L_S = 0x004,
18744 NM_CVT_L_D = 0x104,
18745 NM_CVT_W_S = 0x024,
18746 NM_CVT_W_D = 0x124,
18748 NM_RSQRT_S = 0x008,
18749 NM_RSQRT_D = 0x108,
18751 NM_SQRT_S = 0x028,
18752 NM_SQRT_D = 0x128,
18754 NM_RECIP_S = 0x048,
18755 NM_RECIP_D = 0x148,
18757 NM_FLOOR_L_S = 0x00c,
18758 NM_FLOOR_L_D = 0x10c,
18760 NM_FLOOR_W_S = 0x02c,
18761 NM_FLOOR_W_D = 0x12c,
18763 NM_CEIL_L_S = 0x04c,
18764 NM_CEIL_L_D = 0x14c,
18765 NM_CEIL_W_S = 0x06c,
18766 NM_CEIL_W_D = 0x16c,
18767 NM_TRUNC_L_S = 0x08c,
18768 NM_TRUNC_L_D = 0x18c,
18769 NM_TRUNC_W_S = 0x0ac,
18770 NM_TRUNC_W_D = 0x1ac,
18771 NM_ROUND_L_S = 0x0cc,
18772 NM_ROUND_L_D = 0x1cc,
18773 NM_ROUND_W_S = 0x0ec,
18774 NM_ROUND_W_D = 0x1ec,
18776 NM_MOV_S = 0x01,
18777 NM_MOV_D = 0x81,
18778 NM_ABS_S = 0x0d,
18779 NM_ABS_D = 0x8d,
18780 NM_NEG_S = 0x2d,
18781 NM_NEG_D = 0xad,
18782 NM_CVT_D_S = 0x04d,
18783 NM_CVT_D_W = 0x0cd,
18784 NM_CVT_D_L = 0x14d,
18785 NM_CVT_S_D = 0x06d,
18786 NM_CVT_S_W = 0x0ed,
18787 NM_CVT_S_L = 0x16d,
18790 /* P.LL instruction pool */
18791 enum {
18792 NM_LL = 0x00,
18793 NM_LLWP = 0x01,
18796 /* P.SC instruction pool */
18797 enum {
18798 NM_SC = 0x00,
18799 NM_SCWP = 0x01,
18802 /* P.DVP instruction pool */
18803 enum {
18804 NM_DVP = 0x00,
18805 NM_EVP = 0x01,
18811 * nanoMIPS decoding engine
18816 /* extraction utilities */
18818 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
18819 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
18820 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
18821 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18822 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18824 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18825 static inline int decode_gpr_gpr3(int r)
18827 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18829 return map[r & 0x7];
18832 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18833 static inline int decode_gpr_gpr3_src_store(int r)
18835 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18837 return map[r & 0x7];
18840 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18841 static inline int decode_gpr_gpr4(int r)
18843 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18844 16, 17, 18, 19, 20, 21, 22, 23 };
18846 return map[r & 0xf];
18849 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18850 static inline int decode_gpr_gpr4_zero(int r)
18852 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18853 16, 17, 18, 19, 20, 21, 22, 23 };
18855 return map[r & 0xf];
18859 static void gen_adjust_sp(DisasContext *ctx, int u)
18861 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18864 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18865 uint8_t gp, uint16_t u)
18867 int counter = 0;
18868 TCGv va = tcg_temp_new();
18869 TCGv t0 = tcg_temp_new();
18871 while (counter != count) {
18872 bool use_gp = gp && (counter == count - 1);
18873 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18874 int this_offset = -((counter + 1) << 2);
18875 gen_base_offset_addr(ctx, va, 29, this_offset);
18876 gen_load_gpr(t0, this_rt);
18877 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18878 (MO_TEUL | ctx->default_tcg_memop_mask));
18879 counter++;
18882 /* adjust stack pointer */
18883 gen_adjust_sp(ctx, -u);
18885 tcg_temp_free(t0);
18886 tcg_temp_free(va);
18889 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18890 uint8_t gp, uint16_t u)
18892 int counter = 0;
18893 TCGv va = tcg_temp_new();
18894 TCGv t0 = tcg_temp_new();
18896 while (counter != count) {
18897 bool use_gp = gp && (counter == count - 1);
18898 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18899 int this_offset = u - ((counter + 1) << 2);
18900 gen_base_offset_addr(ctx, va, 29, this_offset);
18901 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18902 ctx->default_tcg_memop_mask);
18903 tcg_gen_ext32s_tl(t0, t0);
18904 gen_store_gpr(t0, this_rt);
18905 counter++;
18908 /* adjust stack pointer */
18909 gen_adjust_sp(ctx, u);
18911 tcg_temp_free(t0);
18912 tcg_temp_free(va);
18915 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18917 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
18918 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
18920 switch (extract32(ctx->opcode, 2, 2)) {
18921 case NM_NOT16:
18922 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18923 break;
18924 case NM_AND16:
18925 gen_logic(ctx, OPC_AND, rt, rt, rs);
18926 break;
18927 case NM_XOR16:
18928 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18929 break;
18930 case NM_OR16:
18931 gen_logic(ctx, OPC_OR, rt, rt, rs);
18932 break;
18936 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18938 int rt = extract32(ctx->opcode, 21, 5);
18939 int rs = extract32(ctx->opcode, 16, 5);
18940 int rd = extract32(ctx->opcode, 11, 5);
18942 switch (extract32(ctx->opcode, 3, 7)) {
18943 case NM_P_TRAP:
18944 switch (extract32(ctx->opcode, 10, 1)) {
18945 case NM_TEQ:
18946 check_nms(ctx);
18947 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18948 break;
18949 case NM_TNE:
18950 check_nms(ctx);
18951 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18952 break;
18954 break;
18955 case NM_RDHWR:
18956 check_nms(ctx);
18957 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18958 break;
18959 case NM_SEB:
18960 check_nms(ctx);
18961 gen_bshfl(ctx, OPC_SEB, rs, rt);
18962 break;
18963 case NM_SEH:
18964 gen_bshfl(ctx, OPC_SEH, rs, rt);
18965 break;
18966 case NM_SLLV:
18967 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18968 break;
18969 case NM_SRLV:
18970 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18971 break;
18972 case NM_SRAV:
18973 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18974 break;
18975 case NM_ROTRV:
18976 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18977 break;
18978 case NM_ADD:
18979 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18980 break;
18981 case NM_ADDU:
18982 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18983 break;
18984 case NM_SUB:
18985 check_nms(ctx);
18986 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18987 break;
18988 case NM_SUBU:
18989 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18990 break;
18991 case NM_P_CMOVE:
18992 switch (extract32(ctx->opcode, 10, 1)) {
18993 case NM_MOVZ:
18994 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18995 break;
18996 case NM_MOVN:
18997 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18998 break;
19000 break;
19001 case NM_AND:
19002 gen_logic(ctx, OPC_AND, rd, rs, rt);
19003 break;
19004 case NM_OR:
19005 gen_logic(ctx, OPC_OR, rd, rs, rt);
19006 break;
19007 case NM_NOR:
19008 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19009 break;
19010 case NM_XOR:
19011 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19012 break;
19013 case NM_SLT:
19014 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19015 break;
19016 case NM_P_SLTU:
19017 if (rd == 0) {
19018 /* P_DVP */
19019 #ifndef CONFIG_USER_ONLY
19020 TCGv t0 = tcg_temp_new();
19021 switch (extract32(ctx->opcode, 10, 1)) {
19022 case NM_DVP:
19023 if (ctx->vp) {
19024 check_cp0_enabled(ctx);
19025 gen_helper_dvp(t0, cpu_env);
19026 gen_store_gpr(t0, rt);
19028 break;
19029 case NM_EVP:
19030 if (ctx->vp) {
19031 check_cp0_enabled(ctx);
19032 gen_helper_evp(t0, cpu_env);
19033 gen_store_gpr(t0, rt);
19035 break;
19037 tcg_temp_free(t0);
19038 #endif
19039 } else {
19040 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19042 break;
19043 case NM_SOV:
19045 TCGv t0 = tcg_temp_new();
19046 TCGv t1 = tcg_temp_new();
19047 TCGv t2 = tcg_temp_new();
19049 gen_load_gpr(t1, rs);
19050 gen_load_gpr(t2, rt);
19051 tcg_gen_add_tl(t0, t1, t2);
19052 tcg_gen_ext32s_tl(t0, t0);
19053 tcg_gen_xor_tl(t1, t1, t2);
19054 tcg_gen_xor_tl(t2, t0, t2);
19055 tcg_gen_andc_tl(t1, t2, t1);
19057 /* operands of same sign, result different sign */
19058 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19059 gen_store_gpr(t0, rd);
19061 tcg_temp_free(t0);
19062 tcg_temp_free(t1);
19063 tcg_temp_free(t2);
19065 break;
19066 case NM_MUL:
19067 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19068 break;
19069 case NM_MUH:
19070 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19071 break;
19072 case NM_MULU:
19073 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19074 break;
19075 case NM_MUHU:
19076 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19077 break;
19078 case NM_DIV:
19079 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19080 break;
19081 case NM_MOD:
19082 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19083 break;
19084 case NM_DIVU:
19085 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19086 break;
19087 case NM_MODU:
19088 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19089 break;
19090 #ifndef CONFIG_USER_ONLY
19091 case NM_MFC0:
19092 check_cp0_enabled(ctx);
19093 if (rt == 0) {
19094 /* Treat as NOP. */
19095 break;
19097 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19098 break;
19099 case NM_MTC0:
19100 check_cp0_enabled(ctx);
19102 TCGv t0 = tcg_temp_new();
19104 gen_load_gpr(t0, rt);
19105 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19106 tcg_temp_free(t0);
19108 break;
19109 case NM_D_E_MT_VPE:
19111 uint8_t sc = extract32(ctx->opcode, 10, 1);
19112 TCGv t0 = tcg_temp_new();
19114 switch (sc) {
19115 case 0:
19116 if (rs == 1) {
19117 /* DMT */
19118 check_cp0_mt(ctx);
19119 gen_helper_dmt(t0);
19120 gen_store_gpr(t0, rt);
19121 } else if (rs == 0) {
19122 /* DVPE */
19123 check_cp0_mt(ctx);
19124 gen_helper_dvpe(t0, cpu_env);
19125 gen_store_gpr(t0, rt);
19126 } else {
19127 generate_exception_end(ctx, EXCP_RI);
19129 break;
19130 case 1:
19131 if (rs == 1) {
19132 /* EMT */
19133 check_cp0_mt(ctx);
19134 gen_helper_emt(t0);
19135 gen_store_gpr(t0, rt);
19136 } else if (rs == 0) {
19137 /* EVPE */
19138 check_cp0_mt(ctx);
19139 gen_helper_evpe(t0, cpu_env);
19140 gen_store_gpr(t0, rt);
19141 } else {
19142 generate_exception_end(ctx, EXCP_RI);
19144 break;
19147 tcg_temp_free(t0);
19149 break;
19150 case NM_FORK:
19151 check_mt(ctx);
19153 TCGv t0 = tcg_temp_new();
19154 TCGv t1 = tcg_temp_new();
19156 gen_load_gpr(t0, rt);
19157 gen_load_gpr(t1, rs);
19158 gen_helper_fork(t0, t1);
19159 tcg_temp_free(t0);
19160 tcg_temp_free(t1);
19162 break;
19163 case NM_MFTR:
19164 case NM_MFHTR:
19165 check_cp0_enabled(ctx);
19166 if (rd == 0) {
19167 /* Treat as NOP. */
19168 return;
19170 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19171 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19172 break;
19173 case NM_MTTR:
19174 case NM_MTHTR:
19175 check_cp0_enabled(ctx);
19176 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19177 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19178 break;
19179 case NM_YIELD:
19180 check_mt(ctx);
19182 TCGv t0 = tcg_temp_new();
19184 gen_load_gpr(t0, rs);
19185 gen_helper_yield(t0, cpu_env, t0);
19186 gen_store_gpr(t0, rt);
19187 tcg_temp_free(t0);
19189 break;
19190 #endif
19191 default:
19192 generate_exception_end(ctx, EXCP_RI);
19193 break;
19197 /* dsp */
19198 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19199 int ret, int v1, int v2)
19201 TCGv_i32 t0;
19202 TCGv v0_t;
19203 TCGv v1_t;
19205 t0 = tcg_temp_new_i32();
19207 v0_t = tcg_temp_new();
19208 v1_t = tcg_temp_new();
19210 tcg_gen_movi_i32(t0, v2 >> 3);
19212 gen_load_gpr(v0_t, ret);
19213 gen_load_gpr(v1_t, v1);
19215 switch (opc) {
19216 case NM_MAQ_S_W_PHR:
19217 check_dsp(ctx);
19218 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19219 break;
19220 case NM_MAQ_S_W_PHL:
19221 check_dsp(ctx);
19222 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19223 break;
19224 case NM_MAQ_SA_W_PHR:
19225 check_dsp(ctx);
19226 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19227 break;
19228 case NM_MAQ_SA_W_PHL:
19229 check_dsp(ctx);
19230 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19231 break;
19232 default:
19233 generate_exception_end(ctx, EXCP_RI);
19234 break;
19237 tcg_temp_free_i32(t0);
19239 tcg_temp_free(v0_t);
19240 tcg_temp_free(v1_t);
19244 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19245 int ret, int v1, int v2)
19247 int16_t imm;
19248 TCGv t0 = tcg_temp_new();
19249 TCGv t1 = tcg_temp_new();
19250 TCGv v0_t = tcg_temp_new();
19252 gen_load_gpr(v0_t, v1);
19254 switch (opc) {
19255 case NM_POOL32AXF_1_0:
19256 check_dsp(ctx);
19257 switch (extract32(ctx->opcode, 12, 2)) {
19258 case NM_MFHI:
19259 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19260 break;
19261 case NM_MFLO:
19262 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19263 break;
19264 case NM_MTHI:
19265 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19266 break;
19267 case NM_MTLO:
19268 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19269 break;
19271 break;
19272 case NM_POOL32AXF_1_1:
19273 check_dsp(ctx);
19274 switch (extract32(ctx->opcode, 12, 2)) {
19275 case NM_MTHLIP:
19276 tcg_gen_movi_tl(t0, v2);
19277 gen_helper_mthlip(t0, v0_t, cpu_env);
19278 break;
19279 case NM_SHILOV:
19280 tcg_gen_movi_tl(t0, v2 >> 3);
19281 gen_helper_shilo(t0, v0_t, cpu_env);
19282 break;
19283 default:
19284 generate_exception_end(ctx, EXCP_RI);
19285 break;
19287 break;
19288 case NM_POOL32AXF_1_3:
19289 check_dsp(ctx);
19290 imm = extract32(ctx->opcode, 14, 7);
19291 switch (extract32(ctx->opcode, 12, 2)) {
19292 case NM_RDDSP:
19293 tcg_gen_movi_tl(t0, imm);
19294 gen_helper_rddsp(t0, t0, cpu_env);
19295 gen_store_gpr(t0, ret);
19296 break;
19297 case NM_WRDSP:
19298 gen_load_gpr(t0, ret);
19299 tcg_gen_movi_tl(t1, imm);
19300 gen_helper_wrdsp(t0, t1, cpu_env);
19301 break;
19302 case NM_EXTP:
19303 tcg_gen_movi_tl(t0, v2 >> 3);
19304 tcg_gen_movi_tl(t1, v1);
19305 gen_helper_extp(t0, t0, t1, cpu_env);
19306 gen_store_gpr(t0, ret);
19307 break;
19308 case NM_EXTPDP:
19309 tcg_gen_movi_tl(t0, v2 >> 3);
19310 tcg_gen_movi_tl(t1, v1);
19311 gen_helper_extpdp(t0, t0, t1, cpu_env);
19312 gen_store_gpr(t0, ret);
19313 break;
19315 break;
19316 case NM_POOL32AXF_1_4:
19317 check_dsp(ctx);
19318 tcg_gen_movi_tl(t0, v2 >> 2);
19319 switch (extract32(ctx->opcode, 12, 1)) {
19320 case NM_SHLL_QB:
19321 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19322 gen_store_gpr(t0, ret);
19323 break;
19324 case NM_SHRL_QB:
19325 gen_helper_shrl_qb(t0, t0, v0_t);
19326 gen_store_gpr(t0, ret);
19327 break;
19329 break;
19330 case NM_POOL32AXF_1_5:
19331 opc = extract32(ctx->opcode, 12, 2);
19332 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19333 break;
19334 case NM_POOL32AXF_1_7:
19335 check_dsp(ctx);
19336 tcg_gen_movi_tl(t0, v2 >> 3);
19337 tcg_gen_movi_tl(t1, v1);
19338 switch (extract32(ctx->opcode, 12, 2)) {
19339 case NM_EXTR_W:
19340 gen_helper_extr_w(t0, t0, t1, cpu_env);
19341 gen_store_gpr(t0, ret);
19342 break;
19343 case NM_EXTR_R_W:
19344 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19345 gen_store_gpr(t0, ret);
19346 break;
19347 case NM_EXTR_RS_W:
19348 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19349 gen_store_gpr(t0, ret);
19350 break;
19351 case NM_EXTR_S_H:
19352 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19353 gen_store_gpr(t0, ret);
19354 break;
19356 break;
19357 default:
19358 generate_exception_end(ctx, EXCP_RI);
19359 break;
19362 tcg_temp_free(t0);
19363 tcg_temp_free(t1);
19364 tcg_temp_free(v0_t);
19367 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19368 TCGv v0, TCGv v1, int rd)
19370 TCGv_i32 t0;
19372 t0 = tcg_temp_new_i32();
19374 tcg_gen_movi_i32(t0, rd >> 3);
19376 switch (opc) {
19377 case NM_POOL32AXF_2_0_7:
19378 switch (extract32(ctx->opcode, 9, 3)) {
19379 case NM_DPA_W_PH:
19380 check_dsp_r2(ctx);
19381 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19382 break;
19383 case NM_DPAQ_S_W_PH:
19384 check_dsp(ctx);
19385 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19386 break;
19387 case NM_DPS_W_PH:
19388 check_dsp_r2(ctx);
19389 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19390 break;
19391 case NM_DPSQ_S_W_PH:
19392 check_dsp(ctx);
19393 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19394 break;
19395 default:
19396 generate_exception_end(ctx, EXCP_RI);
19397 break;
19399 break;
19400 case NM_POOL32AXF_2_8_15:
19401 switch (extract32(ctx->opcode, 9, 3)) {
19402 case NM_DPAX_W_PH:
19403 check_dsp_r2(ctx);
19404 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19405 break;
19406 case NM_DPAQ_SA_L_W:
19407 check_dsp(ctx);
19408 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19409 break;
19410 case NM_DPSX_W_PH:
19411 check_dsp_r2(ctx);
19412 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19413 break;
19414 case NM_DPSQ_SA_L_W:
19415 check_dsp(ctx);
19416 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19417 break;
19418 default:
19419 generate_exception_end(ctx, EXCP_RI);
19420 break;
19422 break;
19423 case NM_POOL32AXF_2_16_23:
19424 switch (extract32(ctx->opcode, 9, 3)) {
19425 case NM_DPAU_H_QBL:
19426 check_dsp(ctx);
19427 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19428 break;
19429 case NM_DPAQX_S_W_PH:
19430 check_dsp_r2(ctx);
19431 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19432 break;
19433 case NM_DPSU_H_QBL:
19434 check_dsp(ctx);
19435 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19436 break;
19437 case NM_DPSQX_S_W_PH:
19438 check_dsp_r2(ctx);
19439 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19440 break;
19441 case NM_MULSA_W_PH:
19442 check_dsp_r2(ctx);
19443 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19444 break;
19445 default:
19446 generate_exception_end(ctx, EXCP_RI);
19447 break;
19449 break;
19450 case NM_POOL32AXF_2_24_31:
19451 switch (extract32(ctx->opcode, 9, 3)) {
19452 case NM_DPAU_H_QBR:
19453 check_dsp(ctx);
19454 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19455 break;
19456 case NM_DPAQX_SA_W_PH:
19457 check_dsp_r2(ctx);
19458 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19459 break;
19460 case NM_DPSU_H_QBR:
19461 check_dsp(ctx);
19462 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19463 break;
19464 case NM_DPSQX_SA_W_PH:
19465 check_dsp_r2(ctx);
19466 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19467 break;
19468 case NM_MULSAQ_S_W_PH:
19469 check_dsp(ctx);
19470 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19471 break;
19472 default:
19473 generate_exception_end(ctx, EXCP_RI);
19474 break;
19476 break;
19477 default:
19478 generate_exception_end(ctx, EXCP_RI);
19479 break;
19482 tcg_temp_free_i32(t0);
19485 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19486 int rt, int rs, int rd)
19488 int ret = rt;
19489 TCGv t0 = tcg_temp_new();
19490 TCGv t1 = tcg_temp_new();
19491 TCGv v0_t = tcg_temp_new();
19492 TCGv v1_t = tcg_temp_new();
19494 gen_load_gpr(v0_t, rt);
19495 gen_load_gpr(v1_t, rs);
19497 switch (opc) {
19498 case NM_POOL32AXF_2_0_7:
19499 switch (extract32(ctx->opcode, 9, 3)) {
19500 case NM_DPA_W_PH:
19501 case NM_DPAQ_S_W_PH:
19502 case NM_DPS_W_PH:
19503 case NM_DPSQ_S_W_PH:
19504 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19505 break;
19506 case NM_BALIGN:
19507 check_dsp_r2(ctx);
19508 if (rt != 0) {
19509 gen_load_gpr(t0, rs);
19510 rd &= 3;
19511 if (rd != 0 && rd != 2) {
19512 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19513 tcg_gen_ext32u_tl(t0, t0);
19514 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19515 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19517 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19519 break;
19520 case NM_MADD:
19521 check_dsp(ctx);
19523 int acc = extract32(ctx->opcode, 14, 2);
19524 TCGv_i64 t2 = tcg_temp_new_i64();
19525 TCGv_i64 t3 = tcg_temp_new_i64();
19527 gen_load_gpr(t0, rt);
19528 gen_load_gpr(t1, rs);
19529 tcg_gen_ext_tl_i64(t2, t0);
19530 tcg_gen_ext_tl_i64(t3, t1);
19531 tcg_gen_mul_i64(t2, t2, t3);
19532 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19533 tcg_gen_add_i64(t2, t2, t3);
19534 tcg_temp_free_i64(t3);
19535 gen_move_low32(cpu_LO[acc], t2);
19536 gen_move_high32(cpu_HI[acc], t2);
19537 tcg_temp_free_i64(t2);
19539 break;
19540 case NM_MULT:
19541 check_dsp(ctx);
19543 int acc = extract32(ctx->opcode, 14, 2);
19544 TCGv_i32 t2 = tcg_temp_new_i32();
19545 TCGv_i32 t3 = tcg_temp_new_i32();
19547 gen_load_gpr(t0, rs);
19548 gen_load_gpr(t1, rt);
19549 tcg_gen_trunc_tl_i32(t2, t0);
19550 tcg_gen_trunc_tl_i32(t3, t1);
19551 tcg_gen_muls2_i32(t2, t3, t2, t3);
19552 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19553 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19554 tcg_temp_free_i32(t2);
19555 tcg_temp_free_i32(t3);
19557 break;
19558 case NM_EXTRV_W:
19559 check_dsp(ctx);
19560 gen_load_gpr(v1_t, rs);
19561 tcg_gen_movi_tl(t0, rd >> 3);
19562 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19563 gen_store_gpr(t0, ret);
19564 break;
19566 break;
19567 case NM_POOL32AXF_2_8_15:
19568 switch (extract32(ctx->opcode, 9, 3)) {
19569 case NM_DPAX_W_PH:
19570 case NM_DPAQ_SA_L_W:
19571 case NM_DPSX_W_PH:
19572 case NM_DPSQ_SA_L_W:
19573 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19574 break;
19575 case NM_MADDU:
19576 check_dsp(ctx);
19578 int acc = extract32(ctx->opcode, 14, 2);
19579 TCGv_i64 t2 = tcg_temp_new_i64();
19580 TCGv_i64 t3 = tcg_temp_new_i64();
19582 gen_load_gpr(t0, rs);
19583 gen_load_gpr(t1, rt);
19584 tcg_gen_ext32u_tl(t0, t0);
19585 tcg_gen_ext32u_tl(t1, t1);
19586 tcg_gen_extu_tl_i64(t2, t0);
19587 tcg_gen_extu_tl_i64(t3, t1);
19588 tcg_gen_mul_i64(t2, t2, t3);
19589 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19590 tcg_gen_add_i64(t2, t2, t3);
19591 tcg_temp_free_i64(t3);
19592 gen_move_low32(cpu_LO[acc], t2);
19593 gen_move_high32(cpu_HI[acc], t2);
19594 tcg_temp_free_i64(t2);
19596 break;
19597 case NM_MULTU:
19598 check_dsp(ctx);
19600 int acc = extract32(ctx->opcode, 14, 2);
19601 TCGv_i32 t2 = tcg_temp_new_i32();
19602 TCGv_i32 t3 = tcg_temp_new_i32();
19604 gen_load_gpr(t0, rs);
19605 gen_load_gpr(t1, rt);
19606 tcg_gen_trunc_tl_i32(t2, t0);
19607 tcg_gen_trunc_tl_i32(t3, t1);
19608 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19609 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19610 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19611 tcg_temp_free_i32(t2);
19612 tcg_temp_free_i32(t3);
19614 break;
19615 case NM_EXTRV_R_W:
19616 check_dsp(ctx);
19617 tcg_gen_movi_tl(t0, rd >> 3);
19618 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19619 gen_store_gpr(t0, ret);
19620 break;
19621 default:
19622 generate_exception_end(ctx, EXCP_RI);
19623 break;
19625 break;
19626 case NM_POOL32AXF_2_16_23:
19627 switch (extract32(ctx->opcode, 9, 3)) {
19628 case NM_DPAU_H_QBL:
19629 case NM_DPAQX_S_W_PH:
19630 case NM_DPSU_H_QBL:
19631 case NM_DPSQX_S_W_PH:
19632 case NM_MULSA_W_PH:
19633 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19634 break;
19635 case NM_EXTPV:
19636 check_dsp(ctx);
19637 tcg_gen_movi_tl(t0, rd >> 3);
19638 gen_helper_extp(t0, t0, v1_t, cpu_env);
19639 gen_store_gpr(t0, ret);
19640 break;
19641 case NM_MSUB:
19642 check_dsp(ctx);
19644 int acc = extract32(ctx->opcode, 14, 2);
19645 TCGv_i64 t2 = tcg_temp_new_i64();
19646 TCGv_i64 t3 = tcg_temp_new_i64();
19648 gen_load_gpr(t0, rs);
19649 gen_load_gpr(t1, rt);
19650 tcg_gen_ext_tl_i64(t2, t0);
19651 tcg_gen_ext_tl_i64(t3, t1);
19652 tcg_gen_mul_i64(t2, t2, t3);
19653 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19654 tcg_gen_sub_i64(t2, t3, t2);
19655 tcg_temp_free_i64(t3);
19656 gen_move_low32(cpu_LO[acc], t2);
19657 gen_move_high32(cpu_HI[acc], t2);
19658 tcg_temp_free_i64(t2);
19660 break;
19661 case NM_EXTRV_RS_W:
19662 check_dsp(ctx);
19663 tcg_gen_movi_tl(t0, rd >> 3);
19664 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19665 gen_store_gpr(t0, ret);
19666 break;
19668 break;
19669 case NM_POOL32AXF_2_24_31:
19670 switch (extract32(ctx->opcode, 9, 3)) {
19671 case NM_DPAU_H_QBR:
19672 case NM_DPAQX_SA_W_PH:
19673 case NM_DPSU_H_QBR:
19674 case NM_DPSQX_SA_W_PH:
19675 case NM_MULSAQ_S_W_PH:
19676 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19677 break;
19678 case NM_EXTPDPV:
19679 check_dsp(ctx);
19680 tcg_gen_movi_tl(t0, rd >> 3);
19681 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19682 gen_store_gpr(t0, ret);
19683 break;
19684 case NM_MSUBU:
19685 check_dsp(ctx);
19687 int acc = extract32(ctx->opcode, 14, 2);
19688 TCGv_i64 t2 = tcg_temp_new_i64();
19689 TCGv_i64 t3 = tcg_temp_new_i64();
19691 gen_load_gpr(t0, rs);
19692 gen_load_gpr(t1, rt);
19693 tcg_gen_ext32u_tl(t0, t0);
19694 tcg_gen_ext32u_tl(t1, t1);
19695 tcg_gen_extu_tl_i64(t2, t0);
19696 tcg_gen_extu_tl_i64(t3, t1);
19697 tcg_gen_mul_i64(t2, t2, t3);
19698 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19699 tcg_gen_sub_i64(t2, t3, t2);
19700 tcg_temp_free_i64(t3);
19701 gen_move_low32(cpu_LO[acc], t2);
19702 gen_move_high32(cpu_HI[acc], t2);
19703 tcg_temp_free_i64(t2);
19705 break;
19706 case NM_EXTRV_S_H:
19707 check_dsp(ctx);
19708 tcg_gen_movi_tl(t0, rd >> 3);
19709 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19710 gen_store_gpr(t0, ret);
19711 break;
19713 break;
19714 default:
19715 generate_exception_end(ctx, EXCP_RI);
19716 break;
19719 tcg_temp_free(t0);
19720 tcg_temp_free(t1);
19722 tcg_temp_free(v0_t);
19723 tcg_temp_free(v1_t);
19726 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19727 int rt, int rs)
19729 int ret = rt;
19730 TCGv t0 = tcg_temp_new();
19731 TCGv v0_t = tcg_temp_new();
19733 gen_load_gpr(v0_t, rs);
19735 switch (opc) {
19736 case NM_ABSQ_S_QB:
19737 check_dsp_r2(ctx);
19738 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19739 gen_store_gpr(v0_t, ret);
19740 break;
19741 case NM_ABSQ_S_PH:
19742 check_dsp(ctx);
19743 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19744 gen_store_gpr(v0_t, ret);
19745 break;
19746 case NM_ABSQ_S_W:
19747 check_dsp(ctx);
19748 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19749 gen_store_gpr(v0_t, ret);
19750 break;
19751 case NM_PRECEQ_W_PHL:
19752 check_dsp(ctx);
19753 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19754 tcg_gen_ext32s_tl(v0_t, v0_t);
19755 gen_store_gpr(v0_t, ret);
19756 break;
19757 case NM_PRECEQ_W_PHR:
19758 check_dsp(ctx);
19759 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19760 tcg_gen_shli_tl(v0_t, v0_t, 16);
19761 tcg_gen_ext32s_tl(v0_t, v0_t);
19762 gen_store_gpr(v0_t, ret);
19763 break;
19764 case NM_PRECEQU_PH_QBL:
19765 check_dsp(ctx);
19766 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19767 gen_store_gpr(v0_t, ret);
19768 break;
19769 case NM_PRECEQU_PH_QBR:
19770 check_dsp(ctx);
19771 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19772 gen_store_gpr(v0_t, ret);
19773 break;
19774 case NM_PRECEQU_PH_QBLA:
19775 check_dsp(ctx);
19776 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19777 gen_store_gpr(v0_t, ret);
19778 break;
19779 case NM_PRECEQU_PH_QBRA:
19780 check_dsp(ctx);
19781 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19782 gen_store_gpr(v0_t, ret);
19783 break;
19784 case NM_PRECEU_PH_QBL:
19785 check_dsp(ctx);
19786 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19787 gen_store_gpr(v0_t, ret);
19788 break;
19789 case NM_PRECEU_PH_QBR:
19790 check_dsp(ctx);
19791 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19792 gen_store_gpr(v0_t, ret);
19793 break;
19794 case NM_PRECEU_PH_QBLA:
19795 check_dsp(ctx);
19796 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19797 gen_store_gpr(v0_t, ret);
19798 break;
19799 case NM_PRECEU_PH_QBRA:
19800 check_dsp(ctx);
19801 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19802 gen_store_gpr(v0_t, ret);
19803 break;
19804 case NM_REPLV_PH:
19805 check_dsp(ctx);
19806 tcg_gen_ext16u_tl(v0_t, v0_t);
19807 tcg_gen_shli_tl(t0, v0_t, 16);
19808 tcg_gen_or_tl(v0_t, v0_t, t0);
19809 tcg_gen_ext32s_tl(v0_t, v0_t);
19810 gen_store_gpr(v0_t, ret);
19811 break;
19812 case NM_REPLV_QB:
19813 check_dsp(ctx);
19814 tcg_gen_ext8u_tl(v0_t, v0_t);
19815 tcg_gen_shli_tl(t0, v0_t, 8);
19816 tcg_gen_or_tl(v0_t, v0_t, t0);
19817 tcg_gen_shli_tl(t0, v0_t, 16);
19818 tcg_gen_or_tl(v0_t, v0_t, t0);
19819 tcg_gen_ext32s_tl(v0_t, v0_t);
19820 gen_store_gpr(v0_t, ret);
19821 break;
19822 case NM_BITREV:
19823 check_dsp(ctx);
19824 gen_helper_bitrev(v0_t, v0_t);
19825 gen_store_gpr(v0_t, ret);
19826 break;
19827 case NM_INSV:
19828 check_dsp(ctx);
19830 TCGv tv0 = tcg_temp_new();
19832 gen_load_gpr(tv0, rt);
19833 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19834 gen_store_gpr(v0_t, ret);
19835 tcg_temp_free(tv0);
19837 break;
19838 case NM_RADDU_W_QB:
19839 check_dsp(ctx);
19840 gen_helper_raddu_w_qb(v0_t, v0_t);
19841 gen_store_gpr(v0_t, ret);
19842 break;
19843 case NM_BITSWAP:
19844 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19845 break;
19846 case NM_CLO:
19847 check_nms(ctx);
19848 gen_cl(ctx, OPC_CLO, ret, rs);
19849 break;
19850 case NM_CLZ:
19851 check_nms(ctx);
19852 gen_cl(ctx, OPC_CLZ, ret, rs);
19853 break;
19854 case NM_WSBH:
19855 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19856 break;
19857 default:
19858 generate_exception_end(ctx, EXCP_RI);
19859 break;
19862 tcg_temp_free(v0_t);
19863 tcg_temp_free(t0);
19866 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19867 int rt, int rs, int rd)
19869 TCGv t0 = tcg_temp_new();
19870 TCGv rs_t = tcg_temp_new();
19872 gen_load_gpr(rs_t, rs);
19874 switch (opc) {
19875 case NM_SHRA_R_QB:
19876 check_dsp_r2(ctx);
19877 tcg_gen_movi_tl(t0, rd >> 2);
19878 switch (extract32(ctx->opcode, 12, 1)) {
19879 case 0:
19880 /* NM_SHRA_QB */
19881 gen_helper_shra_qb(t0, t0, rs_t);
19882 gen_store_gpr(t0, rt);
19883 break;
19884 case 1:
19885 /* NM_SHRA_R_QB */
19886 gen_helper_shra_r_qb(t0, t0, rs_t);
19887 gen_store_gpr(t0, rt);
19888 break;
19890 break;
19891 case NM_SHRL_PH:
19892 check_dsp_r2(ctx);
19893 tcg_gen_movi_tl(t0, rd >> 1);
19894 gen_helper_shrl_ph(t0, t0, rs_t);
19895 gen_store_gpr(t0, rt);
19896 break;
19897 case NM_REPL_QB:
19898 check_dsp(ctx);
19900 int16_t imm;
19901 target_long result;
19902 imm = extract32(ctx->opcode, 13, 8);
19903 result = (uint32_t)imm << 24 |
19904 (uint32_t)imm << 16 |
19905 (uint32_t)imm << 8 |
19906 (uint32_t)imm;
19907 result = (int32_t)result;
19908 tcg_gen_movi_tl(t0, result);
19909 gen_store_gpr(t0, rt);
19911 break;
19912 default:
19913 generate_exception_end(ctx, EXCP_RI);
19914 break;
19916 tcg_temp_free(t0);
19917 tcg_temp_free(rs_t);
19921 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19923 int rt = extract32(ctx->opcode, 21, 5);
19924 int rs = extract32(ctx->opcode, 16, 5);
19925 int rd = extract32(ctx->opcode, 11, 5);
19927 switch (extract32(ctx->opcode, 6, 3)) {
19928 case NM_POOL32AXF_1:
19930 int32_t op1 = extract32(ctx->opcode, 9, 3);
19931 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19933 break;
19934 case NM_POOL32AXF_2:
19936 int32_t op1 = extract32(ctx->opcode, 12, 2);
19937 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19939 break;
19940 case NM_POOL32AXF_4:
19942 int32_t op1 = extract32(ctx->opcode, 9, 7);
19943 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19945 break;
19946 case NM_POOL32AXF_5:
19947 switch (extract32(ctx->opcode, 9, 7)) {
19948 #ifndef CONFIG_USER_ONLY
19949 case NM_TLBP:
19950 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19951 break;
19952 case NM_TLBR:
19953 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19954 break;
19955 case NM_TLBWI:
19956 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19957 break;
19958 case NM_TLBWR:
19959 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19960 break;
19961 case NM_TLBINV:
19962 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19963 break;
19964 case NM_TLBINVF:
19965 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19966 break;
19967 case NM_DI:
19968 check_cp0_enabled(ctx);
19970 TCGv t0 = tcg_temp_new();
19972 save_cpu_state(ctx, 1);
19973 gen_helper_di(t0, cpu_env);
19974 gen_store_gpr(t0, rt);
19975 /* Stop translation as we may have switched the execution mode */
19976 ctx->base.is_jmp = DISAS_STOP;
19977 tcg_temp_free(t0);
19979 break;
19980 case NM_EI:
19981 check_cp0_enabled(ctx);
19983 TCGv t0 = tcg_temp_new();
19985 save_cpu_state(ctx, 1);
19986 gen_helper_ei(t0, cpu_env);
19987 gen_store_gpr(t0, rt);
19988 /* Stop translation as we may have switched the execution mode */
19989 ctx->base.is_jmp = DISAS_STOP;
19990 tcg_temp_free(t0);
19992 break;
19993 case NM_RDPGPR:
19994 gen_load_srsgpr(rs, rt);
19995 break;
19996 case NM_WRPGPR:
19997 gen_store_srsgpr(rs, rt);
19998 break;
19999 case NM_WAIT:
20000 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20001 break;
20002 case NM_DERET:
20003 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20004 break;
20005 case NM_ERETX:
20006 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20007 break;
20008 #endif
20009 default:
20010 generate_exception_end(ctx, EXCP_RI);
20011 break;
20013 break;
20014 case NM_POOL32AXF_7:
20016 int32_t op1 = extract32(ctx->opcode, 9, 3);
20017 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20019 break;
20020 default:
20021 generate_exception_end(ctx, EXCP_RI);
20022 break;
20026 /* Immediate Value Compact Branches */
20027 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20028 int rt, int32_t imm, int32_t offset)
20030 TCGCond cond;
20031 int bcond_compute = 0;
20032 TCGv t0 = tcg_temp_new();
20033 TCGv t1 = tcg_temp_new();
20035 gen_load_gpr(t0, rt);
20036 tcg_gen_movi_tl(t1, imm);
20037 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20039 /* Load needed operands and calculate btarget */
20040 switch (opc) {
20041 case NM_BEQIC:
20042 if (rt == 0 && imm == 0) {
20043 /* Unconditional branch */
20044 } else if (rt == 0 && imm != 0) {
20045 /* Treat as NOP */
20046 goto out;
20047 } else {
20048 bcond_compute = 1;
20049 cond = TCG_COND_EQ;
20051 break;
20052 case NM_BBEQZC:
20053 case NM_BBNEZC:
20054 check_nms(ctx);
20055 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20056 generate_exception_end(ctx, EXCP_RI);
20057 goto out;
20058 } else if (rt == 0 && opc == NM_BBEQZC) {
20059 /* Unconditional branch */
20060 } else if (rt == 0 && opc == NM_BBNEZC) {
20061 /* Treat as NOP */
20062 goto out;
20063 } else {
20064 tcg_gen_shri_tl(t0, t0, imm);
20065 tcg_gen_andi_tl(t0, t0, 1);
20066 tcg_gen_movi_tl(t1, 0);
20067 bcond_compute = 1;
20068 if (opc == NM_BBEQZC) {
20069 cond = TCG_COND_EQ;
20070 } else {
20071 cond = TCG_COND_NE;
20074 break;
20075 case NM_BNEIC:
20076 if (rt == 0 && imm == 0) {
20077 /* Treat as NOP */
20078 goto out;
20079 } else if (rt == 0 && imm != 0) {
20080 /* Unconditional branch */
20081 } else {
20082 bcond_compute = 1;
20083 cond = TCG_COND_NE;
20085 break;
20086 case NM_BGEIC:
20087 if (rt == 0 && imm == 0) {
20088 /* Unconditional branch */
20089 } else {
20090 bcond_compute = 1;
20091 cond = TCG_COND_GE;
20093 break;
20094 case NM_BLTIC:
20095 bcond_compute = 1;
20096 cond = TCG_COND_LT;
20097 break;
20098 case NM_BGEIUC:
20099 if (rt == 0 && imm == 0) {
20100 /* Unconditional branch */
20101 } else {
20102 bcond_compute = 1;
20103 cond = TCG_COND_GEU;
20105 break;
20106 case NM_BLTIUC:
20107 bcond_compute = 1;
20108 cond = TCG_COND_LTU;
20109 break;
20110 default:
20111 MIPS_INVAL("Immediate Value Compact branch");
20112 generate_exception_end(ctx, EXCP_RI);
20113 goto out;
20116 /* branch completion */
20117 clear_branch_hflags(ctx);
20118 ctx->base.is_jmp = DISAS_NORETURN;
20120 if (bcond_compute == 0) {
20121 /* Uncoditional compact branch */
20122 gen_goto_tb(ctx, 0, ctx->btarget);
20123 } else {
20124 /* Conditional compact branch */
20125 TCGLabel *fs = gen_new_label();
20127 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20129 gen_goto_tb(ctx, 1, ctx->btarget);
20130 gen_set_label(fs);
20132 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20135 out:
20136 tcg_temp_free(t0);
20137 tcg_temp_free(t1);
20140 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20141 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20142 int rt)
20144 TCGv t0 = tcg_temp_new();
20145 TCGv t1 = tcg_temp_new();
20147 /* load rs */
20148 gen_load_gpr(t0, rs);
20150 /* link */
20151 if (rt != 0) {
20152 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20155 /* calculate btarget */
20156 tcg_gen_shli_tl(t0, t0, 1);
20157 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20158 gen_op_addr_add(ctx, btarget, t1, t0);
20160 /* branch completion */
20161 clear_branch_hflags(ctx);
20162 ctx->base.is_jmp = DISAS_NORETURN;
20164 /* unconditional branch to register */
20165 tcg_gen_mov_tl(cpu_PC, btarget);
20166 tcg_gen_lookup_and_goto_ptr();
20168 tcg_temp_free(t0);
20169 tcg_temp_free(t1);
20172 /* nanoMIPS Branches */
20173 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20174 int rs, int rt, int32_t offset)
20176 int bcond_compute = 0;
20177 TCGv t0 = tcg_temp_new();
20178 TCGv t1 = tcg_temp_new();
20180 /* Load needed operands and calculate btarget */
20181 switch (opc) {
20182 /* compact branch */
20183 case OPC_BGEC:
20184 case OPC_BLTC:
20185 gen_load_gpr(t0, rs);
20186 gen_load_gpr(t1, rt);
20187 bcond_compute = 1;
20188 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20189 break;
20190 case OPC_BGEUC:
20191 case OPC_BLTUC:
20192 if (rs == 0 || rs == rt) {
20193 /* OPC_BLEZALC, OPC_BGEZALC */
20194 /* OPC_BGTZALC, OPC_BLTZALC */
20195 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20197 gen_load_gpr(t0, rs);
20198 gen_load_gpr(t1, rt);
20199 bcond_compute = 1;
20200 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20201 break;
20202 case OPC_BC:
20203 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20204 break;
20205 case OPC_BEQZC:
20206 if (rs != 0) {
20207 /* OPC_BEQZC, OPC_BNEZC */
20208 gen_load_gpr(t0, rs);
20209 bcond_compute = 1;
20210 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20211 } else {
20212 /* OPC_JIC, OPC_JIALC */
20213 TCGv tbase = tcg_temp_new();
20214 TCGv toffset = tcg_temp_new();
20216 gen_load_gpr(tbase, rt);
20217 tcg_gen_movi_tl(toffset, offset);
20218 gen_op_addr_add(ctx, btarget, tbase, toffset);
20219 tcg_temp_free(tbase);
20220 tcg_temp_free(toffset);
20222 break;
20223 default:
20224 MIPS_INVAL("Compact branch/jump");
20225 generate_exception_end(ctx, EXCP_RI);
20226 goto out;
20229 if (bcond_compute == 0) {
20230 /* Uncoditional compact branch */
20231 switch (opc) {
20232 case OPC_BC:
20233 gen_goto_tb(ctx, 0, ctx->btarget);
20234 break;
20235 default:
20236 MIPS_INVAL("Compact branch/jump");
20237 generate_exception_end(ctx, EXCP_RI);
20238 goto out;
20240 } else {
20241 /* Conditional compact branch */
20242 TCGLabel *fs = gen_new_label();
20244 switch (opc) {
20245 case OPC_BGEUC:
20246 if (rs == 0 && rt != 0) {
20247 /* OPC_BLEZALC */
20248 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20249 } else if (rs != 0 && rt != 0 && rs == rt) {
20250 /* OPC_BGEZALC */
20251 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20252 } else {
20253 /* OPC_BGEUC */
20254 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20256 break;
20257 case OPC_BLTUC:
20258 if (rs == 0 && rt != 0) {
20259 /* OPC_BGTZALC */
20260 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20261 } else if (rs != 0 && rt != 0 && rs == rt) {
20262 /* OPC_BLTZALC */
20263 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20264 } else {
20265 /* OPC_BLTUC */
20266 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20268 break;
20269 case OPC_BGEC:
20270 if (rs == 0 && rt != 0) {
20271 /* OPC_BLEZC */
20272 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20273 } else if (rs != 0 && rt != 0 && rs == rt) {
20274 /* OPC_BGEZC */
20275 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20276 } else {
20277 /* OPC_BGEC */
20278 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20280 break;
20281 case OPC_BLTC:
20282 if (rs == 0 && rt != 0) {
20283 /* OPC_BGTZC */
20284 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20285 } else if (rs != 0 && rt != 0 && rs == rt) {
20286 /* OPC_BLTZC */
20287 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20288 } else {
20289 /* OPC_BLTC */
20290 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20292 break;
20293 case OPC_BEQZC:
20294 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20295 break;
20296 default:
20297 MIPS_INVAL("Compact conditional branch/jump");
20298 generate_exception_end(ctx, EXCP_RI);
20299 goto out;
20302 /* branch completion */
20303 clear_branch_hflags(ctx);
20304 ctx->base.is_jmp = DISAS_NORETURN;
20306 /* Generating branch here as compact branches don't have delay slot */
20307 gen_goto_tb(ctx, 1, ctx->btarget);
20308 gen_set_label(fs);
20310 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20313 out:
20314 tcg_temp_free(t0);
20315 tcg_temp_free(t1);
20319 /* nanoMIPS CP1 Branches */
20320 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20321 int32_t ft, int32_t offset)
20323 target_ulong btarget;
20324 TCGv_i64 t0 = tcg_temp_new_i64();
20326 gen_load_fpr64(ctx, t0, ft);
20327 tcg_gen_andi_i64(t0, t0, 1);
20329 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20331 switch (op) {
20332 case NM_BC1EQZC:
20333 tcg_gen_xori_i64(t0, t0, 1);
20334 ctx->hflags |= MIPS_HFLAG_BC;
20335 break;
20336 case NM_BC1NEZC:
20337 /* t0 already set */
20338 ctx->hflags |= MIPS_HFLAG_BC;
20339 break;
20340 default:
20341 MIPS_INVAL("cp1 cond branch");
20342 generate_exception_end(ctx, EXCP_RI);
20343 goto out;
20346 tcg_gen_trunc_i64_tl(bcond, t0);
20348 ctx->btarget = btarget;
20350 out:
20351 tcg_temp_free_i64(t0);
20355 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20357 TCGv t0, t1;
20358 t0 = tcg_temp_new();
20359 t1 = tcg_temp_new();
20361 gen_load_gpr(t0, rs);
20362 gen_load_gpr(t1, rt);
20364 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20365 /* PP.LSXS instructions require shifting */
20366 switch (extract32(ctx->opcode, 7, 4)) {
20367 case NM_SHXS:
20368 check_nms(ctx);
20369 /* fall through */
20370 case NM_LHXS:
20371 case NM_LHUXS:
20372 tcg_gen_shli_tl(t0, t0, 1);
20373 break;
20374 case NM_SWXS:
20375 check_nms(ctx);
20376 /* fall through */
20377 case NM_LWXS:
20378 case NM_LWC1XS:
20379 case NM_SWC1XS:
20380 tcg_gen_shli_tl(t0, t0, 2);
20381 break;
20382 case NM_LDC1XS:
20383 case NM_SDC1XS:
20384 tcg_gen_shli_tl(t0, t0, 3);
20385 break;
20388 gen_op_addr_add(ctx, t0, t0, t1);
20390 switch (extract32(ctx->opcode, 7, 4)) {
20391 case NM_LBX:
20392 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20393 MO_SB);
20394 gen_store_gpr(t0, rd);
20395 break;
20396 case NM_LHX:
20397 /*case NM_LHXS:*/
20398 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20399 MO_TESW);
20400 gen_store_gpr(t0, rd);
20401 break;
20402 case NM_LWX:
20403 /*case NM_LWXS:*/
20404 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20405 MO_TESL);
20406 gen_store_gpr(t0, rd);
20407 break;
20408 case NM_LBUX:
20409 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20410 MO_UB);
20411 gen_store_gpr(t0, rd);
20412 break;
20413 case NM_LHUX:
20414 /*case NM_LHUXS:*/
20415 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20416 MO_TEUW);
20417 gen_store_gpr(t0, rd);
20418 break;
20419 case NM_SBX:
20420 check_nms(ctx);
20421 gen_load_gpr(t1, rd);
20422 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20423 MO_8);
20424 break;
20425 case NM_SHX:
20426 /*case NM_SHXS:*/
20427 check_nms(ctx);
20428 gen_load_gpr(t1, rd);
20429 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20430 MO_TEUW);
20431 break;
20432 case NM_SWX:
20433 /*case NM_SWXS:*/
20434 check_nms(ctx);
20435 gen_load_gpr(t1, rd);
20436 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20437 MO_TEUL);
20438 break;
20439 case NM_LWC1X:
20440 /*case NM_LWC1XS:*/
20441 case NM_LDC1X:
20442 /*case NM_LDC1XS:*/
20443 case NM_SWC1X:
20444 /*case NM_SWC1XS:*/
20445 case NM_SDC1X:
20446 /*case NM_SDC1XS:*/
20447 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20448 check_cp1_enabled(ctx);
20449 switch (extract32(ctx->opcode, 7, 4)) {
20450 case NM_LWC1X:
20451 /*case NM_LWC1XS:*/
20452 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20453 break;
20454 case NM_LDC1X:
20455 /*case NM_LDC1XS:*/
20456 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20457 break;
20458 case NM_SWC1X:
20459 /*case NM_SWC1XS:*/
20460 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20461 break;
20462 case NM_SDC1X:
20463 /*case NM_SDC1XS:*/
20464 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20465 break;
20467 } else {
20468 generate_exception_err(ctx, EXCP_CpU, 1);
20470 break;
20471 default:
20472 generate_exception_end(ctx, EXCP_RI);
20473 break;
20476 tcg_temp_free(t0);
20477 tcg_temp_free(t1);
20480 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20482 int rt, rs, rd;
20484 rt = extract32(ctx->opcode, 21, 5);
20485 rs = extract32(ctx->opcode, 16, 5);
20486 rd = extract32(ctx->opcode, 11, 5);
20488 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20489 generate_exception_end(ctx, EXCP_RI);
20490 return;
20492 check_cp1_enabled(ctx);
20493 switch (extract32(ctx->opcode, 0, 3)) {
20494 case NM_POOL32F_0:
20495 switch (extract32(ctx->opcode, 3, 7)) {
20496 case NM_RINT_S:
20497 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20498 break;
20499 case NM_RINT_D:
20500 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20501 break;
20502 case NM_CLASS_S:
20503 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20504 break;
20505 case NM_CLASS_D:
20506 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20507 break;
20508 case NM_ADD_S:
20509 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20510 break;
20511 case NM_ADD_D:
20512 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20513 break;
20514 case NM_SUB_S:
20515 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20516 break;
20517 case NM_SUB_D:
20518 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20519 break;
20520 case NM_MUL_S:
20521 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20522 break;
20523 case NM_MUL_D:
20524 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20525 break;
20526 case NM_DIV_S:
20527 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20528 break;
20529 case NM_DIV_D:
20530 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20531 break;
20532 case NM_SELEQZ_S:
20533 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20534 break;
20535 case NM_SELEQZ_D:
20536 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20537 break;
20538 case NM_SELNEZ_S:
20539 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20540 break;
20541 case NM_SELNEZ_D:
20542 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20543 break;
20544 case NM_SEL_S:
20545 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20546 break;
20547 case NM_SEL_D:
20548 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20549 break;
20550 case NM_MADDF_S:
20551 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20552 break;
20553 case NM_MADDF_D:
20554 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20555 break;
20556 case NM_MSUBF_S:
20557 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20558 break;
20559 case NM_MSUBF_D:
20560 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20561 break;
20562 default:
20563 generate_exception_end(ctx, EXCP_RI);
20564 break;
20566 break;
20567 case NM_POOL32F_3:
20568 switch (extract32(ctx->opcode, 3, 3)) {
20569 case NM_MIN_FMT:
20570 switch (extract32(ctx->opcode, 9, 1)) {
20571 case FMT_SDPS_S:
20572 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20573 break;
20574 case FMT_SDPS_D:
20575 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20576 break;
20578 break;
20579 case NM_MAX_FMT:
20580 switch (extract32(ctx->opcode, 9, 1)) {
20581 case FMT_SDPS_S:
20582 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20583 break;
20584 case FMT_SDPS_D:
20585 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20586 break;
20588 break;
20589 case NM_MINA_FMT:
20590 switch (extract32(ctx->opcode, 9, 1)) {
20591 case FMT_SDPS_S:
20592 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20593 break;
20594 case FMT_SDPS_D:
20595 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20596 break;
20598 break;
20599 case NM_MAXA_FMT:
20600 switch (extract32(ctx->opcode, 9, 1)) {
20601 case FMT_SDPS_S:
20602 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20603 break;
20604 case FMT_SDPS_D:
20605 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20606 break;
20608 break;
20609 case NM_POOL32FXF:
20610 switch (extract32(ctx->opcode, 6, 8)) {
20611 case NM_CFC1:
20612 gen_cp1(ctx, OPC_CFC1, rt, rs);
20613 break;
20614 case NM_CTC1:
20615 gen_cp1(ctx, OPC_CTC1, rt, rs);
20616 break;
20617 case NM_MFC1:
20618 gen_cp1(ctx, OPC_MFC1, rt, rs);
20619 break;
20620 case NM_MTC1:
20621 gen_cp1(ctx, OPC_MTC1, rt, rs);
20622 break;
20623 case NM_MFHC1:
20624 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20625 break;
20626 case NM_MTHC1:
20627 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20628 break;
20629 case NM_CVT_S_PL:
20630 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20631 break;
20632 case NM_CVT_S_PU:
20633 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20634 break;
20635 default:
20636 switch (extract32(ctx->opcode, 6, 9)) {
20637 case NM_CVT_L_S:
20638 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20639 break;
20640 case NM_CVT_L_D:
20641 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20642 break;
20643 case NM_CVT_W_S:
20644 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20645 break;
20646 case NM_CVT_W_D:
20647 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20648 break;
20649 case NM_RSQRT_S:
20650 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20651 break;
20652 case NM_RSQRT_D:
20653 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20654 break;
20655 case NM_SQRT_S:
20656 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20657 break;
20658 case NM_SQRT_D:
20659 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20660 break;
20661 case NM_RECIP_S:
20662 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20663 break;
20664 case NM_RECIP_D:
20665 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20666 break;
20667 case NM_FLOOR_L_S:
20668 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20669 break;
20670 case NM_FLOOR_L_D:
20671 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20672 break;
20673 case NM_FLOOR_W_S:
20674 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20675 break;
20676 case NM_FLOOR_W_D:
20677 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20678 break;
20679 case NM_CEIL_L_S:
20680 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20681 break;
20682 case NM_CEIL_L_D:
20683 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20684 break;
20685 case NM_CEIL_W_S:
20686 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20687 break;
20688 case NM_CEIL_W_D:
20689 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20690 break;
20691 case NM_TRUNC_L_S:
20692 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20693 break;
20694 case NM_TRUNC_L_D:
20695 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20696 break;
20697 case NM_TRUNC_W_S:
20698 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
20699 break;
20700 case NM_TRUNC_W_D:
20701 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
20702 break;
20703 case NM_ROUND_L_S:
20704 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
20705 break;
20706 case NM_ROUND_L_D:
20707 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
20708 break;
20709 case NM_ROUND_W_S:
20710 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
20711 break;
20712 case NM_ROUND_W_D:
20713 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20714 break;
20715 case NM_MOV_S:
20716 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20717 break;
20718 case NM_MOV_D:
20719 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20720 break;
20721 case NM_ABS_S:
20722 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20723 break;
20724 case NM_ABS_D:
20725 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20726 break;
20727 case NM_NEG_S:
20728 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20729 break;
20730 case NM_NEG_D:
20731 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20732 break;
20733 case NM_CVT_D_S:
20734 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20735 break;
20736 case NM_CVT_D_W:
20737 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20738 break;
20739 case NM_CVT_D_L:
20740 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20741 break;
20742 case NM_CVT_S_D:
20743 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20744 break;
20745 case NM_CVT_S_W:
20746 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20747 break;
20748 case NM_CVT_S_L:
20749 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20750 break;
20751 default:
20752 generate_exception_end(ctx, EXCP_RI);
20753 break;
20755 break;
20757 break;
20759 break;
20760 case NM_POOL32F_5:
20761 switch (extract32(ctx->opcode, 3, 3)) {
20762 case NM_CMP_CONDN_S:
20763 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20764 break;
20765 case NM_CMP_CONDN_D:
20766 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20767 break;
20768 default:
20769 generate_exception_end(ctx, EXCP_RI);
20770 break;
20772 break;
20773 default:
20774 generate_exception_end(ctx, EXCP_RI);
20775 break;
20779 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20780 int rd, int rs, int rt)
20782 int ret = rd;
20783 TCGv t0 = tcg_temp_new();
20784 TCGv v1_t = tcg_temp_new();
20785 TCGv v2_t = tcg_temp_new();
20787 gen_load_gpr(v1_t, rs);
20788 gen_load_gpr(v2_t, rt);
20790 switch (opc) {
20791 case NM_CMP_EQ_PH:
20792 check_dsp(ctx);
20793 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20794 break;
20795 case NM_CMP_LT_PH:
20796 check_dsp(ctx);
20797 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20798 break;
20799 case NM_CMP_LE_PH:
20800 check_dsp(ctx);
20801 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20802 break;
20803 case NM_CMPU_EQ_QB:
20804 check_dsp(ctx);
20805 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20806 break;
20807 case NM_CMPU_LT_QB:
20808 check_dsp(ctx);
20809 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20810 break;
20811 case NM_CMPU_LE_QB:
20812 check_dsp(ctx);
20813 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20814 break;
20815 case NM_CMPGU_EQ_QB:
20816 check_dsp(ctx);
20817 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20818 gen_store_gpr(v1_t, ret);
20819 break;
20820 case NM_CMPGU_LT_QB:
20821 check_dsp(ctx);
20822 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20823 gen_store_gpr(v1_t, ret);
20824 break;
20825 case NM_CMPGU_LE_QB:
20826 check_dsp(ctx);
20827 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20828 gen_store_gpr(v1_t, ret);
20829 break;
20830 case NM_CMPGDU_EQ_QB:
20831 check_dsp_r2(ctx);
20832 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20833 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20834 gen_store_gpr(v1_t, ret);
20835 break;
20836 case NM_CMPGDU_LT_QB:
20837 check_dsp_r2(ctx);
20838 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20839 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20840 gen_store_gpr(v1_t, ret);
20841 break;
20842 case NM_CMPGDU_LE_QB:
20843 check_dsp_r2(ctx);
20844 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20845 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20846 gen_store_gpr(v1_t, ret);
20847 break;
20848 case NM_PACKRL_PH:
20849 check_dsp(ctx);
20850 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20851 gen_store_gpr(v1_t, ret);
20852 break;
20853 case NM_PICK_QB:
20854 check_dsp(ctx);
20855 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20856 gen_store_gpr(v1_t, ret);
20857 break;
20858 case NM_PICK_PH:
20859 check_dsp(ctx);
20860 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20861 gen_store_gpr(v1_t, ret);
20862 break;
20863 case NM_ADDQ_S_W:
20864 check_dsp(ctx);
20865 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20866 gen_store_gpr(v1_t, ret);
20867 break;
20868 case NM_SUBQ_S_W:
20869 check_dsp(ctx);
20870 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20871 gen_store_gpr(v1_t, ret);
20872 break;
20873 case NM_ADDSC:
20874 check_dsp(ctx);
20875 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20876 gen_store_gpr(v1_t, ret);
20877 break;
20878 case NM_ADDWC:
20879 check_dsp(ctx);
20880 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20881 gen_store_gpr(v1_t, ret);
20882 break;
20883 case NM_ADDQ_S_PH:
20884 check_dsp(ctx);
20885 switch (extract32(ctx->opcode, 10, 1)) {
20886 case 0:
20887 /* ADDQ_PH */
20888 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20889 gen_store_gpr(v1_t, ret);
20890 break;
20891 case 1:
20892 /* ADDQ_S_PH */
20893 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20894 gen_store_gpr(v1_t, ret);
20895 break;
20897 break;
20898 case NM_ADDQH_R_PH:
20899 check_dsp_r2(ctx);
20900 switch (extract32(ctx->opcode, 10, 1)) {
20901 case 0:
20902 /* ADDQH_PH */
20903 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20904 gen_store_gpr(v1_t, ret);
20905 break;
20906 case 1:
20907 /* ADDQH_R_PH */
20908 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20909 gen_store_gpr(v1_t, ret);
20910 break;
20912 break;
20913 case NM_ADDQH_R_W:
20914 check_dsp_r2(ctx);
20915 switch (extract32(ctx->opcode, 10, 1)) {
20916 case 0:
20917 /* ADDQH_W */
20918 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20919 gen_store_gpr(v1_t, ret);
20920 break;
20921 case 1:
20922 /* ADDQH_R_W */
20923 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20924 gen_store_gpr(v1_t, ret);
20925 break;
20927 break;
20928 case NM_ADDU_S_QB:
20929 check_dsp(ctx);
20930 switch (extract32(ctx->opcode, 10, 1)) {
20931 case 0:
20932 /* ADDU_QB */
20933 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20934 gen_store_gpr(v1_t, ret);
20935 break;
20936 case 1:
20937 /* ADDU_S_QB */
20938 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20939 gen_store_gpr(v1_t, ret);
20940 break;
20942 break;
20943 case NM_ADDU_S_PH:
20944 check_dsp_r2(ctx);
20945 switch (extract32(ctx->opcode, 10, 1)) {
20946 case 0:
20947 /* ADDU_PH */
20948 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20949 gen_store_gpr(v1_t, ret);
20950 break;
20951 case 1:
20952 /* ADDU_S_PH */
20953 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20954 gen_store_gpr(v1_t, ret);
20955 break;
20957 break;
20958 case NM_ADDUH_R_QB:
20959 check_dsp_r2(ctx);
20960 switch (extract32(ctx->opcode, 10, 1)) {
20961 case 0:
20962 /* ADDUH_QB */
20963 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20964 gen_store_gpr(v1_t, ret);
20965 break;
20966 case 1:
20967 /* ADDUH_R_QB */
20968 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20969 gen_store_gpr(v1_t, ret);
20970 break;
20972 break;
20973 case NM_SHRAV_R_PH:
20974 check_dsp(ctx);
20975 switch (extract32(ctx->opcode, 10, 1)) {
20976 case 0:
20977 /* SHRAV_PH */
20978 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20979 gen_store_gpr(v1_t, ret);
20980 break;
20981 case 1:
20982 /* SHRAV_R_PH */
20983 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20984 gen_store_gpr(v1_t, ret);
20985 break;
20987 break;
20988 case NM_SHRAV_R_QB:
20989 check_dsp_r2(ctx);
20990 switch (extract32(ctx->opcode, 10, 1)) {
20991 case 0:
20992 /* SHRAV_QB */
20993 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20994 gen_store_gpr(v1_t, ret);
20995 break;
20996 case 1:
20997 /* SHRAV_R_QB */
20998 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20999 gen_store_gpr(v1_t, ret);
21000 break;
21002 break;
21003 case NM_SUBQ_S_PH:
21004 check_dsp(ctx);
21005 switch (extract32(ctx->opcode, 10, 1)) {
21006 case 0:
21007 /* SUBQ_PH */
21008 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21009 gen_store_gpr(v1_t, ret);
21010 break;
21011 case 1:
21012 /* SUBQ_S_PH */
21013 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21014 gen_store_gpr(v1_t, ret);
21015 break;
21017 break;
21018 case NM_SUBQH_R_PH:
21019 check_dsp_r2(ctx);
21020 switch (extract32(ctx->opcode, 10, 1)) {
21021 case 0:
21022 /* SUBQH_PH */
21023 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21024 gen_store_gpr(v1_t, ret);
21025 break;
21026 case 1:
21027 /* SUBQH_R_PH */
21028 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21029 gen_store_gpr(v1_t, ret);
21030 break;
21032 break;
21033 case NM_SUBQH_R_W:
21034 check_dsp_r2(ctx);
21035 switch (extract32(ctx->opcode, 10, 1)) {
21036 case 0:
21037 /* SUBQH_W */
21038 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21039 gen_store_gpr(v1_t, ret);
21040 break;
21041 case 1:
21042 /* SUBQH_R_W */
21043 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21044 gen_store_gpr(v1_t, ret);
21045 break;
21047 break;
21048 case NM_SUBU_S_QB:
21049 check_dsp(ctx);
21050 switch (extract32(ctx->opcode, 10, 1)) {
21051 case 0:
21052 /* SUBU_QB */
21053 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21054 gen_store_gpr(v1_t, ret);
21055 break;
21056 case 1:
21057 /* SUBU_S_QB */
21058 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21059 gen_store_gpr(v1_t, ret);
21060 break;
21062 break;
21063 case NM_SUBU_S_PH:
21064 check_dsp_r2(ctx);
21065 switch (extract32(ctx->opcode, 10, 1)) {
21066 case 0:
21067 /* SUBU_PH */
21068 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21069 gen_store_gpr(v1_t, ret);
21070 break;
21071 case 1:
21072 /* SUBU_S_PH */
21073 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21074 gen_store_gpr(v1_t, ret);
21075 break;
21077 break;
21078 case NM_SUBUH_R_QB:
21079 check_dsp_r2(ctx);
21080 switch (extract32(ctx->opcode, 10, 1)) {
21081 case 0:
21082 /* SUBUH_QB */
21083 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21084 gen_store_gpr(v1_t, ret);
21085 break;
21086 case 1:
21087 /* SUBUH_R_QB */
21088 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21089 gen_store_gpr(v1_t, ret);
21090 break;
21092 break;
21093 case NM_SHLLV_S_PH:
21094 check_dsp(ctx);
21095 switch (extract32(ctx->opcode, 10, 1)) {
21096 case 0:
21097 /* SHLLV_PH */
21098 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21099 gen_store_gpr(v1_t, ret);
21100 break;
21101 case 1:
21102 /* SHLLV_S_PH */
21103 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21104 gen_store_gpr(v1_t, ret);
21105 break;
21107 break;
21108 case NM_PRECR_SRA_R_PH_W:
21109 check_dsp_r2(ctx);
21110 switch (extract32(ctx->opcode, 10, 1)) {
21111 case 0:
21112 /* PRECR_SRA_PH_W */
21114 TCGv_i32 sa_t = tcg_const_i32(rd);
21115 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21116 cpu_gpr[rt]);
21117 gen_store_gpr(v1_t, rt);
21118 tcg_temp_free_i32(sa_t);
21120 break;
21121 case 1:
21122 /* PRECR_SRA_R_PH_W */
21124 TCGv_i32 sa_t = tcg_const_i32(rd);
21125 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21126 cpu_gpr[rt]);
21127 gen_store_gpr(v1_t, rt);
21128 tcg_temp_free_i32(sa_t);
21130 break;
21132 break;
21133 case NM_MULEU_S_PH_QBL:
21134 check_dsp(ctx);
21135 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21136 gen_store_gpr(v1_t, ret);
21137 break;
21138 case NM_MULEU_S_PH_QBR:
21139 check_dsp(ctx);
21140 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21141 gen_store_gpr(v1_t, ret);
21142 break;
21143 case NM_MULQ_RS_PH:
21144 check_dsp(ctx);
21145 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21146 gen_store_gpr(v1_t, ret);
21147 break;
21148 case NM_MULQ_S_PH:
21149 check_dsp_r2(ctx);
21150 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21151 gen_store_gpr(v1_t, ret);
21152 break;
21153 case NM_MULQ_RS_W:
21154 check_dsp_r2(ctx);
21155 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21156 gen_store_gpr(v1_t, ret);
21157 break;
21158 case NM_MULQ_S_W:
21159 check_dsp_r2(ctx);
21160 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21161 gen_store_gpr(v1_t, ret);
21162 break;
21163 case NM_APPEND:
21164 check_dsp_r2(ctx);
21165 gen_load_gpr(t0, rs);
21166 if (rd != 0) {
21167 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21169 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21170 break;
21171 case NM_MODSUB:
21172 check_dsp(ctx);
21173 gen_helper_modsub(v1_t, v1_t, v2_t);
21174 gen_store_gpr(v1_t, ret);
21175 break;
21176 case NM_SHRAV_R_W:
21177 check_dsp(ctx);
21178 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21179 gen_store_gpr(v1_t, ret);
21180 break;
21181 case NM_SHRLV_PH:
21182 check_dsp_r2(ctx);
21183 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21184 gen_store_gpr(v1_t, ret);
21185 break;
21186 case NM_SHRLV_QB:
21187 check_dsp(ctx);
21188 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21189 gen_store_gpr(v1_t, ret);
21190 break;
21191 case NM_SHLLV_QB:
21192 check_dsp(ctx);
21193 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21194 gen_store_gpr(v1_t, ret);
21195 break;
21196 case NM_SHLLV_S_W:
21197 check_dsp(ctx);
21198 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21199 gen_store_gpr(v1_t, ret);
21200 break;
21201 case NM_SHILO:
21202 check_dsp(ctx);
21204 TCGv tv0 = tcg_temp_new();
21205 TCGv tv1 = tcg_temp_new();
21206 int16_t imm = extract32(ctx->opcode, 16, 7);
21208 tcg_gen_movi_tl(tv0, rd >> 3);
21209 tcg_gen_movi_tl(tv1, imm);
21210 gen_helper_shilo(tv0, tv1, cpu_env);
21212 break;
21213 case NM_MULEQ_S_W_PHL:
21214 check_dsp(ctx);
21215 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21216 gen_store_gpr(v1_t, ret);
21217 break;
21218 case NM_MULEQ_S_W_PHR:
21219 check_dsp(ctx);
21220 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21221 gen_store_gpr(v1_t, ret);
21222 break;
21223 case NM_MUL_S_PH:
21224 check_dsp_r2(ctx);
21225 switch (extract32(ctx->opcode, 10, 1)) {
21226 case 0:
21227 /* MUL_PH */
21228 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21229 gen_store_gpr(v1_t, ret);
21230 break;
21231 case 1:
21232 /* MUL_S_PH */
21233 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21234 gen_store_gpr(v1_t, ret);
21235 break;
21237 break;
21238 case NM_PRECR_QB_PH:
21239 check_dsp_r2(ctx);
21240 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21241 gen_store_gpr(v1_t, ret);
21242 break;
21243 case NM_PRECRQ_QB_PH:
21244 check_dsp(ctx);
21245 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21246 gen_store_gpr(v1_t, ret);
21247 break;
21248 case NM_PRECRQ_PH_W:
21249 check_dsp(ctx);
21250 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21251 gen_store_gpr(v1_t, ret);
21252 break;
21253 case NM_PRECRQ_RS_PH_W:
21254 check_dsp(ctx);
21255 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21256 gen_store_gpr(v1_t, ret);
21257 break;
21258 case NM_PRECRQU_S_QB_PH:
21259 check_dsp(ctx);
21260 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21261 gen_store_gpr(v1_t, ret);
21262 break;
21263 case NM_SHRA_R_W:
21264 check_dsp(ctx);
21265 tcg_gen_movi_tl(t0, rd);
21266 gen_helper_shra_r_w(v1_t, t0, v1_t);
21267 gen_store_gpr(v1_t, rt);
21268 break;
21269 case NM_SHRA_R_PH:
21270 check_dsp(ctx);
21271 tcg_gen_movi_tl(t0, rd >> 1);
21272 switch (extract32(ctx->opcode, 10, 1)) {
21273 case 0:
21274 /* SHRA_PH */
21275 gen_helper_shra_ph(v1_t, t0, v1_t);
21276 gen_store_gpr(v1_t, rt);
21277 break;
21278 case 1:
21279 /* SHRA_R_PH */
21280 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21281 gen_store_gpr(v1_t, rt);
21282 break;
21284 break;
21285 case NM_SHLL_S_PH:
21286 check_dsp(ctx);
21287 tcg_gen_movi_tl(t0, rd >> 1);
21288 switch (extract32(ctx->opcode, 10, 2)) {
21289 case 0:
21290 /* SHLL_PH */
21291 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21292 gen_store_gpr(v1_t, rt);
21293 break;
21294 case 2:
21295 /* SHLL_S_PH */
21296 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21297 gen_store_gpr(v1_t, rt);
21298 break;
21299 default:
21300 generate_exception_end(ctx, EXCP_RI);
21301 break;
21303 break;
21304 case NM_SHLL_S_W:
21305 check_dsp(ctx);
21306 tcg_gen_movi_tl(t0, rd);
21307 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21308 gen_store_gpr(v1_t, rt);
21309 break;
21310 case NM_REPL_PH:
21311 check_dsp(ctx);
21313 int16_t imm;
21314 imm = sextract32(ctx->opcode, 11, 11);
21315 imm = (int16_t)(imm << 6) >> 6;
21316 if (rt != 0) {
21317 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21320 break;
21321 default:
21322 generate_exception_end(ctx, EXCP_RI);
21323 break;
21327 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21329 uint16_t insn;
21330 uint32_t op;
21331 int rt, rs, rd;
21332 int offset;
21333 int imm;
21335 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21336 ctx->opcode = (ctx->opcode << 16) | insn;
21338 rt = extract32(ctx->opcode, 21, 5);
21339 rs = extract32(ctx->opcode, 16, 5);
21340 rd = extract32(ctx->opcode, 11, 5);
21342 op = extract32(ctx->opcode, 26, 6);
21343 switch (op) {
21344 case NM_P_ADDIU:
21345 if (rt == 0) {
21346 /* P.RI */
21347 switch (extract32(ctx->opcode, 19, 2)) {
21348 case NM_SIGRIE:
21349 default:
21350 generate_exception_end(ctx, EXCP_RI);
21351 break;
21352 case NM_P_SYSCALL:
21353 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21354 generate_exception_end(ctx, EXCP_SYSCALL);
21355 } else {
21356 generate_exception_end(ctx, EXCP_RI);
21358 break;
21359 case NM_BREAK:
21360 generate_exception_end(ctx, EXCP_BREAK);
21361 break;
21362 case NM_SDBBP:
21363 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21364 gen_helper_do_semihosting(cpu_env);
21365 } else {
21366 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21367 generate_exception_end(ctx, EXCP_RI);
21368 } else {
21369 generate_exception_end(ctx, EXCP_DBp);
21372 break;
21374 } else {
21375 /* NM_ADDIU */
21376 imm = extract32(ctx->opcode, 0, 16);
21377 if (rs != 0) {
21378 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21379 } else {
21380 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21382 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21384 break;
21385 case NM_ADDIUPC:
21386 if (rt != 0) {
21387 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21388 extract32(ctx->opcode, 1, 20) << 1;
21389 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21390 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21392 break;
21393 case NM_POOL32A:
21394 switch (ctx->opcode & 0x07) {
21395 case NM_POOL32A0:
21396 gen_pool32a0_nanomips_insn(env, ctx);
21397 break;
21398 case NM_POOL32A5:
21400 int32_t op1 = extract32(ctx->opcode, 3, 7);
21401 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21403 break;
21404 case NM_POOL32A7:
21405 switch (extract32(ctx->opcode, 3, 3)) {
21406 case NM_P_LSX:
21407 gen_p_lsx(ctx, rd, rs, rt);
21408 break;
21409 case NM_LSA:
21411 * In nanoMIPS, the shift field directly encodes the shift
21412 * amount, meaning that the supported shift values are in
21413 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21415 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21416 extract32(ctx->opcode, 9, 2) - 1);
21417 break;
21418 case NM_EXTW:
21419 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21420 break;
21421 case NM_POOL32AXF:
21422 gen_pool32axf_nanomips_insn(env, ctx);
21423 break;
21424 default:
21425 generate_exception_end(ctx, EXCP_RI);
21426 break;
21428 break;
21429 default:
21430 generate_exception_end(ctx, EXCP_RI);
21431 break;
21433 break;
21434 case NM_P_GP_W:
21435 switch (ctx->opcode & 0x03) {
21436 case NM_ADDIUGP_W:
21437 if (rt != 0) {
21438 offset = extract32(ctx->opcode, 0, 21);
21439 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21441 break;
21442 case NM_LWGP:
21443 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21444 break;
21445 case NM_SWGP:
21446 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21447 break;
21448 default:
21449 generate_exception_end(ctx, EXCP_RI);
21450 break;
21452 break;
21453 case NM_P48I:
21455 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21456 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21457 switch (extract32(ctx->opcode, 16, 5)) {
21458 case NM_LI48:
21459 check_nms(ctx);
21460 if (rt != 0) {
21461 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21463 break;
21464 case NM_ADDIU48:
21465 check_nms(ctx);
21466 if (rt != 0) {
21467 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21468 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21470 break;
21471 case NM_ADDIUGP48:
21472 check_nms(ctx);
21473 if (rt != 0) {
21474 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21476 break;
21477 case NM_ADDIUPC48:
21478 check_nms(ctx);
21479 if (rt != 0) {
21480 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21481 addr_off);
21483 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21485 break;
21486 case NM_LWPC48:
21487 check_nms(ctx);
21488 if (rt != 0) {
21489 TCGv t0;
21490 t0 = tcg_temp_new();
21492 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21493 addr_off);
21495 tcg_gen_movi_tl(t0, addr);
21496 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21497 tcg_temp_free(t0);
21499 break;
21500 case NM_SWPC48:
21501 check_nms(ctx);
21503 TCGv t0, t1;
21504 t0 = tcg_temp_new();
21505 t1 = tcg_temp_new();
21507 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21508 addr_off);
21510 tcg_gen_movi_tl(t0, addr);
21511 gen_load_gpr(t1, rt);
21513 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21515 tcg_temp_free(t0);
21516 tcg_temp_free(t1);
21518 break;
21519 default:
21520 generate_exception_end(ctx, EXCP_RI);
21521 break;
21523 return 6;
21525 case NM_P_U12:
21526 switch (extract32(ctx->opcode, 12, 4)) {
21527 case NM_ORI:
21528 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21529 break;
21530 case NM_XORI:
21531 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21532 break;
21533 case NM_ANDI:
21534 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21535 break;
21536 case NM_P_SR:
21537 switch (extract32(ctx->opcode, 20, 1)) {
21538 case NM_PP_SR:
21539 switch (ctx->opcode & 3) {
21540 case NM_SAVE:
21541 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21542 extract32(ctx->opcode, 2, 1),
21543 extract32(ctx->opcode, 3, 9) << 3);
21544 break;
21545 case NM_RESTORE:
21546 case NM_RESTORE_JRC:
21547 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21548 extract32(ctx->opcode, 2, 1),
21549 extract32(ctx->opcode, 3, 9) << 3);
21550 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21551 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21553 break;
21554 default:
21555 generate_exception_end(ctx, EXCP_RI);
21556 break;
21558 break;
21559 case NM_P_SR_F:
21560 generate_exception_end(ctx, EXCP_RI);
21561 break;
21563 break;
21564 case NM_SLTI:
21565 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21566 break;
21567 case NM_SLTIU:
21568 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21569 break;
21570 case NM_SEQI:
21572 TCGv t0 = tcg_temp_new();
21574 imm = extract32(ctx->opcode, 0, 12);
21575 gen_load_gpr(t0, rs);
21576 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21577 gen_store_gpr(t0, rt);
21579 tcg_temp_free(t0);
21581 break;
21582 case NM_ADDIUNEG:
21583 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21584 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21585 break;
21586 case NM_P_SHIFT:
21588 int shift = extract32(ctx->opcode, 0, 5);
21589 switch (extract32(ctx->opcode, 5, 4)) {
21590 case NM_P_SLL:
21591 if (rt == 0 && shift == 0) {
21592 /* NOP */
21593 } else if (rt == 0 && shift == 3) {
21594 /* EHB - treat as NOP */
21595 } else if (rt == 0 && shift == 5) {
21596 /* PAUSE - treat as NOP */
21597 } else if (rt == 0 && shift == 6) {
21598 /* SYNC */
21599 gen_sync(extract32(ctx->opcode, 16, 5));
21600 } else {
21601 /* SLL */
21602 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21603 extract32(ctx->opcode, 0, 5));
21605 break;
21606 case NM_SRL:
21607 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21608 extract32(ctx->opcode, 0, 5));
21609 break;
21610 case NM_SRA:
21611 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21612 extract32(ctx->opcode, 0, 5));
21613 break;
21614 case NM_ROTR:
21615 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21616 extract32(ctx->opcode, 0, 5));
21617 break;
21620 break;
21621 case NM_P_ROTX:
21622 check_nms(ctx);
21623 if (rt != 0) {
21624 TCGv t0 = tcg_temp_new();
21625 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21626 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21627 << 1);
21628 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21630 gen_load_gpr(t0, rs);
21631 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21632 tcg_temp_free(t0);
21634 tcg_temp_free_i32(shift);
21635 tcg_temp_free_i32(shiftx);
21636 tcg_temp_free_i32(stripe);
21638 break;
21639 case NM_P_INS:
21640 switch (((ctx->opcode >> 10) & 2) |
21641 (extract32(ctx->opcode, 5, 1))) {
21642 case NM_INS:
21643 check_nms(ctx);
21644 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21645 extract32(ctx->opcode, 6, 5));
21646 break;
21647 default:
21648 generate_exception_end(ctx, EXCP_RI);
21649 break;
21651 break;
21652 case NM_P_EXT:
21653 switch (((ctx->opcode >> 10) & 2) |
21654 (extract32(ctx->opcode, 5, 1))) {
21655 case NM_EXT:
21656 check_nms(ctx);
21657 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21658 extract32(ctx->opcode, 6, 5));
21659 break;
21660 default:
21661 generate_exception_end(ctx, EXCP_RI);
21662 break;
21664 break;
21665 default:
21666 generate_exception_end(ctx, EXCP_RI);
21667 break;
21669 break;
21670 case NM_POOL32F:
21671 gen_pool32f_nanomips_insn(ctx);
21672 break;
21673 case NM_POOL32S:
21674 break;
21675 case NM_P_LUI:
21676 switch (extract32(ctx->opcode, 1, 1)) {
21677 case NM_LUI:
21678 if (rt != 0) {
21679 tcg_gen_movi_tl(cpu_gpr[rt],
21680 sextract32(ctx->opcode, 0, 1) << 31 |
21681 extract32(ctx->opcode, 2, 10) << 21 |
21682 extract32(ctx->opcode, 12, 9) << 12);
21684 break;
21685 case NM_ALUIPC:
21686 if (rt != 0) {
21687 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21688 extract32(ctx->opcode, 2, 10) << 21 |
21689 extract32(ctx->opcode, 12, 9) << 12;
21690 target_long addr;
21691 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21692 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21694 break;
21696 break;
21697 case NM_P_GP_BH:
21699 uint32_t u = extract32(ctx->opcode, 0, 18);
21701 switch (extract32(ctx->opcode, 18, 3)) {
21702 case NM_LBGP:
21703 gen_ld(ctx, OPC_LB, rt, 28, u);
21704 break;
21705 case NM_SBGP:
21706 gen_st(ctx, OPC_SB, rt, 28, u);
21707 break;
21708 case NM_LBUGP:
21709 gen_ld(ctx, OPC_LBU, rt, 28, u);
21710 break;
21711 case NM_ADDIUGP_B:
21712 if (rt != 0) {
21713 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21715 break;
21716 case NM_P_GP_LH:
21717 u &= ~1;
21718 switch (ctx->opcode & 1) {
21719 case NM_LHGP:
21720 gen_ld(ctx, OPC_LH, rt, 28, u);
21721 break;
21722 case NM_LHUGP:
21723 gen_ld(ctx, OPC_LHU, rt, 28, u);
21724 break;
21726 break;
21727 case NM_P_GP_SH:
21728 u &= ~1;
21729 switch (ctx->opcode & 1) {
21730 case NM_SHGP:
21731 gen_st(ctx, OPC_SH, rt, 28, u);
21732 break;
21733 default:
21734 generate_exception_end(ctx, EXCP_RI);
21735 break;
21737 break;
21738 case NM_P_GP_CP1:
21739 u &= ~0x3;
21740 switch (ctx->opcode & 0x3) {
21741 case NM_LWC1GP:
21742 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21743 break;
21744 case NM_LDC1GP:
21745 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21746 break;
21747 case NM_SWC1GP:
21748 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21749 break;
21750 case NM_SDC1GP:
21751 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21752 break;
21754 break;
21755 default:
21756 generate_exception_end(ctx, EXCP_RI);
21757 break;
21760 break;
21761 case NM_P_LS_U12:
21763 uint32_t u = extract32(ctx->opcode, 0, 12);
21765 switch (extract32(ctx->opcode, 12, 4)) {
21766 case NM_P_PREFU12:
21767 if (rt == 31) {
21768 /* SYNCI */
21770 * Break the TB to be able to sync copied instructions
21771 * immediately.
21773 ctx->base.is_jmp = DISAS_STOP;
21774 } else {
21775 /* PREF */
21776 /* Treat as NOP. */
21778 break;
21779 case NM_LB:
21780 gen_ld(ctx, OPC_LB, rt, rs, u);
21781 break;
21782 case NM_LH:
21783 gen_ld(ctx, OPC_LH, rt, rs, u);
21784 break;
21785 case NM_LW:
21786 gen_ld(ctx, OPC_LW, rt, rs, u);
21787 break;
21788 case NM_LBU:
21789 gen_ld(ctx, OPC_LBU, rt, rs, u);
21790 break;
21791 case NM_LHU:
21792 gen_ld(ctx, OPC_LHU, rt, rs, u);
21793 break;
21794 case NM_SB:
21795 gen_st(ctx, OPC_SB, rt, rs, u);
21796 break;
21797 case NM_SH:
21798 gen_st(ctx, OPC_SH, rt, rs, u);
21799 break;
21800 case NM_SW:
21801 gen_st(ctx, OPC_SW, rt, rs, u);
21802 break;
21803 case NM_LWC1:
21804 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21805 break;
21806 case NM_LDC1:
21807 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21808 break;
21809 case NM_SWC1:
21810 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21811 break;
21812 case NM_SDC1:
21813 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21814 break;
21815 default:
21816 generate_exception_end(ctx, EXCP_RI);
21817 break;
21820 break;
21821 case NM_P_LS_S9:
21823 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21824 extract32(ctx->opcode, 0, 8);
21826 switch (extract32(ctx->opcode, 8, 3)) {
21827 case NM_P_LS_S0:
21828 switch (extract32(ctx->opcode, 11, 4)) {
21829 case NM_LBS9:
21830 gen_ld(ctx, OPC_LB, rt, rs, s);
21831 break;
21832 case NM_LHS9:
21833 gen_ld(ctx, OPC_LH, rt, rs, s);
21834 break;
21835 case NM_LWS9:
21836 gen_ld(ctx, OPC_LW, rt, rs, s);
21837 break;
21838 case NM_LBUS9:
21839 gen_ld(ctx, OPC_LBU, rt, rs, s);
21840 break;
21841 case NM_LHUS9:
21842 gen_ld(ctx, OPC_LHU, rt, rs, s);
21843 break;
21844 case NM_SBS9:
21845 gen_st(ctx, OPC_SB, rt, rs, s);
21846 break;
21847 case NM_SHS9:
21848 gen_st(ctx, OPC_SH, rt, rs, s);
21849 break;
21850 case NM_SWS9:
21851 gen_st(ctx, OPC_SW, rt, rs, s);
21852 break;
21853 case NM_LWC1S9:
21854 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21855 break;
21856 case NM_LDC1S9:
21857 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21858 break;
21859 case NM_SWC1S9:
21860 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21861 break;
21862 case NM_SDC1S9:
21863 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21864 break;
21865 case NM_P_PREFS9:
21866 if (rt == 31) {
21867 /* SYNCI */
21869 * Break the TB to be able to sync copied instructions
21870 * immediately.
21872 ctx->base.is_jmp = DISAS_STOP;
21873 } else {
21874 /* PREF */
21875 /* Treat as NOP. */
21877 break;
21878 default:
21879 generate_exception_end(ctx, EXCP_RI);
21880 break;
21882 break;
21883 case NM_P_LS_S1:
21884 switch (extract32(ctx->opcode, 11, 4)) {
21885 case NM_UALH:
21886 case NM_UASH:
21887 check_nms(ctx);
21889 TCGv t0 = tcg_temp_new();
21890 TCGv t1 = tcg_temp_new();
21892 gen_base_offset_addr(ctx, t0, rs, s);
21894 switch (extract32(ctx->opcode, 11, 4)) {
21895 case NM_UALH:
21896 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21897 MO_UNALN);
21898 gen_store_gpr(t0, rt);
21899 break;
21900 case NM_UASH:
21901 gen_load_gpr(t1, rt);
21902 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21903 MO_UNALN);
21904 break;
21906 tcg_temp_free(t0);
21907 tcg_temp_free(t1);
21909 break;
21910 case NM_P_LL:
21911 switch (ctx->opcode & 0x03) {
21912 case NM_LL:
21913 gen_ld(ctx, OPC_LL, rt, rs, s);
21914 break;
21915 case NM_LLWP:
21916 check_xnp(ctx);
21917 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21918 break;
21920 break;
21921 case NM_P_SC:
21922 switch (ctx->opcode & 0x03) {
21923 case NM_SC:
21924 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
21925 break;
21926 case NM_SCWP:
21927 check_xnp(ctx);
21928 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21929 false);
21930 break;
21932 break;
21933 case NM_CACHE:
21934 check_cp0_enabled(ctx);
21935 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21936 gen_cache_operation(ctx, rt, rs, s);
21938 break;
21940 break;
21941 case NM_P_LS_E0:
21942 switch (extract32(ctx->opcode, 11, 4)) {
21943 case NM_LBE:
21944 check_eva(ctx);
21945 check_cp0_enabled(ctx);
21946 gen_ld(ctx, OPC_LBE, rt, rs, s);
21947 break;
21948 case NM_SBE:
21949 check_eva(ctx);
21950 check_cp0_enabled(ctx);
21951 gen_st(ctx, OPC_SBE, rt, rs, s);
21952 break;
21953 case NM_LBUE:
21954 check_eva(ctx);
21955 check_cp0_enabled(ctx);
21956 gen_ld(ctx, OPC_LBUE, rt, rs, s);
21957 break;
21958 case NM_P_PREFE:
21959 if (rt == 31) {
21960 /* case NM_SYNCIE */
21961 check_eva(ctx);
21962 check_cp0_enabled(ctx);
21964 * Break the TB to be able to sync copied instructions
21965 * immediately.
21967 ctx->base.is_jmp = DISAS_STOP;
21968 } else {
21969 /* case NM_PREFE */
21970 check_eva(ctx);
21971 check_cp0_enabled(ctx);
21972 /* Treat as NOP. */
21974 break;
21975 case NM_LHE:
21976 check_eva(ctx);
21977 check_cp0_enabled(ctx);
21978 gen_ld(ctx, OPC_LHE, rt, rs, s);
21979 break;
21980 case NM_SHE:
21981 check_eva(ctx);
21982 check_cp0_enabled(ctx);
21983 gen_st(ctx, OPC_SHE, rt, rs, s);
21984 break;
21985 case NM_LHUE:
21986 check_eva(ctx);
21987 check_cp0_enabled(ctx);
21988 gen_ld(ctx, OPC_LHUE, rt, rs, s);
21989 break;
21990 case NM_CACHEE:
21991 check_nms_dl_il_sl_tl_l2c(ctx);
21992 gen_cache_operation(ctx, rt, rs, s);
21993 break;
21994 case NM_LWE:
21995 check_eva(ctx);
21996 check_cp0_enabled(ctx);
21997 gen_ld(ctx, OPC_LWE, rt, rs, s);
21998 break;
21999 case NM_SWE:
22000 check_eva(ctx);
22001 check_cp0_enabled(ctx);
22002 gen_st(ctx, OPC_SWE, rt, rs, s);
22003 break;
22004 case NM_P_LLE:
22005 switch (extract32(ctx->opcode, 2, 2)) {
22006 case NM_LLE:
22007 check_xnp(ctx);
22008 check_eva(ctx);
22009 check_cp0_enabled(ctx);
22010 gen_ld(ctx, OPC_LLE, rt, rs, s);
22011 break;
22012 case NM_LLWPE:
22013 check_xnp(ctx);
22014 check_eva(ctx);
22015 check_cp0_enabled(ctx);
22016 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22017 break;
22018 default:
22019 generate_exception_end(ctx, EXCP_RI);
22020 break;
22022 break;
22023 case NM_P_SCE:
22024 switch (extract32(ctx->opcode, 2, 2)) {
22025 case NM_SCE:
22026 check_xnp(ctx);
22027 check_eva(ctx);
22028 check_cp0_enabled(ctx);
22029 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22030 break;
22031 case NM_SCWPE:
22032 check_xnp(ctx);
22033 check_eva(ctx);
22034 check_cp0_enabled(ctx);
22035 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22036 true);
22037 break;
22038 default:
22039 generate_exception_end(ctx, EXCP_RI);
22040 break;
22042 break;
22044 break;
22045 case NM_P_LS_WM:
22046 case NM_P_LS_UAWM:
22047 check_nms(ctx);
22049 int count = extract32(ctx->opcode, 12, 3);
22050 int counter = 0;
22052 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22053 extract32(ctx->opcode, 0, 8);
22054 TCGv va = tcg_temp_new();
22055 TCGv t1 = tcg_temp_new();
22056 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22057 NM_P_LS_UAWM ? MO_UNALN : 0;
22059 count = (count == 0) ? 8 : count;
22060 while (counter != count) {
22061 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22062 int this_offset = offset + (counter << 2);
22064 gen_base_offset_addr(ctx, va, rs, this_offset);
22066 switch (extract32(ctx->opcode, 11, 1)) {
22067 case NM_LWM:
22068 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22069 memop | MO_TESL);
22070 gen_store_gpr(t1, this_rt);
22071 if ((this_rt == rs) &&
22072 (counter != (count - 1))) {
22073 /* UNPREDICTABLE */
22075 break;
22076 case NM_SWM:
22077 this_rt = (rt == 0) ? 0 : this_rt;
22078 gen_load_gpr(t1, this_rt);
22079 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22080 memop | MO_TEUL);
22081 break;
22083 counter++;
22085 tcg_temp_free(va);
22086 tcg_temp_free(t1);
22088 break;
22089 default:
22090 generate_exception_end(ctx, EXCP_RI);
22091 break;
22094 break;
22095 case NM_MOVE_BALC:
22096 check_nms(ctx);
22098 TCGv t0 = tcg_temp_new();
22099 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22100 extract32(ctx->opcode, 1, 20) << 1;
22101 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22102 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22103 extract32(ctx->opcode, 21, 3));
22104 gen_load_gpr(t0, rt);
22105 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22106 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22107 tcg_temp_free(t0);
22109 break;
22110 case NM_P_BAL:
22112 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22113 extract32(ctx->opcode, 1, 24) << 1;
22115 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22116 /* BC */
22117 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22118 } else {
22119 /* BALC */
22120 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22123 break;
22124 case NM_P_J:
22125 switch (extract32(ctx->opcode, 12, 4)) {
22126 case NM_JALRC:
22127 case NM_JALRC_HB:
22128 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22129 break;
22130 case NM_P_BALRSC:
22131 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22132 break;
22133 default:
22134 generate_exception_end(ctx, EXCP_RI);
22135 break;
22137 break;
22138 case NM_P_BR1:
22140 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22141 extract32(ctx->opcode, 1, 13) << 1;
22142 switch (extract32(ctx->opcode, 14, 2)) {
22143 case NM_BEQC:
22144 check_nms(ctx);
22145 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22146 break;
22147 case NM_P_BR3A:
22148 s = sextract32(ctx->opcode, 0, 1) << 14 |
22149 extract32(ctx->opcode, 1, 13) << 1;
22150 check_cp1_enabled(ctx);
22151 switch (extract32(ctx->opcode, 16, 5)) {
22152 case NM_BC1EQZC:
22153 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22154 break;
22155 case NM_BC1NEZC:
22156 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22157 break;
22158 case NM_BPOSGE32C:
22159 check_dsp_r3(ctx);
22161 int32_t imm = extract32(ctx->opcode, 1, 13) |
22162 extract32(ctx->opcode, 0, 1) << 13;
22164 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22165 imm);
22167 break;
22168 default:
22169 generate_exception_end(ctx, EXCP_RI);
22170 break;
22172 break;
22173 case NM_BGEC:
22174 if (rs == rt) {
22175 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22176 } else {
22177 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22179 break;
22180 case NM_BGEUC:
22181 if (rs == rt || rt == 0) {
22182 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22183 } else if (rs == 0) {
22184 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22185 } else {
22186 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22188 break;
22191 break;
22192 case NM_P_BR2:
22194 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22195 extract32(ctx->opcode, 1, 13) << 1;
22196 switch (extract32(ctx->opcode, 14, 2)) {
22197 case NM_BNEC:
22198 check_nms(ctx);
22199 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22200 break;
22201 case NM_BLTC:
22202 if (rs != 0 && rt != 0 && rs == rt) {
22203 /* NOP */
22204 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22205 } else {
22206 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22208 break;
22209 case NM_BLTUC:
22210 if (rs == 0 || rs == rt) {
22211 /* NOP */
22212 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22213 } else {
22214 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22216 break;
22217 default:
22218 generate_exception_end(ctx, EXCP_RI);
22219 break;
22222 break;
22223 case NM_P_BRI:
22225 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22226 extract32(ctx->opcode, 1, 10) << 1;
22227 uint32_t u = extract32(ctx->opcode, 11, 7);
22229 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22230 rt, u, s);
22232 break;
22233 default:
22234 generate_exception_end(ctx, EXCP_RI);
22235 break;
22237 return 4;
22240 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22242 uint32_t op;
22243 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22244 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22245 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22246 int offset;
22247 int imm;
22249 /* make sure instructions are on a halfword boundary */
22250 if (ctx->base.pc_next & 0x1) {
22251 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22252 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22253 tcg_temp_free(tmp);
22254 generate_exception_end(ctx, EXCP_AdEL);
22255 return 2;
22258 op = extract32(ctx->opcode, 10, 6);
22259 switch (op) {
22260 case NM_P16_MV:
22261 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22262 if (rt != 0) {
22263 /* MOVE */
22264 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22265 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22266 } else {
22267 /* P16.RI */
22268 switch (extract32(ctx->opcode, 3, 2)) {
22269 case NM_P16_SYSCALL:
22270 if (extract32(ctx->opcode, 2, 1) == 0) {
22271 generate_exception_end(ctx, EXCP_SYSCALL);
22272 } else {
22273 generate_exception_end(ctx, EXCP_RI);
22275 break;
22276 case NM_BREAK16:
22277 generate_exception_end(ctx, EXCP_BREAK);
22278 break;
22279 case NM_SDBBP16:
22280 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22281 gen_helper_do_semihosting(cpu_env);
22282 } else {
22283 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22284 generate_exception_end(ctx, EXCP_RI);
22285 } else {
22286 generate_exception_end(ctx, EXCP_DBp);
22289 break;
22290 default:
22291 generate_exception_end(ctx, EXCP_RI);
22292 break;
22295 break;
22296 case NM_P16_SHIFT:
22298 int shift = extract32(ctx->opcode, 0, 3);
22299 uint32_t opc = 0;
22300 shift = (shift == 0) ? 8 : shift;
22302 switch (extract32(ctx->opcode, 3, 1)) {
22303 case NM_SLL16:
22304 opc = OPC_SLL;
22305 break;
22306 case NM_SRL16:
22307 opc = OPC_SRL;
22308 break;
22310 gen_shift_imm(ctx, opc, rt, rs, shift);
22312 break;
22313 case NM_P16C:
22314 switch (ctx->opcode & 1) {
22315 case NM_POOL16C_0:
22316 gen_pool16c_nanomips_insn(ctx);
22317 break;
22318 case NM_LWXS16:
22319 gen_ldxs(ctx, rt, rs, rd);
22320 break;
22322 break;
22323 case NM_P16_A1:
22324 switch (extract32(ctx->opcode, 6, 1)) {
22325 case NM_ADDIUR1SP:
22326 imm = extract32(ctx->opcode, 0, 6) << 2;
22327 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22328 break;
22329 default:
22330 generate_exception_end(ctx, EXCP_RI);
22331 break;
22333 break;
22334 case NM_P16_A2:
22335 switch (extract32(ctx->opcode, 3, 1)) {
22336 case NM_ADDIUR2:
22337 imm = extract32(ctx->opcode, 0, 3) << 2;
22338 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22339 break;
22340 case NM_P_ADDIURS5:
22341 rt = extract32(ctx->opcode, 5, 5);
22342 if (rt != 0) {
22343 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22344 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22345 (extract32(ctx->opcode, 0, 3));
22346 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22348 break;
22350 break;
22351 case NM_P16_ADDU:
22352 switch (ctx->opcode & 0x1) {
22353 case NM_ADDU16:
22354 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22355 break;
22356 case NM_SUBU16:
22357 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22358 break;
22360 break;
22361 case NM_P16_4X4:
22362 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22363 extract32(ctx->opcode, 5, 3);
22364 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22365 extract32(ctx->opcode, 0, 3);
22366 rt = decode_gpr_gpr4(rt);
22367 rs = decode_gpr_gpr4(rs);
22368 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22369 (extract32(ctx->opcode, 3, 1))) {
22370 case NM_ADDU4X4:
22371 check_nms(ctx);
22372 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22373 break;
22374 case NM_MUL4X4:
22375 check_nms(ctx);
22376 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22377 break;
22378 default:
22379 generate_exception_end(ctx, EXCP_RI);
22380 break;
22382 break;
22383 case NM_LI16:
22385 int imm = extract32(ctx->opcode, 0, 7);
22386 imm = (imm == 0x7f ? -1 : imm);
22387 if (rt != 0) {
22388 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22391 break;
22392 case NM_ANDI16:
22394 uint32_t u = extract32(ctx->opcode, 0, 4);
22395 u = (u == 12) ? 0xff :
22396 (u == 13) ? 0xffff : u;
22397 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22399 break;
22400 case NM_P16_LB:
22401 offset = extract32(ctx->opcode, 0, 2);
22402 switch (extract32(ctx->opcode, 2, 2)) {
22403 case NM_LB16:
22404 gen_ld(ctx, OPC_LB, rt, rs, offset);
22405 break;
22406 case NM_SB16:
22407 rt = decode_gpr_gpr3_src_store(
22408 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22409 gen_st(ctx, OPC_SB, rt, rs, offset);
22410 break;
22411 case NM_LBU16:
22412 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22413 break;
22414 default:
22415 generate_exception_end(ctx, EXCP_RI);
22416 break;
22418 break;
22419 case NM_P16_LH:
22420 offset = extract32(ctx->opcode, 1, 2) << 1;
22421 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22422 case NM_LH16:
22423 gen_ld(ctx, OPC_LH, rt, rs, offset);
22424 break;
22425 case NM_SH16:
22426 rt = decode_gpr_gpr3_src_store(
22427 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22428 gen_st(ctx, OPC_SH, rt, rs, offset);
22429 break;
22430 case NM_LHU16:
22431 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22432 break;
22433 default:
22434 generate_exception_end(ctx, EXCP_RI);
22435 break;
22437 break;
22438 case NM_LW16:
22439 offset = extract32(ctx->opcode, 0, 4) << 2;
22440 gen_ld(ctx, OPC_LW, rt, rs, offset);
22441 break;
22442 case NM_LWSP16:
22443 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22444 offset = extract32(ctx->opcode, 0, 5) << 2;
22445 gen_ld(ctx, OPC_LW, rt, 29, offset);
22446 break;
22447 case NM_LW4X4:
22448 check_nms(ctx);
22449 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22450 extract32(ctx->opcode, 5, 3);
22451 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22452 extract32(ctx->opcode, 0, 3);
22453 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22454 (extract32(ctx->opcode, 8, 1) << 2);
22455 rt = decode_gpr_gpr4(rt);
22456 rs = decode_gpr_gpr4(rs);
22457 gen_ld(ctx, OPC_LW, rt, rs, offset);
22458 break;
22459 case NM_SW4X4:
22460 check_nms(ctx);
22461 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22462 extract32(ctx->opcode, 5, 3);
22463 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22464 extract32(ctx->opcode, 0, 3);
22465 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22466 (extract32(ctx->opcode, 8, 1) << 2);
22467 rt = decode_gpr_gpr4_zero(rt);
22468 rs = decode_gpr_gpr4(rs);
22469 gen_st(ctx, OPC_SW, rt, rs, offset);
22470 break;
22471 case NM_LWGP16:
22472 offset = extract32(ctx->opcode, 0, 7) << 2;
22473 gen_ld(ctx, OPC_LW, rt, 28, offset);
22474 break;
22475 case NM_SWSP16:
22476 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22477 offset = extract32(ctx->opcode, 0, 5) << 2;
22478 gen_st(ctx, OPC_SW, rt, 29, offset);
22479 break;
22480 case NM_SW16:
22481 rt = decode_gpr_gpr3_src_store(
22482 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22483 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22484 offset = extract32(ctx->opcode, 0, 4) << 2;
22485 gen_st(ctx, OPC_SW, rt, rs, offset);
22486 break;
22487 case NM_SWGP16:
22488 rt = decode_gpr_gpr3_src_store(
22489 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22490 offset = extract32(ctx->opcode, 0, 7) << 2;
22491 gen_st(ctx, OPC_SW, rt, 28, offset);
22492 break;
22493 case NM_BC16:
22494 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22495 (sextract32(ctx->opcode, 0, 1) << 10) |
22496 (extract32(ctx->opcode, 1, 9) << 1));
22497 break;
22498 case NM_BALC16:
22499 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22500 (sextract32(ctx->opcode, 0, 1) << 10) |
22501 (extract32(ctx->opcode, 1, 9) << 1));
22502 break;
22503 case NM_BEQZC16:
22504 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22505 (sextract32(ctx->opcode, 0, 1) << 7) |
22506 (extract32(ctx->opcode, 1, 6) << 1));
22507 break;
22508 case NM_BNEZC16:
22509 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22510 (sextract32(ctx->opcode, 0, 1) << 7) |
22511 (extract32(ctx->opcode, 1, 6) << 1));
22512 break;
22513 case NM_P16_BR:
22514 switch (ctx->opcode & 0xf) {
22515 case 0:
22516 /* P16.JRC */
22517 switch (extract32(ctx->opcode, 4, 1)) {
22518 case NM_JRC:
22519 gen_compute_branch_nm(ctx, OPC_JR, 2,
22520 extract32(ctx->opcode, 5, 5), 0, 0);
22521 break;
22522 case NM_JALRC16:
22523 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22524 extract32(ctx->opcode, 5, 5), 31, 0);
22525 break;
22527 break;
22528 default:
22530 /* P16.BRI */
22531 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22532 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22533 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22534 extract32(ctx->opcode, 0, 4) << 1);
22536 break;
22538 break;
22539 case NM_P16_SR:
22541 int count = extract32(ctx->opcode, 0, 4);
22542 int u = extract32(ctx->opcode, 4, 4) << 4;
22544 rt = 30 + extract32(ctx->opcode, 9, 1);
22545 switch (extract32(ctx->opcode, 8, 1)) {
22546 case NM_SAVE16:
22547 gen_save(ctx, rt, count, 0, u);
22548 break;
22549 case NM_RESTORE_JRC16:
22550 gen_restore(ctx, rt, count, 0, u);
22551 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22552 break;
22555 break;
22556 case NM_MOVEP:
22557 case NM_MOVEPREV:
22558 check_nms(ctx);
22560 static const int gpr2reg1[] = {4, 5, 6, 7};
22561 static const int gpr2reg2[] = {5, 6, 7, 8};
22562 int re;
22563 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22564 extract32(ctx->opcode, 8, 1);
22565 int r1 = gpr2reg1[rd2];
22566 int r2 = gpr2reg2[rd2];
22567 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22568 extract32(ctx->opcode, 0, 3);
22569 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22570 extract32(ctx->opcode, 5, 3);
22571 TCGv t0 = tcg_temp_new();
22572 TCGv t1 = tcg_temp_new();
22573 if (op == NM_MOVEP) {
22574 rd = r1;
22575 re = r2;
22576 rs = decode_gpr_gpr4_zero(r3);
22577 rt = decode_gpr_gpr4_zero(r4);
22578 } else {
22579 rd = decode_gpr_gpr4(r3);
22580 re = decode_gpr_gpr4(r4);
22581 rs = r1;
22582 rt = r2;
22584 gen_load_gpr(t0, rs);
22585 gen_load_gpr(t1, rt);
22586 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22587 tcg_gen_mov_tl(cpu_gpr[re], t1);
22588 tcg_temp_free(t0);
22589 tcg_temp_free(t1);
22591 break;
22592 default:
22593 return decode_nanomips_32_48_opc(env, ctx);
22596 return 2;
22600 /* SmartMIPS extension to MIPS32 */
22602 #if defined(TARGET_MIPS64)
22604 /* MDMX extension to MIPS64 */
22606 #endif
22608 /* MIPSDSP functions. */
22609 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22610 int rd, int base, int offset)
22612 TCGv t0;
22614 check_dsp(ctx);
22615 t0 = tcg_temp_new();
22617 if (base == 0) {
22618 gen_load_gpr(t0, offset);
22619 } else if (offset == 0) {
22620 gen_load_gpr(t0, base);
22621 } else {
22622 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22625 switch (opc) {
22626 case OPC_LBUX:
22627 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22628 gen_store_gpr(t0, rd);
22629 break;
22630 case OPC_LHX:
22631 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22632 gen_store_gpr(t0, rd);
22633 break;
22634 case OPC_LWX:
22635 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22636 gen_store_gpr(t0, rd);
22637 break;
22638 #if defined(TARGET_MIPS64)
22639 case OPC_LDX:
22640 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22641 gen_store_gpr(t0, rd);
22642 break;
22643 #endif
22645 tcg_temp_free(t0);
22648 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22649 int ret, int v1, int v2)
22651 TCGv v1_t;
22652 TCGv v2_t;
22654 if (ret == 0) {
22655 /* Treat as NOP. */
22656 return;
22659 v1_t = tcg_temp_new();
22660 v2_t = tcg_temp_new();
22662 gen_load_gpr(v1_t, v1);
22663 gen_load_gpr(v2_t, v2);
22665 switch (op1) {
22666 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22667 case OPC_MULT_G_2E:
22668 check_dsp_r2(ctx);
22669 switch (op2) {
22670 case OPC_ADDUH_QB:
22671 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22672 break;
22673 case OPC_ADDUH_R_QB:
22674 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22675 break;
22676 case OPC_ADDQH_PH:
22677 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22678 break;
22679 case OPC_ADDQH_R_PH:
22680 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22681 break;
22682 case OPC_ADDQH_W:
22683 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22684 break;
22685 case OPC_ADDQH_R_W:
22686 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22687 break;
22688 case OPC_SUBUH_QB:
22689 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22690 break;
22691 case OPC_SUBUH_R_QB:
22692 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22693 break;
22694 case OPC_SUBQH_PH:
22695 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22696 break;
22697 case OPC_SUBQH_R_PH:
22698 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22699 break;
22700 case OPC_SUBQH_W:
22701 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
22702 break;
22703 case OPC_SUBQH_R_W:
22704 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22705 break;
22707 break;
22708 case OPC_ABSQ_S_PH_DSP:
22709 switch (op2) {
22710 case OPC_ABSQ_S_QB:
22711 check_dsp_r2(ctx);
22712 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
22713 break;
22714 case OPC_ABSQ_S_PH:
22715 check_dsp(ctx);
22716 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
22717 break;
22718 case OPC_ABSQ_S_W:
22719 check_dsp(ctx);
22720 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
22721 break;
22722 case OPC_PRECEQ_W_PHL:
22723 check_dsp(ctx);
22724 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
22725 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22726 break;
22727 case OPC_PRECEQ_W_PHR:
22728 check_dsp(ctx);
22729 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
22730 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
22731 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22732 break;
22733 case OPC_PRECEQU_PH_QBL:
22734 check_dsp(ctx);
22735 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
22736 break;
22737 case OPC_PRECEQU_PH_QBR:
22738 check_dsp(ctx);
22739 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
22740 break;
22741 case OPC_PRECEQU_PH_QBLA:
22742 check_dsp(ctx);
22743 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
22744 break;
22745 case OPC_PRECEQU_PH_QBRA:
22746 check_dsp(ctx);
22747 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
22748 break;
22749 case OPC_PRECEU_PH_QBL:
22750 check_dsp(ctx);
22751 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
22752 break;
22753 case OPC_PRECEU_PH_QBR:
22754 check_dsp(ctx);
22755 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
22756 break;
22757 case OPC_PRECEU_PH_QBLA:
22758 check_dsp(ctx);
22759 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
22760 break;
22761 case OPC_PRECEU_PH_QBRA:
22762 check_dsp(ctx);
22763 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
22764 break;
22766 break;
22767 case OPC_ADDU_QB_DSP:
22768 switch (op2) {
22769 case OPC_ADDQ_PH:
22770 check_dsp(ctx);
22771 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22772 break;
22773 case OPC_ADDQ_S_PH:
22774 check_dsp(ctx);
22775 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22776 break;
22777 case OPC_ADDQ_S_W:
22778 check_dsp(ctx);
22779 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22780 break;
22781 case OPC_ADDU_QB:
22782 check_dsp(ctx);
22783 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22784 break;
22785 case OPC_ADDU_S_QB:
22786 check_dsp(ctx);
22787 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22788 break;
22789 case OPC_ADDU_PH:
22790 check_dsp_r2(ctx);
22791 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22792 break;
22793 case OPC_ADDU_S_PH:
22794 check_dsp_r2(ctx);
22795 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22796 break;
22797 case OPC_SUBQ_PH:
22798 check_dsp(ctx);
22799 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22800 break;
22801 case OPC_SUBQ_S_PH:
22802 check_dsp(ctx);
22803 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22804 break;
22805 case OPC_SUBQ_S_W:
22806 check_dsp(ctx);
22807 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22808 break;
22809 case OPC_SUBU_QB:
22810 check_dsp(ctx);
22811 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22812 break;
22813 case OPC_SUBU_S_QB:
22814 check_dsp(ctx);
22815 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22816 break;
22817 case OPC_SUBU_PH:
22818 check_dsp_r2(ctx);
22819 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22820 break;
22821 case OPC_SUBU_S_PH:
22822 check_dsp_r2(ctx);
22823 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22824 break;
22825 case OPC_ADDSC:
22826 check_dsp(ctx);
22827 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22828 break;
22829 case OPC_ADDWC:
22830 check_dsp(ctx);
22831 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22832 break;
22833 case OPC_MODSUB:
22834 check_dsp(ctx);
22835 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22836 break;
22837 case OPC_RADDU_W_QB:
22838 check_dsp(ctx);
22839 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22840 break;
22842 break;
22843 case OPC_CMPU_EQ_QB_DSP:
22844 switch (op2) {
22845 case OPC_PRECR_QB_PH:
22846 check_dsp_r2(ctx);
22847 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22848 break;
22849 case OPC_PRECRQ_QB_PH:
22850 check_dsp(ctx);
22851 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22852 break;
22853 case OPC_PRECR_SRA_PH_W:
22854 check_dsp_r2(ctx);
22856 TCGv_i32 sa_t = tcg_const_i32(v2);
22857 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22858 cpu_gpr[ret]);
22859 tcg_temp_free_i32(sa_t);
22860 break;
22862 case OPC_PRECR_SRA_R_PH_W:
22863 check_dsp_r2(ctx);
22865 TCGv_i32 sa_t = tcg_const_i32(v2);
22866 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22867 cpu_gpr[ret]);
22868 tcg_temp_free_i32(sa_t);
22869 break;
22871 case OPC_PRECRQ_PH_W:
22872 check_dsp(ctx);
22873 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22874 break;
22875 case OPC_PRECRQ_RS_PH_W:
22876 check_dsp(ctx);
22877 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22878 break;
22879 case OPC_PRECRQU_S_QB_PH:
22880 check_dsp(ctx);
22881 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22882 break;
22884 break;
22885 #ifdef TARGET_MIPS64
22886 case OPC_ABSQ_S_QH_DSP:
22887 switch (op2) {
22888 case OPC_PRECEQ_L_PWL:
22889 check_dsp(ctx);
22890 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22891 break;
22892 case OPC_PRECEQ_L_PWR:
22893 check_dsp(ctx);
22894 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22895 break;
22896 case OPC_PRECEQ_PW_QHL:
22897 check_dsp(ctx);
22898 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22899 break;
22900 case OPC_PRECEQ_PW_QHR:
22901 check_dsp(ctx);
22902 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22903 break;
22904 case OPC_PRECEQ_PW_QHLA:
22905 check_dsp(ctx);
22906 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22907 break;
22908 case OPC_PRECEQ_PW_QHRA:
22909 check_dsp(ctx);
22910 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22911 break;
22912 case OPC_PRECEQU_QH_OBL:
22913 check_dsp(ctx);
22914 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22915 break;
22916 case OPC_PRECEQU_QH_OBR:
22917 check_dsp(ctx);
22918 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22919 break;
22920 case OPC_PRECEQU_QH_OBLA:
22921 check_dsp(ctx);
22922 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22923 break;
22924 case OPC_PRECEQU_QH_OBRA:
22925 check_dsp(ctx);
22926 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22927 break;
22928 case OPC_PRECEU_QH_OBL:
22929 check_dsp(ctx);
22930 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22931 break;
22932 case OPC_PRECEU_QH_OBR:
22933 check_dsp(ctx);
22934 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22935 break;
22936 case OPC_PRECEU_QH_OBLA:
22937 check_dsp(ctx);
22938 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22939 break;
22940 case OPC_PRECEU_QH_OBRA:
22941 check_dsp(ctx);
22942 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22943 break;
22944 case OPC_ABSQ_S_OB:
22945 check_dsp_r2(ctx);
22946 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22947 break;
22948 case OPC_ABSQ_S_PW:
22949 check_dsp(ctx);
22950 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22951 break;
22952 case OPC_ABSQ_S_QH:
22953 check_dsp(ctx);
22954 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22955 break;
22957 break;
22958 case OPC_ADDU_OB_DSP:
22959 switch (op2) {
22960 case OPC_RADDU_L_OB:
22961 check_dsp(ctx);
22962 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22963 break;
22964 case OPC_SUBQ_PW:
22965 check_dsp(ctx);
22966 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22967 break;
22968 case OPC_SUBQ_S_PW:
22969 check_dsp(ctx);
22970 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22971 break;
22972 case OPC_SUBQ_QH:
22973 check_dsp(ctx);
22974 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22975 break;
22976 case OPC_SUBQ_S_QH:
22977 check_dsp(ctx);
22978 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22979 break;
22980 case OPC_SUBU_OB:
22981 check_dsp(ctx);
22982 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22983 break;
22984 case OPC_SUBU_S_OB:
22985 check_dsp(ctx);
22986 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22987 break;
22988 case OPC_SUBU_QH:
22989 check_dsp_r2(ctx);
22990 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22991 break;
22992 case OPC_SUBU_S_QH:
22993 check_dsp_r2(ctx);
22994 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22995 break;
22996 case OPC_SUBUH_OB:
22997 check_dsp_r2(ctx);
22998 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22999 break;
23000 case OPC_SUBUH_R_OB:
23001 check_dsp_r2(ctx);
23002 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23003 break;
23004 case OPC_ADDQ_PW:
23005 check_dsp(ctx);
23006 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23007 break;
23008 case OPC_ADDQ_S_PW:
23009 check_dsp(ctx);
23010 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23011 break;
23012 case OPC_ADDQ_QH:
23013 check_dsp(ctx);
23014 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23015 break;
23016 case OPC_ADDQ_S_QH:
23017 check_dsp(ctx);
23018 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23019 break;
23020 case OPC_ADDU_OB:
23021 check_dsp(ctx);
23022 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23023 break;
23024 case OPC_ADDU_S_OB:
23025 check_dsp(ctx);
23026 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23027 break;
23028 case OPC_ADDU_QH:
23029 check_dsp_r2(ctx);
23030 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23031 break;
23032 case OPC_ADDU_S_QH:
23033 check_dsp_r2(ctx);
23034 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23035 break;
23036 case OPC_ADDUH_OB:
23037 check_dsp_r2(ctx);
23038 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23039 break;
23040 case OPC_ADDUH_R_OB:
23041 check_dsp_r2(ctx);
23042 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23043 break;
23045 break;
23046 case OPC_CMPU_EQ_OB_DSP:
23047 switch (op2) {
23048 case OPC_PRECR_OB_QH:
23049 check_dsp_r2(ctx);
23050 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23051 break;
23052 case OPC_PRECR_SRA_QH_PW:
23053 check_dsp_r2(ctx);
23055 TCGv_i32 ret_t = tcg_const_i32(ret);
23056 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23057 tcg_temp_free_i32(ret_t);
23058 break;
23060 case OPC_PRECR_SRA_R_QH_PW:
23061 check_dsp_r2(ctx);
23063 TCGv_i32 sa_v = tcg_const_i32(ret);
23064 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23065 tcg_temp_free_i32(sa_v);
23066 break;
23068 case OPC_PRECRQ_OB_QH:
23069 check_dsp(ctx);
23070 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23071 break;
23072 case OPC_PRECRQ_PW_L:
23073 check_dsp(ctx);
23074 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23075 break;
23076 case OPC_PRECRQ_QH_PW:
23077 check_dsp(ctx);
23078 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23079 break;
23080 case OPC_PRECRQ_RS_QH_PW:
23081 check_dsp(ctx);
23082 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23083 break;
23084 case OPC_PRECRQU_S_OB_QH:
23085 check_dsp(ctx);
23086 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23087 break;
23089 break;
23090 #endif
23093 tcg_temp_free(v1_t);
23094 tcg_temp_free(v2_t);
23097 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23098 int ret, int v1, int v2)
23100 uint32_t op2;
23101 TCGv t0;
23102 TCGv v1_t;
23103 TCGv v2_t;
23105 if (ret == 0) {
23106 /* Treat as NOP. */
23107 return;
23110 t0 = tcg_temp_new();
23111 v1_t = tcg_temp_new();
23112 v2_t = tcg_temp_new();
23114 tcg_gen_movi_tl(t0, v1);
23115 gen_load_gpr(v1_t, v1);
23116 gen_load_gpr(v2_t, v2);
23118 switch (opc) {
23119 case OPC_SHLL_QB_DSP:
23121 op2 = MASK_SHLL_QB(ctx->opcode);
23122 switch (op2) {
23123 case OPC_SHLL_QB:
23124 check_dsp(ctx);
23125 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23126 break;
23127 case OPC_SHLLV_QB:
23128 check_dsp(ctx);
23129 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23130 break;
23131 case OPC_SHLL_PH:
23132 check_dsp(ctx);
23133 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23134 break;
23135 case OPC_SHLLV_PH:
23136 check_dsp(ctx);
23137 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23138 break;
23139 case OPC_SHLL_S_PH:
23140 check_dsp(ctx);
23141 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23142 break;
23143 case OPC_SHLLV_S_PH:
23144 check_dsp(ctx);
23145 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23146 break;
23147 case OPC_SHLL_S_W:
23148 check_dsp(ctx);
23149 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23150 break;
23151 case OPC_SHLLV_S_W:
23152 check_dsp(ctx);
23153 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23154 break;
23155 case OPC_SHRL_QB:
23156 check_dsp(ctx);
23157 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23158 break;
23159 case OPC_SHRLV_QB:
23160 check_dsp(ctx);
23161 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23162 break;
23163 case OPC_SHRL_PH:
23164 check_dsp_r2(ctx);
23165 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23166 break;
23167 case OPC_SHRLV_PH:
23168 check_dsp_r2(ctx);
23169 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23170 break;
23171 case OPC_SHRA_QB:
23172 check_dsp_r2(ctx);
23173 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23174 break;
23175 case OPC_SHRA_R_QB:
23176 check_dsp_r2(ctx);
23177 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23178 break;
23179 case OPC_SHRAV_QB:
23180 check_dsp_r2(ctx);
23181 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23182 break;
23183 case OPC_SHRAV_R_QB:
23184 check_dsp_r2(ctx);
23185 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23186 break;
23187 case OPC_SHRA_PH:
23188 check_dsp(ctx);
23189 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23190 break;
23191 case OPC_SHRA_R_PH:
23192 check_dsp(ctx);
23193 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23194 break;
23195 case OPC_SHRAV_PH:
23196 check_dsp(ctx);
23197 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23198 break;
23199 case OPC_SHRAV_R_PH:
23200 check_dsp(ctx);
23201 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23202 break;
23203 case OPC_SHRA_R_W:
23204 check_dsp(ctx);
23205 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23206 break;
23207 case OPC_SHRAV_R_W:
23208 check_dsp(ctx);
23209 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23210 break;
23211 default: /* Invalid */
23212 MIPS_INVAL("MASK SHLL.QB");
23213 generate_exception_end(ctx, EXCP_RI);
23214 break;
23216 break;
23218 #ifdef TARGET_MIPS64
23219 case OPC_SHLL_OB_DSP:
23220 op2 = MASK_SHLL_OB(ctx->opcode);
23221 switch (op2) {
23222 case OPC_SHLL_PW:
23223 check_dsp(ctx);
23224 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23225 break;
23226 case OPC_SHLLV_PW:
23227 check_dsp(ctx);
23228 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23229 break;
23230 case OPC_SHLL_S_PW:
23231 check_dsp(ctx);
23232 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23233 break;
23234 case OPC_SHLLV_S_PW:
23235 check_dsp(ctx);
23236 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23237 break;
23238 case OPC_SHLL_OB:
23239 check_dsp(ctx);
23240 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23241 break;
23242 case OPC_SHLLV_OB:
23243 check_dsp(ctx);
23244 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23245 break;
23246 case OPC_SHLL_QH:
23247 check_dsp(ctx);
23248 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23249 break;
23250 case OPC_SHLLV_QH:
23251 check_dsp(ctx);
23252 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23253 break;
23254 case OPC_SHLL_S_QH:
23255 check_dsp(ctx);
23256 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23257 break;
23258 case OPC_SHLLV_S_QH:
23259 check_dsp(ctx);
23260 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23261 break;
23262 case OPC_SHRA_OB:
23263 check_dsp_r2(ctx);
23264 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23265 break;
23266 case OPC_SHRAV_OB:
23267 check_dsp_r2(ctx);
23268 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23269 break;
23270 case OPC_SHRA_R_OB:
23271 check_dsp_r2(ctx);
23272 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23273 break;
23274 case OPC_SHRAV_R_OB:
23275 check_dsp_r2(ctx);
23276 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23277 break;
23278 case OPC_SHRA_PW:
23279 check_dsp(ctx);
23280 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23281 break;
23282 case OPC_SHRAV_PW:
23283 check_dsp(ctx);
23284 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23285 break;
23286 case OPC_SHRA_R_PW:
23287 check_dsp(ctx);
23288 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23289 break;
23290 case OPC_SHRAV_R_PW:
23291 check_dsp(ctx);
23292 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23293 break;
23294 case OPC_SHRA_QH:
23295 check_dsp(ctx);
23296 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23297 break;
23298 case OPC_SHRAV_QH:
23299 check_dsp(ctx);
23300 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23301 break;
23302 case OPC_SHRA_R_QH:
23303 check_dsp(ctx);
23304 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23305 break;
23306 case OPC_SHRAV_R_QH:
23307 check_dsp(ctx);
23308 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23309 break;
23310 case OPC_SHRL_OB:
23311 check_dsp(ctx);
23312 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23313 break;
23314 case OPC_SHRLV_OB:
23315 check_dsp(ctx);
23316 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23317 break;
23318 case OPC_SHRL_QH:
23319 check_dsp_r2(ctx);
23320 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23321 break;
23322 case OPC_SHRLV_QH:
23323 check_dsp_r2(ctx);
23324 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23325 break;
23326 default: /* Invalid */
23327 MIPS_INVAL("MASK SHLL.OB");
23328 generate_exception_end(ctx, EXCP_RI);
23329 break;
23331 break;
23332 #endif
23335 tcg_temp_free(t0);
23336 tcg_temp_free(v1_t);
23337 tcg_temp_free(v2_t);
23340 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23341 int ret, int v1, int v2, int check_ret)
23343 TCGv_i32 t0;
23344 TCGv v1_t;
23345 TCGv v2_t;
23347 if ((ret == 0) && (check_ret == 1)) {
23348 /* Treat as NOP. */
23349 return;
23352 t0 = tcg_temp_new_i32();
23353 v1_t = tcg_temp_new();
23354 v2_t = tcg_temp_new();
23356 tcg_gen_movi_i32(t0, ret);
23357 gen_load_gpr(v1_t, v1);
23358 gen_load_gpr(v2_t, v2);
23360 switch (op1) {
23362 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23363 * the same mask and op1.
23365 case OPC_MULT_G_2E:
23366 check_dsp_r2(ctx);
23367 switch (op2) {
23368 case OPC_MUL_PH:
23369 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23370 break;
23371 case OPC_MUL_S_PH:
23372 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23373 break;
23374 case OPC_MULQ_S_W:
23375 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23376 break;
23377 case OPC_MULQ_RS_W:
23378 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23379 break;
23381 break;
23382 case OPC_DPA_W_PH_DSP:
23383 switch (op2) {
23384 case OPC_DPAU_H_QBL:
23385 check_dsp(ctx);
23386 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23387 break;
23388 case OPC_DPAU_H_QBR:
23389 check_dsp(ctx);
23390 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23391 break;
23392 case OPC_DPSU_H_QBL:
23393 check_dsp(ctx);
23394 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23395 break;
23396 case OPC_DPSU_H_QBR:
23397 check_dsp(ctx);
23398 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23399 break;
23400 case OPC_DPA_W_PH:
23401 check_dsp_r2(ctx);
23402 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23403 break;
23404 case OPC_DPAX_W_PH:
23405 check_dsp_r2(ctx);
23406 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23407 break;
23408 case OPC_DPAQ_S_W_PH:
23409 check_dsp(ctx);
23410 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23411 break;
23412 case OPC_DPAQX_S_W_PH:
23413 check_dsp_r2(ctx);
23414 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23415 break;
23416 case OPC_DPAQX_SA_W_PH:
23417 check_dsp_r2(ctx);
23418 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23419 break;
23420 case OPC_DPS_W_PH:
23421 check_dsp_r2(ctx);
23422 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23423 break;
23424 case OPC_DPSX_W_PH:
23425 check_dsp_r2(ctx);
23426 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23427 break;
23428 case OPC_DPSQ_S_W_PH:
23429 check_dsp(ctx);
23430 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23431 break;
23432 case OPC_DPSQX_S_W_PH:
23433 check_dsp_r2(ctx);
23434 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23435 break;
23436 case OPC_DPSQX_SA_W_PH:
23437 check_dsp_r2(ctx);
23438 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23439 break;
23440 case OPC_MULSAQ_S_W_PH:
23441 check_dsp(ctx);
23442 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23443 break;
23444 case OPC_DPAQ_SA_L_W:
23445 check_dsp(ctx);
23446 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23447 break;
23448 case OPC_DPSQ_SA_L_W:
23449 check_dsp(ctx);
23450 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23451 break;
23452 case OPC_MAQ_S_W_PHL:
23453 check_dsp(ctx);
23454 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23455 break;
23456 case OPC_MAQ_S_W_PHR:
23457 check_dsp(ctx);
23458 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23459 break;
23460 case OPC_MAQ_SA_W_PHL:
23461 check_dsp(ctx);
23462 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23463 break;
23464 case OPC_MAQ_SA_W_PHR:
23465 check_dsp(ctx);
23466 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23467 break;
23468 case OPC_MULSA_W_PH:
23469 check_dsp_r2(ctx);
23470 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23471 break;
23473 break;
23474 #ifdef TARGET_MIPS64
23475 case OPC_DPAQ_W_QH_DSP:
23477 int ac = ret & 0x03;
23478 tcg_gen_movi_i32(t0, ac);
23480 switch (op2) {
23481 case OPC_DMADD:
23482 check_dsp(ctx);
23483 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23484 break;
23485 case OPC_DMADDU:
23486 check_dsp(ctx);
23487 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23488 break;
23489 case OPC_DMSUB:
23490 check_dsp(ctx);
23491 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23492 break;
23493 case OPC_DMSUBU:
23494 check_dsp(ctx);
23495 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23496 break;
23497 case OPC_DPA_W_QH:
23498 check_dsp_r2(ctx);
23499 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23500 break;
23501 case OPC_DPAQ_S_W_QH:
23502 check_dsp(ctx);
23503 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23504 break;
23505 case OPC_DPAQ_SA_L_PW:
23506 check_dsp(ctx);
23507 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23508 break;
23509 case OPC_DPAU_H_OBL:
23510 check_dsp(ctx);
23511 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23512 break;
23513 case OPC_DPAU_H_OBR:
23514 check_dsp(ctx);
23515 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23516 break;
23517 case OPC_DPS_W_QH:
23518 check_dsp_r2(ctx);
23519 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23520 break;
23521 case OPC_DPSQ_S_W_QH:
23522 check_dsp(ctx);
23523 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23524 break;
23525 case OPC_DPSQ_SA_L_PW:
23526 check_dsp(ctx);
23527 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23528 break;
23529 case OPC_DPSU_H_OBL:
23530 check_dsp(ctx);
23531 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23532 break;
23533 case OPC_DPSU_H_OBR:
23534 check_dsp(ctx);
23535 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23536 break;
23537 case OPC_MAQ_S_L_PWL:
23538 check_dsp(ctx);
23539 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23540 break;
23541 case OPC_MAQ_S_L_PWR:
23542 check_dsp(ctx);
23543 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23544 break;
23545 case OPC_MAQ_S_W_QHLL:
23546 check_dsp(ctx);
23547 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23548 break;
23549 case OPC_MAQ_SA_W_QHLL:
23550 check_dsp(ctx);
23551 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23552 break;
23553 case OPC_MAQ_S_W_QHLR:
23554 check_dsp(ctx);
23555 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23556 break;
23557 case OPC_MAQ_SA_W_QHLR:
23558 check_dsp(ctx);
23559 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23560 break;
23561 case OPC_MAQ_S_W_QHRL:
23562 check_dsp(ctx);
23563 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23564 break;
23565 case OPC_MAQ_SA_W_QHRL:
23566 check_dsp(ctx);
23567 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23568 break;
23569 case OPC_MAQ_S_W_QHRR:
23570 check_dsp(ctx);
23571 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23572 break;
23573 case OPC_MAQ_SA_W_QHRR:
23574 check_dsp(ctx);
23575 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23576 break;
23577 case OPC_MULSAQ_S_L_PW:
23578 check_dsp(ctx);
23579 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23580 break;
23581 case OPC_MULSAQ_S_W_QH:
23582 check_dsp(ctx);
23583 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23584 break;
23587 break;
23588 #endif
23589 case OPC_ADDU_QB_DSP:
23590 switch (op2) {
23591 case OPC_MULEU_S_PH_QBL:
23592 check_dsp(ctx);
23593 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23594 break;
23595 case OPC_MULEU_S_PH_QBR:
23596 check_dsp(ctx);
23597 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23598 break;
23599 case OPC_MULQ_RS_PH:
23600 check_dsp(ctx);
23601 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23602 break;
23603 case OPC_MULEQ_S_W_PHL:
23604 check_dsp(ctx);
23605 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23606 break;
23607 case OPC_MULEQ_S_W_PHR:
23608 check_dsp(ctx);
23609 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23610 break;
23611 case OPC_MULQ_S_PH:
23612 check_dsp_r2(ctx);
23613 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23614 break;
23616 break;
23617 #ifdef TARGET_MIPS64
23618 case OPC_ADDU_OB_DSP:
23619 switch (op2) {
23620 case OPC_MULEQ_S_PW_QHL:
23621 check_dsp(ctx);
23622 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23623 break;
23624 case OPC_MULEQ_S_PW_QHR:
23625 check_dsp(ctx);
23626 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23627 break;
23628 case OPC_MULEU_S_QH_OBL:
23629 check_dsp(ctx);
23630 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23631 break;
23632 case OPC_MULEU_S_QH_OBR:
23633 check_dsp(ctx);
23634 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23635 break;
23636 case OPC_MULQ_RS_QH:
23637 check_dsp(ctx);
23638 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23639 break;
23641 break;
23642 #endif
23645 tcg_temp_free_i32(t0);
23646 tcg_temp_free(v1_t);
23647 tcg_temp_free(v2_t);
23650 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23651 int ret, int val)
23653 int16_t imm;
23654 TCGv t0;
23655 TCGv val_t;
23657 if (ret == 0) {
23658 /* Treat as NOP. */
23659 return;
23662 t0 = tcg_temp_new();
23663 val_t = tcg_temp_new();
23664 gen_load_gpr(val_t, val);
23666 switch (op1) {
23667 case OPC_ABSQ_S_PH_DSP:
23668 switch (op2) {
23669 case OPC_BITREV:
23670 check_dsp(ctx);
23671 gen_helper_bitrev(cpu_gpr[ret], val_t);
23672 break;
23673 case OPC_REPL_QB:
23674 check_dsp(ctx);
23676 target_long result;
23677 imm = (ctx->opcode >> 16) & 0xFF;
23678 result = (uint32_t)imm << 24 |
23679 (uint32_t)imm << 16 |
23680 (uint32_t)imm << 8 |
23681 (uint32_t)imm;
23682 result = (int32_t)result;
23683 tcg_gen_movi_tl(cpu_gpr[ret], result);
23685 break;
23686 case OPC_REPLV_QB:
23687 check_dsp(ctx);
23688 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23689 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23690 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23691 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23692 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23693 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23694 break;
23695 case OPC_REPL_PH:
23696 check_dsp(ctx);
23698 imm = (ctx->opcode >> 16) & 0x03FF;
23699 imm = (int16_t)(imm << 6) >> 6;
23700 tcg_gen_movi_tl(cpu_gpr[ret], \
23701 (target_long)((int32_t)imm << 16 | \
23702 (uint16_t)imm));
23704 break;
23705 case OPC_REPLV_PH:
23706 check_dsp(ctx);
23707 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23708 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23709 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23710 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23711 break;
23713 break;
23714 #ifdef TARGET_MIPS64
23715 case OPC_ABSQ_S_QH_DSP:
23716 switch (op2) {
23717 case OPC_REPL_OB:
23718 check_dsp(ctx);
23720 target_long temp;
23722 imm = (ctx->opcode >> 16) & 0xFF;
23723 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
23724 temp = (temp << 16) | temp;
23725 temp = (temp << 32) | temp;
23726 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23727 break;
23729 case OPC_REPL_PW:
23730 check_dsp(ctx);
23732 target_long temp;
23734 imm = (ctx->opcode >> 16) & 0x03FF;
23735 imm = (int16_t)(imm << 6) >> 6;
23736 temp = ((target_long)imm << 32) \
23737 | ((target_long)imm & 0xFFFFFFFF);
23738 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23739 break;
23741 case OPC_REPL_QH:
23742 check_dsp(ctx);
23744 target_long temp;
23746 imm = (ctx->opcode >> 16) & 0x03FF;
23747 imm = (int16_t)(imm << 6) >> 6;
23749 temp = ((uint64_t)(uint16_t)imm << 48) |
23750 ((uint64_t)(uint16_t)imm << 32) |
23751 ((uint64_t)(uint16_t)imm << 16) |
23752 (uint64_t)(uint16_t)imm;
23753 tcg_gen_movi_tl(cpu_gpr[ret], temp);
23754 break;
23756 case OPC_REPLV_OB:
23757 check_dsp(ctx);
23758 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23759 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23760 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23761 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23762 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23763 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23764 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23765 break;
23766 case OPC_REPLV_PW:
23767 check_dsp(ctx);
23768 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
23769 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23770 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23771 break;
23772 case OPC_REPLV_QH:
23773 check_dsp(ctx);
23774 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
23775 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23776 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23777 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
23778 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23779 break;
23781 break;
23782 #endif
23784 tcg_temp_free(t0);
23785 tcg_temp_free(val_t);
23788 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
23789 uint32_t op1, uint32_t op2,
23790 int ret, int v1, int v2, int check_ret)
23792 TCGv t1;
23793 TCGv v1_t;
23794 TCGv v2_t;
23796 if ((ret == 0) && (check_ret == 1)) {
23797 /* Treat as NOP. */
23798 return;
23801 t1 = tcg_temp_new();
23802 v1_t = tcg_temp_new();
23803 v2_t = tcg_temp_new();
23805 gen_load_gpr(v1_t, v1);
23806 gen_load_gpr(v2_t, v2);
23808 switch (op1) {
23809 case OPC_CMPU_EQ_QB_DSP:
23810 switch (op2) {
23811 case OPC_CMPU_EQ_QB:
23812 check_dsp(ctx);
23813 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
23814 break;
23815 case OPC_CMPU_LT_QB:
23816 check_dsp(ctx);
23817 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
23818 break;
23819 case OPC_CMPU_LE_QB:
23820 check_dsp(ctx);
23821 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
23822 break;
23823 case OPC_CMPGU_EQ_QB:
23824 check_dsp(ctx);
23825 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23826 break;
23827 case OPC_CMPGU_LT_QB:
23828 check_dsp(ctx);
23829 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23830 break;
23831 case OPC_CMPGU_LE_QB:
23832 check_dsp(ctx);
23833 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23834 break;
23835 case OPC_CMPGDU_EQ_QB:
23836 check_dsp_r2(ctx);
23837 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23838 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23839 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23840 tcg_gen_shli_tl(t1, t1, 24);
23841 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23842 break;
23843 case OPC_CMPGDU_LT_QB:
23844 check_dsp_r2(ctx);
23845 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23846 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23847 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23848 tcg_gen_shli_tl(t1, t1, 24);
23849 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23850 break;
23851 case OPC_CMPGDU_LE_QB:
23852 check_dsp_r2(ctx);
23853 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23854 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23855 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23856 tcg_gen_shli_tl(t1, t1, 24);
23857 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23858 break;
23859 case OPC_CMP_EQ_PH:
23860 check_dsp(ctx);
23861 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23862 break;
23863 case OPC_CMP_LT_PH:
23864 check_dsp(ctx);
23865 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23866 break;
23867 case OPC_CMP_LE_PH:
23868 check_dsp(ctx);
23869 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23870 break;
23871 case OPC_PICK_QB:
23872 check_dsp(ctx);
23873 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23874 break;
23875 case OPC_PICK_PH:
23876 check_dsp(ctx);
23877 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23878 break;
23879 case OPC_PACKRL_PH:
23880 check_dsp(ctx);
23881 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23882 break;
23884 break;
23885 #ifdef TARGET_MIPS64
23886 case OPC_CMPU_EQ_OB_DSP:
23887 switch (op2) {
23888 case OPC_CMP_EQ_PW:
23889 check_dsp(ctx);
23890 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23891 break;
23892 case OPC_CMP_LT_PW:
23893 check_dsp(ctx);
23894 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23895 break;
23896 case OPC_CMP_LE_PW:
23897 check_dsp(ctx);
23898 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23899 break;
23900 case OPC_CMP_EQ_QH:
23901 check_dsp(ctx);
23902 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23903 break;
23904 case OPC_CMP_LT_QH:
23905 check_dsp(ctx);
23906 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23907 break;
23908 case OPC_CMP_LE_QH:
23909 check_dsp(ctx);
23910 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23911 break;
23912 case OPC_CMPGDU_EQ_OB:
23913 check_dsp_r2(ctx);
23914 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23915 break;
23916 case OPC_CMPGDU_LT_OB:
23917 check_dsp_r2(ctx);
23918 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23919 break;
23920 case OPC_CMPGDU_LE_OB:
23921 check_dsp_r2(ctx);
23922 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23923 break;
23924 case OPC_CMPGU_EQ_OB:
23925 check_dsp(ctx);
23926 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23927 break;
23928 case OPC_CMPGU_LT_OB:
23929 check_dsp(ctx);
23930 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23931 break;
23932 case OPC_CMPGU_LE_OB:
23933 check_dsp(ctx);
23934 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23935 break;
23936 case OPC_CMPU_EQ_OB:
23937 check_dsp(ctx);
23938 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23939 break;
23940 case OPC_CMPU_LT_OB:
23941 check_dsp(ctx);
23942 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23943 break;
23944 case OPC_CMPU_LE_OB:
23945 check_dsp(ctx);
23946 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23947 break;
23948 case OPC_PACKRL_PW:
23949 check_dsp(ctx);
23950 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23951 break;
23952 case OPC_PICK_OB:
23953 check_dsp(ctx);
23954 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23955 break;
23956 case OPC_PICK_PW:
23957 check_dsp(ctx);
23958 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23959 break;
23960 case OPC_PICK_QH:
23961 check_dsp(ctx);
23962 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23963 break;
23965 break;
23966 #endif
23969 tcg_temp_free(t1);
23970 tcg_temp_free(v1_t);
23971 tcg_temp_free(v2_t);
23974 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23975 uint32_t op1, int rt, int rs, int sa)
23977 TCGv t0;
23979 check_dsp_r2(ctx);
23981 if (rt == 0) {
23982 /* Treat as NOP. */
23983 return;
23986 t0 = tcg_temp_new();
23987 gen_load_gpr(t0, rs);
23989 switch (op1) {
23990 case OPC_APPEND_DSP:
23991 switch (MASK_APPEND(ctx->opcode)) {
23992 case OPC_APPEND:
23993 if (sa != 0) {
23994 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23996 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23997 break;
23998 case OPC_PREPEND:
23999 if (sa != 0) {
24000 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24001 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24002 tcg_gen_shli_tl(t0, t0, 32 - sa);
24003 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24005 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24006 break;
24007 case OPC_BALIGN:
24008 sa &= 3;
24009 if (sa != 0 && sa != 2) {
24010 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24011 tcg_gen_ext32u_tl(t0, t0);
24012 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24013 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24015 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24016 break;
24017 default: /* Invalid */
24018 MIPS_INVAL("MASK APPEND");
24019 generate_exception_end(ctx, EXCP_RI);
24020 break;
24022 break;
24023 #ifdef TARGET_MIPS64
24024 case OPC_DAPPEND_DSP:
24025 switch (MASK_DAPPEND(ctx->opcode)) {
24026 case OPC_DAPPEND:
24027 if (sa != 0) {
24028 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24030 break;
24031 case OPC_PREPENDD:
24032 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24033 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24034 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24035 break;
24036 case OPC_PREPENDW:
24037 if (sa != 0) {
24038 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24039 tcg_gen_shli_tl(t0, t0, 64 - sa);
24040 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24042 break;
24043 case OPC_DBALIGN:
24044 sa &= 7;
24045 if (sa != 0 && sa != 2 && sa != 4) {
24046 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24047 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24048 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24050 break;
24051 default: /* Invalid */
24052 MIPS_INVAL("MASK DAPPEND");
24053 generate_exception_end(ctx, EXCP_RI);
24054 break;
24056 break;
24057 #endif
24059 tcg_temp_free(t0);
24062 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24063 int ret, int v1, int v2, int check_ret)
24066 TCGv t0;
24067 TCGv t1;
24068 TCGv v1_t;
24069 TCGv v2_t;
24070 int16_t imm;
24072 if ((ret == 0) && (check_ret == 1)) {
24073 /* Treat as NOP. */
24074 return;
24077 t0 = tcg_temp_new();
24078 t1 = tcg_temp_new();
24079 v1_t = tcg_temp_new();
24080 v2_t = tcg_temp_new();
24082 gen_load_gpr(v1_t, v1);
24083 gen_load_gpr(v2_t, v2);
24085 switch (op1) {
24086 case OPC_EXTR_W_DSP:
24087 check_dsp(ctx);
24088 switch (op2) {
24089 case OPC_EXTR_W:
24090 tcg_gen_movi_tl(t0, v2);
24091 tcg_gen_movi_tl(t1, v1);
24092 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24093 break;
24094 case OPC_EXTR_R_W:
24095 tcg_gen_movi_tl(t0, v2);
24096 tcg_gen_movi_tl(t1, v1);
24097 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24098 break;
24099 case OPC_EXTR_RS_W:
24100 tcg_gen_movi_tl(t0, v2);
24101 tcg_gen_movi_tl(t1, v1);
24102 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24103 break;
24104 case OPC_EXTR_S_H:
24105 tcg_gen_movi_tl(t0, v2);
24106 tcg_gen_movi_tl(t1, v1);
24107 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24108 break;
24109 case OPC_EXTRV_S_H:
24110 tcg_gen_movi_tl(t0, v2);
24111 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24112 break;
24113 case OPC_EXTRV_W:
24114 tcg_gen_movi_tl(t0, v2);
24115 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24116 break;
24117 case OPC_EXTRV_R_W:
24118 tcg_gen_movi_tl(t0, v2);
24119 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24120 break;
24121 case OPC_EXTRV_RS_W:
24122 tcg_gen_movi_tl(t0, v2);
24123 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24124 break;
24125 case OPC_EXTP:
24126 tcg_gen_movi_tl(t0, v2);
24127 tcg_gen_movi_tl(t1, v1);
24128 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24129 break;
24130 case OPC_EXTPV:
24131 tcg_gen_movi_tl(t0, v2);
24132 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24133 break;
24134 case OPC_EXTPDP:
24135 tcg_gen_movi_tl(t0, v2);
24136 tcg_gen_movi_tl(t1, v1);
24137 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24138 break;
24139 case OPC_EXTPDPV:
24140 tcg_gen_movi_tl(t0, v2);
24141 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24142 break;
24143 case OPC_SHILO:
24144 imm = (ctx->opcode >> 20) & 0x3F;
24145 tcg_gen_movi_tl(t0, ret);
24146 tcg_gen_movi_tl(t1, imm);
24147 gen_helper_shilo(t0, t1, cpu_env);
24148 break;
24149 case OPC_SHILOV:
24150 tcg_gen_movi_tl(t0, ret);
24151 gen_helper_shilo(t0, v1_t, cpu_env);
24152 break;
24153 case OPC_MTHLIP:
24154 tcg_gen_movi_tl(t0, ret);
24155 gen_helper_mthlip(t0, v1_t, cpu_env);
24156 break;
24157 case OPC_WRDSP:
24158 imm = (ctx->opcode >> 11) & 0x3FF;
24159 tcg_gen_movi_tl(t0, imm);
24160 gen_helper_wrdsp(v1_t, t0, cpu_env);
24161 break;
24162 case OPC_RDDSP:
24163 imm = (ctx->opcode >> 16) & 0x03FF;
24164 tcg_gen_movi_tl(t0, imm);
24165 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24166 break;
24168 break;
24169 #ifdef TARGET_MIPS64
24170 case OPC_DEXTR_W_DSP:
24171 check_dsp(ctx);
24172 switch (op2) {
24173 case OPC_DMTHLIP:
24174 tcg_gen_movi_tl(t0, ret);
24175 gen_helper_dmthlip(v1_t, t0, cpu_env);
24176 break;
24177 case OPC_DSHILO:
24179 int shift = (ctx->opcode >> 19) & 0x7F;
24180 int ac = (ctx->opcode >> 11) & 0x03;
24181 tcg_gen_movi_tl(t0, shift);
24182 tcg_gen_movi_tl(t1, ac);
24183 gen_helper_dshilo(t0, t1, cpu_env);
24184 break;
24186 case OPC_DSHILOV:
24188 int ac = (ctx->opcode >> 11) & 0x03;
24189 tcg_gen_movi_tl(t0, ac);
24190 gen_helper_dshilo(v1_t, t0, cpu_env);
24191 break;
24193 case OPC_DEXTP:
24194 tcg_gen_movi_tl(t0, v2);
24195 tcg_gen_movi_tl(t1, v1);
24197 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24198 break;
24199 case OPC_DEXTPV:
24200 tcg_gen_movi_tl(t0, v2);
24201 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24202 break;
24203 case OPC_DEXTPDP:
24204 tcg_gen_movi_tl(t0, v2);
24205 tcg_gen_movi_tl(t1, v1);
24206 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24207 break;
24208 case OPC_DEXTPDPV:
24209 tcg_gen_movi_tl(t0, v2);
24210 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24211 break;
24212 case OPC_DEXTR_L:
24213 tcg_gen_movi_tl(t0, v2);
24214 tcg_gen_movi_tl(t1, v1);
24215 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24216 break;
24217 case OPC_DEXTR_R_L:
24218 tcg_gen_movi_tl(t0, v2);
24219 tcg_gen_movi_tl(t1, v1);
24220 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24221 break;
24222 case OPC_DEXTR_RS_L:
24223 tcg_gen_movi_tl(t0, v2);
24224 tcg_gen_movi_tl(t1, v1);
24225 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24226 break;
24227 case OPC_DEXTR_W:
24228 tcg_gen_movi_tl(t0, v2);
24229 tcg_gen_movi_tl(t1, v1);
24230 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24231 break;
24232 case OPC_DEXTR_R_W:
24233 tcg_gen_movi_tl(t0, v2);
24234 tcg_gen_movi_tl(t1, v1);
24235 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24236 break;
24237 case OPC_DEXTR_RS_W:
24238 tcg_gen_movi_tl(t0, v2);
24239 tcg_gen_movi_tl(t1, v1);
24240 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24241 break;
24242 case OPC_DEXTR_S_H:
24243 tcg_gen_movi_tl(t0, v2);
24244 tcg_gen_movi_tl(t1, v1);
24245 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24246 break;
24247 case OPC_DEXTRV_S_H:
24248 tcg_gen_movi_tl(t0, v2);
24249 tcg_gen_movi_tl(t1, v1);
24250 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24251 break;
24252 case OPC_DEXTRV_L:
24253 tcg_gen_movi_tl(t0, v2);
24254 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24255 break;
24256 case OPC_DEXTRV_R_L:
24257 tcg_gen_movi_tl(t0, v2);
24258 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24259 break;
24260 case OPC_DEXTRV_RS_L:
24261 tcg_gen_movi_tl(t0, v2);
24262 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24263 break;
24264 case OPC_DEXTRV_W:
24265 tcg_gen_movi_tl(t0, v2);
24266 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24267 break;
24268 case OPC_DEXTRV_R_W:
24269 tcg_gen_movi_tl(t0, v2);
24270 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24271 break;
24272 case OPC_DEXTRV_RS_W:
24273 tcg_gen_movi_tl(t0, v2);
24274 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24275 break;
24277 break;
24278 #endif
24281 tcg_temp_free(t0);
24282 tcg_temp_free(t1);
24283 tcg_temp_free(v1_t);
24284 tcg_temp_free(v2_t);
24287 /* End MIPSDSP functions. */
24289 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24291 int rs, rt, rd, sa;
24292 uint32_t op1, op2;
24294 rs = (ctx->opcode >> 21) & 0x1f;
24295 rt = (ctx->opcode >> 16) & 0x1f;
24296 rd = (ctx->opcode >> 11) & 0x1f;
24297 sa = (ctx->opcode >> 6) & 0x1f;
24299 op1 = MASK_SPECIAL(ctx->opcode);
24300 switch (op1) {
24301 case OPC_LSA:
24302 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24303 break;
24304 case OPC_MULT:
24305 case OPC_MULTU:
24306 case OPC_DIV:
24307 case OPC_DIVU:
24308 op2 = MASK_R6_MULDIV(ctx->opcode);
24309 switch (op2) {
24310 case R6_OPC_MUL:
24311 case R6_OPC_MUH:
24312 case R6_OPC_MULU:
24313 case R6_OPC_MUHU:
24314 case R6_OPC_DIV:
24315 case R6_OPC_MOD:
24316 case R6_OPC_DIVU:
24317 case R6_OPC_MODU:
24318 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24319 break;
24320 default:
24321 MIPS_INVAL("special_r6 muldiv");
24322 generate_exception_end(ctx, EXCP_RI);
24323 break;
24325 break;
24326 case OPC_SELEQZ:
24327 case OPC_SELNEZ:
24328 gen_cond_move(ctx, op1, rd, rs, rt);
24329 break;
24330 case R6_OPC_CLO:
24331 case R6_OPC_CLZ:
24332 if (rt == 0 && sa == 1) {
24334 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24335 * We need additionally to check other fields.
24337 gen_cl(ctx, op1, rd, rs);
24338 } else {
24339 generate_exception_end(ctx, EXCP_RI);
24341 break;
24342 case R6_OPC_SDBBP:
24343 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24344 gen_helper_do_semihosting(cpu_env);
24345 } else {
24346 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24347 generate_exception_end(ctx, EXCP_RI);
24348 } else {
24349 generate_exception_end(ctx, EXCP_DBp);
24352 break;
24353 #if defined(TARGET_MIPS64)
24354 case OPC_DLSA:
24355 check_mips_64(ctx);
24356 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24357 break;
24358 case R6_OPC_DCLO:
24359 case R6_OPC_DCLZ:
24360 if (rt == 0 && sa == 1) {
24362 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24363 * We need additionally to check other fields.
24365 check_mips_64(ctx);
24366 gen_cl(ctx, op1, rd, rs);
24367 } else {
24368 generate_exception_end(ctx, EXCP_RI);
24370 break;
24371 case OPC_DMULT:
24372 case OPC_DMULTU:
24373 case OPC_DDIV:
24374 case OPC_DDIVU:
24376 op2 = MASK_R6_MULDIV(ctx->opcode);
24377 switch (op2) {
24378 case R6_OPC_DMUL:
24379 case R6_OPC_DMUH:
24380 case R6_OPC_DMULU:
24381 case R6_OPC_DMUHU:
24382 case R6_OPC_DDIV:
24383 case R6_OPC_DMOD:
24384 case R6_OPC_DDIVU:
24385 case R6_OPC_DMODU:
24386 check_mips_64(ctx);
24387 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24388 break;
24389 default:
24390 MIPS_INVAL("special_r6 muldiv");
24391 generate_exception_end(ctx, EXCP_RI);
24392 break;
24394 break;
24395 #endif
24396 default: /* Invalid */
24397 MIPS_INVAL("special_r6");
24398 generate_exception_end(ctx, EXCP_RI);
24399 break;
24403 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24405 int rs = extract32(ctx->opcode, 21, 5);
24406 int rt = extract32(ctx->opcode, 16, 5);
24407 int rd = extract32(ctx->opcode, 11, 5);
24408 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24410 switch (op1) {
24411 case OPC_MOVN: /* Conditional move */
24412 case OPC_MOVZ:
24413 gen_cond_move(ctx, op1, rd, rs, rt);
24414 break;
24415 case OPC_MFHI: /* Move from HI/LO */
24416 case OPC_MFLO:
24417 gen_HILO(ctx, op1, 0, rd);
24418 break;
24419 case OPC_MTHI:
24420 case OPC_MTLO: /* Move to HI/LO */
24421 gen_HILO(ctx, op1, 0, rs);
24422 break;
24423 case OPC_MULT:
24424 case OPC_MULTU:
24425 gen_mul_txx9(ctx, op1, rd, rs, rt);
24426 break;
24427 case OPC_DIV:
24428 case OPC_DIVU:
24429 gen_muldiv(ctx, op1, 0, rs, rt);
24430 break;
24431 #if defined(TARGET_MIPS64)
24432 case OPC_DMULT:
24433 case OPC_DMULTU:
24434 case OPC_DDIV:
24435 case OPC_DDIVU:
24436 check_insn_opc_user_only(ctx, INSN_R5900);
24437 gen_muldiv(ctx, op1, 0, rs, rt);
24438 break;
24439 #endif
24440 case OPC_JR:
24441 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24442 break;
24443 default: /* Invalid */
24444 MIPS_INVAL("special_tx79");
24445 generate_exception_end(ctx, EXCP_RI);
24446 break;
24450 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24452 int rs, rt, rd, sa;
24453 uint32_t op1;
24455 rs = (ctx->opcode >> 21) & 0x1f;
24456 rt = (ctx->opcode >> 16) & 0x1f;
24457 rd = (ctx->opcode >> 11) & 0x1f;
24458 sa = (ctx->opcode >> 6) & 0x1f;
24460 op1 = MASK_SPECIAL(ctx->opcode);
24461 switch (op1) {
24462 case OPC_MOVN: /* Conditional move */
24463 case OPC_MOVZ:
24464 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24465 INSN_LOONGSON2E | INSN_LOONGSON2F);
24466 gen_cond_move(ctx, op1, rd, rs, rt);
24467 break;
24468 case OPC_MFHI: /* Move from HI/LO */
24469 case OPC_MFLO:
24470 gen_HILO(ctx, op1, rs & 3, rd);
24471 break;
24472 case OPC_MTHI:
24473 case OPC_MTLO: /* Move to HI/LO */
24474 gen_HILO(ctx, op1, rd & 3, rs);
24475 break;
24476 case OPC_MOVCI:
24477 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24478 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24479 check_cp1_enabled(ctx);
24480 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24481 (ctx->opcode >> 16) & 1);
24482 } else {
24483 generate_exception_err(ctx, EXCP_CpU, 1);
24485 break;
24486 case OPC_MULT:
24487 case OPC_MULTU:
24488 if (sa) {
24489 check_insn(ctx, INSN_VR54XX);
24490 op1 = MASK_MUL_VR54XX(ctx->opcode);
24491 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24492 } else {
24493 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24495 break;
24496 case OPC_DIV:
24497 case OPC_DIVU:
24498 gen_muldiv(ctx, op1, 0, rs, rt);
24499 break;
24500 #if defined(TARGET_MIPS64)
24501 case OPC_DMULT:
24502 case OPC_DMULTU:
24503 case OPC_DDIV:
24504 case OPC_DDIVU:
24505 check_insn(ctx, ISA_MIPS3);
24506 check_mips_64(ctx);
24507 gen_muldiv(ctx, op1, 0, rs, rt);
24508 break;
24509 #endif
24510 case OPC_JR:
24511 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24512 break;
24513 case OPC_SPIM:
24514 #ifdef MIPS_STRICT_STANDARD
24515 MIPS_INVAL("SPIM");
24516 generate_exception_end(ctx, EXCP_RI);
24517 #else
24518 /* Implemented as RI exception for now. */
24519 MIPS_INVAL("spim (unofficial)");
24520 generate_exception_end(ctx, EXCP_RI);
24521 #endif
24522 break;
24523 default: /* Invalid */
24524 MIPS_INVAL("special_legacy");
24525 generate_exception_end(ctx, EXCP_RI);
24526 break;
24530 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24532 int rs, rt, rd, sa;
24533 uint32_t op1;
24535 rs = (ctx->opcode >> 21) & 0x1f;
24536 rt = (ctx->opcode >> 16) & 0x1f;
24537 rd = (ctx->opcode >> 11) & 0x1f;
24538 sa = (ctx->opcode >> 6) & 0x1f;
24540 op1 = MASK_SPECIAL(ctx->opcode);
24541 switch (op1) {
24542 case OPC_SLL: /* Shift with immediate */
24543 if (sa == 5 && rd == 0 &&
24544 rs == 0 && rt == 0) { /* PAUSE */
24545 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24546 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24547 generate_exception_end(ctx, EXCP_RI);
24548 break;
24551 /* Fallthrough */
24552 case OPC_SRA:
24553 gen_shift_imm(ctx, op1, rd, rt, sa);
24554 break;
24555 case OPC_SRL:
24556 switch ((ctx->opcode >> 21) & 0x1f) {
24557 case 1:
24558 /* rotr is decoded as srl on non-R2 CPUs */
24559 if (ctx->insn_flags & ISA_MIPS32R2) {
24560 op1 = OPC_ROTR;
24562 /* Fallthrough */
24563 case 0:
24564 gen_shift_imm(ctx, op1, rd, rt, sa);
24565 break;
24566 default:
24567 generate_exception_end(ctx, EXCP_RI);
24568 break;
24570 break;
24571 case OPC_ADD:
24572 case OPC_ADDU:
24573 case OPC_SUB:
24574 case OPC_SUBU:
24575 gen_arith(ctx, op1, rd, rs, rt);
24576 break;
24577 case OPC_SLLV: /* Shifts */
24578 case OPC_SRAV:
24579 gen_shift(ctx, op1, rd, rs, rt);
24580 break;
24581 case OPC_SRLV:
24582 switch ((ctx->opcode >> 6) & 0x1f) {
24583 case 1:
24584 /* rotrv is decoded as srlv on non-R2 CPUs */
24585 if (ctx->insn_flags & ISA_MIPS32R2) {
24586 op1 = OPC_ROTRV;
24588 /* Fallthrough */
24589 case 0:
24590 gen_shift(ctx, op1, rd, rs, rt);
24591 break;
24592 default:
24593 generate_exception_end(ctx, EXCP_RI);
24594 break;
24596 break;
24597 case OPC_SLT: /* Set on less than */
24598 case OPC_SLTU:
24599 gen_slt(ctx, op1, rd, rs, rt);
24600 break;
24601 case OPC_AND: /* Logic*/
24602 case OPC_OR:
24603 case OPC_NOR:
24604 case OPC_XOR:
24605 gen_logic(ctx, op1, rd, rs, rt);
24606 break;
24607 case OPC_JALR:
24608 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24609 break;
24610 case OPC_TGE: /* Traps */
24611 case OPC_TGEU:
24612 case OPC_TLT:
24613 case OPC_TLTU:
24614 case OPC_TEQ:
24615 case OPC_TNE:
24616 check_insn(ctx, ISA_MIPS2);
24617 gen_trap(ctx, op1, rs, rt, -1);
24618 break;
24619 case OPC_LSA: /* OPC_PMON */
24620 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24621 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24622 decode_opc_special_r6(env, ctx);
24623 } else {
24624 /* Pmon entry point, also R4010 selsl */
24625 #ifdef MIPS_STRICT_STANDARD
24626 MIPS_INVAL("PMON / selsl");
24627 generate_exception_end(ctx, EXCP_RI);
24628 #else
24629 gen_helper_0e0i(pmon, sa);
24630 #endif
24632 break;
24633 case OPC_SYSCALL:
24634 generate_exception_end(ctx, EXCP_SYSCALL);
24635 break;
24636 case OPC_BREAK:
24637 generate_exception_end(ctx, EXCP_BREAK);
24638 break;
24639 case OPC_SYNC:
24640 check_insn(ctx, ISA_MIPS2);
24641 gen_sync(extract32(ctx->opcode, 6, 5));
24642 break;
24644 #if defined(TARGET_MIPS64)
24645 /* MIPS64 specific opcodes */
24646 case OPC_DSLL:
24647 case OPC_DSRA:
24648 case OPC_DSLL32:
24649 case OPC_DSRA32:
24650 check_insn(ctx, ISA_MIPS3);
24651 check_mips_64(ctx);
24652 gen_shift_imm(ctx, op1, rd, rt, sa);
24653 break;
24654 case OPC_DSRL:
24655 switch ((ctx->opcode >> 21) & 0x1f) {
24656 case 1:
24657 /* drotr is decoded as dsrl on non-R2 CPUs */
24658 if (ctx->insn_flags & ISA_MIPS32R2) {
24659 op1 = OPC_DROTR;
24661 /* Fallthrough */
24662 case 0:
24663 check_insn(ctx, ISA_MIPS3);
24664 check_mips_64(ctx);
24665 gen_shift_imm(ctx, op1, rd, rt, sa);
24666 break;
24667 default:
24668 generate_exception_end(ctx, EXCP_RI);
24669 break;
24671 break;
24672 case OPC_DSRL32:
24673 switch ((ctx->opcode >> 21) & 0x1f) {
24674 case 1:
24675 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24676 if (ctx->insn_flags & ISA_MIPS32R2) {
24677 op1 = OPC_DROTR32;
24679 /* Fallthrough */
24680 case 0:
24681 check_insn(ctx, ISA_MIPS3);
24682 check_mips_64(ctx);
24683 gen_shift_imm(ctx, op1, rd, rt, sa);
24684 break;
24685 default:
24686 generate_exception_end(ctx, EXCP_RI);
24687 break;
24689 break;
24690 case OPC_DADD:
24691 case OPC_DADDU:
24692 case OPC_DSUB:
24693 case OPC_DSUBU:
24694 check_insn(ctx, ISA_MIPS3);
24695 check_mips_64(ctx);
24696 gen_arith(ctx, op1, rd, rs, rt);
24697 break;
24698 case OPC_DSLLV:
24699 case OPC_DSRAV:
24700 check_insn(ctx, ISA_MIPS3);
24701 check_mips_64(ctx);
24702 gen_shift(ctx, op1, rd, rs, rt);
24703 break;
24704 case OPC_DSRLV:
24705 switch ((ctx->opcode >> 6) & 0x1f) {
24706 case 1:
24707 /* drotrv is decoded as dsrlv on non-R2 CPUs */
24708 if (ctx->insn_flags & ISA_MIPS32R2) {
24709 op1 = OPC_DROTRV;
24711 /* Fallthrough */
24712 case 0:
24713 check_insn(ctx, ISA_MIPS3);
24714 check_mips_64(ctx);
24715 gen_shift(ctx, op1, rd, rs, rt);
24716 break;
24717 default:
24718 generate_exception_end(ctx, EXCP_RI);
24719 break;
24721 break;
24722 case OPC_DLSA:
24723 if ((ctx->insn_flags & ISA_MIPS32R6) ||
24724 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
24725 decode_opc_special_r6(env, ctx);
24727 break;
24728 #endif
24729 default:
24730 if (ctx->insn_flags & ISA_MIPS32R6) {
24731 decode_opc_special_r6(env, ctx);
24732 } else if (ctx->insn_flags & INSN_R5900) {
24733 decode_opc_special_tx79(env, ctx);
24734 } else {
24735 decode_opc_special_legacy(env, ctx);
24741 #if defined(TARGET_MIPS64)
24745 * MMI (MultiMedia Interface) ASE instructions
24746 * ===========================================
24750 * MMI instructions category: data communication
24751 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24753 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
24754 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
24755 * PCPYUD PEXEH PEXTLW PPACW
24756 * PEXEW PEXTUB
24757 * PEXTUH
24758 * PEXTUW
24762 * PCPYH rd, rt
24764 * Parallel Copy Halfword
24766 * 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
24767 * +-----------+---------+---------+---------+---------+-----------+
24768 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
24769 * +-----------+---------+---------+---------+---------+-----------+
24771 static void gen_mmi_pcpyh(DisasContext *ctx)
24773 uint32_t pd, rt, rd;
24774 uint32_t opcode;
24776 opcode = ctx->opcode;
24778 pd = extract32(opcode, 21, 5);
24779 rt = extract32(opcode, 16, 5);
24780 rd = extract32(opcode, 11, 5);
24782 if (unlikely(pd != 0)) {
24783 generate_exception_end(ctx, EXCP_RI);
24784 } else if (rd == 0) {
24785 /* nop */
24786 } else if (rt == 0) {
24787 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24788 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24789 } else {
24790 TCGv_i64 t0 = tcg_temp_new();
24791 TCGv_i64 t1 = tcg_temp_new();
24792 uint64_t mask = (1ULL << 16) - 1;
24794 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
24795 tcg_gen_movi_i64(t1, 0);
24796 tcg_gen_or_i64(t1, t0, t1);
24797 tcg_gen_shli_i64(t0, t0, 16);
24798 tcg_gen_or_i64(t1, t0, t1);
24799 tcg_gen_shli_i64(t0, t0, 16);
24800 tcg_gen_or_i64(t1, t0, t1);
24801 tcg_gen_shli_i64(t0, t0, 16);
24802 tcg_gen_or_i64(t1, t0, t1);
24804 tcg_gen_mov_i64(cpu_gpr[rd], t1);
24806 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
24807 tcg_gen_movi_i64(t1, 0);
24808 tcg_gen_or_i64(t1, t0, t1);
24809 tcg_gen_shli_i64(t0, t0, 16);
24810 tcg_gen_or_i64(t1, t0, t1);
24811 tcg_gen_shli_i64(t0, t0, 16);
24812 tcg_gen_or_i64(t1, t0, t1);
24813 tcg_gen_shli_i64(t0, t0, 16);
24814 tcg_gen_or_i64(t1, t0, t1);
24816 tcg_gen_mov_i64(cpu_mmr[rd], t1);
24818 tcg_temp_free(t0);
24819 tcg_temp_free(t1);
24824 * PCPYLD rd, rs, rt
24826 * Parallel Copy Lower Doubleword
24828 * 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
24829 * +-----------+---------+---------+---------+---------+-----------+
24830 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
24831 * +-----------+---------+---------+---------+---------+-----------+
24833 static void gen_mmi_pcpyld(DisasContext *ctx)
24835 uint32_t rs, rt, rd;
24836 uint32_t opcode;
24838 opcode = ctx->opcode;
24840 rs = extract32(opcode, 21, 5);
24841 rt = extract32(opcode, 16, 5);
24842 rd = extract32(opcode, 11, 5);
24844 if (rd == 0) {
24845 /* nop */
24846 } else {
24847 if (rs == 0) {
24848 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24849 } else {
24850 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
24852 if (rt == 0) {
24853 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24854 } else {
24855 if (rd != rt) {
24856 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
24863 * PCPYUD rd, rs, rt
24865 * Parallel Copy Upper Doubleword
24867 * 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
24868 * +-----------+---------+---------+---------+---------+-----------+
24869 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
24870 * +-----------+---------+---------+---------+---------+-----------+
24872 static void gen_mmi_pcpyud(DisasContext *ctx)
24874 uint32_t rs, rt, rd;
24875 uint32_t opcode;
24877 opcode = ctx->opcode;
24879 rs = extract32(opcode, 21, 5);
24880 rt = extract32(opcode, 16, 5);
24881 rd = extract32(opcode, 11, 5);
24883 if (rd == 0) {
24884 /* nop */
24885 } else {
24886 if (rs == 0) {
24887 tcg_gen_movi_i64(cpu_gpr[rd], 0);
24888 } else {
24889 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
24891 if (rt == 0) {
24892 tcg_gen_movi_i64(cpu_mmr[rd], 0);
24893 } else {
24894 if (rd != rt) {
24895 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
24901 #endif
24904 #if !defined(TARGET_MIPS64)
24906 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
24907 #define MXU_APTN1_A 0
24908 #define MXU_APTN1_S 1
24910 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
24911 #define MXU_APTN2_AA 0
24912 #define MXU_APTN2_AS 1
24913 #define MXU_APTN2_SA 2
24914 #define MXU_APTN2_SS 3
24916 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
24917 #define MXU_EPTN2_AA 0
24918 #define MXU_EPTN2_AS 1
24919 #define MXU_EPTN2_SA 2
24920 #define MXU_EPTN2_SS 3
24922 /* MXU operand getting pattern 'optn2' */
24923 #define MXU_OPTN2_PTN0 0
24924 #define MXU_OPTN2_PTN1 1
24925 #define MXU_OPTN2_PTN2 2
24926 #define MXU_OPTN2_PTN3 3
24927 /* alternative naming scheme for 'optn2' */
24928 #define MXU_OPTN2_WW 0
24929 #define MXU_OPTN2_LW 1
24930 #define MXU_OPTN2_HW 2
24931 #define MXU_OPTN2_XW 3
24933 /* MXU operand getting pattern 'optn3' */
24934 #define MXU_OPTN3_PTN0 0
24935 #define MXU_OPTN3_PTN1 1
24936 #define MXU_OPTN3_PTN2 2
24937 #define MXU_OPTN3_PTN3 3
24938 #define MXU_OPTN3_PTN4 4
24939 #define MXU_OPTN3_PTN5 5
24940 #define MXU_OPTN3_PTN6 6
24941 #define MXU_OPTN3_PTN7 7
24945 * S32I2M XRa, rb - Register move from GRF to XRF
24947 static void gen_mxu_s32i2m(DisasContext *ctx)
24949 TCGv t0;
24950 uint32_t XRa, Rb;
24952 t0 = tcg_temp_new();
24954 XRa = extract32(ctx->opcode, 6, 5);
24955 Rb = extract32(ctx->opcode, 16, 5);
24957 gen_load_gpr(t0, Rb);
24958 if (XRa <= 15) {
24959 gen_store_mxu_gpr(t0, XRa);
24960 } else if (XRa == 16) {
24961 gen_store_mxu_cr(t0);
24964 tcg_temp_free(t0);
24968 * S32M2I XRa, rb - Register move from XRF to GRF
24970 static void gen_mxu_s32m2i(DisasContext *ctx)
24972 TCGv t0;
24973 uint32_t XRa, Rb;
24975 t0 = tcg_temp_new();
24977 XRa = extract32(ctx->opcode, 6, 5);
24978 Rb = extract32(ctx->opcode, 16, 5);
24980 if (XRa <= 15) {
24981 gen_load_mxu_gpr(t0, XRa);
24982 } else if (XRa == 16) {
24983 gen_load_mxu_cr(t0);
24986 gen_store_gpr(t0, Rb);
24988 tcg_temp_free(t0);
24992 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
24994 static void gen_mxu_s8ldd(DisasContext *ctx)
24996 TCGv t0, t1;
24997 uint32_t XRa, Rb, s8, optn3;
24999 t0 = tcg_temp_new();
25000 t1 = tcg_temp_new();
25002 XRa = extract32(ctx->opcode, 6, 4);
25003 s8 = extract32(ctx->opcode, 10, 8);
25004 optn3 = extract32(ctx->opcode, 18, 3);
25005 Rb = extract32(ctx->opcode, 21, 5);
25007 gen_load_gpr(t0, Rb);
25008 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25010 switch (optn3) {
25011 /* XRa[7:0] = tmp8 */
25012 case MXU_OPTN3_PTN0:
25013 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25014 gen_load_mxu_gpr(t0, XRa);
25015 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25016 break;
25017 /* XRa[15:8] = tmp8 */
25018 case MXU_OPTN3_PTN1:
25019 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25020 gen_load_mxu_gpr(t0, XRa);
25021 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25022 break;
25023 /* XRa[23:16] = tmp8 */
25024 case MXU_OPTN3_PTN2:
25025 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25026 gen_load_mxu_gpr(t0, XRa);
25027 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25028 break;
25029 /* XRa[31:24] = tmp8 */
25030 case MXU_OPTN3_PTN3:
25031 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25032 gen_load_mxu_gpr(t0, XRa);
25033 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25034 break;
25035 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25036 case MXU_OPTN3_PTN4:
25037 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25038 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25039 break;
25040 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25041 case MXU_OPTN3_PTN5:
25042 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25043 tcg_gen_shli_tl(t1, t1, 8);
25044 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25045 break;
25046 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25047 case MXU_OPTN3_PTN6:
25048 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25049 tcg_gen_mov_tl(t0, t1);
25050 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25051 tcg_gen_shli_tl(t1, t1, 16);
25052 tcg_gen_or_tl(t0, t0, t1);
25053 break;
25054 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25055 case MXU_OPTN3_PTN7:
25056 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25057 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25058 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25059 break;
25062 gen_store_mxu_gpr(t0, XRa);
25064 tcg_temp_free(t0);
25065 tcg_temp_free(t1);
25069 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25071 static void gen_mxu_d16mul(DisasContext *ctx)
25073 TCGv t0, t1, t2, t3;
25074 uint32_t XRa, XRb, XRc, XRd, optn2;
25076 t0 = tcg_temp_new();
25077 t1 = tcg_temp_new();
25078 t2 = tcg_temp_new();
25079 t3 = tcg_temp_new();
25081 XRa = extract32(ctx->opcode, 6, 4);
25082 XRb = extract32(ctx->opcode, 10, 4);
25083 XRc = extract32(ctx->opcode, 14, 4);
25084 XRd = extract32(ctx->opcode, 18, 4);
25085 optn2 = extract32(ctx->opcode, 22, 2);
25087 gen_load_mxu_gpr(t1, XRb);
25088 tcg_gen_sextract_tl(t0, t1, 0, 16);
25089 tcg_gen_sextract_tl(t1, t1, 16, 16);
25090 gen_load_mxu_gpr(t3, XRc);
25091 tcg_gen_sextract_tl(t2, t3, 0, 16);
25092 tcg_gen_sextract_tl(t3, t3, 16, 16);
25094 switch (optn2) {
25095 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25096 tcg_gen_mul_tl(t3, t1, t3);
25097 tcg_gen_mul_tl(t2, t0, t2);
25098 break;
25099 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25100 tcg_gen_mul_tl(t3, t0, t3);
25101 tcg_gen_mul_tl(t2, t0, t2);
25102 break;
25103 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25104 tcg_gen_mul_tl(t3, t1, t3);
25105 tcg_gen_mul_tl(t2, t1, t2);
25106 break;
25107 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25108 tcg_gen_mul_tl(t3, t0, t3);
25109 tcg_gen_mul_tl(t2, t1, t2);
25110 break;
25112 gen_store_mxu_gpr(t3, XRa);
25113 gen_store_mxu_gpr(t2, XRd);
25115 tcg_temp_free(t0);
25116 tcg_temp_free(t1);
25117 tcg_temp_free(t2);
25118 tcg_temp_free(t3);
25122 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25123 * and accumulate
25125 static void gen_mxu_d16mac(DisasContext *ctx)
25127 TCGv t0, t1, t2, t3;
25128 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25130 t0 = tcg_temp_new();
25131 t1 = tcg_temp_new();
25132 t2 = tcg_temp_new();
25133 t3 = tcg_temp_new();
25135 XRa = extract32(ctx->opcode, 6, 4);
25136 XRb = extract32(ctx->opcode, 10, 4);
25137 XRc = extract32(ctx->opcode, 14, 4);
25138 XRd = extract32(ctx->opcode, 18, 4);
25139 optn2 = extract32(ctx->opcode, 22, 2);
25140 aptn2 = extract32(ctx->opcode, 24, 2);
25142 gen_load_mxu_gpr(t1, XRb);
25143 tcg_gen_sextract_tl(t0, t1, 0, 16);
25144 tcg_gen_sextract_tl(t1, t1, 16, 16);
25146 gen_load_mxu_gpr(t3, XRc);
25147 tcg_gen_sextract_tl(t2, t3, 0, 16);
25148 tcg_gen_sextract_tl(t3, t3, 16, 16);
25150 switch (optn2) {
25151 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25152 tcg_gen_mul_tl(t3, t1, t3);
25153 tcg_gen_mul_tl(t2, t0, t2);
25154 break;
25155 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25156 tcg_gen_mul_tl(t3, t0, t3);
25157 tcg_gen_mul_tl(t2, t0, t2);
25158 break;
25159 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25160 tcg_gen_mul_tl(t3, t1, t3);
25161 tcg_gen_mul_tl(t2, t1, t2);
25162 break;
25163 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25164 tcg_gen_mul_tl(t3, t0, t3);
25165 tcg_gen_mul_tl(t2, t1, t2);
25166 break;
25168 gen_load_mxu_gpr(t0, XRa);
25169 gen_load_mxu_gpr(t1, XRd);
25171 switch (aptn2) {
25172 case MXU_APTN2_AA:
25173 tcg_gen_add_tl(t3, t0, t3);
25174 tcg_gen_add_tl(t2, t1, t2);
25175 break;
25176 case MXU_APTN2_AS:
25177 tcg_gen_add_tl(t3, t0, t3);
25178 tcg_gen_sub_tl(t2, t1, t2);
25179 break;
25180 case MXU_APTN2_SA:
25181 tcg_gen_sub_tl(t3, t0, t3);
25182 tcg_gen_add_tl(t2, t1, t2);
25183 break;
25184 case MXU_APTN2_SS:
25185 tcg_gen_sub_tl(t3, t0, t3);
25186 tcg_gen_sub_tl(t2, t1, t2);
25187 break;
25189 gen_store_mxu_gpr(t3, XRa);
25190 gen_store_mxu_gpr(t2, XRd);
25192 tcg_temp_free(t0);
25193 tcg_temp_free(t1);
25194 tcg_temp_free(t2);
25195 tcg_temp_free(t3);
25199 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25200 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25202 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25204 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25205 uint32_t XRa, XRb, XRc, XRd, sel;
25207 t0 = tcg_temp_new();
25208 t1 = tcg_temp_new();
25209 t2 = tcg_temp_new();
25210 t3 = tcg_temp_new();
25211 t4 = tcg_temp_new();
25212 t5 = tcg_temp_new();
25213 t6 = tcg_temp_new();
25214 t7 = tcg_temp_new();
25216 XRa = extract32(ctx->opcode, 6, 4);
25217 XRb = extract32(ctx->opcode, 10, 4);
25218 XRc = extract32(ctx->opcode, 14, 4);
25219 XRd = extract32(ctx->opcode, 18, 4);
25220 sel = extract32(ctx->opcode, 22, 2);
25222 gen_load_mxu_gpr(t3, XRb);
25223 gen_load_mxu_gpr(t7, XRc);
25225 if (sel == 0x2) {
25226 /* Q8MULSU */
25227 tcg_gen_ext8s_tl(t0, t3);
25228 tcg_gen_shri_tl(t3, t3, 8);
25229 tcg_gen_ext8s_tl(t1, t3);
25230 tcg_gen_shri_tl(t3, t3, 8);
25231 tcg_gen_ext8s_tl(t2, t3);
25232 tcg_gen_shri_tl(t3, t3, 8);
25233 tcg_gen_ext8s_tl(t3, t3);
25234 } else {
25235 /* Q8MUL */
25236 tcg_gen_ext8u_tl(t0, t3);
25237 tcg_gen_shri_tl(t3, t3, 8);
25238 tcg_gen_ext8u_tl(t1, t3);
25239 tcg_gen_shri_tl(t3, t3, 8);
25240 tcg_gen_ext8u_tl(t2, t3);
25241 tcg_gen_shri_tl(t3, t3, 8);
25242 tcg_gen_ext8u_tl(t3, t3);
25245 tcg_gen_ext8u_tl(t4, t7);
25246 tcg_gen_shri_tl(t7, t7, 8);
25247 tcg_gen_ext8u_tl(t5, t7);
25248 tcg_gen_shri_tl(t7, t7, 8);
25249 tcg_gen_ext8u_tl(t6, t7);
25250 tcg_gen_shri_tl(t7, t7, 8);
25251 tcg_gen_ext8u_tl(t7, t7);
25253 tcg_gen_mul_tl(t0, t0, t4);
25254 tcg_gen_mul_tl(t1, t1, t5);
25255 tcg_gen_mul_tl(t2, t2, t6);
25256 tcg_gen_mul_tl(t3, t3, t7);
25258 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25259 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25260 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25261 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25263 tcg_gen_shli_tl(t1, t1, 16);
25264 tcg_gen_shli_tl(t3, t3, 16);
25266 tcg_gen_or_tl(t0, t0, t1);
25267 tcg_gen_or_tl(t1, t2, t3);
25269 gen_store_mxu_gpr(t0, XRd);
25270 gen_store_mxu_gpr(t1, XRa);
25272 tcg_temp_free(t0);
25273 tcg_temp_free(t1);
25274 tcg_temp_free(t2);
25275 tcg_temp_free(t3);
25276 tcg_temp_free(t4);
25277 tcg_temp_free(t5);
25278 tcg_temp_free(t6);
25279 tcg_temp_free(t7);
25283 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25284 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25286 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25288 TCGv t0, t1;
25289 uint32_t XRa, Rb, s12, sel;
25291 t0 = tcg_temp_new();
25292 t1 = tcg_temp_new();
25294 XRa = extract32(ctx->opcode, 6, 4);
25295 s12 = extract32(ctx->opcode, 10, 10);
25296 sel = extract32(ctx->opcode, 20, 1);
25297 Rb = extract32(ctx->opcode, 21, 5);
25299 gen_load_gpr(t0, Rb);
25301 tcg_gen_movi_tl(t1, s12);
25302 tcg_gen_shli_tl(t1, t1, 2);
25303 if (s12 & 0x200) {
25304 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25306 tcg_gen_add_tl(t1, t0, t1);
25307 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25309 if (sel == 1) {
25310 /* S32LDDR */
25311 tcg_gen_bswap32_tl(t1, t1);
25313 gen_store_mxu_gpr(t1, XRa);
25315 tcg_temp_free(t0);
25316 tcg_temp_free(t1);
25321 * MXU instruction category: logic
25322 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25324 * S32NOR S32AND S32OR S32XOR
25328 * S32NOR XRa, XRb, XRc
25329 * Update XRa with the result of logical bitwise 'nor' operation
25330 * applied to the content of XRb and XRc.
25332 * 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
25333 * +-----------+---------+-----+-------+-------+-------+-----------+
25334 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25335 * +-----------+---------+-----+-------+-------+-------+-----------+
25337 static void gen_mxu_S32NOR(DisasContext *ctx)
25339 uint32_t pad, XRc, XRb, XRa;
25341 pad = extract32(ctx->opcode, 21, 5);
25342 XRc = extract32(ctx->opcode, 14, 4);
25343 XRb = extract32(ctx->opcode, 10, 4);
25344 XRa = extract32(ctx->opcode, 6, 4);
25346 if (unlikely(pad != 0)) {
25347 /* opcode padding incorrect -> do nothing */
25348 } else if (unlikely(XRa == 0)) {
25349 /* destination is zero register -> do nothing */
25350 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25351 /* both operands zero registers -> just set destination to all 1s */
25352 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25353 } else if (unlikely(XRb == 0)) {
25354 /* XRb zero register -> just set destination to the negation of XRc */
25355 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25356 } else if (unlikely(XRc == 0)) {
25357 /* XRa zero register -> just set destination to the negation of XRb */
25358 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25359 } else if (unlikely(XRb == XRc)) {
25360 /* both operands same -> just set destination to the negation of XRb */
25361 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25362 } else {
25363 /* the most general case */
25364 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25369 * S32AND XRa, XRb, XRc
25370 * Update XRa with the result of logical bitwise 'and' operation
25371 * applied to the content of XRb and XRc.
25373 * 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
25374 * +-----------+---------+-----+-------+-------+-------+-----------+
25375 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25376 * +-----------+---------+-----+-------+-------+-------+-----------+
25378 static void gen_mxu_S32AND(DisasContext *ctx)
25380 uint32_t pad, XRc, XRb, XRa;
25382 pad = extract32(ctx->opcode, 21, 5);
25383 XRc = extract32(ctx->opcode, 14, 4);
25384 XRb = extract32(ctx->opcode, 10, 4);
25385 XRa = extract32(ctx->opcode, 6, 4);
25387 if (unlikely(pad != 0)) {
25388 /* opcode padding incorrect -> do nothing */
25389 } else if (unlikely(XRa == 0)) {
25390 /* destination is zero register -> do nothing */
25391 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25392 /* one of operands zero register -> just set destination to all 0s */
25393 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25394 } else if (unlikely(XRb == XRc)) {
25395 /* both operands same -> just set destination to one of them */
25396 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25397 } else {
25398 /* the most general case */
25399 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25404 * S32OR XRa, XRb, XRc
25405 * Update XRa with the result of logical bitwise 'or' operation
25406 * applied to the content of XRb and XRc.
25408 * 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
25409 * +-----------+---------+-----+-------+-------+-------+-----------+
25410 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25411 * +-----------+---------+-----+-------+-------+-------+-----------+
25413 static void gen_mxu_S32OR(DisasContext *ctx)
25415 uint32_t pad, XRc, XRb, XRa;
25417 pad = extract32(ctx->opcode, 21, 5);
25418 XRc = extract32(ctx->opcode, 14, 4);
25419 XRb = extract32(ctx->opcode, 10, 4);
25420 XRa = extract32(ctx->opcode, 6, 4);
25422 if (unlikely(pad != 0)) {
25423 /* opcode padding incorrect -> do nothing */
25424 } else if (unlikely(XRa == 0)) {
25425 /* destination is zero register -> do nothing */
25426 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25427 /* both operands zero registers -> just set destination to all 0s */
25428 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25429 } else if (unlikely(XRb == 0)) {
25430 /* XRb zero register -> just set destination to the content of XRc */
25431 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25432 } else if (unlikely(XRc == 0)) {
25433 /* XRc zero register -> just set destination to the content of XRb */
25434 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25435 } else if (unlikely(XRb == XRc)) {
25436 /* both operands same -> just set destination to one of them */
25437 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25438 } else {
25439 /* the most general case */
25440 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25445 * S32XOR XRa, XRb, XRc
25446 * Update XRa with the result of logical bitwise 'xor' operation
25447 * applied to the content of XRb and XRc.
25449 * 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
25450 * +-----------+---------+-----+-------+-------+-------+-----------+
25451 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25452 * +-----------+---------+-----+-------+-------+-------+-----------+
25454 static void gen_mxu_S32XOR(DisasContext *ctx)
25456 uint32_t pad, XRc, XRb, XRa;
25458 pad = extract32(ctx->opcode, 21, 5);
25459 XRc = extract32(ctx->opcode, 14, 4);
25460 XRb = extract32(ctx->opcode, 10, 4);
25461 XRa = extract32(ctx->opcode, 6, 4);
25463 if (unlikely(pad != 0)) {
25464 /* opcode padding incorrect -> do nothing */
25465 } else if (unlikely(XRa == 0)) {
25466 /* destination is zero register -> do nothing */
25467 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25468 /* both operands zero registers -> just set destination to all 0s */
25469 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25470 } else if (unlikely(XRb == 0)) {
25471 /* XRb zero register -> just set destination to the content of XRc */
25472 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25473 } else if (unlikely(XRc == 0)) {
25474 /* XRc zero register -> just set destination to the content of XRb */
25475 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25476 } else if (unlikely(XRb == XRc)) {
25477 /* both operands same -> just set destination to all 0s */
25478 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25479 } else {
25480 /* the most general case */
25481 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25487 * MXU instruction category max/min
25488 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25490 * S32MAX D16MAX Q8MAX
25491 * S32MIN D16MIN Q8MIN
25495 * S32MAX XRa, XRb, XRc
25496 * Update XRa with the maximum of signed 32-bit integers contained
25497 * in XRb and XRc.
25499 * S32MIN XRa, XRb, XRc
25500 * Update XRa with the minimum of signed 32-bit integers contained
25501 * in XRb and XRc.
25503 * 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
25504 * +-----------+---------+-----+-------+-------+-------+-----------+
25505 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25506 * +-----------+---------+-----+-------+-------+-------+-----------+
25508 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25510 uint32_t pad, opc, XRc, XRb, XRa;
25512 pad = extract32(ctx->opcode, 21, 5);
25513 opc = extract32(ctx->opcode, 18, 3);
25514 XRc = extract32(ctx->opcode, 14, 4);
25515 XRb = extract32(ctx->opcode, 10, 4);
25516 XRa = extract32(ctx->opcode, 6, 4);
25518 if (unlikely(pad != 0)) {
25519 /* opcode padding incorrect -> do nothing */
25520 } else if (unlikely(XRa == 0)) {
25521 /* destination is zero register -> do nothing */
25522 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25523 /* both operands zero registers -> just set destination to zero */
25524 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25525 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25526 /* exactly one operand is zero register - find which one is not...*/
25527 uint32_t XRx = XRb ? XRb : XRc;
25528 /* ...and do max/min operation with one operand 0 */
25529 if (opc == OPC_MXU_S32MAX) {
25530 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25531 } else {
25532 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25534 } else if (unlikely(XRb == XRc)) {
25535 /* both operands same -> just set destination to one of them */
25536 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25537 } else {
25538 /* the most general case */
25539 if (opc == OPC_MXU_S32MAX) {
25540 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25541 mxu_gpr[XRc - 1]);
25542 } else {
25543 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25544 mxu_gpr[XRc - 1]);
25550 * D16MAX
25551 * Update XRa with the 16-bit-wise maximums of signed integers
25552 * contained in XRb and XRc.
25554 * D16MIN
25555 * Update XRa with the 16-bit-wise minimums of signed integers
25556 * contained in XRb and XRc.
25558 * 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
25559 * +-----------+---------+-----+-------+-------+-------+-----------+
25560 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25561 * +-----------+---------+-----+-------+-------+-------+-----------+
25563 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25565 uint32_t pad, opc, XRc, XRb, XRa;
25567 pad = extract32(ctx->opcode, 21, 5);
25568 opc = extract32(ctx->opcode, 18, 3);
25569 XRc = extract32(ctx->opcode, 14, 4);
25570 XRb = extract32(ctx->opcode, 10, 4);
25571 XRa = extract32(ctx->opcode, 6, 4);
25573 if (unlikely(pad != 0)) {
25574 /* opcode padding incorrect -> do nothing */
25575 } else if (unlikely(XRc == 0)) {
25576 /* destination is zero register -> do nothing */
25577 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25578 /* both operands zero registers -> just set destination to zero */
25579 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25580 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25581 /* exactly one operand is zero register - find which one is not...*/
25582 uint32_t XRx = XRb ? XRb : XRc;
25583 /* ...and do half-word-wise max/min with one operand 0 */
25584 TCGv_i32 t0 = tcg_temp_new();
25585 TCGv_i32 t1 = tcg_const_i32(0);
25587 /* the left half-word first */
25588 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25589 if (opc == OPC_MXU_D16MAX) {
25590 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25591 } else {
25592 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25595 /* the right half-word */
25596 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25597 /* move half-words to the leftmost position */
25598 tcg_gen_shli_i32(t0, t0, 16);
25599 /* t0 will be max/min of t0 and t1 */
25600 if (opc == OPC_MXU_D16MAX) {
25601 tcg_gen_smax_i32(t0, t0, t1);
25602 } else {
25603 tcg_gen_smin_i32(t0, t0, t1);
25605 /* return resulting half-words to its original position */
25606 tcg_gen_shri_i32(t0, t0, 16);
25607 /* finaly update the destination */
25608 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25610 tcg_temp_free(t1);
25611 tcg_temp_free(t0);
25612 } else if (unlikely(XRb == XRc)) {
25613 /* both operands same -> just set destination to one of them */
25614 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25615 } else {
25616 /* the most general case */
25617 TCGv_i32 t0 = tcg_temp_new();
25618 TCGv_i32 t1 = tcg_temp_new();
25620 /* the left half-word first */
25621 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25622 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25623 if (opc == OPC_MXU_D16MAX) {
25624 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25625 } else {
25626 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25629 /* the right half-word */
25630 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25631 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25632 /* move half-words to the leftmost position */
25633 tcg_gen_shli_i32(t0, t0, 16);
25634 tcg_gen_shli_i32(t1, t1, 16);
25635 /* t0 will be max/min of t0 and t1 */
25636 if (opc == OPC_MXU_D16MAX) {
25637 tcg_gen_smax_i32(t0, t0, t1);
25638 } else {
25639 tcg_gen_smin_i32(t0, t0, t1);
25641 /* return resulting half-words to its original position */
25642 tcg_gen_shri_i32(t0, t0, 16);
25643 /* finaly update the destination */
25644 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25646 tcg_temp_free(t1);
25647 tcg_temp_free(t0);
25652 * Q8MAX
25653 * Update XRa with the 8-bit-wise maximums of signed integers
25654 * contained in XRb and XRc.
25656 * Q8MIN
25657 * Update XRa with the 8-bit-wise minimums of signed integers
25658 * contained in XRb and XRc.
25660 * 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
25661 * +-----------+---------+-----+-------+-------+-------+-----------+
25662 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25663 * +-----------+---------+-----+-------+-------+-------+-----------+
25665 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25667 uint32_t pad, opc, XRc, XRb, XRa;
25669 pad = extract32(ctx->opcode, 21, 5);
25670 opc = extract32(ctx->opcode, 18, 3);
25671 XRc = extract32(ctx->opcode, 14, 4);
25672 XRb = extract32(ctx->opcode, 10, 4);
25673 XRa = extract32(ctx->opcode, 6, 4);
25675 if (unlikely(pad != 0)) {
25676 /* opcode padding incorrect -> do nothing */
25677 } else if (unlikely(XRa == 0)) {
25678 /* destination is zero register -> do nothing */
25679 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25680 /* both operands zero registers -> just set destination to zero */
25681 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25682 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25683 /* exactly one operand is zero register - make it be the first...*/
25684 uint32_t XRx = XRb ? XRb : XRc;
25685 /* ...and do byte-wise max/min with one operand 0 */
25686 TCGv_i32 t0 = tcg_temp_new();
25687 TCGv_i32 t1 = tcg_const_i32(0);
25688 int32_t i;
25690 /* the leftmost byte (byte 3) first */
25691 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25692 if (opc == OPC_MXU_Q8MAX) {
25693 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25694 } else {
25695 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25698 /* bytes 2, 1, 0 */
25699 for (i = 2; i >= 0; i--) {
25700 /* extract the byte */
25701 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
25702 /* move the byte to the leftmost position */
25703 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25704 /* t0 will be max/min of t0 and t1 */
25705 if (opc == OPC_MXU_Q8MAX) {
25706 tcg_gen_smax_i32(t0, t0, t1);
25707 } else {
25708 tcg_gen_smin_i32(t0, t0, t1);
25710 /* return resulting byte to its original position */
25711 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25712 /* finaly update the destination */
25713 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25716 tcg_temp_free(t1);
25717 tcg_temp_free(t0);
25718 } else if (unlikely(XRb == XRc)) {
25719 /* both operands same -> just set destination to one of them */
25720 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25721 } else {
25722 /* the most general case */
25723 TCGv_i32 t0 = tcg_temp_new();
25724 TCGv_i32 t1 = tcg_temp_new();
25725 int32_t i;
25727 /* the leftmost bytes (bytes 3) first */
25728 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
25729 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25730 if (opc == OPC_MXU_Q8MAX) {
25731 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25732 } else {
25733 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25736 /* bytes 2, 1, 0 */
25737 for (i = 2; i >= 0; i--) {
25738 /* extract corresponding bytes */
25739 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
25740 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
25741 /* move the bytes to the leftmost position */
25742 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
25743 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
25744 /* t0 will be max/min of t0 and t1 */
25745 if (opc == OPC_MXU_Q8MAX) {
25746 tcg_gen_smax_i32(t0, t0, t1);
25747 } else {
25748 tcg_gen_smin_i32(t0, t0, t1);
25750 /* return resulting byte to its original position */
25751 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
25752 /* finaly update the destination */
25753 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25756 tcg_temp_free(t1);
25757 tcg_temp_free(t0);
25763 * MXU instruction category: align
25764 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25766 * S32ALN S32ALNI
25770 * S32ALNI XRc, XRb, XRa, optn3
25771 * Arrange bytes from XRb and XRc according to one of five sets of
25772 * rules determined by optn3, and place the result in XRa.
25774 * 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
25775 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25776 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
25777 * +-----------+-----+---+-----+-------+-------+-------+-----------+
25780 static void gen_mxu_S32ALNI(DisasContext *ctx)
25782 uint32_t optn3, pad, XRc, XRb, XRa;
25784 optn3 = extract32(ctx->opcode, 23, 3);
25785 pad = extract32(ctx->opcode, 21, 2);
25786 XRc = extract32(ctx->opcode, 14, 4);
25787 XRb = extract32(ctx->opcode, 10, 4);
25788 XRa = extract32(ctx->opcode, 6, 4);
25790 if (unlikely(pad != 0)) {
25791 /* opcode padding incorrect -> do nothing */
25792 } else if (unlikely(XRa == 0)) {
25793 /* destination is zero register -> do nothing */
25794 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25795 /* both operands zero registers -> just set destination to all 0s */
25796 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25797 } else if (unlikely(XRb == 0)) {
25798 /* XRb zero register -> just appropriatelly shift XRc into XRa */
25799 switch (optn3) {
25800 case MXU_OPTN3_PTN0:
25801 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25802 break;
25803 case MXU_OPTN3_PTN1:
25804 case MXU_OPTN3_PTN2:
25805 case MXU_OPTN3_PTN3:
25806 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
25807 8 * (4 - optn3));
25808 break;
25809 case MXU_OPTN3_PTN4:
25810 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25811 break;
25813 } else if (unlikely(XRc == 0)) {
25814 /* XRc zero register -> just appropriatelly shift XRb into XRa */
25815 switch (optn3) {
25816 case MXU_OPTN3_PTN0:
25817 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25818 break;
25819 case MXU_OPTN3_PTN1:
25820 case MXU_OPTN3_PTN2:
25821 case MXU_OPTN3_PTN3:
25822 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25823 break;
25824 case MXU_OPTN3_PTN4:
25825 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25826 break;
25828 } else if (unlikely(XRb == XRc)) {
25829 /* both operands same -> just rotation or moving from any of them */
25830 switch (optn3) {
25831 case MXU_OPTN3_PTN0:
25832 case MXU_OPTN3_PTN4:
25833 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25834 break;
25835 case MXU_OPTN3_PTN1:
25836 case MXU_OPTN3_PTN2:
25837 case MXU_OPTN3_PTN3:
25838 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
25839 break;
25841 } else {
25842 /* the most general case */
25843 switch (optn3) {
25844 case MXU_OPTN3_PTN0:
25846 /* */
25847 /* XRb XRc */
25848 /* +---------------+ */
25849 /* | A B C D | E F G H */
25850 /* +-------+-------+ */
25851 /* | */
25852 /* XRa */
25853 /* */
25855 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25857 break;
25858 case MXU_OPTN3_PTN1:
25860 /* */
25861 /* XRb XRc */
25862 /* +-------------------+ */
25863 /* A | B C D E | F G H */
25864 /* +---------+---------+ */
25865 /* | */
25866 /* XRa */
25867 /* */
25869 TCGv_i32 t0 = tcg_temp_new();
25870 TCGv_i32 t1 = tcg_temp_new();
25872 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
25873 tcg_gen_shli_i32(t0, t0, 8);
25875 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
25876 tcg_gen_shri_i32(t1, t1, 24);
25878 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25880 tcg_temp_free(t1);
25881 tcg_temp_free(t0);
25883 break;
25884 case MXU_OPTN3_PTN2:
25886 /* */
25887 /* XRb XRc */
25888 /* +-------------------+ */
25889 /* A B | C D E F | G H */
25890 /* +---------+---------+ */
25891 /* | */
25892 /* XRa */
25893 /* */
25895 TCGv_i32 t0 = tcg_temp_new();
25896 TCGv_i32 t1 = tcg_temp_new();
25898 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25899 tcg_gen_shli_i32(t0, t0, 16);
25901 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25902 tcg_gen_shri_i32(t1, t1, 16);
25904 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25906 tcg_temp_free(t1);
25907 tcg_temp_free(t0);
25909 break;
25910 case MXU_OPTN3_PTN3:
25912 /* */
25913 /* XRb XRc */
25914 /* +-------------------+ */
25915 /* A B C | D E F G | H */
25916 /* +---------+---------+ */
25917 /* | */
25918 /* XRa */
25919 /* */
25921 TCGv_i32 t0 = tcg_temp_new();
25922 TCGv_i32 t1 = tcg_temp_new();
25924 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
25925 tcg_gen_shli_i32(t0, t0, 24);
25927 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
25928 tcg_gen_shri_i32(t1, t1, 8);
25930 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
25932 tcg_temp_free(t1);
25933 tcg_temp_free(t0);
25935 break;
25936 case MXU_OPTN3_PTN4:
25938 /* */
25939 /* XRb XRc */
25940 /* +---------------+ */
25941 /* A B C D | E F G H | */
25942 /* +-------+-------+ */
25943 /* | */
25944 /* XRa */
25945 /* */
25947 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25949 break;
25956 * Decoding engine for MXU
25957 * =======================
25962 * Decode MXU pool00
25964 * 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
25965 * +-----------+---------+-----+-------+-------+-------+-----------+
25966 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
25967 * +-----------+---------+-----+-------+-------+-------+-----------+
25970 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
25972 uint32_t opcode = extract32(ctx->opcode, 18, 3);
25974 switch (opcode) {
25975 case OPC_MXU_S32MAX:
25976 case OPC_MXU_S32MIN:
25977 gen_mxu_S32MAX_S32MIN(ctx);
25978 break;
25979 case OPC_MXU_D16MAX:
25980 case OPC_MXU_D16MIN:
25981 gen_mxu_D16MAX_D16MIN(ctx);
25982 break;
25983 case OPC_MXU_Q8MAX:
25984 case OPC_MXU_Q8MIN:
25985 gen_mxu_Q8MAX_Q8MIN(ctx);
25986 break;
25987 case OPC_MXU_Q8SLT:
25988 /* TODO: Implement emulation of Q8SLT instruction. */
25989 MIPS_INVAL("OPC_MXU_Q8SLT");
25990 generate_exception_end(ctx, EXCP_RI);
25991 break;
25992 case OPC_MXU_Q8SLTU:
25993 /* TODO: Implement emulation of Q8SLTU instruction. */
25994 MIPS_INVAL("OPC_MXU_Q8SLTU");
25995 generate_exception_end(ctx, EXCP_RI);
25996 break;
25997 default:
25998 MIPS_INVAL("decode_opc_mxu");
25999 generate_exception_end(ctx, EXCP_RI);
26000 break;
26006 * Decode MXU pool01
26008 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26009 * 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
26010 * +-----------+---------+-----+-------+-------+-------+-----------+
26011 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26012 * +-----------+---------+-----+-------+-------+-------+-----------+
26014 * Q8ADD:
26015 * 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
26016 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26017 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26018 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26021 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26023 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26025 switch (opcode) {
26026 case OPC_MXU_S32SLT:
26027 /* TODO: Implement emulation of S32SLT instruction. */
26028 MIPS_INVAL("OPC_MXU_S32SLT");
26029 generate_exception_end(ctx, EXCP_RI);
26030 break;
26031 case OPC_MXU_D16SLT:
26032 /* TODO: Implement emulation of D16SLT instruction. */
26033 MIPS_INVAL("OPC_MXU_D16SLT");
26034 generate_exception_end(ctx, EXCP_RI);
26035 break;
26036 case OPC_MXU_D16AVG:
26037 /* TODO: Implement emulation of D16AVG instruction. */
26038 MIPS_INVAL("OPC_MXU_D16AVG");
26039 generate_exception_end(ctx, EXCP_RI);
26040 break;
26041 case OPC_MXU_D16AVGR:
26042 /* TODO: Implement emulation of D16AVGR instruction. */
26043 MIPS_INVAL("OPC_MXU_D16AVGR");
26044 generate_exception_end(ctx, EXCP_RI);
26045 break;
26046 case OPC_MXU_Q8AVG:
26047 /* TODO: Implement emulation of Q8AVG instruction. */
26048 MIPS_INVAL("OPC_MXU_Q8AVG");
26049 generate_exception_end(ctx, EXCP_RI);
26050 break;
26051 case OPC_MXU_Q8AVGR:
26052 /* TODO: Implement emulation of Q8AVGR instruction. */
26053 MIPS_INVAL("OPC_MXU_Q8AVGR");
26054 generate_exception_end(ctx, EXCP_RI);
26055 break;
26056 case OPC_MXU_Q8ADD:
26057 /* TODO: Implement emulation of Q8ADD instruction. */
26058 MIPS_INVAL("OPC_MXU_Q8ADD");
26059 generate_exception_end(ctx, EXCP_RI);
26060 break;
26061 default:
26062 MIPS_INVAL("decode_opc_mxu");
26063 generate_exception_end(ctx, EXCP_RI);
26064 break;
26070 * Decode MXU pool02
26072 * 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
26073 * +-----------+---------+-----+-------+-------+-------+-----------+
26074 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26075 * +-----------+---------+-----+-------+-------+-------+-----------+
26078 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26080 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26082 switch (opcode) {
26083 case OPC_MXU_S32CPS:
26084 /* TODO: Implement emulation of S32CPS instruction. */
26085 MIPS_INVAL("OPC_MXU_S32CPS");
26086 generate_exception_end(ctx, EXCP_RI);
26087 break;
26088 case OPC_MXU_D16CPS:
26089 /* TODO: Implement emulation of D16CPS instruction. */
26090 MIPS_INVAL("OPC_MXU_D16CPS");
26091 generate_exception_end(ctx, EXCP_RI);
26092 break;
26093 case OPC_MXU_Q8ABD:
26094 /* TODO: Implement emulation of Q8ABD instruction. */
26095 MIPS_INVAL("OPC_MXU_Q8ABD");
26096 generate_exception_end(ctx, EXCP_RI);
26097 break;
26098 case OPC_MXU_Q16SAT:
26099 /* TODO: Implement emulation of Q16SAT instruction. */
26100 MIPS_INVAL("OPC_MXU_Q16SAT");
26101 generate_exception_end(ctx, EXCP_RI);
26102 break;
26103 default:
26104 MIPS_INVAL("decode_opc_mxu");
26105 generate_exception_end(ctx, EXCP_RI);
26106 break;
26112 * Decode MXU pool03
26114 * D16MULF:
26115 * 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
26116 * +-----------+---+---+-------+-------+-------+-------+-----------+
26117 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26118 * +-----------+---+---+-------+-------+-------+-------+-----------+
26120 * D16MULE:
26121 * 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
26122 * +-----------+---+---+-------+-------+-------+-------+-----------+
26123 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26124 * +-----------+---+---+-------+-------+-------+-------+-----------+
26127 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26129 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26131 switch (opcode) {
26132 case OPC_MXU_D16MULF:
26133 /* TODO: Implement emulation of D16MULF instruction. */
26134 MIPS_INVAL("OPC_MXU_D16MULF");
26135 generate_exception_end(ctx, EXCP_RI);
26136 break;
26137 case OPC_MXU_D16MULE:
26138 /* TODO: Implement emulation of D16MULE instruction. */
26139 MIPS_INVAL("OPC_MXU_D16MULE");
26140 generate_exception_end(ctx, EXCP_RI);
26141 break;
26142 default:
26143 MIPS_INVAL("decode_opc_mxu");
26144 generate_exception_end(ctx, EXCP_RI);
26145 break;
26151 * Decode MXU pool04
26153 * 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
26154 * +-----------+---------+-+-------------------+-------+-----------+
26155 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26156 * +-----------+---------+-+-------------------+-------+-----------+
26159 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26161 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26163 switch (opcode) {
26164 case OPC_MXU_S32LDD:
26165 case OPC_MXU_S32LDDR:
26166 gen_mxu_s32ldd_s32lddr(ctx);
26167 break;
26168 default:
26169 MIPS_INVAL("decode_opc_mxu");
26170 generate_exception_end(ctx, EXCP_RI);
26171 break;
26177 * Decode MXU pool05
26179 * 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
26180 * +-----------+---------+-+-------------------+-------+-----------+
26181 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26182 * +-----------+---------+-+-------------------+-------+-----------+
26185 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26187 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26189 switch (opcode) {
26190 case OPC_MXU_S32STD:
26191 /* TODO: Implement emulation of S32STD instruction. */
26192 MIPS_INVAL("OPC_MXU_S32STD");
26193 generate_exception_end(ctx, EXCP_RI);
26194 break;
26195 case OPC_MXU_S32STDR:
26196 /* TODO: Implement emulation of S32STDR instruction. */
26197 MIPS_INVAL("OPC_MXU_S32STDR");
26198 generate_exception_end(ctx, EXCP_RI);
26199 break;
26200 default:
26201 MIPS_INVAL("decode_opc_mxu");
26202 generate_exception_end(ctx, EXCP_RI);
26203 break;
26209 * Decode MXU pool06
26211 * 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
26212 * +-----------+---------+---------+---+-------+-------+-----------+
26213 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26214 * +-----------+---------+---------+---+-------+-------+-----------+
26217 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26219 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26221 switch (opcode) {
26222 case OPC_MXU_S32LDDV:
26223 /* TODO: Implement emulation of S32LDDV instruction. */
26224 MIPS_INVAL("OPC_MXU_S32LDDV");
26225 generate_exception_end(ctx, EXCP_RI);
26226 break;
26227 case OPC_MXU_S32LDDVR:
26228 /* TODO: Implement emulation of S32LDDVR instruction. */
26229 MIPS_INVAL("OPC_MXU_S32LDDVR");
26230 generate_exception_end(ctx, EXCP_RI);
26231 break;
26232 default:
26233 MIPS_INVAL("decode_opc_mxu");
26234 generate_exception_end(ctx, EXCP_RI);
26235 break;
26241 * Decode MXU pool07
26243 * 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
26244 * +-----------+---------+---------+---+-------+-------+-----------+
26245 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26246 * +-----------+---------+---------+---+-------+-------+-----------+
26249 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26251 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26253 switch (opcode) {
26254 case OPC_MXU_S32STDV:
26255 /* TODO: Implement emulation of S32TDV instruction. */
26256 MIPS_INVAL("OPC_MXU_S32TDV");
26257 generate_exception_end(ctx, EXCP_RI);
26258 break;
26259 case OPC_MXU_S32STDVR:
26260 /* TODO: Implement emulation of S32TDVR instruction. */
26261 MIPS_INVAL("OPC_MXU_S32TDVR");
26262 generate_exception_end(ctx, EXCP_RI);
26263 break;
26264 default:
26265 MIPS_INVAL("decode_opc_mxu");
26266 generate_exception_end(ctx, EXCP_RI);
26267 break;
26273 * Decode MXU pool08
26275 * 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
26276 * +-----------+---------+-+-------------------+-------+-----------+
26277 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26278 * +-----------+---------+-+-------------------+-------+-----------+
26281 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26283 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26285 switch (opcode) {
26286 case OPC_MXU_S32LDI:
26287 /* TODO: Implement emulation of S32LDI instruction. */
26288 MIPS_INVAL("OPC_MXU_S32LDI");
26289 generate_exception_end(ctx, EXCP_RI);
26290 break;
26291 case OPC_MXU_S32LDIR:
26292 /* TODO: Implement emulation of S32LDIR instruction. */
26293 MIPS_INVAL("OPC_MXU_S32LDIR");
26294 generate_exception_end(ctx, EXCP_RI);
26295 break;
26296 default:
26297 MIPS_INVAL("decode_opc_mxu");
26298 generate_exception_end(ctx, EXCP_RI);
26299 break;
26305 * Decode MXU pool09
26307 * 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
26308 * +-----------+---------+-+-------------------+-------+-----------+
26309 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26310 * +-----------+---------+-+-------------------+-------+-----------+
26313 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26315 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26317 switch (opcode) {
26318 case OPC_MXU_S32SDI:
26319 /* TODO: Implement emulation of S32SDI instruction. */
26320 MIPS_INVAL("OPC_MXU_S32SDI");
26321 generate_exception_end(ctx, EXCP_RI);
26322 break;
26323 case OPC_MXU_S32SDIR:
26324 /* TODO: Implement emulation of S32SDIR instruction. */
26325 MIPS_INVAL("OPC_MXU_S32SDIR");
26326 generate_exception_end(ctx, EXCP_RI);
26327 break;
26328 default:
26329 MIPS_INVAL("decode_opc_mxu");
26330 generate_exception_end(ctx, EXCP_RI);
26331 break;
26337 * Decode MXU pool10
26339 * 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
26340 * +-----------+---------+---------+---+-------+-------+-----------+
26341 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26342 * +-----------+---------+---------+---+-------+-------+-----------+
26345 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26347 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26349 switch (opcode) {
26350 case OPC_MXU_S32LDIV:
26351 /* TODO: Implement emulation of S32LDIV instruction. */
26352 MIPS_INVAL("OPC_MXU_S32LDIV");
26353 generate_exception_end(ctx, EXCP_RI);
26354 break;
26355 case OPC_MXU_S32LDIVR:
26356 /* TODO: Implement emulation of S32LDIVR instruction. */
26357 MIPS_INVAL("OPC_MXU_S32LDIVR");
26358 generate_exception_end(ctx, EXCP_RI);
26359 break;
26360 default:
26361 MIPS_INVAL("decode_opc_mxu");
26362 generate_exception_end(ctx, EXCP_RI);
26363 break;
26369 * Decode MXU pool11
26371 * 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
26372 * +-----------+---------+---------+---+-------+-------+-----------+
26373 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26374 * +-----------+---------+---------+---+-------+-------+-----------+
26377 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26379 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26381 switch (opcode) {
26382 case OPC_MXU_S32SDIV:
26383 /* TODO: Implement emulation of S32SDIV instruction. */
26384 MIPS_INVAL("OPC_MXU_S32SDIV");
26385 generate_exception_end(ctx, EXCP_RI);
26386 break;
26387 case OPC_MXU_S32SDIVR:
26388 /* TODO: Implement emulation of S32SDIVR instruction. */
26389 MIPS_INVAL("OPC_MXU_S32SDIVR");
26390 generate_exception_end(ctx, EXCP_RI);
26391 break;
26392 default:
26393 MIPS_INVAL("decode_opc_mxu");
26394 generate_exception_end(ctx, EXCP_RI);
26395 break;
26401 * Decode MXU pool12
26403 * 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
26404 * +-----------+---+---+-------+-------+-------+-------+-----------+
26405 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26406 * +-----------+---+---+-------+-------+-------+-------+-----------+
26409 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26411 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26413 switch (opcode) {
26414 case OPC_MXU_D32ACC:
26415 /* TODO: Implement emulation of D32ACC instruction. */
26416 MIPS_INVAL("OPC_MXU_D32ACC");
26417 generate_exception_end(ctx, EXCP_RI);
26418 break;
26419 case OPC_MXU_D32ACCM:
26420 /* TODO: Implement emulation of D32ACCM instruction. */
26421 MIPS_INVAL("OPC_MXU_D32ACCM");
26422 generate_exception_end(ctx, EXCP_RI);
26423 break;
26424 case OPC_MXU_D32ASUM:
26425 /* TODO: Implement emulation of D32ASUM instruction. */
26426 MIPS_INVAL("OPC_MXU_D32ASUM");
26427 generate_exception_end(ctx, EXCP_RI);
26428 break;
26429 default:
26430 MIPS_INVAL("decode_opc_mxu");
26431 generate_exception_end(ctx, EXCP_RI);
26432 break;
26438 * Decode MXU pool13
26440 * 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
26441 * +-----------+---+---+-------+-------+-------+-------+-----------+
26442 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26443 * +-----------+---+---+-------+-------+-------+-------+-----------+
26446 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26448 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26450 switch (opcode) {
26451 case OPC_MXU_Q16ACC:
26452 /* TODO: Implement emulation of Q16ACC instruction. */
26453 MIPS_INVAL("OPC_MXU_Q16ACC");
26454 generate_exception_end(ctx, EXCP_RI);
26455 break;
26456 case OPC_MXU_Q16ACCM:
26457 /* TODO: Implement emulation of Q16ACCM instruction. */
26458 MIPS_INVAL("OPC_MXU_Q16ACCM");
26459 generate_exception_end(ctx, EXCP_RI);
26460 break;
26461 case OPC_MXU_Q16ASUM:
26462 /* TODO: Implement emulation of Q16ASUM instruction. */
26463 MIPS_INVAL("OPC_MXU_Q16ASUM");
26464 generate_exception_end(ctx, EXCP_RI);
26465 break;
26466 default:
26467 MIPS_INVAL("decode_opc_mxu");
26468 generate_exception_end(ctx, EXCP_RI);
26469 break;
26475 * Decode MXU pool14
26477 * Q8ADDE, Q8ACCE:
26478 * 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
26479 * +-----------+---+---+-------+-------+-------+-------+-----------+
26480 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26481 * +-----------+---+---+-------+-------+-------+-------+-----------+
26483 * D8SUM, D8SUMC:
26484 * 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
26485 * +-----------+---+---+-------+-------+-------+-------+-----------+
26486 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26487 * +-----------+---+---+-------+-------+-------+-------+-----------+
26490 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26492 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26494 switch (opcode) {
26495 case OPC_MXU_Q8ADDE:
26496 /* TODO: Implement emulation of Q8ADDE instruction. */
26497 MIPS_INVAL("OPC_MXU_Q8ADDE");
26498 generate_exception_end(ctx, EXCP_RI);
26499 break;
26500 case OPC_MXU_D8SUM:
26501 /* TODO: Implement emulation of D8SUM instruction. */
26502 MIPS_INVAL("OPC_MXU_D8SUM");
26503 generate_exception_end(ctx, EXCP_RI);
26504 break;
26505 case OPC_MXU_D8SUMC:
26506 /* TODO: Implement emulation of D8SUMC instruction. */
26507 MIPS_INVAL("OPC_MXU_D8SUMC");
26508 generate_exception_end(ctx, EXCP_RI);
26509 break;
26510 default:
26511 MIPS_INVAL("decode_opc_mxu");
26512 generate_exception_end(ctx, EXCP_RI);
26513 break;
26519 * Decode MXU pool15
26521 * S32MUL, S32MULU, S32EXTRV:
26522 * 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
26523 * +-----------+---------+---------+---+-------+-------+-----------+
26524 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26525 * +-----------+---------+---------+---+-------+-------+-----------+
26527 * S32EXTR:
26528 * 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
26529 * +-----------+---------+---------+---+-------+-------+-----------+
26530 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26531 * +-----------+---------+---------+---+-------+-------+-----------+
26534 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26536 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26538 switch (opcode) {
26539 case OPC_MXU_S32MUL:
26540 /* TODO: Implement emulation of S32MUL instruction. */
26541 MIPS_INVAL("OPC_MXU_S32MUL");
26542 generate_exception_end(ctx, EXCP_RI);
26543 break;
26544 case OPC_MXU_S32MULU:
26545 /* TODO: Implement emulation of S32MULU instruction. */
26546 MIPS_INVAL("OPC_MXU_S32MULU");
26547 generate_exception_end(ctx, EXCP_RI);
26548 break;
26549 case OPC_MXU_S32EXTR:
26550 /* TODO: Implement emulation of S32EXTR instruction. */
26551 MIPS_INVAL("OPC_MXU_S32EXTR");
26552 generate_exception_end(ctx, EXCP_RI);
26553 break;
26554 case OPC_MXU_S32EXTRV:
26555 /* TODO: Implement emulation of S32EXTRV instruction. */
26556 MIPS_INVAL("OPC_MXU_S32EXTRV");
26557 generate_exception_end(ctx, EXCP_RI);
26558 break;
26559 default:
26560 MIPS_INVAL("decode_opc_mxu");
26561 generate_exception_end(ctx, EXCP_RI);
26562 break;
26568 * Decode MXU pool16
26570 * D32SARW:
26571 * 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
26572 * +-----------+---------+-----+-------+-------+-------+-----------+
26573 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26574 * +-----------+---------+-----+-------+-------+-------+-----------+
26576 * S32ALN:
26577 * 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
26578 * +-----------+---------+-----+-------+-------+-------+-----------+
26579 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26580 * +-----------+---------+-----+-------+-------+-------+-----------+
26582 * S32ALNI:
26583 * 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
26584 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26585 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26586 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26588 * S32LUI:
26589 * 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
26590 * +-----------+-----+---+-----+-------+---------------+-----------+
26591 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26592 * +-----------+-----+---+-----+-------+---------------+-----------+
26594 * S32NOR, S32AND, S32OR, S32XOR:
26595 * 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
26596 * +-----------+---------+-----+-------+-------+-------+-----------+
26597 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26598 * +-----------+---------+-----+-------+-------+-------+-----------+
26601 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26603 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26605 switch (opcode) {
26606 case OPC_MXU_D32SARW:
26607 /* TODO: Implement emulation of D32SARW instruction. */
26608 MIPS_INVAL("OPC_MXU_D32SARW");
26609 generate_exception_end(ctx, EXCP_RI);
26610 break;
26611 case OPC_MXU_S32ALN:
26612 /* TODO: Implement emulation of S32ALN instruction. */
26613 MIPS_INVAL("OPC_MXU_S32ALN");
26614 generate_exception_end(ctx, EXCP_RI);
26615 break;
26616 case OPC_MXU_S32ALNI:
26617 gen_mxu_S32ALNI(ctx);
26618 break;
26619 case OPC_MXU_S32LUI:
26620 /* TODO: Implement emulation of S32LUI instruction. */
26621 MIPS_INVAL("OPC_MXU_S32LUI");
26622 generate_exception_end(ctx, EXCP_RI);
26623 break;
26624 case OPC_MXU_S32NOR:
26625 gen_mxu_S32NOR(ctx);
26626 break;
26627 case OPC_MXU_S32AND:
26628 gen_mxu_S32AND(ctx);
26629 break;
26630 case OPC_MXU_S32OR:
26631 gen_mxu_S32OR(ctx);
26632 break;
26633 case OPC_MXU_S32XOR:
26634 gen_mxu_S32XOR(ctx);
26635 break;
26636 default:
26637 MIPS_INVAL("decode_opc_mxu");
26638 generate_exception_end(ctx, EXCP_RI);
26639 break;
26645 * Decode MXU pool17
26647 * 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
26648 * +-----------+---------+---------+---+---------+-----+-----------+
26649 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26650 * +-----------+---------+---------+---+---------+-----+-----------+
26653 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26655 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26657 switch (opcode) {
26658 case OPC_MXU_LXW:
26659 /* TODO: Implement emulation of LXW instruction. */
26660 MIPS_INVAL("OPC_MXU_LXW");
26661 generate_exception_end(ctx, EXCP_RI);
26662 break;
26663 case OPC_MXU_LXH:
26664 /* TODO: Implement emulation of LXH instruction. */
26665 MIPS_INVAL("OPC_MXU_LXH");
26666 generate_exception_end(ctx, EXCP_RI);
26667 break;
26668 case OPC_MXU_LXHU:
26669 /* TODO: Implement emulation of LXHU instruction. */
26670 MIPS_INVAL("OPC_MXU_LXHU");
26671 generate_exception_end(ctx, EXCP_RI);
26672 break;
26673 case OPC_MXU_LXB:
26674 /* TODO: Implement emulation of LXB instruction. */
26675 MIPS_INVAL("OPC_MXU_LXB");
26676 generate_exception_end(ctx, EXCP_RI);
26677 break;
26678 case OPC_MXU_LXBU:
26679 /* TODO: Implement emulation of LXBU instruction. */
26680 MIPS_INVAL("OPC_MXU_LXBU");
26681 generate_exception_end(ctx, EXCP_RI);
26682 break;
26683 default:
26684 MIPS_INVAL("decode_opc_mxu");
26685 generate_exception_end(ctx, EXCP_RI);
26686 break;
26691 * Decode MXU pool18
26693 * 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
26694 * +-----------+---------+-----+-------+-------+-------+-----------+
26695 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26696 * +-----------+---------+-----+-------+-------+-------+-----------+
26699 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
26701 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26703 switch (opcode) {
26704 case OPC_MXU_D32SLLV:
26705 /* TODO: Implement emulation of D32SLLV instruction. */
26706 MIPS_INVAL("OPC_MXU_D32SLLV");
26707 generate_exception_end(ctx, EXCP_RI);
26708 break;
26709 case OPC_MXU_D32SLRV:
26710 /* TODO: Implement emulation of D32SLRV instruction. */
26711 MIPS_INVAL("OPC_MXU_D32SLRV");
26712 generate_exception_end(ctx, EXCP_RI);
26713 break;
26714 case OPC_MXU_D32SARV:
26715 /* TODO: Implement emulation of D32SARV instruction. */
26716 MIPS_INVAL("OPC_MXU_D32SARV");
26717 generate_exception_end(ctx, EXCP_RI);
26718 break;
26719 case OPC_MXU_Q16SLLV:
26720 /* TODO: Implement emulation of Q16SLLV instruction. */
26721 MIPS_INVAL("OPC_MXU_Q16SLLV");
26722 generate_exception_end(ctx, EXCP_RI);
26723 break;
26724 case OPC_MXU_Q16SLRV:
26725 /* TODO: Implement emulation of Q16SLRV instruction. */
26726 MIPS_INVAL("OPC_MXU_Q16SLRV");
26727 generate_exception_end(ctx, EXCP_RI);
26728 break;
26729 case OPC_MXU_Q16SARV:
26730 /* TODO: Implement emulation of Q16SARV instruction. */
26731 MIPS_INVAL("OPC_MXU_Q16SARV");
26732 generate_exception_end(ctx, EXCP_RI);
26733 break;
26734 default:
26735 MIPS_INVAL("decode_opc_mxu");
26736 generate_exception_end(ctx, EXCP_RI);
26737 break;
26743 * Decode MXU pool19
26745 * 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
26746 * +-----------+---+---+-------+-------+-------+-------+-----------+
26747 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
26748 * +-----------+---+---+-------+-------+-------+-------+-----------+
26751 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
26753 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26755 switch (opcode) {
26756 case OPC_MXU_Q8MUL:
26757 case OPC_MXU_Q8MULSU:
26758 gen_mxu_q8mul_q8mulsu(ctx);
26759 break;
26760 default:
26761 MIPS_INVAL("decode_opc_mxu");
26762 generate_exception_end(ctx, EXCP_RI);
26763 break;
26769 * Decode MXU pool20
26771 * 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
26772 * +-----------+---------+-----+-------+-------+-------+-----------+
26773 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
26774 * +-----------+---------+-----+-------+-------+-------+-----------+
26777 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
26779 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26781 switch (opcode) {
26782 case OPC_MXU_Q8MOVZ:
26783 /* TODO: Implement emulation of Q8MOVZ instruction. */
26784 MIPS_INVAL("OPC_MXU_Q8MOVZ");
26785 generate_exception_end(ctx, EXCP_RI);
26786 break;
26787 case OPC_MXU_Q8MOVN:
26788 /* TODO: Implement emulation of Q8MOVN instruction. */
26789 MIPS_INVAL("OPC_MXU_Q8MOVN");
26790 generate_exception_end(ctx, EXCP_RI);
26791 break;
26792 case OPC_MXU_D16MOVZ:
26793 /* TODO: Implement emulation of D16MOVZ instruction. */
26794 MIPS_INVAL("OPC_MXU_D16MOVZ");
26795 generate_exception_end(ctx, EXCP_RI);
26796 break;
26797 case OPC_MXU_D16MOVN:
26798 /* TODO: Implement emulation of D16MOVN instruction. */
26799 MIPS_INVAL("OPC_MXU_D16MOVN");
26800 generate_exception_end(ctx, EXCP_RI);
26801 break;
26802 case OPC_MXU_S32MOVZ:
26803 /* TODO: Implement emulation of S32MOVZ instruction. */
26804 MIPS_INVAL("OPC_MXU_S32MOVZ");
26805 generate_exception_end(ctx, EXCP_RI);
26806 break;
26807 case OPC_MXU_S32MOVN:
26808 /* TODO: Implement emulation of S32MOVN instruction. */
26809 MIPS_INVAL("OPC_MXU_S32MOVN");
26810 generate_exception_end(ctx, EXCP_RI);
26811 break;
26812 default:
26813 MIPS_INVAL("decode_opc_mxu");
26814 generate_exception_end(ctx, EXCP_RI);
26815 break;
26821 * Decode MXU pool21
26823 * 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
26824 * +-----------+---+---+-------+-------+-------+-------+-----------+
26825 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
26826 * +-----------+---+---+-------+-------+-------+-------+-----------+
26829 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
26831 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26833 switch (opcode) {
26834 case OPC_MXU_Q8MAC:
26835 /* TODO: Implement emulation of Q8MAC instruction. */
26836 MIPS_INVAL("OPC_MXU_Q8MAC");
26837 generate_exception_end(ctx, EXCP_RI);
26838 break;
26839 case OPC_MXU_Q8MACSU:
26840 /* TODO: Implement emulation of Q8MACSU instruction. */
26841 MIPS_INVAL("OPC_MXU_Q8MACSU");
26842 generate_exception_end(ctx, EXCP_RI);
26843 break;
26844 default:
26845 MIPS_INVAL("decode_opc_mxu");
26846 generate_exception_end(ctx, EXCP_RI);
26847 break;
26853 * Main MXU decoding function
26855 * 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
26856 * +-----------+---------------------------------------+-----------+
26857 * | SPECIAL2 | |x x x x x x|
26858 * +-----------+---------------------------------------+-----------+
26861 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
26864 * TODO: Investigate necessity of including handling of
26865 * CLZ, CLO, SDBB in this function, as they belong to
26866 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
26868 uint32_t opcode = extract32(ctx->opcode, 0, 6);
26870 if (opcode == OPC__MXU_MUL) {
26871 uint32_t rs, rt, rd, op1;
26873 rs = extract32(ctx->opcode, 21, 5);
26874 rt = extract32(ctx->opcode, 16, 5);
26875 rd = extract32(ctx->opcode, 11, 5);
26876 op1 = MASK_SPECIAL2(ctx->opcode);
26878 gen_arith(ctx, op1, rd, rs, rt);
26880 return;
26883 if (opcode == OPC_MXU_S32M2I) {
26884 gen_mxu_s32m2i(ctx);
26885 return;
26888 if (opcode == OPC_MXU_S32I2M) {
26889 gen_mxu_s32i2m(ctx);
26890 return;
26894 TCGv t_mxu_cr = tcg_temp_new();
26895 TCGLabel *l_exit = gen_new_label();
26897 gen_load_mxu_cr(t_mxu_cr);
26898 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
26899 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
26901 switch (opcode) {
26902 case OPC_MXU_S32MADD:
26903 /* TODO: Implement emulation of S32MADD instruction. */
26904 MIPS_INVAL("OPC_MXU_S32MADD");
26905 generate_exception_end(ctx, EXCP_RI);
26906 break;
26907 case OPC_MXU_S32MADDU:
26908 /* TODO: Implement emulation of S32MADDU instruction. */
26909 MIPS_INVAL("OPC_MXU_S32MADDU");
26910 generate_exception_end(ctx, EXCP_RI);
26911 break;
26912 case OPC_MXU__POOL00:
26913 decode_opc_mxu__pool00(env, ctx);
26914 break;
26915 case OPC_MXU_S32MSUB:
26916 /* TODO: Implement emulation of S32MSUB instruction. */
26917 MIPS_INVAL("OPC_MXU_S32MSUB");
26918 generate_exception_end(ctx, EXCP_RI);
26919 break;
26920 case OPC_MXU_S32MSUBU:
26921 /* TODO: Implement emulation of S32MSUBU instruction. */
26922 MIPS_INVAL("OPC_MXU_S32MSUBU");
26923 generate_exception_end(ctx, EXCP_RI);
26924 break;
26925 case OPC_MXU__POOL01:
26926 decode_opc_mxu__pool01(env, ctx);
26927 break;
26928 case OPC_MXU__POOL02:
26929 decode_opc_mxu__pool02(env, ctx);
26930 break;
26931 case OPC_MXU_D16MUL:
26932 gen_mxu_d16mul(ctx);
26933 break;
26934 case OPC_MXU__POOL03:
26935 decode_opc_mxu__pool03(env, ctx);
26936 break;
26937 case OPC_MXU_D16MAC:
26938 gen_mxu_d16mac(ctx);
26939 break;
26940 case OPC_MXU_D16MACF:
26941 /* TODO: Implement emulation of D16MACF instruction. */
26942 MIPS_INVAL("OPC_MXU_D16MACF");
26943 generate_exception_end(ctx, EXCP_RI);
26944 break;
26945 case OPC_MXU_D16MADL:
26946 /* TODO: Implement emulation of D16MADL instruction. */
26947 MIPS_INVAL("OPC_MXU_D16MADL");
26948 generate_exception_end(ctx, EXCP_RI);
26949 break;
26950 case OPC_MXU_S16MAD:
26951 /* TODO: Implement emulation of S16MAD instruction. */
26952 MIPS_INVAL("OPC_MXU_S16MAD");
26953 generate_exception_end(ctx, EXCP_RI);
26954 break;
26955 case OPC_MXU_Q16ADD:
26956 /* TODO: Implement emulation of Q16ADD instruction. */
26957 MIPS_INVAL("OPC_MXU_Q16ADD");
26958 generate_exception_end(ctx, EXCP_RI);
26959 break;
26960 case OPC_MXU_D16MACE:
26961 /* TODO: Implement emulation of D16MACE instruction. */
26962 MIPS_INVAL("OPC_MXU_D16MACE");
26963 generate_exception_end(ctx, EXCP_RI);
26964 break;
26965 case OPC_MXU__POOL04:
26966 decode_opc_mxu__pool04(env, ctx);
26967 break;
26968 case OPC_MXU__POOL05:
26969 decode_opc_mxu__pool05(env, ctx);
26970 break;
26971 case OPC_MXU__POOL06:
26972 decode_opc_mxu__pool06(env, ctx);
26973 break;
26974 case OPC_MXU__POOL07:
26975 decode_opc_mxu__pool07(env, ctx);
26976 break;
26977 case OPC_MXU__POOL08:
26978 decode_opc_mxu__pool08(env, ctx);
26979 break;
26980 case OPC_MXU__POOL09:
26981 decode_opc_mxu__pool09(env, ctx);
26982 break;
26983 case OPC_MXU__POOL10:
26984 decode_opc_mxu__pool10(env, ctx);
26985 break;
26986 case OPC_MXU__POOL11:
26987 decode_opc_mxu__pool11(env, ctx);
26988 break;
26989 case OPC_MXU_D32ADD:
26990 /* TODO: Implement emulation of D32ADD instruction. */
26991 MIPS_INVAL("OPC_MXU_D32ADD");
26992 generate_exception_end(ctx, EXCP_RI);
26993 break;
26994 case OPC_MXU__POOL12:
26995 decode_opc_mxu__pool12(env, ctx);
26996 break;
26997 case OPC_MXU__POOL13:
26998 decode_opc_mxu__pool13(env, ctx);
26999 break;
27000 case OPC_MXU__POOL14:
27001 decode_opc_mxu__pool14(env, ctx);
27002 break;
27003 case OPC_MXU_Q8ACCE:
27004 /* TODO: Implement emulation of Q8ACCE instruction. */
27005 MIPS_INVAL("OPC_MXU_Q8ACCE");
27006 generate_exception_end(ctx, EXCP_RI);
27007 break;
27008 case OPC_MXU_S8LDD:
27009 gen_mxu_s8ldd(ctx);
27010 break;
27011 case OPC_MXU_S8STD:
27012 /* TODO: Implement emulation of S8STD instruction. */
27013 MIPS_INVAL("OPC_MXU_S8STD");
27014 generate_exception_end(ctx, EXCP_RI);
27015 break;
27016 case OPC_MXU_S8LDI:
27017 /* TODO: Implement emulation of S8LDI instruction. */
27018 MIPS_INVAL("OPC_MXU_S8LDI");
27019 generate_exception_end(ctx, EXCP_RI);
27020 break;
27021 case OPC_MXU_S8SDI:
27022 /* TODO: Implement emulation of S8SDI instruction. */
27023 MIPS_INVAL("OPC_MXU_S8SDI");
27024 generate_exception_end(ctx, EXCP_RI);
27025 break;
27026 case OPC_MXU__POOL15:
27027 decode_opc_mxu__pool15(env, ctx);
27028 break;
27029 case OPC_MXU__POOL16:
27030 decode_opc_mxu__pool16(env, ctx);
27031 break;
27032 case OPC_MXU__POOL17:
27033 decode_opc_mxu__pool17(env, ctx);
27034 break;
27035 case OPC_MXU_S16LDD:
27036 /* TODO: Implement emulation of S16LDD instruction. */
27037 MIPS_INVAL("OPC_MXU_S16LDD");
27038 generate_exception_end(ctx, EXCP_RI);
27039 break;
27040 case OPC_MXU_S16STD:
27041 /* TODO: Implement emulation of S16STD instruction. */
27042 MIPS_INVAL("OPC_MXU_S16STD");
27043 generate_exception_end(ctx, EXCP_RI);
27044 break;
27045 case OPC_MXU_S16LDI:
27046 /* TODO: Implement emulation of S16LDI instruction. */
27047 MIPS_INVAL("OPC_MXU_S16LDI");
27048 generate_exception_end(ctx, EXCP_RI);
27049 break;
27050 case OPC_MXU_S16SDI:
27051 /* TODO: Implement emulation of S16SDI instruction. */
27052 MIPS_INVAL("OPC_MXU_S16SDI");
27053 generate_exception_end(ctx, EXCP_RI);
27054 break;
27055 case OPC_MXU_D32SLL:
27056 /* TODO: Implement emulation of D32SLL instruction. */
27057 MIPS_INVAL("OPC_MXU_D32SLL");
27058 generate_exception_end(ctx, EXCP_RI);
27059 break;
27060 case OPC_MXU_D32SLR:
27061 /* TODO: Implement emulation of D32SLR instruction. */
27062 MIPS_INVAL("OPC_MXU_D32SLR");
27063 generate_exception_end(ctx, EXCP_RI);
27064 break;
27065 case OPC_MXU_D32SARL:
27066 /* TODO: Implement emulation of D32SARL instruction. */
27067 MIPS_INVAL("OPC_MXU_D32SARL");
27068 generate_exception_end(ctx, EXCP_RI);
27069 break;
27070 case OPC_MXU_D32SAR:
27071 /* TODO: Implement emulation of D32SAR instruction. */
27072 MIPS_INVAL("OPC_MXU_D32SAR");
27073 generate_exception_end(ctx, EXCP_RI);
27074 break;
27075 case OPC_MXU_Q16SLL:
27076 /* TODO: Implement emulation of Q16SLL instruction. */
27077 MIPS_INVAL("OPC_MXU_Q16SLL");
27078 generate_exception_end(ctx, EXCP_RI);
27079 break;
27080 case OPC_MXU_Q16SLR:
27081 /* TODO: Implement emulation of Q16SLR instruction. */
27082 MIPS_INVAL("OPC_MXU_Q16SLR");
27083 generate_exception_end(ctx, EXCP_RI);
27084 break;
27085 case OPC_MXU__POOL18:
27086 decode_opc_mxu__pool18(env, ctx);
27087 break;
27088 case OPC_MXU_Q16SAR:
27089 /* TODO: Implement emulation of Q16SAR instruction. */
27090 MIPS_INVAL("OPC_MXU_Q16SAR");
27091 generate_exception_end(ctx, EXCP_RI);
27092 break;
27093 case OPC_MXU__POOL19:
27094 decode_opc_mxu__pool19(env, ctx);
27095 break;
27096 case OPC_MXU__POOL20:
27097 decode_opc_mxu__pool20(env, ctx);
27098 break;
27099 case OPC_MXU__POOL21:
27100 decode_opc_mxu__pool21(env, ctx);
27101 break;
27102 case OPC_MXU_Q16SCOP:
27103 /* TODO: Implement emulation of Q16SCOP instruction. */
27104 MIPS_INVAL("OPC_MXU_Q16SCOP");
27105 generate_exception_end(ctx, EXCP_RI);
27106 break;
27107 case OPC_MXU_Q8MADL:
27108 /* TODO: Implement emulation of Q8MADL instruction. */
27109 MIPS_INVAL("OPC_MXU_Q8MADL");
27110 generate_exception_end(ctx, EXCP_RI);
27111 break;
27112 case OPC_MXU_S32SFL:
27113 /* TODO: Implement emulation of S32SFL instruction. */
27114 MIPS_INVAL("OPC_MXU_S32SFL");
27115 generate_exception_end(ctx, EXCP_RI);
27116 break;
27117 case OPC_MXU_Q8SAD:
27118 /* TODO: Implement emulation of Q8SAD instruction. */
27119 MIPS_INVAL("OPC_MXU_Q8SAD");
27120 generate_exception_end(ctx, EXCP_RI);
27121 break;
27122 default:
27123 MIPS_INVAL("decode_opc_mxu");
27124 generate_exception_end(ctx, EXCP_RI);
27127 gen_set_label(l_exit);
27128 tcg_temp_free(t_mxu_cr);
27132 #endif /* !defined(TARGET_MIPS64) */
27135 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27137 int rs, rt, rd;
27138 uint32_t op1;
27140 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27142 rs = (ctx->opcode >> 21) & 0x1f;
27143 rt = (ctx->opcode >> 16) & 0x1f;
27144 rd = (ctx->opcode >> 11) & 0x1f;
27146 op1 = MASK_SPECIAL2(ctx->opcode);
27147 switch (op1) {
27148 case OPC_MADD: /* Multiply and add/sub */
27149 case OPC_MADDU:
27150 case OPC_MSUB:
27151 case OPC_MSUBU:
27152 check_insn(ctx, ISA_MIPS32);
27153 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27154 break;
27155 case OPC_MUL:
27156 gen_arith(ctx, op1, rd, rs, rt);
27157 break;
27158 case OPC_DIV_G_2F:
27159 case OPC_DIVU_G_2F:
27160 case OPC_MULT_G_2F:
27161 case OPC_MULTU_G_2F:
27162 case OPC_MOD_G_2F:
27163 case OPC_MODU_G_2F:
27164 check_insn(ctx, INSN_LOONGSON2F);
27165 gen_loongson_integer(ctx, op1, rd, rs, rt);
27166 break;
27167 case OPC_CLO:
27168 case OPC_CLZ:
27169 check_insn(ctx, ISA_MIPS32);
27170 gen_cl(ctx, op1, rd, rs);
27171 break;
27172 case OPC_SDBBP:
27173 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27174 gen_helper_do_semihosting(cpu_env);
27175 } else {
27177 * XXX: not clear which exception should be raised
27178 * when in debug mode...
27180 check_insn(ctx, ISA_MIPS32);
27181 generate_exception_end(ctx, EXCP_DBp);
27183 break;
27184 #if defined(TARGET_MIPS64)
27185 case OPC_DCLO:
27186 case OPC_DCLZ:
27187 check_insn(ctx, ISA_MIPS64);
27188 check_mips_64(ctx);
27189 gen_cl(ctx, op1, rd, rs);
27190 break;
27191 case OPC_DMULT_G_2F:
27192 case OPC_DMULTU_G_2F:
27193 case OPC_DDIV_G_2F:
27194 case OPC_DDIVU_G_2F:
27195 case OPC_DMOD_G_2F:
27196 case OPC_DMODU_G_2F:
27197 check_insn(ctx, INSN_LOONGSON2F);
27198 gen_loongson_integer(ctx, op1, rd, rs, rt);
27199 break;
27200 #endif
27201 default: /* Invalid */
27202 MIPS_INVAL("special2_legacy");
27203 generate_exception_end(ctx, EXCP_RI);
27204 break;
27208 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27210 int rs, rt, rd, sa;
27211 uint32_t op1, op2;
27212 int16_t imm;
27214 rs = (ctx->opcode >> 21) & 0x1f;
27215 rt = (ctx->opcode >> 16) & 0x1f;
27216 rd = (ctx->opcode >> 11) & 0x1f;
27217 sa = (ctx->opcode >> 6) & 0x1f;
27218 imm = (int16_t)ctx->opcode >> 7;
27220 op1 = MASK_SPECIAL3(ctx->opcode);
27221 switch (op1) {
27222 case R6_OPC_PREF:
27223 if (rt >= 24) {
27224 /* hint codes 24-31 are reserved and signal RI */
27225 generate_exception_end(ctx, EXCP_RI);
27227 /* Treat as NOP. */
27228 break;
27229 case R6_OPC_CACHE:
27230 check_cp0_enabled(ctx);
27231 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27232 gen_cache_operation(ctx, rt, rs, imm);
27234 break;
27235 case R6_OPC_SC:
27236 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27237 break;
27238 case R6_OPC_LL:
27239 gen_ld(ctx, op1, rt, rs, imm);
27240 break;
27241 case OPC_BSHFL:
27243 if (rd == 0) {
27244 /* Treat as NOP. */
27245 break;
27247 op2 = MASK_BSHFL(ctx->opcode);
27248 switch (op2) {
27249 case OPC_ALIGN:
27250 case OPC_ALIGN_1:
27251 case OPC_ALIGN_2:
27252 case OPC_ALIGN_3:
27253 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27254 break;
27255 case OPC_BITSWAP:
27256 gen_bitswap(ctx, op2, rd, rt);
27257 break;
27260 break;
27261 #ifndef CONFIG_USER_ONLY
27262 case OPC_GINV:
27263 if (unlikely(ctx->gi <= 1)) {
27264 generate_exception_end(ctx, EXCP_RI);
27266 check_cp0_enabled(ctx);
27267 switch ((ctx->opcode >> 6) & 3) {
27268 case 0: /* GINVI */
27269 /* Treat as NOP. */
27270 break;
27271 case 2: /* GINVT */
27272 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27273 break;
27274 default:
27275 generate_exception_end(ctx, EXCP_RI);
27276 break;
27278 break;
27279 #endif
27280 #if defined(TARGET_MIPS64)
27281 case R6_OPC_SCD:
27282 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27283 break;
27284 case R6_OPC_LLD:
27285 gen_ld(ctx, op1, rt, rs, imm);
27286 break;
27287 case OPC_DBSHFL:
27288 check_mips_64(ctx);
27290 if (rd == 0) {
27291 /* Treat as NOP. */
27292 break;
27294 op2 = MASK_DBSHFL(ctx->opcode);
27295 switch (op2) {
27296 case OPC_DALIGN:
27297 case OPC_DALIGN_1:
27298 case OPC_DALIGN_2:
27299 case OPC_DALIGN_3:
27300 case OPC_DALIGN_4:
27301 case OPC_DALIGN_5:
27302 case OPC_DALIGN_6:
27303 case OPC_DALIGN_7:
27304 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27305 break;
27306 case OPC_DBITSWAP:
27307 gen_bitswap(ctx, op2, rd, rt);
27308 break;
27312 break;
27313 #endif
27314 default: /* Invalid */
27315 MIPS_INVAL("special3_r6");
27316 generate_exception_end(ctx, EXCP_RI);
27317 break;
27321 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27323 int rs, rt, rd;
27324 uint32_t op1, op2;
27326 rs = (ctx->opcode >> 21) & 0x1f;
27327 rt = (ctx->opcode >> 16) & 0x1f;
27328 rd = (ctx->opcode >> 11) & 0x1f;
27330 op1 = MASK_SPECIAL3(ctx->opcode);
27331 switch (op1) {
27332 case OPC_DIV_G_2E:
27333 case OPC_DIVU_G_2E:
27334 case OPC_MOD_G_2E:
27335 case OPC_MODU_G_2E:
27336 case OPC_MULT_G_2E:
27337 case OPC_MULTU_G_2E:
27339 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27340 * the same mask and op1.
27342 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27343 op2 = MASK_ADDUH_QB(ctx->opcode);
27344 switch (op2) {
27345 case OPC_ADDUH_QB:
27346 case OPC_ADDUH_R_QB:
27347 case OPC_ADDQH_PH:
27348 case OPC_ADDQH_R_PH:
27349 case OPC_ADDQH_W:
27350 case OPC_ADDQH_R_W:
27351 case OPC_SUBUH_QB:
27352 case OPC_SUBUH_R_QB:
27353 case OPC_SUBQH_PH:
27354 case OPC_SUBQH_R_PH:
27355 case OPC_SUBQH_W:
27356 case OPC_SUBQH_R_W:
27357 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27358 break;
27359 case OPC_MUL_PH:
27360 case OPC_MUL_S_PH:
27361 case OPC_MULQ_S_W:
27362 case OPC_MULQ_RS_W:
27363 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27364 break;
27365 default:
27366 MIPS_INVAL("MASK ADDUH.QB");
27367 generate_exception_end(ctx, EXCP_RI);
27368 break;
27370 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27371 gen_loongson_integer(ctx, op1, rd, rs, rt);
27372 } else {
27373 generate_exception_end(ctx, EXCP_RI);
27375 break;
27376 case OPC_LX_DSP:
27377 op2 = MASK_LX(ctx->opcode);
27378 switch (op2) {
27379 #if defined(TARGET_MIPS64)
27380 case OPC_LDX:
27381 #endif
27382 case OPC_LBUX:
27383 case OPC_LHX:
27384 case OPC_LWX:
27385 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27386 break;
27387 default: /* Invalid */
27388 MIPS_INVAL("MASK LX");
27389 generate_exception_end(ctx, EXCP_RI);
27390 break;
27392 break;
27393 case OPC_ABSQ_S_PH_DSP:
27394 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27395 switch (op2) {
27396 case OPC_ABSQ_S_QB:
27397 case OPC_ABSQ_S_PH:
27398 case OPC_ABSQ_S_W:
27399 case OPC_PRECEQ_W_PHL:
27400 case OPC_PRECEQ_W_PHR:
27401 case OPC_PRECEQU_PH_QBL:
27402 case OPC_PRECEQU_PH_QBR:
27403 case OPC_PRECEQU_PH_QBLA:
27404 case OPC_PRECEQU_PH_QBRA:
27405 case OPC_PRECEU_PH_QBL:
27406 case OPC_PRECEU_PH_QBR:
27407 case OPC_PRECEU_PH_QBLA:
27408 case OPC_PRECEU_PH_QBRA:
27409 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27410 break;
27411 case OPC_BITREV:
27412 case OPC_REPL_QB:
27413 case OPC_REPLV_QB:
27414 case OPC_REPL_PH:
27415 case OPC_REPLV_PH:
27416 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27417 break;
27418 default:
27419 MIPS_INVAL("MASK ABSQ_S.PH");
27420 generate_exception_end(ctx, EXCP_RI);
27421 break;
27423 break;
27424 case OPC_ADDU_QB_DSP:
27425 op2 = MASK_ADDU_QB(ctx->opcode);
27426 switch (op2) {
27427 case OPC_ADDQ_PH:
27428 case OPC_ADDQ_S_PH:
27429 case OPC_ADDQ_S_W:
27430 case OPC_ADDU_QB:
27431 case OPC_ADDU_S_QB:
27432 case OPC_ADDU_PH:
27433 case OPC_ADDU_S_PH:
27434 case OPC_SUBQ_PH:
27435 case OPC_SUBQ_S_PH:
27436 case OPC_SUBQ_S_W:
27437 case OPC_SUBU_QB:
27438 case OPC_SUBU_S_QB:
27439 case OPC_SUBU_PH:
27440 case OPC_SUBU_S_PH:
27441 case OPC_ADDSC:
27442 case OPC_ADDWC:
27443 case OPC_MODSUB:
27444 case OPC_RADDU_W_QB:
27445 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27446 break;
27447 case OPC_MULEU_S_PH_QBL:
27448 case OPC_MULEU_S_PH_QBR:
27449 case OPC_MULQ_RS_PH:
27450 case OPC_MULEQ_S_W_PHL:
27451 case OPC_MULEQ_S_W_PHR:
27452 case OPC_MULQ_S_PH:
27453 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27454 break;
27455 default: /* Invalid */
27456 MIPS_INVAL("MASK ADDU.QB");
27457 generate_exception_end(ctx, EXCP_RI);
27458 break;
27461 break;
27462 case OPC_CMPU_EQ_QB_DSP:
27463 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27464 switch (op2) {
27465 case OPC_PRECR_SRA_PH_W:
27466 case OPC_PRECR_SRA_R_PH_W:
27467 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27468 break;
27469 case OPC_PRECR_QB_PH:
27470 case OPC_PRECRQ_QB_PH:
27471 case OPC_PRECRQ_PH_W:
27472 case OPC_PRECRQ_RS_PH_W:
27473 case OPC_PRECRQU_S_QB_PH:
27474 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27475 break;
27476 case OPC_CMPU_EQ_QB:
27477 case OPC_CMPU_LT_QB:
27478 case OPC_CMPU_LE_QB:
27479 case OPC_CMP_EQ_PH:
27480 case OPC_CMP_LT_PH:
27481 case OPC_CMP_LE_PH:
27482 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27483 break;
27484 case OPC_CMPGU_EQ_QB:
27485 case OPC_CMPGU_LT_QB:
27486 case OPC_CMPGU_LE_QB:
27487 case OPC_CMPGDU_EQ_QB:
27488 case OPC_CMPGDU_LT_QB:
27489 case OPC_CMPGDU_LE_QB:
27490 case OPC_PICK_QB:
27491 case OPC_PICK_PH:
27492 case OPC_PACKRL_PH:
27493 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27494 break;
27495 default: /* Invalid */
27496 MIPS_INVAL("MASK CMPU.EQ.QB");
27497 generate_exception_end(ctx, EXCP_RI);
27498 break;
27500 break;
27501 case OPC_SHLL_QB_DSP:
27502 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27503 break;
27504 case OPC_DPA_W_PH_DSP:
27505 op2 = MASK_DPA_W_PH(ctx->opcode);
27506 switch (op2) {
27507 case OPC_DPAU_H_QBL:
27508 case OPC_DPAU_H_QBR:
27509 case OPC_DPSU_H_QBL:
27510 case OPC_DPSU_H_QBR:
27511 case OPC_DPA_W_PH:
27512 case OPC_DPAX_W_PH:
27513 case OPC_DPAQ_S_W_PH:
27514 case OPC_DPAQX_S_W_PH:
27515 case OPC_DPAQX_SA_W_PH:
27516 case OPC_DPS_W_PH:
27517 case OPC_DPSX_W_PH:
27518 case OPC_DPSQ_S_W_PH:
27519 case OPC_DPSQX_S_W_PH:
27520 case OPC_DPSQX_SA_W_PH:
27521 case OPC_MULSAQ_S_W_PH:
27522 case OPC_DPAQ_SA_L_W:
27523 case OPC_DPSQ_SA_L_W:
27524 case OPC_MAQ_S_W_PHL:
27525 case OPC_MAQ_S_W_PHR:
27526 case OPC_MAQ_SA_W_PHL:
27527 case OPC_MAQ_SA_W_PHR:
27528 case OPC_MULSA_W_PH:
27529 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27530 break;
27531 default: /* Invalid */
27532 MIPS_INVAL("MASK DPAW.PH");
27533 generate_exception_end(ctx, EXCP_RI);
27534 break;
27536 break;
27537 case OPC_INSV_DSP:
27538 op2 = MASK_INSV(ctx->opcode);
27539 switch (op2) {
27540 case OPC_INSV:
27541 check_dsp(ctx);
27543 TCGv t0, t1;
27545 if (rt == 0) {
27546 break;
27549 t0 = tcg_temp_new();
27550 t1 = tcg_temp_new();
27552 gen_load_gpr(t0, rt);
27553 gen_load_gpr(t1, rs);
27555 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27557 tcg_temp_free(t0);
27558 tcg_temp_free(t1);
27559 break;
27561 default: /* Invalid */
27562 MIPS_INVAL("MASK INSV");
27563 generate_exception_end(ctx, EXCP_RI);
27564 break;
27566 break;
27567 case OPC_APPEND_DSP:
27568 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27569 break;
27570 case OPC_EXTR_W_DSP:
27571 op2 = MASK_EXTR_W(ctx->opcode);
27572 switch (op2) {
27573 case OPC_EXTR_W:
27574 case OPC_EXTR_R_W:
27575 case OPC_EXTR_RS_W:
27576 case OPC_EXTR_S_H:
27577 case OPC_EXTRV_S_H:
27578 case OPC_EXTRV_W:
27579 case OPC_EXTRV_R_W:
27580 case OPC_EXTRV_RS_W:
27581 case OPC_EXTP:
27582 case OPC_EXTPV:
27583 case OPC_EXTPDP:
27584 case OPC_EXTPDPV:
27585 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27586 break;
27587 case OPC_RDDSP:
27588 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27589 break;
27590 case OPC_SHILO:
27591 case OPC_SHILOV:
27592 case OPC_MTHLIP:
27593 case OPC_WRDSP:
27594 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27595 break;
27596 default: /* Invalid */
27597 MIPS_INVAL("MASK EXTR.W");
27598 generate_exception_end(ctx, EXCP_RI);
27599 break;
27601 break;
27602 #if defined(TARGET_MIPS64)
27603 case OPC_DDIV_G_2E:
27604 case OPC_DDIVU_G_2E:
27605 case OPC_DMULT_G_2E:
27606 case OPC_DMULTU_G_2E:
27607 case OPC_DMOD_G_2E:
27608 case OPC_DMODU_G_2E:
27609 check_insn(ctx, INSN_LOONGSON2E);
27610 gen_loongson_integer(ctx, op1, rd, rs, rt);
27611 break;
27612 case OPC_ABSQ_S_QH_DSP:
27613 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27614 switch (op2) {
27615 case OPC_PRECEQ_L_PWL:
27616 case OPC_PRECEQ_L_PWR:
27617 case OPC_PRECEQ_PW_QHL:
27618 case OPC_PRECEQ_PW_QHR:
27619 case OPC_PRECEQ_PW_QHLA:
27620 case OPC_PRECEQ_PW_QHRA:
27621 case OPC_PRECEQU_QH_OBL:
27622 case OPC_PRECEQU_QH_OBR:
27623 case OPC_PRECEQU_QH_OBLA:
27624 case OPC_PRECEQU_QH_OBRA:
27625 case OPC_PRECEU_QH_OBL:
27626 case OPC_PRECEU_QH_OBR:
27627 case OPC_PRECEU_QH_OBLA:
27628 case OPC_PRECEU_QH_OBRA:
27629 case OPC_ABSQ_S_OB:
27630 case OPC_ABSQ_S_PW:
27631 case OPC_ABSQ_S_QH:
27632 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27633 break;
27634 case OPC_REPL_OB:
27635 case OPC_REPL_PW:
27636 case OPC_REPL_QH:
27637 case OPC_REPLV_OB:
27638 case OPC_REPLV_PW:
27639 case OPC_REPLV_QH:
27640 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27641 break;
27642 default: /* Invalid */
27643 MIPS_INVAL("MASK ABSQ_S.QH");
27644 generate_exception_end(ctx, EXCP_RI);
27645 break;
27647 break;
27648 case OPC_ADDU_OB_DSP:
27649 op2 = MASK_ADDU_OB(ctx->opcode);
27650 switch (op2) {
27651 case OPC_RADDU_L_OB:
27652 case OPC_SUBQ_PW:
27653 case OPC_SUBQ_S_PW:
27654 case OPC_SUBQ_QH:
27655 case OPC_SUBQ_S_QH:
27656 case OPC_SUBU_OB:
27657 case OPC_SUBU_S_OB:
27658 case OPC_SUBU_QH:
27659 case OPC_SUBU_S_QH:
27660 case OPC_SUBUH_OB:
27661 case OPC_SUBUH_R_OB:
27662 case OPC_ADDQ_PW:
27663 case OPC_ADDQ_S_PW:
27664 case OPC_ADDQ_QH:
27665 case OPC_ADDQ_S_QH:
27666 case OPC_ADDU_OB:
27667 case OPC_ADDU_S_OB:
27668 case OPC_ADDU_QH:
27669 case OPC_ADDU_S_QH:
27670 case OPC_ADDUH_OB:
27671 case OPC_ADDUH_R_OB:
27672 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27673 break;
27674 case OPC_MULEQ_S_PW_QHL:
27675 case OPC_MULEQ_S_PW_QHR:
27676 case OPC_MULEU_S_QH_OBL:
27677 case OPC_MULEU_S_QH_OBR:
27678 case OPC_MULQ_RS_QH:
27679 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27680 break;
27681 default: /* Invalid */
27682 MIPS_INVAL("MASK ADDU.OB");
27683 generate_exception_end(ctx, EXCP_RI);
27684 break;
27686 break;
27687 case OPC_CMPU_EQ_OB_DSP:
27688 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27689 switch (op2) {
27690 case OPC_PRECR_SRA_QH_PW:
27691 case OPC_PRECR_SRA_R_QH_PW:
27692 /* Return value is rt. */
27693 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27694 break;
27695 case OPC_PRECR_OB_QH:
27696 case OPC_PRECRQ_OB_QH:
27697 case OPC_PRECRQ_PW_L:
27698 case OPC_PRECRQ_QH_PW:
27699 case OPC_PRECRQ_RS_QH_PW:
27700 case OPC_PRECRQU_S_OB_QH:
27701 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27702 break;
27703 case OPC_CMPU_EQ_OB:
27704 case OPC_CMPU_LT_OB:
27705 case OPC_CMPU_LE_OB:
27706 case OPC_CMP_EQ_QH:
27707 case OPC_CMP_LT_QH:
27708 case OPC_CMP_LE_QH:
27709 case OPC_CMP_EQ_PW:
27710 case OPC_CMP_LT_PW:
27711 case OPC_CMP_LE_PW:
27712 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27713 break;
27714 case OPC_CMPGDU_EQ_OB:
27715 case OPC_CMPGDU_LT_OB:
27716 case OPC_CMPGDU_LE_OB:
27717 case OPC_CMPGU_EQ_OB:
27718 case OPC_CMPGU_LT_OB:
27719 case OPC_CMPGU_LE_OB:
27720 case OPC_PACKRL_PW:
27721 case OPC_PICK_OB:
27722 case OPC_PICK_PW:
27723 case OPC_PICK_QH:
27724 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27725 break;
27726 default: /* Invalid */
27727 MIPS_INVAL("MASK CMPU_EQ.OB");
27728 generate_exception_end(ctx, EXCP_RI);
27729 break;
27731 break;
27732 case OPC_DAPPEND_DSP:
27733 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27734 break;
27735 case OPC_DEXTR_W_DSP:
27736 op2 = MASK_DEXTR_W(ctx->opcode);
27737 switch (op2) {
27738 case OPC_DEXTP:
27739 case OPC_DEXTPDP:
27740 case OPC_DEXTPDPV:
27741 case OPC_DEXTPV:
27742 case OPC_DEXTR_L:
27743 case OPC_DEXTR_R_L:
27744 case OPC_DEXTR_RS_L:
27745 case OPC_DEXTR_W:
27746 case OPC_DEXTR_R_W:
27747 case OPC_DEXTR_RS_W:
27748 case OPC_DEXTR_S_H:
27749 case OPC_DEXTRV_L:
27750 case OPC_DEXTRV_R_L:
27751 case OPC_DEXTRV_RS_L:
27752 case OPC_DEXTRV_S_H:
27753 case OPC_DEXTRV_W:
27754 case OPC_DEXTRV_R_W:
27755 case OPC_DEXTRV_RS_W:
27756 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27757 break;
27758 case OPC_DMTHLIP:
27759 case OPC_DSHILO:
27760 case OPC_DSHILOV:
27761 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27762 break;
27763 default: /* Invalid */
27764 MIPS_INVAL("MASK EXTR.W");
27765 generate_exception_end(ctx, EXCP_RI);
27766 break;
27768 break;
27769 case OPC_DPAQ_W_QH_DSP:
27770 op2 = MASK_DPAQ_W_QH(ctx->opcode);
27771 switch (op2) {
27772 case OPC_DPAU_H_OBL:
27773 case OPC_DPAU_H_OBR:
27774 case OPC_DPSU_H_OBL:
27775 case OPC_DPSU_H_OBR:
27776 case OPC_DPA_W_QH:
27777 case OPC_DPAQ_S_W_QH:
27778 case OPC_DPS_W_QH:
27779 case OPC_DPSQ_S_W_QH:
27780 case OPC_MULSAQ_S_W_QH:
27781 case OPC_DPAQ_SA_L_PW:
27782 case OPC_DPSQ_SA_L_PW:
27783 case OPC_MULSAQ_S_L_PW:
27784 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27785 break;
27786 case OPC_MAQ_S_W_QHLL:
27787 case OPC_MAQ_S_W_QHLR:
27788 case OPC_MAQ_S_W_QHRL:
27789 case OPC_MAQ_S_W_QHRR:
27790 case OPC_MAQ_SA_W_QHLL:
27791 case OPC_MAQ_SA_W_QHLR:
27792 case OPC_MAQ_SA_W_QHRL:
27793 case OPC_MAQ_SA_W_QHRR:
27794 case OPC_MAQ_S_L_PWL:
27795 case OPC_MAQ_S_L_PWR:
27796 case OPC_DMADD:
27797 case OPC_DMADDU:
27798 case OPC_DMSUB:
27799 case OPC_DMSUBU:
27800 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27801 break;
27802 default: /* Invalid */
27803 MIPS_INVAL("MASK DPAQ.W.QH");
27804 generate_exception_end(ctx, EXCP_RI);
27805 break;
27807 break;
27808 case OPC_DINSV_DSP:
27809 op2 = MASK_INSV(ctx->opcode);
27810 switch (op2) {
27811 case OPC_DINSV:
27813 TCGv t0, t1;
27815 if (rt == 0) {
27816 break;
27818 check_dsp(ctx);
27820 t0 = tcg_temp_new();
27821 t1 = tcg_temp_new();
27823 gen_load_gpr(t0, rt);
27824 gen_load_gpr(t1, rs);
27826 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
27828 tcg_temp_free(t0);
27829 tcg_temp_free(t1);
27830 break;
27832 default: /* Invalid */
27833 MIPS_INVAL("MASK DINSV");
27834 generate_exception_end(ctx, EXCP_RI);
27835 break;
27837 break;
27838 case OPC_SHLL_OB_DSP:
27839 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27840 break;
27841 #endif
27842 default: /* Invalid */
27843 MIPS_INVAL("special3_legacy");
27844 generate_exception_end(ctx, EXCP_RI);
27845 break;
27850 #if defined(TARGET_MIPS64)
27852 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
27854 uint32_t opc = MASK_MMI0(ctx->opcode);
27856 switch (opc) {
27857 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
27858 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
27859 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
27860 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
27861 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
27862 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
27863 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
27864 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
27865 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
27866 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
27867 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
27868 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
27869 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
27870 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
27871 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
27872 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
27873 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
27874 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
27875 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
27876 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
27877 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
27878 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
27879 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
27880 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
27881 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
27882 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
27883 break;
27884 default:
27885 MIPS_INVAL("TX79 MMI class MMI0");
27886 generate_exception_end(ctx, EXCP_RI);
27887 break;
27891 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
27893 uint32_t opc = MASK_MMI1(ctx->opcode);
27895 switch (opc) {
27896 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
27897 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
27898 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
27899 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
27900 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
27901 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
27902 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
27903 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
27904 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
27905 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
27906 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
27907 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
27908 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
27909 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
27910 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
27911 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
27912 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
27913 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
27914 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
27915 break;
27916 default:
27917 MIPS_INVAL("TX79 MMI class MMI1");
27918 generate_exception_end(ctx, EXCP_RI);
27919 break;
27923 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
27925 uint32_t opc = MASK_MMI2(ctx->opcode);
27927 switch (opc) {
27928 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
27929 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
27930 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
27931 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
27932 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
27933 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
27934 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
27935 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
27936 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
27937 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
27938 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
27939 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
27940 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
27941 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
27942 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
27943 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
27944 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
27945 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
27946 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
27947 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
27948 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
27949 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
27950 break;
27951 case MMI_OPC_2_PCPYLD:
27952 gen_mmi_pcpyld(ctx);
27953 break;
27954 default:
27955 MIPS_INVAL("TX79 MMI class MMI2");
27956 generate_exception_end(ctx, EXCP_RI);
27957 break;
27961 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
27963 uint32_t opc = MASK_MMI3(ctx->opcode);
27965 switch (opc) {
27966 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
27967 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
27968 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
27969 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
27970 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
27971 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
27972 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
27973 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
27974 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
27975 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
27976 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
27977 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
27978 break;
27979 case MMI_OPC_3_PCPYH:
27980 gen_mmi_pcpyh(ctx);
27981 break;
27982 case MMI_OPC_3_PCPYUD:
27983 gen_mmi_pcpyud(ctx);
27984 break;
27985 default:
27986 MIPS_INVAL("TX79 MMI class MMI3");
27987 generate_exception_end(ctx, EXCP_RI);
27988 break;
27992 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
27994 uint32_t opc = MASK_MMI(ctx->opcode);
27995 int rs = extract32(ctx->opcode, 21, 5);
27996 int rt = extract32(ctx->opcode, 16, 5);
27997 int rd = extract32(ctx->opcode, 11, 5);
27999 switch (opc) {
28000 case MMI_OPC_CLASS_MMI0:
28001 decode_mmi0(env, ctx);
28002 break;
28003 case MMI_OPC_CLASS_MMI1:
28004 decode_mmi1(env, ctx);
28005 break;
28006 case MMI_OPC_CLASS_MMI2:
28007 decode_mmi2(env, ctx);
28008 break;
28009 case MMI_OPC_CLASS_MMI3:
28010 decode_mmi3(env, ctx);
28011 break;
28012 case MMI_OPC_MULT1:
28013 case MMI_OPC_MULTU1:
28014 case MMI_OPC_MADD:
28015 case MMI_OPC_MADDU:
28016 case MMI_OPC_MADD1:
28017 case MMI_OPC_MADDU1:
28018 gen_mul_txx9(ctx, opc, rd, rs, rt);
28019 break;
28020 case MMI_OPC_DIV1:
28021 case MMI_OPC_DIVU1:
28022 gen_div1_tx79(ctx, opc, rs, rt);
28023 break;
28024 case MMI_OPC_MTLO1:
28025 case MMI_OPC_MTHI1:
28026 gen_HILO1_tx79(ctx, opc, rs);
28027 break;
28028 case MMI_OPC_MFLO1:
28029 case MMI_OPC_MFHI1:
28030 gen_HILO1_tx79(ctx, opc, rd);
28031 break;
28032 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28033 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28034 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28035 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28036 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28037 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28038 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28039 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28040 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28041 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
28042 break;
28043 default:
28044 MIPS_INVAL("TX79 MMI class");
28045 generate_exception_end(ctx, EXCP_RI);
28046 break;
28050 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28052 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
28055 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28057 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
28061 * The TX79-specific instruction Store Quadword
28063 * +--------+-------+-------+------------------------+
28064 * | 011111 | base | rt | offset | SQ
28065 * +--------+-------+-------+------------------------+
28066 * 6 5 5 16
28068 * has the same opcode as the Read Hardware Register instruction
28070 * +--------+-------+-------+-------+-------+--------+
28071 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28072 * +--------+-------+-------+-------+-------+--------+
28073 * 6 5 5 5 5 6
28075 * that is required, trapped and emulated by the Linux kernel. However, all
28076 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28077 * offset is odd. Therefore all valid SQ instructions can execute normally.
28078 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28079 * between SQ and RDHWR, as the Linux kernel does.
28081 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28083 int base = extract32(ctx->opcode, 21, 5);
28084 int rt = extract32(ctx->opcode, 16, 5);
28085 int offset = extract32(ctx->opcode, 0, 16);
28087 #ifdef CONFIG_USER_ONLY
28088 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28089 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28091 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28092 int rd = extract32(ctx->opcode, 11, 5);
28094 gen_rdhwr(ctx, rt, rd, 0);
28095 return;
28097 #endif
28099 gen_mmi_sq(ctx, base, rt, offset);
28102 #endif
28104 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28106 int rs, rt, rd, sa;
28107 uint32_t op1, op2;
28108 int16_t imm;
28110 rs = (ctx->opcode >> 21) & 0x1f;
28111 rt = (ctx->opcode >> 16) & 0x1f;
28112 rd = (ctx->opcode >> 11) & 0x1f;
28113 sa = (ctx->opcode >> 6) & 0x1f;
28114 imm = sextract32(ctx->opcode, 7, 9);
28116 op1 = MASK_SPECIAL3(ctx->opcode);
28119 * EVA loads and stores overlap Loongson 2E instructions decoded by
28120 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28121 * EVA is absent.
28123 if (ctx->eva) {
28124 switch (op1) {
28125 case OPC_LWLE:
28126 case OPC_LWRE:
28127 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28128 /* fall through */
28129 case OPC_LBUE:
28130 case OPC_LHUE:
28131 case OPC_LBE:
28132 case OPC_LHE:
28133 case OPC_LLE:
28134 case OPC_LWE:
28135 check_cp0_enabled(ctx);
28136 gen_ld(ctx, op1, rt, rs, imm);
28137 return;
28138 case OPC_SWLE:
28139 case OPC_SWRE:
28140 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28141 /* fall through */
28142 case OPC_SBE:
28143 case OPC_SHE:
28144 case OPC_SWE:
28145 check_cp0_enabled(ctx);
28146 gen_st(ctx, op1, rt, rs, imm);
28147 return;
28148 case OPC_SCE:
28149 check_cp0_enabled(ctx);
28150 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28151 return;
28152 case OPC_CACHEE:
28153 check_cp0_enabled(ctx);
28154 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28155 gen_cache_operation(ctx, rt, rs, imm);
28157 /* Treat as NOP. */
28158 return;
28159 case OPC_PREFE:
28160 check_cp0_enabled(ctx);
28161 /* Treat as NOP. */
28162 return;
28166 switch (op1) {
28167 case OPC_EXT:
28168 case OPC_INS:
28169 check_insn(ctx, ISA_MIPS32R2);
28170 gen_bitops(ctx, op1, rt, rs, sa, rd);
28171 break;
28172 case OPC_BSHFL:
28173 op2 = MASK_BSHFL(ctx->opcode);
28174 switch (op2) {
28175 case OPC_ALIGN:
28176 case OPC_ALIGN_1:
28177 case OPC_ALIGN_2:
28178 case OPC_ALIGN_3:
28179 case OPC_BITSWAP:
28180 check_insn(ctx, ISA_MIPS32R6);
28181 decode_opc_special3_r6(env, ctx);
28182 break;
28183 default:
28184 check_insn(ctx, ISA_MIPS32R2);
28185 gen_bshfl(ctx, op2, rt, rd);
28186 break;
28188 break;
28189 #if defined(TARGET_MIPS64)
28190 case OPC_DEXTM:
28191 case OPC_DEXTU:
28192 case OPC_DEXT:
28193 case OPC_DINSM:
28194 case OPC_DINSU:
28195 case OPC_DINS:
28196 check_insn(ctx, ISA_MIPS64R2);
28197 check_mips_64(ctx);
28198 gen_bitops(ctx, op1, rt, rs, sa, rd);
28199 break;
28200 case OPC_DBSHFL:
28201 op2 = MASK_DBSHFL(ctx->opcode);
28202 switch (op2) {
28203 case OPC_DALIGN:
28204 case OPC_DALIGN_1:
28205 case OPC_DALIGN_2:
28206 case OPC_DALIGN_3:
28207 case OPC_DALIGN_4:
28208 case OPC_DALIGN_5:
28209 case OPC_DALIGN_6:
28210 case OPC_DALIGN_7:
28211 case OPC_DBITSWAP:
28212 check_insn(ctx, ISA_MIPS32R6);
28213 decode_opc_special3_r6(env, ctx);
28214 break;
28215 default:
28216 check_insn(ctx, ISA_MIPS64R2);
28217 check_mips_64(ctx);
28218 op2 = MASK_DBSHFL(ctx->opcode);
28219 gen_bshfl(ctx, op2, rt, rd);
28220 break;
28222 break;
28223 #endif
28224 case OPC_RDHWR:
28225 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28226 break;
28227 case OPC_FORK:
28228 check_mt(ctx);
28230 TCGv t0 = tcg_temp_new();
28231 TCGv t1 = tcg_temp_new();
28233 gen_load_gpr(t0, rt);
28234 gen_load_gpr(t1, rs);
28235 gen_helper_fork(t0, t1);
28236 tcg_temp_free(t0);
28237 tcg_temp_free(t1);
28239 break;
28240 case OPC_YIELD:
28241 check_mt(ctx);
28243 TCGv t0 = tcg_temp_new();
28245 gen_load_gpr(t0, rs);
28246 gen_helper_yield(t0, cpu_env, t0);
28247 gen_store_gpr(t0, rd);
28248 tcg_temp_free(t0);
28250 break;
28251 default:
28252 if (ctx->insn_flags & ISA_MIPS32R6) {
28253 decode_opc_special3_r6(env, ctx);
28254 } else {
28255 decode_opc_special3_legacy(env, ctx);
28260 /* MIPS SIMD Architecture (MSA) */
28261 static inline int check_msa_access(DisasContext *ctx)
28263 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28264 !(ctx->hflags & MIPS_HFLAG_F64))) {
28265 generate_exception_end(ctx, EXCP_RI);
28266 return 0;
28269 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28270 if (ctx->insn_flags & ASE_MSA) {
28271 generate_exception_end(ctx, EXCP_MSADIS);
28272 return 0;
28273 } else {
28274 generate_exception_end(ctx, EXCP_RI);
28275 return 0;
28278 return 1;
28281 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28283 /* generates tcg ops to check if any element is 0 */
28284 /* Note this function only works with MSA_WRLEN = 128 */
28285 uint64_t eval_zero_or_big = 0;
28286 uint64_t eval_big = 0;
28287 TCGv_i64 t0 = tcg_temp_new_i64();
28288 TCGv_i64 t1 = tcg_temp_new_i64();
28289 switch (df) {
28290 case DF_BYTE:
28291 eval_zero_or_big = 0x0101010101010101ULL;
28292 eval_big = 0x8080808080808080ULL;
28293 break;
28294 case DF_HALF:
28295 eval_zero_or_big = 0x0001000100010001ULL;
28296 eval_big = 0x8000800080008000ULL;
28297 break;
28298 case DF_WORD:
28299 eval_zero_or_big = 0x0000000100000001ULL;
28300 eval_big = 0x8000000080000000ULL;
28301 break;
28302 case DF_DOUBLE:
28303 eval_zero_or_big = 0x0000000000000001ULL;
28304 eval_big = 0x8000000000000000ULL;
28305 break;
28307 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28308 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28309 tcg_gen_andi_i64(t0, t0, eval_big);
28310 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28311 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28312 tcg_gen_andi_i64(t1, t1, eval_big);
28313 tcg_gen_or_i64(t0, t0, t1);
28314 /* if all bits are zero then all elements are not zero */
28315 /* if some bit is non-zero then some element is zero */
28316 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28317 tcg_gen_trunc_i64_tl(tresult, t0);
28318 tcg_temp_free_i64(t0);
28319 tcg_temp_free_i64(t1);
28322 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28324 uint8_t df = (ctx->opcode >> 21) & 0x3;
28325 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28326 int64_t s16 = (int16_t)ctx->opcode;
28328 check_msa_access(ctx);
28330 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28331 generate_exception_end(ctx, EXCP_RI);
28332 return;
28334 switch (op1) {
28335 case OPC_BZ_V:
28336 case OPC_BNZ_V:
28338 TCGv_i64 t0 = tcg_temp_new_i64();
28339 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28340 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28341 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28342 tcg_gen_trunc_i64_tl(bcond, t0);
28343 tcg_temp_free_i64(t0);
28345 break;
28346 case OPC_BZ_B:
28347 case OPC_BZ_H:
28348 case OPC_BZ_W:
28349 case OPC_BZ_D:
28350 gen_check_zero_element(bcond, df, wt);
28351 break;
28352 case OPC_BNZ_B:
28353 case OPC_BNZ_H:
28354 case OPC_BNZ_W:
28355 case OPC_BNZ_D:
28356 gen_check_zero_element(bcond, df, wt);
28357 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28358 break;
28361 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28363 ctx->hflags |= MIPS_HFLAG_BC;
28364 ctx->hflags |= MIPS_HFLAG_BDS32;
28367 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28369 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28370 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28371 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28372 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28374 TCGv_i32 twd = tcg_const_i32(wd);
28375 TCGv_i32 tws = tcg_const_i32(ws);
28376 TCGv_i32 ti8 = tcg_const_i32(i8);
28378 switch (MASK_MSA_I8(ctx->opcode)) {
28379 case OPC_ANDI_B:
28380 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28381 break;
28382 case OPC_ORI_B:
28383 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28384 break;
28385 case OPC_NORI_B:
28386 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28387 break;
28388 case OPC_XORI_B:
28389 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28390 break;
28391 case OPC_BMNZI_B:
28392 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28393 break;
28394 case OPC_BMZI_B:
28395 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28396 break;
28397 case OPC_BSELI_B:
28398 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28399 break;
28400 case OPC_SHF_B:
28401 case OPC_SHF_H:
28402 case OPC_SHF_W:
28404 uint8_t df = (ctx->opcode >> 24) & 0x3;
28405 if (df == DF_DOUBLE) {
28406 generate_exception_end(ctx, EXCP_RI);
28407 } else {
28408 TCGv_i32 tdf = tcg_const_i32(df);
28409 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28410 tcg_temp_free_i32(tdf);
28413 break;
28414 default:
28415 MIPS_INVAL("MSA instruction");
28416 generate_exception_end(ctx, EXCP_RI);
28417 break;
28420 tcg_temp_free_i32(twd);
28421 tcg_temp_free_i32(tws);
28422 tcg_temp_free_i32(ti8);
28425 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28427 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28428 uint8_t df = (ctx->opcode >> 21) & 0x3;
28429 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28430 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28431 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28432 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28434 TCGv_i32 tdf = tcg_const_i32(df);
28435 TCGv_i32 twd = tcg_const_i32(wd);
28436 TCGv_i32 tws = tcg_const_i32(ws);
28437 TCGv_i32 timm = tcg_temp_new_i32();
28438 tcg_gen_movi_i32(timm, u5);
28440 switch (MASK_MSA_I5(ctx->opcode)) {
28441 case OPC_ADDVI_df:
28442 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28443 break;
28444 case OPC_SUBVI_df:
28445 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28446 break;
28447 case OPC_MAXI_S_df:
28448 tcg_gen_movi_i32(timm, s5);
28449 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28450 break;
28451 case OPC_MAXI_U_df:
28452 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28453 break;
28454 case OPC_MINI_S_df:
28455 tcg_gen_movi_i32(timm, s5);
28456 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28457 break;
28458 case OPC_MINI_U_df:
28459 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28460 break;
28461 case OPC_CEQI_df:
28462 tcg_gen_movi_i32(timm, s5);
28463 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28464 break;
28465 case OPC_CLTI_S_df:
28466 tcg_gen_movi_i32(timm, s5);
28467 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28468 break;
28469 case OPC_CLTI_U_df:
28470 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28471 break;
28472 case OPC_CLEI_S_df:
28473 tcg_gen_movi_i32(timm, s5);
28474 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28475 break;
28476 case OPC_CLEI_U_df:
28477 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28478 break;
28479 case OPC_LDI_df:
28481 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28482 tcg_gen_movi_i32(timm, s10);
28483 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28485 break;
28486 default:
28487 MIPS_INVAL("MSA instruction");
28488 generate_exception_end(ctx, EXCP_RI);
28489 break;
28492 tcg_temp_free_i32(tdf);
28493 tcg_temp_free_i32(twd);
28494 tcg_temp_free_i32(tws);
28495 tcg_temp_free_i32(timm);
28498 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28500 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28501 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28502 uint32_t df = 0, m = 0;
28503 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28504 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28506 TCGv_i32 tdf;
28507 TCGv_i32 tm;
28508 TCGv_i32 twd;
28509 TCGv_i32 tws;
28511 if ((dfm & 0x40) == 0x00) {
28512 m = dfm & 0x3f;
28513 df = DF_DOUBLE;
28514 } else if ((dfm & 0x60) == 0x40) {
28515 m = dfm & 0x1f;
28516 df = DF_WORD;
28517 } else if ((dfm & 0x70) == 0x60) {
28518 m = dfm & 0x0f;
28519 df = DF_HALF;
28520 } else if ((dfm & 0x78) == 0x70) {
28521 m = dfm & 0x7;
28522 df = DF_BYTE;
28523 } else {
28524 generate_exception_end(ctx, EXCP_RI);
28525 return;
28528 tdf = tcg_const_i32(df);
28529 tm = tcg_const_i32(m);
28530 twd = tcg_const_i32(wd);
28531 tws = tcg_const_i32(ws);
28533 switch (MASK_MSA_BIT(ctx->opcode)) {
28534 case OPC_SLLI_df:
28535 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28536 break;
28537 case OPC_SRAI_df:
28538 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28539 break;
28540 case OPC_SRLI_df:
28541 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28542 break;
28543 case OPC_BCLRI_df:
28544 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28545 break;
28546 case OPC_BSETI_df:
28547 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28548 break;
28549 case OPC_BNEGI_df:
28550 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28551 break;
28552 case OPC_BINSLI_df:
28553 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28554 break;
28555 case OPC_BINSRI_df:
28556 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28557 break;
28558 case OPC_SAT_S_df:
28559 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28560 break;
28561 case OPC_SAT_U_df:
28562 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28563 break;
28564 case OPC_SRARI_df:
28565 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28566 break;
28567 case OPC_SRLRI_df:
28568 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28569 break;
28570 default:
28571 MIPS_INVAL("MSA instruction");
28572 generate_exception_end(ctx, EXCP_RI);
28573 break;
28576 tcg_temp_free_i32(tdf);
28577 tcg_temp_free_i32(tm);
28578 tcg_temp_free_i32(twd);
28579 tcg_temp_free_i32(tws);
28582 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28584 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28585 uint8_t df = (ctx->opcode >> 21) & 0x3;
28586 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28587 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28588 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28590 TCGv_i32 tdf = tcg_const_i32(df);
28591 TCGv_i32 twd = tcg_const_i32(wd);
28592 TCGv_i32 tws = tcg_const_i32(ws);
28593 TCGv_i32 twt = tcg_const_i32(wt);
28595 switch (MASK_MSA_3R(ctx->opcode)) {
28596 case OPC_BINSL_df:
28597 switch (df) {
28598 case DF_BYTE:
28599 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28600 break;
28601 case DF_HALF:
28602 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28603 break;
28604 case DF_WORD:
28605 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28606 break;
28607 case DF_DOUBLE:
28608 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28609 break;
28611 break;
28612 case OPC_BINSR_df:
28613 switch (df) {
28614 case DF_BYTE:
28615 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28616 break;
28617 case DF_HALF:
28618 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28619 break;
28620 case DF_WORD:
28621 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28622 break;
28623 case DF_DOUBLE:
28624 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28625 break;
28627 break;
28628 case OPC_BCLR_df:
28629 switch (df) {
28630 case DF_BYTE:
28631 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28632 break;
28633 case DF_HALF:
28634 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28635 break;
28636 case DF_WORD:
28637 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28638 break;
28639 case DF_DOUBLE:
28640 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28641 break;
28643 break;
28644 case OPC_BNEG_df:
28645 switch (df) {
28646 case DF_BYTE:
28647 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28648 break;
28649 case DF_HALF:
28650 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28651 break;
28652 case DF_WORD:
28653 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28654 break;
28655 case DF_DOUBLE:
28656 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28657 break;
28659 break;
28660 case OPC_BSET_df:
28661 switch (df) {
28662 case DF_BYTE:
28663 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28664 break;
28665 case DF_HALF:
28666 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28667 break;
28668 case DF_WORD:
28669 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28670 break;
28671 case DF_DOUBLE:
28672 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28673 break;
28675 break;
28676 case OPC_ADD_A_df:
28677 switch (df) {
28678 case DF_BYTE:
28679 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28680 break;
28681 case DF_HALF:
28682 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28683 break;
28684 case DF_WORD:
28685 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28686 break;
28687 case DF_DOUBLE:
28688 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28689 break;
28691 break;
28692 case OPC_ADDS_A_df:
28693 switch (df) {
28694 case DF_BYTE:
28695 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
28696 break;
28697 case DF_HALF:
28698 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
28699 break;
28700 case DF_WORD:
28701 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
28702 break;
28703 case DF_DOUBLE:
28704 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
28705 break;
28707 break;
28708 case OPC_ADDS_S_df:
28709 switch (df) {
28710 case DF_BYTE:
28711 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
28712 break;
28713 case DF_HALF:
28714 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
28715 break;
28716 case DF_WORD:
28717 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
28718 break;
28719 case DF_DOUBLE:
28720 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
28721 break;
28723 break;
28724 case OPC_ADDS_U_df:
28725 switch (df) {
28726 case DF_BYTE:
28727 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
28728 break;
28729 case DF_HALF:
28730 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
28731 break;
28732 case DF_WORD:
28733 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
28734 break;
28735 case DF_DOUBLE:
28736 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
28737 break;
28739 break;
28740 case OPC_ADDV_df:
28741 switch (df) {
28742 case DF_BYTE:
28743 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
28744 break;
28745 case DF_HALF:
28746 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
28747 break;
28748 case DF_WORD:
28749 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
28750 break;
28751 case DF_DOUBLE:
28752 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
28753 break;
28755 break;
28756 case OPC_AVE_S_df:
28757 switch (df) {
28758 case DF_BYTE:
28759 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
28760 break;
28761 case DF_HALF:
28762 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
28763 break;
28764 case DF_WORD:
28765 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
28766 break;
28767 case DF_DOUBLE:
28768 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
28769 break;
28771 break;
28772 case OPC_AVE_U_df:
28773 switch (df) {
28774 case DF_BYTE:
28775 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
28776 break;
28777 case DF_HALF:
28778 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
28779 break;
28780 case DF_WORD:
28781 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
28782 break;
28783 case DF_DOUBLE:
28784 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
28785 break;
28787 break;
28788 case OPC_AVER_S_df:
28789 switch (df) {
28790 case DF_BYTE:
28791 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
28792 break;
28793 case DF_HALF:
28794 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
28795 break;
28796 case DF_WORD:
28797 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
28798 break;
28799 case DF_DOUBLE:
28800 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
28801 break;
28803 break;
28804 case OPC_AVER_U_df:
28805 switch (df) {
28806 case DF_BYTE:
28807 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
28808 break;
28809 case DF_HALF:
28810 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
28811 break;
28812 case DF_WORD:
28813 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
28814 break;
28815 case DF_DOUBLE:
28816 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
28817 break;
28819 break;
28820 case OPC_CEQ_df:
28821 switch (df) {
28822 case DF_BYTE:
28823 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
28824 break;
28825 case DF_HALF:
28826 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
28827 break;
28828 case DF_WORD:
28829 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
28830 break;
28831 case DF_DOUBLE:
28832 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
28833 break;
28835 break;
28836 case OPC_CLE_S_df:
28837 switch (df) {
28838 case DF_BYTE:
28839 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
28840 break;
28841 case DF_HALF:
28842 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
28843 break;
28844 case DF_WORD:
28845 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
28846 break;
28847 case DF_DOUBLE:
28848 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
28849 break;
28851 break;
28852 case OPC_CLE_U_df:
28853 switch (df) {
28854 case DF_BYTE:
28855 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
28856 break;
28857 case DF_HALF:
28858 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
28859 break;
28860 case DF_WORD:
28861 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
28862 break;
28863 case DF_DOUBLE:
28864 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
28865 break;
28867 break;
28868 case OPC_CLT_S_df:
28869 switch (df) {
28870 case DF_BYTE:
28871 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
28872 break;
28873 case DF_HALF:
28874 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
28875 break;
28876 case DF_WORD:
28877 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
28878 break;
28879 case DF_DOUBLE:
28880 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
28881 break;
28883 break;
28884 case OPC_CLT_U_df:
28885 switch (df) {
28886 case DF_BYTE:
28887 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
28888 break;
28889 case DF_HALF:
28890 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
28891 break;
28892 case DF_WORD:
28893 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
28894 break;
28895 case DF_DOUBLE:
28896 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
28897 break;
28899 break;
28900 case OPC_DIV_S_df:
28901 switch (df) {
28902 case DF_BYTE:
28903 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
28904 break;
28905 case DF_HALF:
28906 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
28907 break;
28908 case DF_WORD:
28909 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
28910 break;
28911 case DF_DOUBLE:
28912 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
28913 break;
28915 break;
28916 case OPC_DIV_U_df:
28917 switch (df) {
28918 case DF_BYTE:
28919 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
28920 break;
28921 case DF_HALF:
28922 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
28923 break;
28924 case DF_WORD:
28925 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
28926 break;
28927 case DF_DOUBLE:
28928 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
28929 break;
28931 break;
28932 case OPC_MAX_A_df:
28933 switch (df) {
28934 case DF_BYTE:
28935 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
28936 break;
28937 case DF_HALF:
28938 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
28939 break;
28940 case DF_WORD:
28941 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
28942 break;
28943 case DF_DOUBLE:
28944 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
28945 break;
28947 break;
28948 case OPC_MAX_S_df:
28949 switch (df) {
28950 case DF_BYTE:
28951 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
28952 break;
28953 case DF_HALF:
28954 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
28955 break;
28956 case DF_WORD:
28957 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
28958 break;
28959 case DF_DOUBLE:
28960 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
28961 break;
28963 break;
28964 case OPC_MAX_U_df:
28965 switch (df) {
28966 case DF_BYTE:
28967 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
28968 break;
28969 case DF_HALF:
28970 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
28971 break;
28972 case DF_WORD:
28973 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
28974 break;
28975 case DF_DOUBLE:
28976 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
28977 break;
28979 break;
28980 case OPC_MIN_A_df:
28981 switch (df) {
28982 case DF_BYTE:
28983 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
28984 break;
28985 case DF_HALF:
28986 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
28987 break;
28988 case DF_WORD:
28989 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
28990 break;
28991 case DF_DOUBLE:
28992 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
28993 break;
28995 break;
28996 case OPC_MIN_S_df:
28997 switch (df) {
28998 case DF_BYTE:
28999 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29000 break;
29001 case DF_HALF:
29002 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29003 break;
29004 case DF_WORD:
29005 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29006 break;
29007 case DF_DOUBLE:
29008 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29009 break;
29011 break;
29012 case OPC_MIN_U_df:
29013 switch (df) {
29014 case DF_BYTE:
29015 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29016 break;
29017 case DF_HALF:
29018 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29019 break;
29020 case DF_WORD:
29021 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29022 break;
29023 case DF_DOUBLE:
29024 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29025 break;
29027 break;
29028 case OPC_MOD_S_df:
29029 switch (df) {
29030 case DF_BYTE:
29031 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29032 break;
29033 case DF_HALF:
29034 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29035 break;
29036 case DF_WORD:
29037 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29038 break;
29039 case DF_DOUBLE:
29040 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29041 break;
29043 break;
29044 case OPC_MOD_U_df:
29045 switch (df) {
29046 case DF_BYTE:
29047 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29048 break;
29049 case DF_HALF:
29050 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29051 break;
29052 case DF_WORD:
29053 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29054 break;
29055 case DF_DOUBLE:
29056 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29057 break;
29059 break;
29060 case OPC_ASUB_S_df:
29061 switch (df) {
29062 case DF_BYTE:
29063 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29064 break;
29065 case DF_HALF:
29066 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29067 break;
29068 case DF_WORD:
29069 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29070 break;
29071 case DF_DOUBLE:
29072 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29073 break;
29075 break;
29076 case OPC_ASUB_U_df:
29077 switch (df) {
29078 case DF_BYTE:
29079 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29080 break;
29081 case DF_HALF:
29082 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29083 break;
29084 case DF_WORD:
29085 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29086 break;
29087 case DF_DOUBLE:
29088 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29089 break;
29091 break;
29092 case OPC_ILVEV_df:
29093 switch (df) {
29094 case DF_BYTE:
29095 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29096 break;
29097 case DF_HALF:
29098 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29099 break;
29100 case DF_WORD:
29101 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29102 break;
29103 case DF_DOUBLE:
29104 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29105 break;
29107 break;
29108 case OPC_ILVOD_df:
29109 switch (df) {
29110 case DF_BYTE:
29111 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29112 break;
29113 case DF_HALF:
29114 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29115 break;
29116 case DF_WORD:
29117 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29118 break;
29119 case DF_DOUBLE:
29120 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29121 break;
29123 break;
29124 case OPC_ILVL_df:
29125 switch (df) {
29126 case DF_BYTE:
29127 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29128 break;
29129 case DF_HALF:
29130 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29131 break;
29132 case DF_WORD:
29133 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29134 break;
29135 case DF_DOUBLE:
29136 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29137 break;
29139 break;
29140 case OPC_ILVR_df:
29141 switch (df) {
29142 case DF_BYTE:
29143 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29144 break;
29145 case DF_HALF:
29146 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29147 break;
29148 case DF_WORD:
29149 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29150 break;
29151 case DF_DOUBLE:
29152 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29153 break;
29155 break;
29156 case OPC_PCKEV_df:
29157 switch (df) {
29158 case DF_BYTE:
29159 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29160 break;
29161 case DF_HALF:
29162 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29163 break;
29164 case DF_WORD:
29165 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29166 break;
29167 case DF_DOUBLE:
29168 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29169 break;
29171 break;
29172 case OPC_PCKOD_df:
29173 switch (df) {
29174 case DF_BYTE:
29175 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29176 break;
29177 case DF_HALF:
29178 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29179 break;
29180 case DF_WORD:
29181 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29182 break;
29183 case DF_DOUBLE:
29184 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29185 break;
29187 break;
29188 case OPC_SLL_df:
29189 switch (df) {
29190 case DF_BYTE:
29191 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29192 break;
29193 case DF_HALF:
29194 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29195 break;
29196 case DF_WORD:
29197 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29198 break;
29199 case DF_DOUBLE:
29200 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29201 break;
29203 break;
29204 case OPC_SRA_df:
29205 switch (df) {
29206 case DF_BYTE:
29207 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29208 break;
29209 case DF_HALF:
29210 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29211 break;
29212 case DF_WORD:
29213 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29214 break;
29215 case DF_DOUBLE:
29216 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29217 break;
29219 break;
29220 case OPC_SRAR_df:
29221 switch (df) {
29222 case DF_BYTE:
29223 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29224 break;
29225 case DF_HALF:
29226 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29227 break;
29228 case DF_WORD:
29229 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29230 break;
29231 case DF_DOUBLE:
29232 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29233 break;
29235 break;
29236 case OPC_SRL_df:
29237 switch (df) {
29238 case DF_BYTE:
29239 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29240 break;
29241 case DF_HALF:
29242 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29243 break;
29244 case DF_WORD:
29245 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29246 break;
29247 case DF_DOUBLE:
29248 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29249 break;
29251 break;
29252 case OPC_SRLR_df:
29253 switch (df) {
29254 case DF_BYTE:
29255 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29256 break;
29257 case DF_HALF:
29258 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29259 break;
29260 case DF_WORD:
29261 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29262 break;
29263 case DF_DOUBLE:
29264 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29265 break;
29267 break;
29268 case OPC_SUBS_S_df:
29269 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
29270 break;
29271 case OPC_MULV_df:
29272 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
29273 break;
29274 case OPC_SLD_df:
29275 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29276 break;
29277 case OPC_VSHF_df:
29278 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29279 break;
29280 case OPC_SUBV_df:
29281 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
29282 break;
29283 case OPC_SUBS_U_df:
29284 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
29285 break;
29286 case OPC_MADDV_df:
29287 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
29288 break;
29289 case OPC_SPLAT_df:
29290 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29291 break;
29292 case OPC_SUBSUS_U_df:
29293 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
29294 break;
29295 case OPC_MSUBV_df:
29296 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
29297 break;
29298 case OPC_SUBSUU_S_df:
29299 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
29300 break;
29302 case OPC_DOTP_S_df:
29303 case OPC_DOTP_U_df:
29304 case OPC_DPADD_S_df:
29305 case OPC_DPADD_U_df:
29306 case OPC_DPSUB_S_df:
29307 case OPC_HADD_S_df:
29308 case OPC_DPSUB_U_df:
29309 case OPC_HADD_U_df:
29310 case OPC_HSUB_S_df:
29311 case OPC_HSUB_U_df:
29312 if (df == DF_BYTE) {
29313 generate_exception_end(ctx, EXCP_RI);
29314 break;
29316 switch (MASK_MSA_3R(ctx->opcode)) {
29317 case OPC_HADD_S_df:
29318 switch (df) {
29319 case DF_HALF:
29320 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29321 break;
29322 case DF_WORD:
29323 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29324 break;
29325 case DF_DOUBLE:
29326 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29327 break;
29329 break;
29330 case OPC_HADD_U_df:
29331 switch (df) {
29332 case DF_HALF:
29333 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29334 break;
29335 case DF_WORD:
29336 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29337 break;
29338 case DF_DOUBLE:
29339 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29340 break;
29342 break;
29343 case OPC_HSUB_S_df:
29344 switch (df) {
29345 case DF_HALF:
29346 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29347 break;
29348 case DF_WORD:
29349 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29350 break;
29351 case DF_DOUBLE:
29352 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29353 break;
29355 break;
29356 case OPC_HSUB_U_df:
29357 switch (df) {
29358 case DF_HALF:
29359 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29360 break;
29361 case DF_WORD:
29362 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29363 break;
29364 case DF_DOUBLE:
29365 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29366 break;
29368 break;
29369 case OPC_DOTP_S_df:
29370 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
29371 break;
29372 case OPC_DOTP_U_df:
29373 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
29374 break;
29375 case OPC_DPADD_S_df:
29376 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
29377 break;
29378 case OPC_DPADD_U_df:
29379 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
29380 break;
29381 case OPC_DPSUB_S_df:
29382 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
29383 break;
29384 case OPC_DPSUB_U_df:
29385 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
29386 break;
29388 break;
29389 default:
29390 MIPS_INVAL("MSA instruction");
29391 generate_exception_end(ctx, EXCP_RI);
29392 break;
29394 tcg_temp_free_i32(twd);
29395 tcg_temp_free_i32(tws);
29396 tcg_temp_free_i32(twt);
29397 tcg_temp_free_i32(tdf);
29400 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29402 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29403 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29404 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29405 TCGv telm = tcg_temp_new();
29406 TCGv_i32 tsr = tcg_const_i32(source);
29407 TCGv_i32 tdt = tcg_const_i32(dest);
29409 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29410 case OPC_CTCMSA:
29411 gen_load_gpr(telm, source);
29412 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29413 break;
29414 case OPC_CFCMSA:
29415 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29416 gen_store_gpr(telm, dest);
29417 break;
29418 case OPC_MOVE_V:
29419 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29420 break;
29421 default:
29422 MIPS_INVAL("MSA instruction");
29423 generate_exception_end(ctx, EXCP_RI);
29424 break;
29427 tcg_temp_free(telm);
29428 tcg_temp_free_i32(tdt);
29429 tcg_temp_free_i32(tsr);
29432 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29433 uint32_t n)
29435 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29436 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29437 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29439 TCGv_i32 tws = tcg_const_i32(ws);
29440 TCGv_i32 twd = tcg_const_i32(wd);
29441 TCGv_i32 tn = tcg_const_i32(n);
29442 TCGv_i32 tdf = tcg_const_i32(df);
29444 switch (MASK_MSA_ELM(ctx->opcode)) {
29445 case OPC_SLDI_df:
29446 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29447 break;
29448 case OPC_SPLATI_df:
29449 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29450 break;
29451 case OPC_INSVE_df:
29452 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29453 break;
29454 case OPC_COPY_S_df:
29455 case OPC_COPY_U_df:
29456 case OPC_INSERT_df:
29457 #if !defined(TARGET_MIPS64)
29458 /* Double format valid only for MIPS64 */
29459 if (df == DF_DOUBLE) {
29460 generate_exception_end(ctx, EXCP_RI);
29461 break;
29463 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29464 (df == DF_WORD)) {
29465 generate_exception_end(ctx, EXCP_RI);
29466 break;
29468 #endif
29469 switch (MASK_MSA_ELM(ctx->opcode)) {
29470 case OPC_COPY_S_df:
29471 if (likely(wd != 0)) {
29472 switch (df) {
29473 case DF_BYTE:
29474 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29475 break;
29476 case DF_HALF:
29477 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29478 break;
29479 case DF_WORD:
29480 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29481 break;
29482 #if defined(TARGET_MIPS64)
29483 case DF_DOUBLE:
29484 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29485 break;
29486 #endif
29487 default:
29488 assert(0);
29491 break;
29492 case OPC_COPY_U_df:
29493 if (likely(wd != 0)) {
29494 switch (df) {
29495 case DF_BYTE:
29496 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29497 break;
29498 case DF_HALF:
29499 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29500 break;
29501 #if defined(TARGET_MIPS64)
29502 case DF_WORD:
29503 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29504 break;
29505 #endif
29506 default:
29507 assert(0);
29510 break;
29511 case OPC_INSERT_df:
29512 switch (df) {
29513 case DF_BYTE:
29514 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29515 break;
29516 case DF_HALF:
29517 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29518 break;
29519 case DF_WORD:
29520 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29521 break;
29522 #if defined(TARGET_MIPS64)
29523 case DF_DOUBLE:
29524 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29525 break;
29526 #endif
29527 default:
29528 assert(0);
29530 break;
29532 break;
29533 default:
29534 MIPS_INVAL("MSA instruction");
29535 generate_exception_end(ctx, EXCP_RI);
29537 tcg_temp_free_i32(twd);
29538 tcg_temp_free_i32(tws);
29539 tcg_temp_free_i32(tn);
29540 tcg_temp_free_i32(tdf);
29543 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
29545 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
29546 uint32_t df = 0, n = 0;
29548 if ((dfn & 0x30) == 0x00) {
29549 n = dfn & 0x0f;
29550 df = DF_BYTE;
29551 } else if ((dfn & 0x38) == 0x20) {
29552 n = dfn & 0x07;
29553 df = DF_HALF;
29554 } else if ((dfn & 0x3c) == 0x30) {
29555 n = dfn & 0x03;
29556 df = DF_WORD;
29557 } else if ((dfn & 0x3e) == 0x38) {
29558 n = dfn & 0x01;
29559 df = DF_DOUBLE;
29560 } else if (dfn == 0x3E) {
29561 /* CTCMSA, CFCMSA, MOVE.V */
29562 gen_msa_elm_3e(env, ctx);
29563 return;
29564 } else {
29565 generate_exception_end(ctx, EXCP_RI);
29566 return;
29569 gen_msa_elm_df(env, ctx, df, n);
29572 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
29574 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29575 uint8_t df = (ctx->opcode >> 21) & 0x1;
29576 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29577 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29578 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29580 TCGv_i32 twd = tcg_const_i32(wd);
29581 TCGv_i32 tws = tcg_const_i32(ws);
29582 TCGv_i32 twt = tcg_const_i32(wt);
29583 TCGv_i32 tdf = tcg_temp_new_i32();
29585 /* adjust df value for floating-point instruction */
29586 tcg_gen_movi_i32(tdf, df + 2);
29588 switch (MASK_MSA_3RF(ctx->opcode)) {
29589 case OPC_FCAF_df:
29590 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
29591 break;
29592 case OPC_FADD_df:
29593 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
29594 break;
29595 case OPC_FCUN_df:
29596 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
29597 break;
29598 case OPC_FSUB_df:
29599 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
29600 break;
29601 case OPC_FCOR_df:
29602 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
29603 break;
29604 case OPC_FCEQ_df:
29605 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
29606 break;
29607 case OPC_FMUL_df:
29608 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
29609 break;
29610 case OPC_FCUNE_df:
29611 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
29612 break;
29613 case OPC_FCUEQ_df:
29614 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
29615 break;
29616 case OPC_FDIV_df:
29617 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
29618 break;
29619 case OPC_FCNE_df:
29620 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
29621 break;
29622 case OPC_FCLT_df:
29623 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
29624 break;
29625 case OPC_FMADD_df:
29626 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
29627 break;
29628 case OPC_MUL_Q_df:
29629 tcg_gen_movi_i32(tdf, df + 1);
29630 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
29631 break;
29632 case OPC_FCULT_df:
29633 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
29634 break;
29635 case OPC_FMSUB_df:
29636 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
29637 break;
29638 case OPC_MADD_Q_df:
29639 tcg_gen_movi_i32(tdf, df + 1);
29640 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
29641 break;
29642 case OPC_FCLE_df:
29643 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
29644 break;
29645 case OPC_MSUB_Q_df:
29646 tcg_gen_movi_i32(tdf, df + 1);
29647 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
29648 break;
29649 case OPC_FCULE_df:
29650 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
29651 break;
29652 case OPC_FEXP2_df:
29653 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
29654 break;
29655 case OPC_FSAF_df:
29656 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
29657 break;
29658 case OPC_FEXDO_df:
29659 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
29660 break;
29661 case OPC_FSUN_df:
29662 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
29663 break;
29664 case OPC_FSOR_df:
29665 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
29666 break;
29667 case OPC_FSEQ_df:
29668 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
29669 break;
29670 case OPC_FTQ_df:
29671 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
29672 break;
29673 case OPC_FSUNE_df:
29674 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
29675 break;
29676 case OPC_FSUEQ_df:
29677 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
29678 break;
29679 case OPC_FSNE_df:
29680 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
29681 break;
29682 case OPC_FSLT_df:
29683 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
29684 break;
29685 case OPC_FMIN_df:
29686 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
29687 break;
29688 case OPC_MULR_Q_df:
29689 tcg_gen_movi_i32(tdf, df + 1);
29690 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
29691 break;
29692 case OPC_FSULT_df:
29693 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
29694 break;
29695 case OPC_FMIN_A_df:
29696 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
29697 break;
29698 case OPC_MADDR_Q_df:
29699 tcg_gen_movi_i32(tdf, df + 1);
29700 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
29701 break;
29702 case OPC_FSLE_df:
29703 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
29704 break;
29705 case OPC_FMAX_df:
29706 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
29707 break;
29708 case OPC_MSUBR_Q_df:
29709 tcg_gen_movi_i32(tdf, df + 1);
29710 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
29711 break;
29712 case OPC_FSULE_df:
29713 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
29714 break;
29715 case OPC_FMAX_A_df:
29716 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
29717 break;
29718 default:
29719 MIPS_INVAL("MSA instruction");
29720 generate_exception_end(ctx, EXCP_RI);
29721 break;
29724 tcg_temp_free_i32(twd);
29725 tcg_temp_free_i32(tws);
29726 tcg_temp_free_i32(twt);
29727 tcg_temp_free_i32(tdf);
29730 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
29732 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29733 (op & (0x7 << 18)))
29734 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29735 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29736 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29737 uint8_t df = (ctx->opcode >> 16) & 0x3;
29738 TCGv_i32 twd = tcg_const_i32(wd);
29739 TCGv_i32 tws = tcg_const_i32(ws);
29740 TCGv_i32 twt = tcg_const_i32(wt);
29741 TCGv_i32 tdf = tcg_const_i32(df);
29743 switch (MASK_MSA_2R(ctx->opcode)) {
29744 case OPC_FILL_df:
29745 #if !defined(TARGET_MIPS64)
29746 /* Double format valid only for MIPS64 */
29747 if (df == DF_DOUBLE) {
29748 generate_exception_end(ctx, EXCP_RI);
29749 break;
29751 #endif
29752 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
29753 break;
29754 case OPC_NLOC_df:
29755 switch (df) {
29756 case DF_BYTE:
29757 gen_helper_msa_nloc_b(cpu_env, twd, tws);
29758 break;
29759 case DF_HALF:
29760 gen_helper_msa_nloc_h(cpu_env, twd, tws);
29761 break;
29762 case DF_WORD:
29763 gen_helper_msa_nloc_w(cpu_env, twd, tws);
29764 break;
29765 case DF_DOUBLE:
29766 gen_helper_msa_nloc_d(cpu_env, twd, tws);
29767 break;
29769 break;
29770 case OPC_NLZC_df:
29771 switch (df) {
29772 case DF_BYTE:
29773 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
29774 break;
29775 case DF_HALF:
29776 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
29777 break;
29778 case DF_WORD:
29779 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
29780 break;
29781 case DF_DOUBLE:
29782 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
29783 break;
29785 break;
29786 case OPC_PCNT_df:
29787 switch (df) {
29788 case DF_BYTE:
29789 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
29790 break;
29791 case DF_HALF:
29792 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
29793 break;
29794 case DF_WORD:
29795 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
29796 break;
29797 case DF_DOUBLE:
29798 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
29799 break;
29801 break;
29802 default:
29803 MIPS_INVAL("MSA instruction");
29804 generate_exception_end(ctx, EXCP_RI);
29805 break;
29808 tcg_temp_free_i32(twd);
29809 tcg_temp_free_i32(tws);
29810 tcg_temp_free_i32(twt);
29811 tcg_temp_free_i32(tdf);
29814 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
29816 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
29817 (op & (0xf << 17)))
29818 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29819 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29820 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29821 uint8_t df = (ctx->opcode >> 16) & 0x1;
29822 TCGv_i32 twd = tcg_const_i32(wd);
29823 TCGv_i32 tws = tcg_const_i32(ws);
29824 TCGv_i32 twt = tcg_const_i32(wt);
29825 /* adjust df value for floating-point instruction */
29826 TCGv_i32 tdf = tcg_const_i32(df + 2);
29828 switch (MASK_MSA_2RF(ctx->opcode)) {
29829 case OPC_FCLASS_df:
29830 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
29831 break;
29832 case OPC_FTRUNC_S_df:
29833 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
29834 break;
29835 case OPC_FTRUNC_U_df:
29836 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
29837 break;
29838 case OPC_FSQRT_df:
29839 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
29840 break;
29841 case OPC_FRSQRT_df:
29842 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
29843 break;
29844 case OPC_FRCP_df:
29845 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
29846 break;
29847 case OPC_FRINT_df:
29848 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
29849 break;
29850 case OPC_FLOG2_df:
29851 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
29852 break;
29853 case OPC_FEXUPL_df:
29854 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
29855 break;
29856 case OPC_FEXUPR_df:
29857 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
29858 break;
29859 case OPC_FFQL_df:
29860 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
29861 break;
29862 case OPC_FFQR_df:
29863 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
29864 break;
29865 case OPC_FTINT_S_df:
29866 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
29867 break;
29868 case OPC_FTINT_U_df:
29869 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
29870 break;
29871 case OPC_FFINT_S_df:
29872 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
29873 break;
29874 case OPC_FFINT_U_df:
29875 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
29876 break;
29879 tcg_temp_free_i32(twd);
29880 tcg_temp_free_i32(tws);
29881 tcg_temp_free_i32(twt);
29882 tcg_temp_free_i32(tdf);
29885 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
29887 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
29888 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29889 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29890 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29891 TCGv_i32 twd = tcg_const_i32(wd);
29892 TCGv_i32 tws = tcg_const_i32(ws);
29893 TCGv_i32 twt = tcg_const_i32(wt);
29895 switch (MASK_MSA_VEC(ctx->opcode)) {
29896 case OPC_AND_V:
29897 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
29898 break;
29899 case OPC_OR_V:
29900 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
29901 break;
29902 case OPC_NOR_V:
29903 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
29904 break;
29905 case OPC_XOR_V:
29906 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
29907 break;
29908 case OPC_BMNZ_V:
29909 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
29910 break;
29911 case OPC_BMZ_V:
29912 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
29913 break;
29914 case OPC_BSEL_V:
29915 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
29916 break;
29917 default:
29918 MIPS_INVAL("MSA instruction");
29919 generate_exception_end(ctx, EXCP_RI);
29920 break;
29923 tcg_temp_free_i32(twd);
29924 tcg_temp_free_i32(tws);
29925 tcg_temp_free_i32(twt);
29928 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
29930 switch (MASK_MSA_VEC(ctx->opcode)) {
29931 case OPC_AND_V:
29932 case OPC_OR_V:
29933 case OPC_NOR_V:
29934 case OPC_XOR_V:
29935 case OPC_BMNZ_V:
29936 case OPC_BMZ_V:
29937 case OPC_BSEL_V:
29938 gen_msa_vec_v(env, ctx);
29939 break;
29940 case OPC_MSA_2R:
29941 gen_msa_2r(env, ctx);
29942 break;
29943 case OPC_MSA_2RF:
29944 gen_msa_2rf(env, ctx);
29945 break;
29946 default:
29947 MIPS_INVAL("MSA instruction");
29948 generate_exception_end(ctx, EXCP_RI);
29949 break;
29953 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
29955 uint32_t opcode = ctx->opcode;
29956 check_insn(ctx, ASE_MSA);
29957 check_msa_access(ctx);
29959 switch (MASK_MSA_MINOR(opcode)) {
29960 case OPC_MSA_I8_00:
29961 case OPC_MSA_I8_01:
29962 case OPC_MSA_I8_02:
29963 gen_msa_i8(env, ctx);
29964 break;
29965 case OPC_MSA_I5_06:
29966 case OPC_MSA_I5_07:
29967 gen_msa_i5(env, ctx);
29968 break;
29969 case OPC_MSA_BIT_09:
29970 case OPC_MSA_BIT_0A:
29971 gen_msa_bit(env, ctx);
29972 break;
29973 case OPC_MSA_3R_0D:
29974 case OPC_MSA_3R_0E:
29975 case OPC_MSA_3R_0F:
29976 case OPC_MSA_3R_10:
29977 case OPC_MSA_3R_11:
29978 case OPC_MSA_3R_12:
29979 case OPC_MSA_3R_13:
29980 case OPC_MSA_3R_14:
29981 case OPC_MSA_3R_15:
29982 gen_msa_3r(env, ctx);
29983 break;
29984 case OPC_MSA_ELM:
29985 gen_msa_elm(env, ctx);
29986 break;
29987 case OPC_MSA_3RF_1A:
29988 case OPC_MSA_3RF_1B:
29989 case OPC_MSA_3RF_1C:
29990 gen_msa_3rf(env, ctx);
29991 break;
29992 case OPC_MSA_VEC:
29993 gen_msa_vec(env, ctx);
29994 break;
29995 case OPC_LD_B:
29996 case OPC_LD_H:
29997 case OPC_LD_W:
29998 case OPC_LD_D:
29999 case OPC_ST_B:
30000 case OPC_ST_H:
30001 case OPC_ST_W:
30002 case OPC_ST_D:
30004 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30005 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30006 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30007 uint8_t df = (ctx->opcode >> 0) & 0x3;
30009 TCGv_i32 twd = tcg_const_i32(wd);
30010 TCGv taddr = tcg_temp_new();
30011 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
30013 switch (MASK_MSA_MINOR(opcode)) {
30014 case OPC_LD_B:
30015 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30016 break;
30017 case OPC_LD_H:
30018 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30019 break;
30020 case OPC_LD_W:
30021 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30022 break;
30023 case OPC_LD_D:
30024 gen_helper_msa_ld_d(cpu_env, twd, taddr);
30025 break;
30026 case OPC_ST_B:
30027 gen_helper_msa_st_b(cpu_env, twd, taddr);
30028 break;
30029 case OPC_ST_H:
30030 gen_helper_msa_st_h(cpu_env, twd, taddr);
30031 break;
30032 case OPC_ST_W:
30033 gen_helper_msa_st_w(cpu_env, twd, taddr);
30034 break;
30035 case OPC_ST_D:
30036 gen_helper_msa_st_d(cpu_env, twd, taddr);
30037 break;
30040 tcg_temp_free_i32(twd);
30041 tcg_temp_free(taddr);
30043 break;
30044 default:
30045 MIPS_INVAL("MSA instruction");
30046 generate_exception_end(ctx, EXCP_RI);
30047 break;
30052 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
30054 int32_t offset;
30055 int rs, rt, rd, sa;
30056 uint32_t op, op1;
30057 int16_t imm;
30059 /* make sure instructions are on a word boundary */
30060 if (ctx->base.pc_next & 0x3) {
30061 env->CP0_BadVAddr = ctx->base.pc_next;
30062 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
30063 return;
30066 /* Handle blikely not taken case */
30067 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
30068 TCGLabel *l1 = gen_new_label();
30070 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30071 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
30072 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
30073 gen_set_label(l1);
30076 op = MASK_OP_MAJOR(ctx->opcode);
30077 rs = (ctx->opcode >> 21) & 0x1f;
30078 rt = (ctx->opcode >> 16) & 0x1f;
30079 rd = (ctx->opcode >> 11) & 0x1f;
30080 sa = (ctx->opcode >> 6) & 0x1f;
30081 imm = (int16_t)ctx->opcode;
30082 switch (op) {
30083 case OPC_SPECIAL:
30084 decode_opc_special(env, ctx);
30085 break;
30086 case OPC_SPECIAL2:
30087 #if defined(TARGET_MIPS64)
30088 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30089 decode_mmi(env, ctx);
30090 #else
30091 if (ctx->insn_flags & ASE_MXU) {
30092 decode_opc_mxu(env, ctx);
30093 #endif
30094 } else {
30095 decode_opc_special2_legacy(env, ctx);
30097 break;
30098 case OPC_SPECIAL3:
30099 #if defined(TARGET_MIPS64)
30100 if (ctx->insn_flags & INSN_R5900) {
30101 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30102 } else {
30103 decode_opc_special3(env, ctx);
30105 #else
30106 decode_opc_special3(env, ctx);
30107 #endif
30108 break;
30109 case OPC_REGIMM:
30110 op1 = MASK_REGIMM(ctx->opcode);
30111 switch (op1) {
30112 case OPC_BLTZL: /* REGIMM branches */
30113 case OPC_BGEZL:
30114 case OPC_BLTZALL:
30115 case OPC_BGEZALL:
30116 check_insn(ctx, ISA_MIPS2);
30117 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30118 /* Fallthrough */
30119 case OPC_BLTZ:
30120 case OPC_BGEZ:
30121 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30122 break;
30123 case OPC_BLTZAL:
30124 case OPC_BGEZAL:
30125 if (ctx->insn_flags & ISA_MIPS32R6) {
30126 if (rs == 0) {
30127 /* OPC_NAL, OPC_BAL */
30128 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30129 } else {
30130 generate_exception_end(ctx, EXCP_RI);
30132 } else {
30133 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30135 break;
30136 case OPC_TGEI: /* REGIMM traps */
30137 case OPC_TGEIU:
30138 case OPC_TLTI:
30139 case OPC_TLTIU:
30140 case OPC_TEQI:
30142 case OPC_TNEI:
30143 check_insn(ctx, ISA_MIPS2);
30144 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30145 gen_trap(ctx, op1, rs, -1, imm);
30146 break;
30147 case OPC_SIGRIE:
30148 check_insn(ctx, ISA_MIPS32R6);
30149 generate_exception_end(ctx, EXCP_RI);
30150 break;
30151 case OPC_SYNCI:
30152 check_insn(ctx, ISA_MIPS32R2);
30154 * Break the TB to be able to sync copied instructions
30155 * immediately.
30157 ctx->base.is_jmp = DISAS_STOP;
30158 break;
30159 case OPC_BPOSGE32: /* MIPS DSP branch */
30160 #if defined(TARGET_MIPS64)
30161 case OPC_BPOSGE64:
30162 #endif
30163 check_dsp(ctx);
30164 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30165 break;
30166 #if defined(TARGET_MIPS64)
30167 case OPC_DAHI:
30168 check_insn(ctx, ISA_MIPS32R6);
30169 check_mips_64(ctx);
30170 if (rs != 0) {
30171 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30173 break;
30174 case OPC_DATI:
30175 check_insn(ctx, ISA_MIPS32R6);
30176 check_mips_64(ctx);
30177 if (rs != 0) {
30178 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30180 break;
30181 #endif
30182 default: /* Invalid */
30183 MIPS_INVAL("regimm");
30184 generate_exception_end(ctx, EXCP_RI);
30185 break;
30187 break;
30188 case OPC_CP0:
30189 check_cp0_enabled(ctx);
30190 op1 = MASK_CP0(ctx->opcode);
30191 switch (op1) {
30192 case OPC_MFC0:
30193 case OPC_MTC0:
30194 case OPC_MFTR:
30195 case OPC_MTTR:
30196 case OPC_MFHC0:
30197 case OPC_MTHC0:
30198 #if defined(TARGET_MIPS64)
30199 case OPC_DMFC0:
30200 case OPC_DMTC0:
30201 #endif
30202 #ifndef CONFIG_USER_ONLY
30203 gen_cp0(env, ctx, op1, rt, rd);
30204 #endif /* !CONFIG_USER_ONLY */
30205 break;
30206 case OPC_C0:
30207 case OPC_C0_1:
30208 case OPC_C0_2:
30209 case OPC_C0_3:
30210 case OPC_C0_4:
30211 case OPC_C0_5:
30212 case OPC_C0_6:
30213 case OPC_C0_7:
30214 case OPC_C0_8:
30215 case OPC_C0_9:
30216 case OPC_C0_A:
30217 case OPC_C0_B:
30218 case OPC_C0_C:
30219 case OPC_C0_D:
30220 case OPC_C0_E:
30221 case OPC_C0_F:
30222 #ifndef CONFIG_USER_ONLY
30223 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30224 #endif /* !CONFIG_USER_ONLY */
30225 break;
30226 case OPC_MFMC0:
30227 #ifndef CONFIG_USER_ONLY
30229 uint32_t op2;
30230 TCGv t0 = tcg_temp_new();
30232 op2 = MASK_MFMC0(ctx->opcode);
30233 switch (op2) {
30234 case OPC_DMT:
30235 check_cp0_mt(ctx);
30236 gen_helper_dmt(t0);
30237 gen_store_gpr(t0, rt);
30238 break;
30239 case OPC_EMT:
30240 check_cp0_mt(ctx);
30241 gen_helper_emt(t0);
30242 gen_store_gpr(t0, rt);
30243 break;
30244 case OPC_DVPE:
30245 check_cp0_mt(ctx);
30246 gen_helper_dvpe(t0, cpu_env);
30247 gen_store_gpr(t0, rt);
30248 break;
30249 case OPC_EVPE:
30250 check_cp0_mt(ctx);
30251 gen_helper_evpe(t0, cpu_env);
30252 gen_store_gpr(t0, rt);
30253 break;
30254 case OPC_DVP:
30255 check_insn(ctx, ISA_MIPS32R6);
30256 if (ctx->vp) {
30257 gen_helper_dvp(t0, cpu_env);
30258 gen_store_gpr(t0, rt);
30260 break;
30261 case OPC_EVP:
30262 check_insn(ctx, ISA_MIPS32R6);
30263 if (ctx->vp) {
30264 gen_helper_evp(t0, cpu_env);
30265 gen_store_gpr(t0, rt);
30267 break;
30268 case OPC_DI:
30269 check_insn(ctx, ISA_MIPS32R2);
30270 save_cpu_state(ctx, 1);
30271 gen_helper_di(t0, cpu_env);
30272 gen_store_gpr(t0, rt);
30274 * Stop translation as we may have switched
30275 * the execution mode.
30277 ctx->base.is_jmp = DISAS_STOP;
30278 break;
30279 case OPC_EI:
30280 check_insn(ctx, ISA_MIPS32R2);
30281 save_cpu_state(ctx, 1);
30282 gen_helper_ei(t0, cpu_env);
30283 gen_store_gpr(t0, rt);
30285 * DISAS_STOP isn't sufficient, we need to ensure we break
30286 * out of translated code to check for pending interrupts.
30288 gen_save_pc(ctx->base.pc_next + 4);
30289 ctx->base.is_jmp = DISAS_EXIT;
30290 break;
30291 default: /* Invalid */
30292 MIPS_INVAL("mfmc0");
30293 generate_exception_end(ctx, EXCP_RI);
30294 break;
30296 tcg_temp_free(t0);
30298 #endif /* !CONFIG_USER_ONLY */
30299 break;
30300 case OPC_RDPGPR:
30301 check_insn(ctx, ISA_MIPS32R2);
30302 gen_load_srsgpr(rt, rd);
30303 break;
30304 case OPC_WRPGPR:
30305 check_insn(ctx, ISA_MIPS32R2);
30306 gen_store_srsgpr(rt, rd);
30307 break;
30308 default:
30309 MIPS_INVAL("cp0");
30310 generate_exception_end(ctx, EXCP_RI);
30311 break;
30313 break;
30314 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30315 if (ctx->insn_flags & ISA_MIPS32R6) {
30316 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30317 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30318 } else {
30319 /* OPC_ADDI */
30320 /* Arithmetic with immediate opcode */
30321 gen_arith_imm(ctx, op, rt, rs, imm);
30323 break;
30324 case OPC_ADDIU:
30325 gen_arith_imm(ctx, op, rt, rs, imm);
30326 break;
30327 case OPC_SLTI: /* Set on less than with immediate opcode */
30328 case OPC_SLTIU:
30329 gen_slt_imm(ctx, op, rt, rs, imm);
30330 break;
30331 case OPC_ANDI: /* Arithmetic with immediate opcode */
30332 case OPC_LUI: /* OPC_AUI */
30333 case OPC_ORI:
30334 case OPC_XORI:
30335 gen_logic_imm(ctx, op, rt, rs, imm);
30336 break;
30337 case OPC_J: /* Jump */
30338 case OPC_JAL:
30339 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30340 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30341 break;
30342 /* Branch */
30343 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30344 if (ctx->insn_flags & ISA_MIPS32R6) {
30345 if (rt == 0) {
30346 generate_exception_end(ctx, EXCP_RI);
30347 break;
30349 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30350 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30351 } else {
30352 /* OPC_BLEZL */
30353 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30355 break;
30356 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30357 if (ctx->insn_flags & ISA_MIPS32R6) {
30358 if (rt == 0) {
30359 generate_exception_end(ctx, EXCP_RI);
30360 break;
30362 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30363 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30364 } else {
30365 /* OPC_BGTZL */
30366 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30368 break;
30369 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30370 if (rt == 0) {
30371 /* OPC_BLEZ */
30372 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30373 } else {
30374 check_insn(ctx, ISA_MIPS32R6);
30375 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30376 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30378 break;
30379 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30380 if (rt == 0) {
30381 /* OPC_BGTZ */
30382 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30383 } else {
30384 check_insn(ctx, ISA_MIPS32R6);
30385 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30386 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30388 break;
30389 case OPC_BEQL:
30390 case OPC_BNEL:
30391 check_insn(ctx, ISA_MIPS2);
30392 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30393 /* Fallthrough */
30394 case OPC_BEQ:
30395 case OPC_BNE:
30396 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30397 break;
30398 case OPC_LL: /* Load and stores */
30399 check_insn(ctx, ISA_MIPS2);
30400 if (ctx->insn_flags & INSN_R5900) {
30401 check_insn_opc_user_only(ctx, INSN_R5900);
30403 /* Fallthrough */
30404 case OPC_LWL:
30405 case OPC_LWR:
30406 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30407 /* Fallthrough */
30408 case OPC_LB:
30409 case OPC_LH:
30410 case OPC_LW:
30411 case OPC_LWPC:
30412 case OPC_LBU:
30413 case OPC_LHU:
30414 gen_ld(ctx, op, rt, rs, imm);
30415 break;
30416 case OPC_SWL:
30417 case OPC_SWR:
30418 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30419 /* fall through */
30420 case OPC_SB:
30421 case OPC_SH:
30422 case OPC_SW:
30423 gen_st(ctx, op, rt, rs, imm);
30424 break;
30425 case OPC_SC:
30426 check_insn(ctx, ISA_MIPS2);
30427 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30428 if (ctx->insn_flags & INSN_R5900) {
30429 check_insn_opc_user_only(ctx, INSN_R5900);
30431 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30432 break;
30433 case OPC_CACHE:
30434 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30435 check_cp0_enabled(ctx);
30436 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
30437 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30438 gen_cache_operation(ctx, rt, rs, imm);
30440 /* Treat as NOP. */
30441 break;
30442 case OPC_PREF:
30443 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30444 if (ctx->insn_flags & INSN_R5900) {
30445 /* Treat as NOP. */
30446 } else {
30447 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
30448 /* Treat as NOP. */
30450 break;
30452 /* Floating point (COP1). */
30453 case OPC_LWC1:
30454 case OPC_LDC1:
30455 case OPC_SWC1:
30456 case OPC_SDC1:
30457 gen_cop1_ldst(ctx, op, rt, rs, imm);
30458 break;
30460 case OPC_CP1:
30461 op1 = MASK_CP1(ctx->opcode);
30463 switch (op1) {
30464 case OPC_MFHC1:
30465 case OPC_MTHC1:
30466 check_cp1_enabled(ctx);
30467 check_insn(ctx, ISA_MIPS32R2);
30468 /* fall through */
30469 case OPC_MFC1:
30470 case OPC_CFC1:
30471 case OPC_MTC1:
30472 case OPC_CTC1:
30473 check_cp1_enabled(ctx);
30474 gen_cp1(ctx, op1, rt, rd);
30475 break;
30476 #if defined(TARGET_MIPS64)
30477 case OPC_DMFC1:
30478 case OPC_DMTC1:
30479 check_cp1_enabled(ctx);
30480 check_insn(ctx, ISA_MIPS3);
30481 check_mips_64(ctx);
30482 gen_cp1(ctx, op1, rt, rd);
30483 break;
30484 #endif
30485 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30486 check_cp1_enabled(ctx);
30487 if (ctx->insn_flags & ISA_MIPS32R6) {
30488 /* OPC_BC1EQZ */
30489 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30490 rt, imm << 2, 4);
30491 } else {
30492 /* OPC_BC1ANY2 */
30493 check_cop1x(ctx);
30494 check_insn(ctx, ASE_MIPS3D);
30495 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30496 (rt >> 2) & 0x7, imm << 2);
30498 break;
30499 case OPC_BC1NEZ:
30500 check_cp1_enabled(ctx);
30501 check_insn(ctx, ISA_MIPS32R6);
30502 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30503 rt, imm << 2, 4);
30504 break;
30505 case OPC_BC1ANY4:
30506 check_cp1_enabled(ctx);
30507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30508 check_cop1x(ctx);
30509 check_insn(ctx, ASE_MIPS3D);
30510 /* fall through */
30511 case OPC_BC1:
30512 check_cp1_enabled(ctx);
30513 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30514 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30515 (rt >> 2) & 0x7, imm << 2);
30516 break;
30517 case OPC_PS_FMT:
30518 check_ps(ctx);
30519 /* fall through */
30520 case OPC_S_FMT:
30521 case OPC_D_FMT:
30522 check_cp1_enabled(ctx);
30523 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30524 (imm >> 8) & 0x7);
30525 break;
30526 case OPC_W_FMT:
30527 case OPC_L_FMT:
30529 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30530 check_cp1_enabled(ctx);
30531 if (ctx->insn_flags & ISA_MIPS32R6) {
30532 switch (r6_op) {
30533 case R6_OPC_CMP_AF_S:
30534 case R6_OPC_CMP_UN_S:
30535 case R6_OPC_CMP_EQ_S:
30536 case R6_OPC_CMP_UEQ_S:
30537 case R6_OPC_CMP_LT_S:
30538 case R6_OPC_CMP_ULT_S:
30539 case R6_OPC_CMP_LE_S:
30540 case R6_OPC_CMP_ULE_S:
30541 case R6_OPC_CMP_SAF_S:
30542 case R6_OPC_CMP_SUN_S:
30543 case R6_OPC_CMP_SEQ_S:
30544 case R6_OPC_CMP_SEUQ_S:
30545 case R6_OPC_CMP_SLT_S:
30546 case R6_OPC_CMP_SULT_S:
30547 case R6_OPC_CMP_SLE_S:
30548 case R6_OPC_CMP_SULE_S:
30549 case R6_OPC_CMP_OR_S:
30550 case R6_OPC_CMP_UNE_S:
30551 case R6_OPC_CMP_NE_S:
30552 case R6_OPC_CMP_SOR_S:
30553 case R6_OPC_CMP_SUNE_S:
30554 case R6_OPC_CMP_SNE_S:
30555 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30556 break;
30557 case R6_OPC_CMP_AF_D:
30558 case R6_OPC_CMP_UN_D:
30559 case R6_OPC_CMP_EQ_D:
30560 case R6_OPC_CMP_UEQ_D:
30561 case R6_OPC_CMP_LT_D:
30562 case R6_OPC_CMP_ULT_D:
30563 case R6_OPC_CMP_LE_D:
30564 case R6_OPC_CMP_ULE_D:
30565 case R6_OPC_CMP_SAF_D:
30566 case R6_OPC_CMP_SUN_D:
30567 case R6_OPC_CMP_SEQ_D:
30568 case R6_OPC_CMP_SEUQ_D:
30569 case R6_OPC_CMP_SLT_D:
30570 case R6_OPC_CMP_SULT_D:
30571 case R6_OPC_CMP_SLE_D:
30572 case R6_OPC_CMP_SULE_D:
30573 case R6_OPC_CMP_OR_D:
30574 case R6_OPC_CMP_UNE_D:
30575 case R6_OPC_CMP_NE_D:
30576 case R6_OPC_CMP_SOR_D:
30577 case R6_OPC_CMP_SUNE_D:
30578 case R6_OPC_CMP_SNE_D:
30579 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
30580 break;
30581 default:
30582 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
30583 rt, rd, sa, (imm >> 8) & 0x7);
30585 break;
30587 } else {
30588 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30589 (imm >> 8) & 0x7);
30591 break;
30593 case OPC_BZ_V:
30594 case OPC_BNZ_V:
30595 case OPC_BZ_B:
30596 case OPC_BZ_H:
30597 case OPC_BZ_W:
30598 case OPC_BZ_D:
30599 case OPC_BNZ_B:
30600 case OPC_BNZ_H:
30601 case OPC_BNZ_W:
30602 case OPC_BNZ_D:
30603 check_insn(ctx, ASE_MSA);
30604 gen_msa_branch(env, ctx, op1);
30605 break;
30606 default:
30607 MIPS_INVAL("cp1");
30608 generate_exception_end(ctx, EXCP_RI);
30609 break;
30611 break;
30613 /* Compact branches [R6] and COP2 [non-R6] */
30614 case OPC_BC: /* OPC_LWC2 */
30615 case OPC_BALC: /* OPC_SWC2 */
30616 if (ctx->insn_flags & ISA_MIPS32R6) {
30617 /* OPC_BC, OPC_BALC */
30618 gen_compute_compact_branch(ctx, op, 0, 0,
30619 sextract32(ctx->opcode << 2, 0, 28));
30620 } else {
30621 /* OPC_LWC2, OPC_SWC2 */
30622 /* COP2: Not implemented. */
30623 generate_exception_err(ctx, EXCP_CpU, 2);
30625 break;
30626 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
30627 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
30628 if (ctx->insn_flags & ISA_MIPS32R6) {
30629 if (rs != 0) {
30630 /* OPC_BEQZC, OPC_BNEZC */
30631 gen_compute_compact_branch(ctx, op, rs, 0,
30632 sextract32(ctx->opcode << 2, 0, 23));
30633 } else {
30634 /* OPC_JIC, OPC_JIALC */
30635 gen_compute_compact_branch(ctx, op, 0, rt, imm);
30637 } else {
30638 /* OPC_LWC2, OPC_SWC2 */
30639 /* COP2: Not implemented. */
30640 generate_exception_err(ctx, EXCP_CpU, 2);
30642 break;
30643 case OPC_CP2:
30644 check_insn(ctx, INSN_LOONGSON2F);
30645 /* Note that these instructions use different fields. */
30646 gen_loongson_multimedia(ctx, sa, rd, rt);
30647 break;
30649 case OPC_CP3:
30650 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30651 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
30652 check_cp1_enabled(ctx);
30653 op1 = MASK_CP3(ctx->opcode);
30654 switch (op1) {
30655 case OPC_LUXC1:
30656 case OPC_SUXC1:
30657 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30658 /* Fallthrough */
30659 case OPC_LWXC1:
30660 case OPC_LDXC1:
30661 case OPC_SWXC1:
30662 case OPC_SDXC1:
30663 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30664 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
30665 break;
30666 case OPC_PREFX:
30667 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30668 /* Treat as NOP. */
30669 break;
30670 case OPC_ALNV_PS:
30671 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
30672 /* Fallthrough */
30673 case OPC_MADD_S:
30674 case OPC_MADD_D:
30675 case OPC_MADD_PS:
30676 case OPC_MSUB_S:
30677 case OPC_MSUB_D:
30678 case OPC_MSUB_PS:
30679 case OPC_NMADD_S:
30680 case OPC_NMADD_D:
30681 case OPC_NMADD_PS:
30682 case OPC_NMSUB_S:
30683 case OPC_NMSUB_D:
30684 case OPC_NMSUB_PS:
30685 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
30686 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
30687 break;
30688 default:
30689 MIPS_INVAL("cp3");
30690 generate_exception_end(ctx, EXCP_RI);
30691 break;
30693 } else {
30694 generate_exception_err(ctx, EXCP_CpU, 1);
30696 break;
30698 #if defined(TARGET_MIPS64)
30699 /* MIPS64 opcodes */
30700 case OPC_LLD:
30701 if (ctx->insn_flags & INSN_R5900) {
30702 check_insn_opc_user_only(ctx, INSN_R5900);
30704 /* fall through */
30705 case OPC_LDL:
30706 case OPC_LDR:
30707 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30708 /* fall through */
30709 case OPC_LWU:
30710 case OPC_LD:
30711 check_insn(ctx, ISA_MIPS3);
30712 check_mips_64(ctx);
30713 gen_ld(ctx, op, rt, rs, imm);
30714 break;
30715 case OPC_SDL:
30716 case OPC_SDR:
30717 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30718 /* fall through */
30719 case OPC_SD:
30720 check_insn(ctx, ISA_MIPS3);
30721 check_mips_64(ctx);
30722 gen_st(ctx, op, rt, rs, imm);
30723 break;
30724 case OPC_SCD:
30725 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30726 check_insn(ctx, ISA_MIPS3);
30727 if (ctx->insn_flags & INSN_R5900) {
30728 check_insn_opc_user_only(ctx, INSN_R5900);
30730 check_mips_64(ctx);
30731 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
30732 break;
30733 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
30734 if (ctx->insn_flags & ISA_MIPS32R6) {
30735 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
30736 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30737 } else {
30738 /* OPC_DADDI */
30739 check_insn(ctx, ISA_MIPS3);
30740 check_mips_64(ctx);
30741 gen_arith_imm(ctx, op, rt, rs, imm);
30743 break;
30744 case OPC_DADDIU:
30745 check_insn(ctx, ISA_MIPS3);
30746 check_mips_64(ctx);
30747 gen_arith_imm(ctx, op, rt, rs, imm);
30748 break;
30749 #else
30750 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
30751 if (ctx->insn_flags & ISA_MIPS32R6) {
30752 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30753 } else {
30754 MIPS_INVAL("major opcode");
30755 generate_exception_end(ctx, EXCP_RI);
30757 break;
30758 #endif
30759 case OPC_DAUI: /* OPC_JALX */
30760 if (ctx->insn_flags & ISA_MIPS32R6) {
30761 #if defined(TARGET_MIPS64)
30762 /* OPC_DAUI */
30763 check_mips_64(ctx);
30764 if (rs == 0) {
30765 generate_exception(ctx, EXCP_RI);
30766 } else if (rt != 0) {
30767 TCGv t0 = tcg_temp_new();
30768 gen_load_gpr(t0, rs);
30769 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
30770 tcg_temp_free(t0);
30772 #else
30773 generate_exception_end(ctx, EXCP_RI);
30774 MIPS_INVAL("major opcode");
30775 #endif
30776 } else {
30777 /* OPC_JALX */
30778 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
30779 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30780 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30782 break;
30783 case OPC_MSA: /* OPC_MDMX */
30784 if (ctx->insn_flags & INSN_R5900) {
30785 #if defined(TARGET_MIPS64)
30786 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
30787 #endif
30788 } else {
30789 /* MDMX: Not implemented. */
30790 gen_msa(env, ctx);
30792 break;
30793 case OPC_PCREL:
30794 check_insn(ctx, ISA_MIPS32R6);
30795 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
30796 break;
30797 default: /* Invalid */
30798 MIPS_INVAL("major opcode");
30799 generate_exception_end(ctx, EXCP_RI);
30800 break;
30804 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
30806 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30807 CPUMIPSState *env = cs->env_ptr;
30809 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
30810 ctx->saved_pc = -1;
30811 ctx->insn_flags = env->insn_flags;
30812 ctx->CP0_Config1 = env->CP0_Config1;
30813 ctx->CP0_Config2 = env->CP0_Config2;
30814 ctx->CP0_Config3 = env->CP0_Config3;
30815 ctx->CP0_Config5 = env->CP0_Config5;
30816 ctx->btarget = 0;
30817 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
30818 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
30819 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
30820 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
30821 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
30822 ctx->PAMask = env->PAMask;
30823 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
30824 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
30825 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
30826 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
30827 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
30828 /* Restore delay slot state from the tb context. */
30829 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
30830 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
30831 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
30832 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
30833 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
30834 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
30835 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
30836 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
30837 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
30838 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
30839 restore_cpu_state(env, ctx);
30840 #ifdef CONFIG_USER_ONLY
30841 ctx->mem_idx = MIPS_HFLAG_UM;
30842 #else
30843 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
30844 #endif
30845 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
30846 MO_UNALN : MO_ALIGN;
30848 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
30849 ctx->hflags);
30852 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
30856 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
30858 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30860 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
30861 ctx->btarget);
30864 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
30865 const CPUBreakpoint *bp)
30867 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30869 save_cpu_state(ctx, 1);
30870 ctx->base.is_jmp = DISAS_NORETURN;
30871 gen_helper_raise_exception_debug(cpu_env);
30873 * The address covered by the breakpoint must be included in
30874 * [tb->pc, tb->pc + tb->size) in order to for it to be
30875 * properly cleared -- thus we increment the PC here so that
30876 * the logic setting tb->size below does the right thing.
30878 ctx->base.pc_next += 4;
30879 return true;
30882 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
30884 CPUMIPSState *env = cs->env_ptr;
30885 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30886 int insn_bytes;
30887 int is_slot;
30889 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
30890 if (ctx->insn_flags & ISA_NANOMIPS32) {
30891 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30892 insn_bytes = decode_nanomips_opc(env, ctx);
30893 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
30894 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
30895 insn_bytes = 4;
30896 decode_opc(env, ctx);
30897 } else if (ctx->insn_flags & ASE_MICROMIPS) {
30898 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30899 insn_bytes = decode_micromips_opc(env, ctx);
30900 } else if (ctx->insn_flags & ASE_MIPS16) {
30901 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
30902 insn_bytes = decode_mips16_opc(env, ctx);
30903 } else {
30904 generate_exception_end(ctx, EXCP_RI);
30905 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
30906 return;
30909 if (ctx->hflags & MIPS_HFLAG_BMASK) {
30910 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
30911 MIPS_HFLAG_FBNSLOT))) {
30913 * Force to generate branch as there is neither delay nor
30914 * forbidden slot.
30916 is_slot = 1;
30918 if ((ctx->hflags & MIPS_HFLAG_M16) &&
30919 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
30921 * Force to generate branch as microMIPS R6 doesn't restrict
30922 * branches in the forbidden slot.
30924 is_slot = 1;
30927 if (is_slot) {
30928 gen_branch(ctx, insn_bytes);
30930 ctx->base.pc_next += insn_bytes;
30932 if (ctx->base.is_jmp != DISAS_NEXT) {
30933 return;
30936 * Execute a branch and its delay slot as a single instruction.
30937 * This is what GDB expects and is consistent with what the
30938 * hardware does (e.g. if a delay slot instruction faults, the
30939 * reported PC is the PC of the branch).
30941 if (ctx->base.singlestep_enabled &&
30942 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
30943 ctx->base.is_jmp = DISAS_TOO_MANY;
30945 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
30946 ctx->base.is_jmp = DISAS_TOO_MANY;
30950 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
30952 DisasContext *ctx = container_of(dcbase, DisasContext, base);
30954 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
30955 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
30956 gen_helper_raise_exception_debug(cpu_env);
30957 } else {
30958 switch (ctx->base.is_jmp) {
30959 case DISAS_STOP:
30960 gen_save_pc(ctx->base.pc_next);
30961 tcg_gen_lookup_and_goto_ptr();
30962 break;
30963 case DISAS_NEXT:
30964 case DISAS_TOO_MANY:
30965 save_cpu_state(ctx, 0);
30966 gen_goto_tb(ctx, 0, ctx->base.pc_next);
30967 break;
30968 case DISAS_EXIT:
30969 tcg_gen_exit_tb(NULL, 0);
30970 break;
30971 case DISAS_NORETURN:
30972 break;
30973 default:
30974 g_assert_not_reached();
30979 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
30981 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
30982 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
30985 static const TranslatorOps mips_tr_ops = {
30986 .init_disas_context = mips_tr_init_disas_context,
30987 .tb_start = mips_tr_tb_start,
30988 .insn_start = mips_tr_insn_start,
30989 .breakpoint_check = mips_tr_breakpoint_check,
30990 .translate_insn = mips_tr_translate_insn,
30991 .tb_stop = mips_tr_tb_stop,
30992 .disas_log = mips_tr_disas_log,
30995 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
30997 DisasContext ctx;
30999 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
31002 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
31004 int i;
31005 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
31007 #define printfpr(fp) \
31008 do { \
31009 if (is_fpu64) \
31010 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31011 " fd:%13g fs:%13g psu: %13g\n", \
31012 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31013 (double)(fp)->fd, \
31014 (double)(fp)->fs[FP_ENDIAN_IDX], \
31015 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
31016 else { \
31017 fpr_t tmp; \
31018 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31019 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
31020 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31021 " fd:%13g fs:%13g psu:%13g\n", \
31022 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31023 (double)tmp.fd, \
31024 (double)tmp.fs[FP_ENDIAN_IDX], \
31025 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31027 } while (0)
31030 qemu_fprintf(f,
31031 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31032 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31033 get_float_exception_flags(&env->active_fpu.fp_status));
31034 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31035 qemu_fprintf(f, "%3s: ", fregnames[i]);
31036 printfpr(&env->active_fpu.fpr[i]);
31039 #undef printfpr
31042 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31044 MIPSCPU *cpu = MIPS_CPU(cs);
31045 CPUMIPSState *env = &cpu->env;
31046 int i;
31048 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31049 " LO=0x" TARGET_FMT_lx " ds %04x "
31050 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31051 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31052 env->hflags, env->btarget, env->bcond);
31053 for (i = 0; i < 32; i++) {
31054 if ((i & 3) == 0) {
31055 qemu_fprintf(f, "GPR%02d:", i);
31057 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31058 regnames[i], env->active_tc.gpr[i]);
31059 if ((i & 3) == 3) {
31060 qemu_fprintf(f, "\n");
31064 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31065 TARGET_FMT_lx "\n",
31066 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31067 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31068 PRIx64 "\n",
31069 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31070 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31071 env->CP0_Config2, env->CP0_Config3);
31072 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31073 env->CP0_Config4, env->CP0_Config5);
31074 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31075 fpu_dump_state(env, f, flags);
31079 void mips_tcg_init(void)
31081 int i;
31083 cpu_gpr[0] = NULL;
31084 for (i = 1; i < 32; i++)
31085 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31086 offsetof(CPUMIPSState,
31087 active_tc.gpr[i]),
31088 regnames[i]);
31090 for (i = 0; i < 32; i++) {
31091 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31092 msa_wr_d[i * 2] =
31093 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31095 * The scalar floating-point unit (FPU) registers are mapped on
31096 * the MSA vector registers.
31098 fpu_f64[i] = msa_wr_d[i * 2];
31099 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31100 msa_wr_d[i * 2 + 1] =
31101 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31104 cpu_PC = tcg_global_mem_new(cpu_env,
31105 offsetof(CPUMIPSState, active_tc.PC), "PC");
31106 for (i = 0; i < MIPS_DSP_ACC; i++) {
31107 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31108 offsetof(CPUMIPSState, active_tc.HI[i]),
31109 regnames_HI[i]);
31110 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31111 offsetof(CPUMIPSState, active_tc.LO[i]),
31112 regnames_LO[i]);
31114 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31115 offsetof(CPUMIPSState,
31116 active_tc.DSPControl),
31117 "DSPControl");
31118 bcond = tcg_global_mem_new(cpu_env,
31119 offsetof(CPUMIPSState, bcond), "bcond");
31120 btarget = tcg_global_mem_new(cpu_env,
31121 offsetof(CPUMIPSState, btarget), "btarget");
31122 hflags = tcg_global_mem_new_i32(cpu_env,
31123 offsetof(CPUMIPSState, hflags), "hflags");
31125 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31126 offsetof(CPUMIPSState, active_fpu.fcr0),
31127 "fcr0");
31128 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31129 offsetof(CPUMIPSState, active_fpu.fcr31),
31130 "fcr31");
31131 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31132 "lladdr");
31133 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31134 "llval");
31136 #if defined(TARGET_MIPS64)
31137 cpu_mmr[0] = NULL;
31138 for (i = 1; i < 32; i++) {
31139 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31140 offsetof(CPUMIPSState,
31141 active_tc.mmr[i]),
31142 regnames[i]);
31144 #endif
31146 #if !defined(TARGET_MIPS64)
31147 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31148 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31149 offsetof(CPUMIPSState,
31150 active_tc.mxu_gpr[i]),
31151 mxuregnames[i]);
31154 mxu_CR = tcg_global_mem_new(cpu_env,
31155 offsetof(CPUMIPSState, active_tc.mxu_cr),
31156 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31157 #endif
31160 #include "translate_init.inc.c"
31162 void cpu_mips_realize_env(CPUMIPSState *env)
31164 env->exception_base = (int32_t)0xBFC00000;
31166 #ifndef CONFIG_USER_ONLY
31167 mmu_init(env, env->cpu_model);
31168 #endif
31169 fpu_init(env, env->cpu_model);
31170 mvp_init(env, env->cpu_model);
31173 bool cpu_supports_cps_smp(const char *cpu_type)
31175 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31176 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
31179 bool cpu_supports_isa(const char *cpu_type, uint64_t isa)
31181 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
31182 return (mcc->cpu_def->insn_flags & isa) != 0;
31185 void cpu_set_exception_base(int vp_index, target_ulong address)
31187 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
31188 vp->env.exception_base = address;
31191 void cpu_state_reset(CPUMIPSState *env)
31193 CPUState *cs = env_cpu(env);
31195 /* Reset registers to their default values */
31196 env->CP0_PRid = env->cpu_model->CP0_PRid;
31197 env->CP0_Config0 = env->cpu_model->CP0_Config0;
31198 #ifdef TARGET_WORDS_BIGENDIAN
31199 env->CP0_Config0 |= (1 << CP0C0_BE);
31200 #endif
31201 env->CP0_Config1 = env->cpu_model->CP0_Config1;
31202 env->CP0_Config2 = env->cpu_model->CP0_Config2;
31203 env->CP0_Config3 = env->cpu_model->CP0_Config3;
31204 env->CP0_Config4 = env->cpu_model->CP0_Config4;
31205 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
31206 env->CP0_Config5 = env->cpu_model->CP0_Config5;
31207 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
31208 env->CP0_Config6 = env->cpu_model->CP0_Config6;
31209 env->CP0_Config7 = env->cpu_model->CP0_Config7;
31210 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
31211 << env->cpu_model->CP0_LLAddr_shift;
31212 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
31213 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
31214 env->CCRes = env->cpu_model->CCRes;
31215 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
31216 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
31217 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
31218 env->current_tc = 0;
31219 env->SEGBITS = env->cpu_model->SEGBITS;
31220 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
31221 #if defined(TARGET_MIPS64)
31222 if (env->cpu_model->insn_flags & ISA_MIPS3) {
31223 env->SEGMask |= 3ULL << 62;
31225 #endif
31226 env->PABITS = env->cpu_model->PABITS;
31227 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
31228 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
31229 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
31230 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
31231 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
31232 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
31233 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
31234 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
31235 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
31236 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
31237 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
31238 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
31239 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
31240 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
31241 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
31242 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
31243 env->msair = env->cpu_model->MSAIR;
31244 env->insn_flags = env->cpu_model->insn_flags;
31246 #if defined(CONFIG_USER_ONLY)
31247 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
31248 # ifdef TARGET_MIPS64
31249 /* Enable 64-bit register mode. */
31250 env->CP0_Status |= (1 << CP0St_PX);
31251 # endif
31252 # ifdef TARGET_ABI_MIPSN64
31253 /* Enable 64-bit address mode. */
31254 env->CP0_Status |= (1 << CP0St_UX);
31255 # endif
31257 * Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
31258 * hardware registers.
31260 env->CP0_HWREna |= 0x0000000F;
31261 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
31262 env->CP0_Status |= (1 << CP0St_CU1);
31264 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
31265 env->CP0_Status |= (1 << CP0St_MX);
31267 # if defined(TARGET_MIPS64)
31268 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
31269 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
31270 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
31271 env->CP0_Status |= (1 << CP0St_FR);
31273 # endif
31274 #else
31275 if (env->hflags & MIPS_HFLAG_BMASK) {
31277 * If the exception was raised from a delay slot,
31278 * come back to the jump.
31280 env->CP0_ErrorEPC = (env->active_tc.PC
31281 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
31282 } else {
31283 env->CP0_ErrorEPC = env->active_tc.PC;
31285 env->active_tc.PC = env->exception_base;
31286 env->CP0_Random = env->tlb->nb_tlb - 1;
31287 env->tlb->tlb_in_use = env->tlb->nb_tlb;
31288 env->CP0_Wired = 0;
31289 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
31290 env->CP0_EBase = (cs->cpu_index & 0x3FF);
31291 if (mips_um_ksegs_enabled()) {
31292 env->CP0_EBase |= 0x40000000;
31293 } else {
31294 env->CP0_EBase |= (int32_t)0x80000000;
31296 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
31297 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
31299 env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ?
31300 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff;
31301 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
31303 * Vectored interrupts not implemented, timer on int 7,
31304 * no performance counters.
31306 env->CP0_IntCtl = 0xe0000000;
31308 int i;
31310 for (i = 0; i < 7; i++) {
31311 env->CP0_WatchLo[i] = 0;
31312 env->CP0_WatchHi[i] = 0x80000000;
31314 env->CP0_WatchLo[7] = 0;
31315 env->CP0_WatchHi[7] = 0;
31317 /* Count register increments in debug mode, EJTAG version 1 */
31318 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
31320 cpu_mips_store_count(env, 1);
31322 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
31323 int i;
31325 /* Only TC0 on VPE 0 starts as active. */
31326 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
31327 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
31328 env->tcs[i].CP0_TCHalt = 1;
31330 env->active_tc.CP0_TCHalt = 1;
31331 cs->halted = 1;
31333 if (cs->cpu_index == 0) {
31334 /* VPE0 starts up enabled. */
31335 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
31336 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
31338 /* TC0 starts up unhalted. */
31339 cs->halted = 0;
31340 env->active_tc.CP0_TCHalt = 0;
31341 env->tcs[0].CP0_TCHalt = 0;
31342 /* With thread 0 active. */
31343 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
31344 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
31349 * Configure default legacy segmentation control. We use this regardless of
31350 * whether segmentation control is presented to the guest.
31352 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
31353 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
31354 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
31355 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
31356 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
31357 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31358 (2 << CP0SC_C);
31359 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
31360 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
31361 (3 << CP0SC_C)) << 16;
31362 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
31363 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31364 (1 << CP0SC_EU) | (2 << CP0SC_C);
31365 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
31366 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
31367 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
31368 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
31369 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
31370 #endif
31371 if ((env->insn_flags & ISA_MIPS32R6) &&
31372 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
31373 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
31374 env->CP0_Status |= (1 << CP0St_FR);
31377 if (env->insn_flags & ISA_MIPS32R6) {
31378 /* PTW = 1 */
31379 env->CP0_PWSize = 0x40;
31380 /* GDI = 12 */
31381 /* UDI = 12 */
31382 /* MDI = 12 */
31383 /* PRI = 12 */
31384 /* PTEI = 2 */
31385 env->CP0_PWField = 0x0C30C302;
31386 } else {
31387 /* GDI = 0 */
31388 /* UDI = 0 */
31389 /* MDI = 0 */
31390 /* PRI = 0 */
31391 /* PTEI = 2 */
31392 env->CP0_PWField = 0x02;
31395 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
31396 /* microMIPS on reset when Config3.ISA is 3 */
31397 env->hflags |= MIPS_HFLAG_M16;
31400 /* MSA */
31401 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
31402 msa_reset(env);
31405 compute_hflags(env);
31406 restore_fp_status(env);
31407 restore_pamask(env);
31408 cs->exception_index = EXCP_NONE;
31410 if (semihosting_get_argc()) {
31411 /* UHI interface can be used to obtain argc and argv */
31412 env->active_tc.gpr[4] = -1;
31416 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31417 target_ulong *data)
31419 env->active_tc.PC = data[0];
31420 env->hflags &= ~MIPS_HFLAG_BMASK;
31421 env->hflags |= data[1];
31422 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31423 case MIPS_HFLAG_BR:
31424 break;
31425 case MIPS_HFLAG_BC:
31426 case MIPS_HFLAG_BL:
31427 case MIPS_HFLAG_B:
31428 env->btarget = data[2];
31429 break;