target/mips: Add nanoMIPS CRC32 instruction pool
[qemu/ar7.git] / target / mips / translate.c
blob4338b9a02228c3e9dc4278f1da72fbcb222a4020
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
467 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
468 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
469 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
470 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
473 /* DBSHFL opcodes */
474 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
476 enum {
477 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
478 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
479 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
480 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
481 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
482 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
483 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
484 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
485 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
486 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
487 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
490 /* MIPS DSP REGIMM opcodes */
491 enum {
492 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
493 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
496 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497 /* MIPS DSP Load */
498 enum {
499 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
500 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
501 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
502 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
505 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
506 enum {
507 /* MIPS DSP Arithmetic Sub-class */
508 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
511 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
512 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
518 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
519 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
520 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
521 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
522 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
523 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
525 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
526 /* MIPS DSP Multiply Sub-class insns */
527 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
528 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
529 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
530 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
531 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
532 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
535 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
536 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
537 enum {
538 /* MIPS DSP Arithmetic Sub-class */
539 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
543 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
548 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
549 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
551 /* MIPS DSP Multiply Sub-class insns */
552 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
553 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
554 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
555 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
558 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
559 enum {
560 /* MIPS DSP Arithmetic Sub-class */
561 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
574 /* DSP Bit/Manipulation Sub-class */
575 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
576 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
577 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
578 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
579 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
582 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
583 enum {
584 /* MIPS DSP Arithmetic Sub-class */
585 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
592 /* DSP Compare-Pick Sub-class */
593 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
603 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
604 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
605 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
606 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
607 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
610 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
611 enum {
612 /* MIPS DSP GPR-Based Shift Sub-class */
613 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
630 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
631 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
632 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
633 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
634 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
637 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
638 enum {
639 /* MIPS DSP Multiply Sub-class insns */
640 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
656 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
657 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
658 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
659 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
660 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
661 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
664 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
665 enum {
666 /* DSP Bit/Manipulation Sub-class */
667 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
670 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Append Sub-class */
673 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
674 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
675 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
678 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
679 enum {
680 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
681 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
688 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
689 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
690 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
691 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
692 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
693 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
694 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
695 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
696 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
697 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
700 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
701 enum {
702 /* MIPS DSP Arithmetic Sub-class */
703 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
720 /* DSP Bit/Manipulation Sub-class */
721 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
722 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
723 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
724 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
725 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
726 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
729 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
730 enum {
731 /* MIPS DSP Multiply Sub-class insns */
732 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
733 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
734 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
735 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
736 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
737 /* MIPS DSP Arithmetic Sub-class */
738 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
744 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
745 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
746 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
747 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
748 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
754 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
755 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
756 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
757 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
758 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
761 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
762 enum {
763 /* DSP Compare-Pick Sub-class */
764 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
783 /* MIPS DSP Arithmetic Sub-class */
784 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
787 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
788 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
789 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
790 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
791 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
794 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
795 enum {
796 /* DSP Append Sub-class */
797 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
798 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
799 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
800 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
803 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
806 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
807 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
822 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
823 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
824 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
825 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
826 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
829 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830 enum {
831 /* DSP Bit/Manipulation Sub-class */
832 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
835 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
836 enum {
837 /* MIPS DSP Multiply Sub-class insns */
838 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
859 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
860 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
861 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
862 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
863 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
866 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
867 enum {
868 /* MIPS DSP GPR-Based Shift Sub-class */
869 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
890 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
891 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
892 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
893 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
894 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
897 /* Coprocessor 0 (rs field) */
898 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
900 enum {
901 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
902 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
903 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
904 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
905 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
906 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
907 OPC_MFTR = (0x08 << 21) | OPC_CP0,
908 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
909 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
910 OPC_MTTR = (0x0C << 21) | OPC_CP0,
911 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
912 OPC_C0 = (0x10 << 21) | OPC_CP0,
913 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
914 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
915 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
916 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
917 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
918 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
919 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
920 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
921 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
922 OPC_C0_A = (0x1A << 21) | OPC_CP0,
923 OPC_C0_B = (0x1B << 21) | OPC_CP0,
924 OPC_C0_C = (0x1C << 21) | OPC_CP0,
925 OPC_C0_D = (0x1D << 21) | OPC_CP0,
926 OPC_C0_E = (0x1E << 21) | OPC_CP0,
927 OPC_C0_F = (0x1F << 21) | OPC_CP0,
930 /* MFMC0 opcodes */
931 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
933 enum {
934 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
935 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
936 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
937 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
938 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
939 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
940 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
941 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
944 /* Coprocessor 0 (with rs == C0) */
945 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
947 enum {
948 OPC_TLBR = 0x01 | OPC_C0,
949 OPC_TLBWI = 0x02 | OPC_C0,
950 OPC_TLBINV = 0x03 | OPC_C0,
951 OPC_TLBINVF = 0x04 | OPC_C0,
952 OPC_TLBWR = 0x06 | OPC_C0,
953 OPC_TLBP = 0x08 | OPC_C0,
954 OPC_RFE = 0x10 | OPC_C0,
955 OPC_ERET = 0x18 | OPC_C0,
956 OPC_DERET = 0x1F | OPC_C0,
957 OPC_WAIT = 0x20 | OPC_C0,
960 /* Coprocessor 1 (rs field) */
961 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
963 /* Values for the fmt field in FP instructions */
964 enum {
965 /* 0 - 15 are reserved */
966 FMT_S = 16, /* single fp */
967 FMT_D = 17, /* double fp */
968 FMT_E = 18, /* extended fp */
969 FMT_Q = 19, /* quad fp */
970 FMT_W = 20, /* 32-bit fixed */
971 FMT_L = 21, /* 64-bit fixed */
972 FMT_PS = 22, /* paired single fp */
973 /* 23 - 31 are reserved */
976 enum {
977 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
978 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
979 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
980 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
981 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
982 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
983 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
984 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
985 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
986 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
987 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
988 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
989 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
990 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
991 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
992 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
993 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
994 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
995 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
996 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
997 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
998 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
999 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1000 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1001 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1002 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1003 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1004 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1005 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1006 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1009 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1010 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1012 enum {
1013 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1014 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1015 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1016 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1019 enum {
1020 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1021 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1024 enum {
1025 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1026 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1029 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1031 enum {
1032 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1033 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1034 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1035 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1036 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1037 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1038 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1039 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1040 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1041 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1042 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1045 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1047 enum {
1048 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1049 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1050 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1051 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1052 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1053 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1054 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1055 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1057 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1059 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1060 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1061 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1062 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1063 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1064 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1066 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1067 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1068 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1069 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1070 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1071 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1072 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1073 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1075 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1076 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1077 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1078 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1079 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1080 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1081 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1082 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1084 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1085 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1086 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1087 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1088 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1089 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1091 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1092 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1093 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1094 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1095 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1096 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1098 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1099 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1100 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1101 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1102 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1103 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1105 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1106 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1107 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1108 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1109 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1110 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1112 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1113 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1114 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1115 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1116 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1117 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1119 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1120 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1121 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1122 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1123 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1124 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1126 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1127 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1128 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1129 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1130 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1131 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1133 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1134 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1135 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1136 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1137 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1138 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1142 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1144 enum {
1145 OPC_LWXC1 = 0x00 | OPC_CP3,
1146 OPC_LDXC1 = 0x01 | OPC_CP3,
1147 OPC_LUXC1 = 0x05 | OPC_CP3,
1148 OPC_SWXC1 = 0x08 | OPC_CP3,
1149 OPC_SDXC1 = 0x09 | OPC_CP3,
1150 OPC_SUXC1 = 0x0D | OPC_CP3,
1151 OPC_PREFX = 0x0F | OPC_CP3,
1152 OPC_ALNV_PS = 0x1E | OPC_CP3,
1153 OPC_MADD_S = 0x20 | OPC_CP3,
1154 OPC_MADD_D = 0x21 | OPC_CP3,
1155 OPC_MADD_PS = 0x26 | OPC_CP3,
1156 OPC_MSUB_S = 0x28 | OPC_CP3,
1157 OPC_MSUB_D = 0x29 | OPC_CP3,
1158 OPC_MSUB_PS = 0x2E | OPC_CP3,
1159 OPC_NMADD_S = 0x30 | OPC_CP3,
1160 OPC_NMADD_D = 0x31 | OPC_CP3,
1161 OPC_NMADD_PS= 0x36 | OPC_CP3,
1162 OPC_NMSUB_S = 0x38 | OPC_CP3,
1163 OPC_NMSUB_D = 0x39 | OPC_CP3,
1164 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1167 /* MSA Opcodes */
1168 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1169 enum {
1170 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1171 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1172 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1173 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1174 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1175 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1176 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1177 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1178 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1179 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1180 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1181 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1182 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1183 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1184 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1185 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1186 OPC_MSA_ELM = 0x19 | OPC_MSA,
1187 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1188 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1189 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1190 OPC_MSA_VEC = 0x1E | OPC_MSA,
1192 /* MI10 instruction */
1193 OPC_LD_B = (0x20) | OPC_MSA,
1194 OPC_LD_H = (0x21) | OPC_MSA,
1195 OPC_LD_W = (0x22) | OPC_MSA,
1196 OPC_LD_D = (0x23) | OPC_MSA,
1197 OPC_ST_B = (0x24) | OPC_MSA,
1198 OPC_ST_H = (0x25) | OPC_MSA,
1199 OPC_ST_W = (0x26) | OPC_MSA,
1200 OPC_ST_D = (0x27) | OPC_MSA,
1203 enum {
1204 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1205 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1206 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1207 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1208 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1209 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1210 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1211 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1212 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1213 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1214 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1215 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1216 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1218 /* I8 instruction */
1219 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1220 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1221 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1222 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1223 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1224 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1225 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1226 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1227 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1228 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1230 /* VEC/2R/2RF instruction */
1231 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1232 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1233 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1234 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1235 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1236 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1237 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1239 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1240 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1242 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1243 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1244 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1245 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1246 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1248 /* 2RF instruction df(bit 16) = _w, _d */
1249 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1250 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1251 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1252 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1253 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1254 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1255 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1256 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1257 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1258 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1259 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1260 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1261 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1262 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1263 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1264 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1266 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1267 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1268 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1269 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1270 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1272 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1274 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1275 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1276 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1277 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1278 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1279 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1280 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1281 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1282 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1283 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1284 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1285 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1286 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1287 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1288 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1289 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1290 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1292 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1293 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1294 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1295 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1296 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1297 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1298 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1299 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1300 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1301 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1302 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1303 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1304 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1305 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1306 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1307 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1308 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1309 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1310 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1311 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1312 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1313 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1314 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1315 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1316 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1317 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1318 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1319 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1320 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1321 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1322 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1323 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1324 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1325 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1326 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1327 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1328 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1329 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1331 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1332 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1333 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1334 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1335 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1336 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1337 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1338 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1339 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1340 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1342 /* 3RF instruction _df(bit 21) = _w, _d */
1343 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1346 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1347 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1348 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1350 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1351 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1352 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1353 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1356 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1357 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1359 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1361 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1362 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1363 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1364 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1365 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1366 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1367 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1369 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1370 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1372 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1373 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1374 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1375 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1376 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1377 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1378 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1379 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1380 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1381 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1382 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1383 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1385 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1386 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1387 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1388 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1389 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1390 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1391 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1392 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1393 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1394 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1395 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1396 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1397 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1402 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1403 * ============================================
1405 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1406 * instructions set. It is designed to fit the needs of signal, graphical and
1407 * video processing applications. MXU instruction set is used in Xburst family
1408 * of microprocessors by Ingenic.
1410 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1411 * the control register.
1413 * The notation used in MXU assembler mnemonics:
1415 * XRa, XRb, XRc, XRd - MXU registers
1416 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1417 * s12 - a subfield of an instruction code
1418 * strd2 - a subfield of an instruction code
1419 * eptn2 - a subfield of an instruction code
1420 * eptn3 - a subfield of an instruction code
1421 * optn2 - a subfield of an instruction code
1422 * optn3 - a subfield of an instruction code
1423 * sft4 - a subfield of an instruction code
1425 * Load/Store instructions Multiplication instructions
1426 * ----------------------- ---------------------------
1428 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1429 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1430 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1431 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1432 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1433 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1434 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1435 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1436 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1437 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1438 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1439 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1440 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1441 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1442 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1443 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1444 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1445 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1446 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1447 * S16SDI XRa, Rb, s10, eptn2
1448 * S8LDD XRa, Rb, s8, eptn3
1449 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1450 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1451 * S8SDI XRa, Rb, s8, eptn3
1452 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1453 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1454 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1455 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1456 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1457 * S32CPS XRa, XRb, XRc
1458 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1459 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1460 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1461 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1462 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1463 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1464 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1465 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1466 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1467 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1468 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1469 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1470 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1471 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1472 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1473 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1474 * Q8SLT XRa, XRb, XRc
1475 * Q8SLTU XRa, XRb, XRc
1476 * Q8MOVZ XRa, XRb, XRc Shift instructions
1477 * Q8MOVN XRa, XRb, XRc ------------------
1479 * D32SLL XRa, XRb, XRc, XRd, sft4
1480 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1481 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1482 * D32SARL XRa, XRb, XRc, sft4
1483 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1484 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1485 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1486 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1487 * Q16SLL XRa, XRb, XRc, XRd, sft4
1488 * Q16SLR XRa, XRb, XRc, XRd, sft4
1489 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1490 * ------------------------- Q16SLLV XRa, XRb, Rb
1491 * Q16SLRV XRa, XRb, Rb
1492 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1493 * S32ALN XRa, XRb, XRc, Rb
1494 * S32ALNI XRa, XRb, XRc, s3
1495 * S32LUI XRa, s8, optn3 Move instructions
1496 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1497 * S32EXTRV XRa, XRb, Rs, Rt
1498 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1499 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1502 * bits
1503 * 05..00
1505 * ┌─ 000000 ─ OPC_MXU_S32MADD
1506 * ├─ 000001 ─ OPC_MXU_S32MADDU
1507 * ├─ 000010 ─ <not assigned>
1508 * │ 20..18
1509 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1510 * │ ├─ 001 ─ OPC_MXU_S32MIN
1511 * │ ├─ 010 ─ OPC_MXU_D16MAX
1512 * │ ├─ 011 ─ OPC_MXU_D16MIN
1513 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1514 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1515 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1516 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1517 * ├─ 000100 ─ OPC_MXU_S32MSUB
1518 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1519 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1520 * │ ├─ 001 ─ OPC_MXU_D16SLT
1521 * │ ├─ 010 ─ OPC_MXU_D16AVG
1522 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1523 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1524 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1525 * │ └─ 111 ─ OPC_MXU_Q8ADD
1526 * │
1527 * │ 20..18
1528 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1529 * │ ├─ 010 ─ OPC_MXU_D16CPS
1530 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1531 * │ └─ 110 ─ OPC_MXU_Q16SAT
1532 * ├─ 001000 ─ OPC_MXU_D16MUL
1533 * │ 25..24
1534 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1535 * │ └─ 01 ─ OPC_MXU_D16MULE
1536 * ├─ 001010 ─ OPC_MXU_D16MAC
1537 * ├─ 001011 ─ OPC_MXU_D16MACF
1538 * ├─ 001100 ─ OPC_MXU_D16MADL
1539 * │ 25..24
1540 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1541 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1542 * ├─ 001110 ─ OPC_MXU_Q16ADD
1543 * ├─ 001111 ─ OPC_MXU_D16MACE
1544 * │ 23
1545 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1546 * │ └─ 1 ─ OPC_MXU_S32LDDR
1547 * │
1548 * │ 23
1549 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1550 * │ └─ 1 ─ OPC_MXU_S32STDR
1551 * │
1552 * │ 13..10
1553 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1554 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1555 * │
1556 * │ 13..10
1557 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1558 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1559 * │
1560 * │ 23
1561 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1562 * │ └─ 1 ─ OPC_MXU_S32LDIR
1563 * │
1564 * │ 23
1565 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1566 * │ └─ 1 ─ OPC_MXU_S32SDIR
1567 * │
1568 * │ 13..10
1569 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1570 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1571 * │
1572 * │ 13..10
1573 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1574 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1575 * ├─ 011000 ─ OPC_MXU_D32ADD
1576 * │ 23..22
1577 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1578 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1579 * │ └─ 10 ─ OPC_MXU_D32ASUM
1580 * ├─ 011010 ─ <not assigned>
1581 * │ 23..22
1582 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1583 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1584 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1585 * │
1586 * │ 23..22
1587 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1588 * │ ├─ 01 ─ OPC_MXU_D8SUM
1589 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1590 * ├─ 011110 ─ <not assigned>
1591 * ├─ 011111 ─ <not assigned>
1592 * ├─ 100000 ─ <not assigned>
1593 * ├─ 100001 ─ <not assigned>
1594 * ├─ 100010 ─ OPC_MXU_S8LDD
1595 * ├─ 100011 ─ OPC_MXU_S8STD
1596 * ├─ 100100 ─ OPC_MXU_S8LDI
1597 * ├─ 100101 ─ OPC_MXU_S8SDI
1598 * │ 15..14
1599 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1600 * │ ├─ 00 ─ OPC_MXU_S32MULU
1601 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1602 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1603 * │
1604 * │ 20..18
1605 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1606 * │ ├─ 001 ─ OPC_MXU_S32ALN
1607 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1608 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1609 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1610 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1611 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1612 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1613 * ├─ 101000 ─ <not assigned>
1614 * ├─ 101001 ─ <not assigned>
1615 * ├─ 101010 ─ <not assigned>
1616 * ├─ 101011 ─ <not assigned>
1617 * ├─ 101100 ─ <not assigned>
1618 * ├─ 101101 ─ <not assigned>
1619 * ├─ 101110 ─ OPC_MXU_S32M2I
1620 * ├─ 101111 ─ OPC_MXU_S32I2M
1621 * ├─ 110000 ─ OPC_MXU_D32SLL
1622 * ├─ 110001 ─ OPC_MXU_D32SLR
1623 * ├─ 110010 ─ OPC_MXU_D32SARL
1624 * ├─ 110011 ─ OPC_MXU_D32SAR
1625 * ├─ 110100 ─ OPC_MXU_Q16SLL
1626 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1627 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1628 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1629 * │ ├─ 010 ─ OPC_MXU_D32SARV
1630 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1631 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1632 * │ └─ 101 ─ OPC_MXU_Q16SARV
1633 * ├─ 110111 ─ OPC_MXU_Q16SAR
1634 * │ 23..22
1635 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1636 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1637 * │
1638 * │ 20..18
1639 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1640 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1641 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1642 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1643 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1644 * │ └─ 101 ─ OPC_MXU_S32MOV
1645 * │
1646 * │ 23..22
1647 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1648 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1649 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1650 * ├─ 111100 ─ OPC_MXU_Q8MADL
1651 * ├─ 111101 ─ OPC_MXU_S32SFL
1652 * ├─ 111110 ─ OPC_MXU_Q8SAD
1653 * └─ 111111 ─ <not assigned>
1656 * Compiled after:
1658 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1659 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1662 enum {
1663 OPC_MXU_S32MADD = 0x00,
1664 OPC_MXU_S32MADDU = 0x01,
1665 /* not assigned 0x02 */
1666 OPC_MXU__POOL00 = 0x03,
1667 OPC_MXU_S32MSUB = 0x04,
1668 OPC_MXU_S32MSUBU = 0x05,
1669 OPC_MXU__POOL01 = 0x06,
1670 OPC_MXU__POOL02 = 0x07,
1671 OPC_MXU_D16MUL = 0x08,
1672 OPC_MXU__POOL03 = 0x09,
1673 OPC_MXU_D16MAC = 0x0A,
1674 OPC_MXU_D16MACF = 0x0B,
1675 OPC_MXU_D16MADL = 0x0C,
1676 OPC_MXU__POOL04 = 0x0D,
1677 OPC_MXU_Q16ADD = 0x0E,
1678 OPC_MXU_D16MACE = 0x0F,
1679 OPC_MXU__POOL05 = 0x10,
1680 OPC_MXU__POOL06 = 0x11,
1681 OPC_MXU__POOL07 = 0x12,
1682 OPC_MXU__POOL08 = 0x13,
1683 OPC_MXU__POOL09 = 0x14,
1684 OPC_MXU__POOL10 = 0x15,
1685 OPC_MXU__POOL11 = 0x16,
1686 OPC_MXU__POOL12 = 0x17,
1687 OPC_MXU_D32ADD = 0x18,
1688 OPC_MXU__POOL13 = 0x19,
1689 /* not assigned 0x1A */
1690 OPC_MXU__POOL14 = 0x1B,
1691 OPC_MXU__POOL15 = 0x1C,
1692 OPC_MXU_Q8ACCE = 0x1D,
1693 /* not assigned 0x1E */
1694 /* not assigned 0x1F */
1695 /* not assigned 0x20 */
1696 /* not assigned 0x21 */
1697 OPC_MXU_S8LDD = 0x22,
1698 OPC_MXU_S8STD = 0x23,
1699 OPC_MXU_S8LDI = 0x24,
1700 OPC_MXU_S8SDI = 0x25,
1701 OPC_MXU__POOL16 = 0x26,
1702 OPC_MXU__POOL17 = 0x27,
1703 OPC_MXU_LXB = 0x28,
1704 /* not assigned 0x29 */
1705 OPC_MXU_S16LDD = 0x2A,
1706 OPC_MXU_S16STD = 0x2B,
1707 OPC_MXU_S16LDI = 0x2C,
1708 OPC_MXU_S16SDI = 0x2D,
1709 OPC_MXU_S32M2I = 0x2E,
1710 OPC_MXU_S32I2M = 0x2F,
1711 OPC_MXU_D32SLL = 0x30,
1712 OPC_MXU_D32SLR = 0x31,
1713 OPC_MXU_D32SARL = 0x32,
1714 OPC_MXU_D32SAR = 0x33,
1715 OPC_MXU_Q16SLL = 0x34,
1716 OPC_MXU_Q16SLR = 0x35,
1717 OPC_MXU__POOL18 = 0x36,
1718 OPC_MXU_Q16SAR = 0x37,
1719 OPC_MXU__POOL19 = 0x38,
1720 OPC_MXU__POOL20 = 0x39,
1721 OPC_MXU__POOL21 = 0x3A,
1722 OPC_MXU_Q16SCOP = 0x3B,
1723 OPC_MXU_Q8MADL = 0x3C,
1724 OPC_MXU_S32SFL = 0x3D,
1725 OPC_MXU_Q8SAD = 0x3E,
1726 /* not assigned 0x3F */
1731 * MXU pool 00
1733 enum {
1734 OPC_MXU_S32MAX = 0x00,
1735 OPC_MXU_S32MIN = 0x01,
1736 OPC_MXU_D16MAX = 0x02,
1737 OPC_MXU_D16MIN = 0x03,
1738 OPC_MXU_Q8MAX = 0x04,
1739 OPC_MXU_Q8MIN = 0x05,
1740 OPC_MXU_Q8SLT = 0x06,
1741 OPC_MXU_Q8SLTU = 0x07,
1745 * MXU pool 01
1747 enum {
1748 OPC_MXU_S32SLT = 0x00,
1749 OPC_MXU_D16SLT = 0x01,
1750 OPC_MXU_D16AVG = 0x02,
1751 OPC_MXU_D16AVGR = 0x03,
1752 OPC_MXU_Q8AVG = 0x04,
1753 OPC_MXU_Q8AVGR = 0x05,
1754 OPC_MXU_Q8ADD = 0x07,
1758 * MXU pool 02
1760 enum {
1761 OPC_MXU_S32CPS = 0x00,
1762 OPC_MXU_D16CPS = 0x02,
1763 OPC_MXU_Q8ABD = 0x04,
1764 OPC_MXU_Q16SAT = 0x06,
1768 * MXU pool 03
1770 enum {
1771 OPC_MXU_D16MULF = 0x00,
1772 OPC_MXU_D16MULE = 0x01,
1776 * MXU pool 04
1778 enum {
1779 OPC_MXU_S16MAD = 0x00,
1780 OPC_MXU_S16MAD_1 = 0x01,
1784 * MXU pool 05
1786 enum {
1787 OPC_MXU_S32LDD = 0x00,
1788 OPC_MXU_S32LDDR = 0x01,
1792 * MXU pool 06
1794 enum {
1795 OPC_MXU_S32STD = 0x00,
1796 OPC_MXU_S32STDR = 0x01,
1800 * MXU pool 07
1802 enum {
1803 OPC_MXU_S32LDDV = 0x00,
1804 OPC_MXU_S32LDDVR = 0x01,
1808 * MXU pool 08
1810 enum {
1811 OPC_MXU_S32STDV = 0x00,
1812 OPC_MXU_S32STDVR = 0x01,
1816 * MXU pool 09
1818 enum {
1819 OPC_MXU_S32LDI = 0x00,
1820 OPC_MXU_S32LDIR = 0x01,
1824 * MXU pool 10
1826 enum {
1827 OPC_MXU_S32SDI = 0x00,
1828 OPC_MXU_S32SDIR = 0x01,
1832 * MXU pool 11
1834 enum {
1835 OPC_MXU_S32LDIV = 0x00,
1836 OPC_MXU_S32LDIVR = 0x01,
1840 * MXU pool 12
1842 enum {
1843 OPC_MXU_S32SDIV = 0x00,
1844 OPC_MXU_S32SDIVR = 0x01,
1848 * MXU pool 13
1850 enum {
1851 OPC_MXU_D32ACC = 0x00,
1852 OPC_MXU_D32ACCM = 0x01,
1853 OPC_MXU_D32ASUM = 0x02,
1857 * MXU pool 14
1859 enum {
1860 OPC_MXU_Q16ACC = 0x00,
1861 OPC_MXU_Q16ACCM = 0x01,
1862 OPC_MXU_Q16ASUM = 0x02,
1866 * MXU pool 15
1868 enum {
1869 OPC_MXU_Q8ADDE = 0x00,
1870 OPC_MXU_D8SUM = 0x01,
1871 OPC_MXU_D8SUMC = 0x02,
1875 * MXU pool 16
1877 enum {
1878 OPC_MXU_S32MUL = 0x00,
1879 OPC_MXU_S32MULU = 0x01,
1880 OPC_MXU_S32EXTR = 0x02,
1881 OPC_MXU_S32EXTRV = 0x03,
1885 * MXU pool 17
1887 enum {
1888 OPC_MXU_D32SARW = 0x00,
1889 OPC_MXU_S32ALN = 0x01,
1890 OPC_MXU_S32ALNI = 0x02,
1891 OPC_MXU_S32NOR = 0x03,
1892 OPC_MXU_S32AND = 0x04,
1893 OPC_MXU_S32OR = 0x05,
1894 OPC_MXU_S32XOR = 0x06,
1895 OPC_MXU_S32LUI = 0x07,
1899 * MXU pool 18
1901 enum {
1902 OPC_MXU_D32SLLV = 0x00,
1903 OPC_MXU_D32SLRV = 0x01,
1904 OPC_MXU_D32SARV = 0x03,
1905 OPC_MXU_Q16SLLV = 0x04,
1906 OPC_MXU_Q16SLRV = 0x05,
1907 OPC_MXU_Q16SARV = 0x07,
1911 * MXU pool 19
1913 enum {
1914 OPC_MXU_Q8MUL = 0x00,
1915 OPC_MXU_Q8MULSU = 0x01,
1919 * MXU pool 20
1921 enum {
1922 OPC_MXU_Q8MOVZ = 0x00,
1923 OPC_MXU_Q8MOVN = 0x01,
1924 OPC_MXU_D16MOVZ = 0x02,
1925 OPC_MXU_D16MOVN = 0x03,
1926 OPC_MXU_S32MOVZ = 0x04,
1927 OPC_MXU_S32MOVN = 0x05,
1931 * MXU pool 21
1933 enum {
1934 OPC_MXU_Q8MAC = 0x00,
1935 OPC_MXU_Q8MACSU = 0x01,
1939 * Overview of the TX79-specific instruction set
1940 * =============================================
1942 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1943 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1944 * instructions and certain multimedia instructions (MMIs). These MMIs
1945 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1946 * or sixteen 8-bit paths.
1948 * Reference:
1950 * The Toshiba TX System RISC TX79 Core Architecture manual,
1951 * https://wiki.qemu.org/File:C790.pdf
1953 * Three-Operand Multiply and Multiply-Add (4 instructions)
1954 * --------------------------------------------------------
1955 * MADD [rd,] rs, rt Multiply/Add
1956 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1957 * MULT [rd,] rs, rt Multiply (3-operand)
1958 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1960 * Multiply Instructions for Pipeline 1 (10 instructions)
1961 * ------------------------------------------------------
1962 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1963 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1964 * DIV1 rs, rt Divide Pipeline 1
1965 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1966 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1967 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1968 * MFHI1 rd Move From HI1 Register
1969 * MFLO1 rd Move From LO1 Register
1970 * MTHI1 rs Move To HI1 Register
1971 * MTLO1 rs Move To LO1 Register
1973 * Arithmetic (19 instructions)
1974 * ----------------------------
1975 * PADDB rd, rs, rt Parallel Add Byte
1976 * PSUBB rd, rs, rt Parallel Subtract Byte
1977 * PADDH rd, rs, rt Parallel Add Halfword
1978 * PSUBH rd, rs, rt Parallel Subtract Halfword
1979 * PADDW rd, rs, rt Parallel Add Word
1980 * PSUBW rd, rs, rt Parallel Subtract Word
1981 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1982 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1983 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1984 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1985 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1986 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1987 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1988 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1989 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1990 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1991 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1992 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1993 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1995 * Min/Max (4 instructions)
1996 * ------------------------
1997 * PMAXH rd, rs, rt Parallel Maximum Halfword
1998 * PMINH rd, rs, rt Parallel Minimum Halfword
1999 * PMAXW rd, rs, rt Parallel Maximum Word
2000 * PMINW rd, rs, rt Parallel Minimum Word
2002 * Absolute (2 instructions)
2003 * -------------------------
2004 * PABSH rd, rt Parallel Absolute Halfword
2005 * PABSW rd, rt Parallel Absolute Word
2007 * Logical (4 instructions)
2008 * ------------------------
2009 * PAND rd, rs, rt Parallel AND
2010 * POR rd, rs, rt Parallel OR
2011 * PXOR rd, rs, rt Parallel XOR
2012 * PNOR rd, rs, rt Parallel NOR
2014 * Shift (9 instructions)
2015 * ----------------------
2016 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2017 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2018 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2019 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2020 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2021 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2022 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2023 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2024 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2026 * Compare (6 instructions)
2027 * ------------------------
2028 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2029 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2030 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2031 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2032 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2033 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2035 * LZC (1 instruction)
2036 * -------------------
2037 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2039 * Quadword Load and Store (2 instructions)
2040 * ----------------------------------------
2041 * LQ rt, offset(base) Load Quadword
2042 * SQ rt, offset(base) Store Quadword
2044 * Multiply and Divide (19 instructions)
2045 * -------------------------------------
2046 * PMULTW rd, rs, rt Parallel Multiply Word
2047 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2048 * PDIVW rs, rt Parallel Divide Word
2049 * PDIVUW rs, rt Parallel Divide Unsigned Word
2050 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2051 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2052 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2053 * PMULTH rd, rs, rt Parallel Multiply Halfword
2054 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2055 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2056 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2057 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2058 * PDIVBW rs, rt Parallel Divide Broadcast Word
2059 * PMFHI rd Parallel Move From HI Register
2060 * PMFLO rd Parallel Move From LO Register
2061 * PMTHI rs Parallel Move To HI Register
2062 * PMTLO rs Parallel Move To LO Register
2063 * PMFHL rd Parallel Move From HI/LO Register
2064 * PMTHL rs Parallel Move To HI/LO Register
2066 * Pack/Extend (11 instructions)
2067 * -----------------------------
2068 * PPAC5 rd, rt Parallel Pack to 5 bits
2069 * PPACB rd, rs, rt Parallel Pack to Byte
2070 * PPACH rd, rs, rt Parallel Pack to Halfword
2071 * PPACW rd, rs, rt Parallel Pack to Word
2072 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2073 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2074 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2075 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2076 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2077 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2078 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2080 * Others (16 instructions)
2081 * ------------------------
2082 * PCPYH rd, rt Parallel Copy Halfword
2083 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2084 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2085 * PREVH rd, rt Parallel Reverse Halfword
2086 * PINTH rd, rs, rt Parallel Interleave Halfword
2087 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2088 * PEXEH rd, rt Parallel Exchange Even Halfword
2089 * PEXCH rd, rt Parallel Exchange Center Halfword
2090 * PEXEW rd, rt Parallel Exchange Even Word
2091 * PEXCW rd, rt Parallel Exchange Center Word
2092 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2093 * MFSA rd Move from Shift Amount Register
2094 * MTSA rs Move to Shift Amount Register
2095 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2096 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2097 * PROT3W rd, rt Parallel Rotate 3 Words
2099 * The TX79-specific Multimedia Instruction encodings
2100 * ==================================================
2102 * TX79 Multimedia Instruction encoding table keys:
2104 * * This code is reserved for future use. An attempt to execute it
2105 * causes a Reserved Instruction exception.
2106 * % This code indicates an instruction class. The instruction word
2107 * must be further decoded by examining additional tables that show
2108 * the values for other instruction fields.
2109 * # This code is reserved for the unsupported instructions DMULT,
2110 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2111 * to execute it causes a Reserved Instruction exception.
2113 * TX79 Multimedia Instructions encoded by opcode field (MMI, LQ, SQ):
2115 * 31 26 0
2116 * +--------+----------------------------------------+
2117 * | opcode | |
2118 * +--------+----------------------------------------+
2120 * opcode bits 28..26
2121 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2122 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2123 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2124 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2125 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2126 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2127 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2128 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2129 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2130 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2131 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2134 enum {
2135 TX79_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2136 TX79_LQ = 0x1E << 26, /* Same as OPC_MSA */
2137 TX79_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2141 * TX79 Multimedia Instructions with opcode field = MMI:
2143 * 31 26 5 0
2144 * +--------+-------------------------------+--------+
2145 * | MMI | |function|
2146 * +--------+-------------------------------+--------+
2148 * function bits 2..0
2149 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2150 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2151 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2152 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2153 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2154 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2155 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2156 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2157 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2158 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2159 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2162 #define MASK_TX79_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2163 enum {
2164 TX79_MMI_MADD = 0x00 | TX79_CLASS_MMI, /* Same as OPC_MADD */
2165 TX79_MMI_MADDU = 0x01 | TX79_CLASS_MMI, /* Same as OPC_MADDU */
2166 TX79_MMI_PLZCW = 0x04 | TX79_CLASS_MMI,
2167 TX79_MMI_CLASS_MMI0 = 0x08 | TX79_CLASS_MMI,
2168 TX79_MMI_CLASS_MMI2 = 0x09 | TX79_CLASS_MMI,
2169 TX79_MMI_MFHI1 = 0x10 | TX79_CLASS_MMI, /* Same minor as OPC_MFHI */
2170 TX79_MMI_MTHI1 = 0x11 | TX79_CLASS_MMI, /* Same minor as OPC_MTHI */
2171 TX79_MMI_MFLO1 = 0x12 | TX79_CLASS_MMI, /* Same minor as OPC_MFLO */
2172 TX79_MMI_MTLO1 = 0x13 | TX79_CLASS_MMI, /* Same minor as OPC_MTLO */
2173 TX79_MMI_MULT1 = 0x18 | TX79_CLASS_MMI, /* Same minor as OPC_MULT */
2174 TX79_MMI_MULTU1 = 0x19 | TX79_CLASS_MMI, /* Same minor as OPC_MULTU */
2175 TX79_MMI_DIV1 = 0x1A | TX79_CLASS_MMI, /* Same minor as OPC_DIV */
2176 TX79_MMI_DIVU1 = 0x1B | TX79_CLASS_MMI, /* Same minor as OPC_DIVU */
2177 TX79_MMI_MADD1 = 0x20 | TX79_CLASS_MMI,
2178 TX79_MMI_MADDU1 = 0x21 | TX79_CLASS_MMI,
2179 TX79_MMI_CLASS_MMI1 = 0x28 | TX79_CLASS_MMI,
2180 TX79_MMI_CLASS_MMI3 = 0x29 | TX79_CLASS_MMI,
2181 TX79_MMI_PMFHL = 0x30 | TX79_CLASS_MMI,
2182 TX79_MMI_PMTHL = 0x31 | TX79_CLASS_MMI,
2183 TX79_MMI_PSLLH = 0x34 | TX79_CLASS_MMI,
2184 TX79_MMI_PSRLH = 0x36 | TX79_CLASS_MMI,
2185 TX79_MMI_PSRAH = 0x37 | TX79_CLASS_MMI,
2186 TX79_MMI_PSLLW = 0x3C | TX79_CLASS_MMI,
2187 TX79_MMI_PSRLW = 0x3E | TX79_CLASS_MMI,
2188 TX79_MMI_PSRAW = 0x3F | TX79_CLASS_MMI,
2192 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI0:
2194 * 31 26 10 6 5 0
2195 * +--------+----------------------+--------+--------+
2196 * | MMI | |function| MMI0 |
2197 * +--------+----------------------+--------+--------+
2199 * function bits 7..6
2200 * bits | 0 | 1 | 2 | 3
2201 * 10..8 | 00 | 01 | 10 | 11
2202 * -------+-------+-------+-------+-------
2203 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2204 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2205 * 2 010 | PADDB | PSUBB | PCGTB | *
2206 * 3 011 | * | * | * | *
2207 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2208 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2209 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2210 * 7 111 | * | * | PEXT5 | PPAC5
2213 #define MASK_TX79_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2214 enum {
2215 TX79_MMI0_PADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI0,
2216 TX79_MMI0_PSUBW = (0x01 << 6) | TX79_MMI_CLASS_MMI0,
2217 TX79_MMI0_PCGTW = (0x02 << 6) | TX79_MMI_CLASS_MMI0,
2218 TX79_MMI0_PMAXW = (0x03 << 6) | TX79_MMI_CLASS_MMI0,
2219 TX79_MMI0_PADDH = (0x04 << 6) | TX79_MMI_CLASS_MMI0,
2220 TX79_MMI0_PSUBH = (0x05 << 6) | TX79_MMI_CLASS_MMI0,
2221 TX79_MMI0_PCGTH = (0x06 << 6) | TX79_MMI_CLASS_MMI0,
2222 TX79_MMI0_PMAXH = (0x07 << 6) | TX79_MMI_CLASS_MMI0,
2223 TX79_MMI0_PADDB = (0x08 << 6) | TX79_MMI_CLASS_MMI0,
2224 TX79_MMI0_PSUBB = (0x09 << 6) | TX79_MMI_CLASS_MMI0,
2225 TX79_MMI0_PCGTB = (0x0A << 6) | TX79_MMI_CLASS_MMI0,
2226 TX79_MMI0_PADDSW = (0x10 << 6) | TX79_MMI_CLASS_MMI0,
2227 TX79_MMI0_PSUBSW = (0x11 << 6) | TX79_MMI_CLASS_MMI0,
2228 TX79_MMI0_PEXTLW = (0x12 << 6) | TX79_MMI_CLASS_MMI0,
2229 TX79_MMI0_PPACW = (0x13 << 6) | TX79_MMI_CLASS_MMI0,
2230 TX79_MMI0_PADDSH = (0x14 << 6) | TX79_MMI_CLASS_MMI0,
2231 TX79_MMI0_PSUBSH = (0x15 << 6) | TX79_MMI_CLASS_MMI0,
2232 TX79_MMI0_PEXTLH = (0x16 << 6) | TX79_MMI_CLASS_MMI0,
2233 TX79_MMI0_PPACH = (0x17 << 6) | TX79_MMI_CLASS_MMI0,
2234 TX79_MMI0_PADDSB = (0x18 << 6) | TX79_MMI_CLASS_MMI0,
2235 TX79_MMI0_PSUBSB = (0x19 << 6) | TX79_MMI_CLASS_MMI0,
2236 TX79_MMI0_PEXTLB = (0x1A << 6) | TX79_MMI_CLASS_MMI0,
2237 TX79_MMI0_PPACB = (0x1B << 6) | TX79_MMI_CLASS_MMI0,
2238 TX79_MMI0_PEXT5 = (0x1E << 6) | TX79_MMI_CLASS_MMI0,
2239 TX79_MMI0_PPAC5 = (0x1F << 6) | TX79_MMI_CLASS_MMI0,
2243 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI1:
2245 * 31 26 10 6 5 0
2246 * +--------+----------------------+--------+--------+
2247 * | MMI | |function| MMI1 |
2248 * +--------+----------------------+--------+--------+
2250 * function bits 7..6
2251 * bits | 0 | 1 | 2 | 3
2252 * 10..8 | 00 | 01 | 10 | 11
2253 * -------+-------+-------+-------+-------
2254 * 0 000 | * | PABSW | PCEQW | PMINW
2255 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2256 * 2 010 | * | * | PCEQB | *
2257 * 3 011 | * | * | * | *
2258 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2259 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2260 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2261 * 7 111 | * | * | * | *
2264 #define MASK_TX79_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2265 enum {
2266 TX79_MMI1_PABSW = (0x01 << 6) | TX79_MMI_CLASS_MMI1,
2267 TX79_MMI1_PCEQW = (0x02 << 6) | TX79_MMI_CLASS_MMI1,
2268 TX79_MMI1_PMINW = (0x03 << 6) | TX79_MMI_CLASS_MMI1,
2269 TX79_MMI1_PADSBH = (0x04 << 6) | TX79_MMI_CLASS_MMI1,
2270 TX79_MMI1_PABSH = (0x05 << 6) | TX79_MMI_CLASS_MMI1,
2271 TX79_MMI1_PCEQH = (0x06 << 6) | TX79_MMI_CLASS_MMI1,
2272 TX79_MMI1_PMINH = (0x07 << 6) | TX79_MMI_CLASS_MMI1,
2273 TX79_MMI1_PCEQB = (0x0A << 6) | TX79_MMI_CLASS_MMI1,
2274 TX79_MMI1_PADDUW = (0x10 << 6) | TX79_MMI_CLASS_MMI1,
2275 TX79_MMI1_PSUBUW = (0x11 << 6) | TX79_MMI_CLASS_MMI1,
2276 TX79_MMI1_PEXTUW = (0x12 << 6) | TX79_MMI_CLASS_MMI1,
2277 TX79_MMI1_PADDUH = (0x14 << 6) | TX79_MMI_CLASS_MMI1,
2278 TX79_MMI1_PSUBUH = (0x15 << 6) | TX79_MMI_CLASS_MMI1,
2279 TX79_MMI1_PEXTUH = (0x16 << 6) | TX79_MMI_CLASS_MMI1,
2280 TX79_MMI1_PADDUB = (0x18 << 6) | TX79_MMI_CLASS_MMI1,
2281 TX79_MMI1_PSUBUB = (0x19 << 6) | TX79_MMI_CLASS_MMI1,
2282 TX79_MMI1_PEXTUB = (0x1A << 6) | TX79_MMI_CLASS_MMI1,
2283 TX79_MMI1_QFSRV = (0x1B << 6) | TX79_MMI_CLASS_MMI1,
2287 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI2:
2289 * 31 26 10 6 5 0
2290 * +--------+----------------------+--------+--------+
2291 * | MMI | |function| MMI2 |
2292 * +--------+----------------------+--------+--------+
2294 * function bits 7..6
2295 * bits | 0 | 1 | 2 | 3
2296 * 10..8 | 00 | 01 | 10 | 11
2297 * -------+-------+-------+-------+-------
2298 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2299 * 1 001 | PMSUBW| * | * | *
2300 * 2 010 | PMFHI | PMFLO | PINTH | *
2301 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2302 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2303 * 5 101 | PMSUBH| PHMSBH| * | *
2304 * 6 110 | * | * | PEXEH | PREVH
2305 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2308 #define MASK_TX79_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2309 enum {
2310 TX79_MMI2_PMADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI2,
2311 TX79_MMI2_PSLLVW = (0x02 << 6) | TX79_MMI_CLASS_MMI2,
2312 TX79_MMI2_PSRLVW = (0x03 << 6) | TX79_MMI_CLASS_MMI2,
2313 TX79_MMI2_PMSUBW = (0x04 << 6) | TX79_MMI_CLASS_MMI2,
2314 TX79_MMI2_PMFHI = (0x08 << 6) | TX79_MMI_CLASS_MMI2,
2315 TX79_MMI2_PMFLO = (0x09 << 6) | TX79_MMI_CLASS_MMI2,
2316 TX79_MMI2_PINTH = (0x0A << 6) | TX79_MMI_CLASS_MMI2,
2317 TX79_MMI2_PMULTW = (0x0C << 6) | TX79_MMI_CLASS_MMI2,
2318 TX79_MMI2_PDIVW = (0x0D << 6) | TX79_MMI_CLASS_MMI2,
2319 TX79_MMI2_PCPYLD = (0x0E << 6) | TX79_MMI_CLASS_MMI2,
2320 TX79_MMI2_PMADDH = (0x10 << 6) | TX79_MMI_CLASS_MMI2,
2321 TX79_MMI2_PHMADH = (0x11 << 6) | TX79_MMI_CLASS_MMI2,
2322 TX79_MMI2_PAND = (0x12 << 6) | TX79_MMI_CLASS_MMI2,
2323 TX79_MMI2_PXOR = (0x13 << 6) | TX79_MMI_CLASS_MMI2,
2324 TX79_MMI2_PMSUBH = (0x14 << 6) | TX79_MMI_CLASS_MMI2,
2325 TX79_MMI2_PHMSBH = (0x15 << 6) | TX79_MMI_CLASS_MMI2,
2326 TX79_MMI2_PEXEH = (0x1A << 6) | TX79_MMI_CLASS_MMI2,
2327 TX79_MMI2_PREVH = (0x1B << 6) | TX79_MMI_CLASS_MMI2,
2328 TX79_MMI2_PMULTH = (0x1C << 6) | TX79_MMI_CLASS_MMI2,
2329 TX79_MMI2_PDIVBW = (0x1D << 6) | TX79_MMI_CLASS_MMI2,
2330 TX79_MMI2_PEXEW = (0x1E << 6) | TX79_MMI_CLASS_MMI2,
2331 TX79_MMI2_PROT3W = (0x1F << 6) | TX79_MMI_CLASS_MMI2,
2335 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI3:
2337 * 31 26 10 6 5 0
2338 * +--------+----------------------+--------+--------+
2339 * | MMI | |function| MMI3 |
2340 * +--------+----------------------+--------+--------+
2342 * function bits 7..6
2343 * bits | 0 | 1 | 2 | 3
2344 * 10..8 | 00 | 01 | 10 | 11
2345 * -------+-------+-------+-------+-------
2346 * 0 000 |PMADDUW| * | * | PSRAVW
2347 * 1 001 | * | * | * | *
2348 * 2 010 | PMTHI | PMTLO | PINTEH| *
2349 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2350 * 4 100 | * | * | POR | PNOR
2351 * 5 101 | * | * | * | *
2352 * 6 110 | * | * | PEXCH | PCPYH
2353 * 7 111 | * | * | PEXCW | *
2356 #define MASK_TX79_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2357 enum {
2358 TX79_MMI3_PMADDUW = (0x00 << 6) | TX79_MMI_CLASS_MMI3,
2359 TX79_MMI3_PSRAVW = (0x03 << 6) | TX79_MMI_CLASS_MMI3,
2360 TX79_MMI3_PMTHI = (0x08 << 6) | TX79_MMI_CLASS_MMI3,
2361 TX79_MMI3_PMTLO = (0x09 << 6) | TX79_MMI_CLASS_MMI3,
2362 TX79_MMI3_PINTEH = (0x0A << 6) | TX79_MMI_CLASS_MMI3,
2363 TX79_MMI3_PMULTUW = (0x0C << 6) | TX79_MMI_CLASS_MMI3,
2364 TX79_MMI3_PDIVUW = (0x0D << 6) | TX79_MMI_CLASS_MMI3,
2365 TX79_MMI3_PCPYUD = (0x0E << 6) | TX79_MMI_CLASS_MMI3,
2366 TX79_MMI3_POR = (0x12 << 6) | TX79_MMI_CLASS_MMI3,
2367 TX79_MMI3_PNOR = (0x13 << 6) | TX79_MMI_CLASS_MMI3,
2368 TX79_MMI3_PEXCH = (0x1A << 6) | TX79_MMI_CLASS_MMI3,
2369 TX79_MMI3_PCPYH = (0x1B << 6) | TX79_MMI_CLASS_MMI3,
2370 TX79_MMI3_PEXCW = (0x1E << 6) | TX79_MMI_CLASS_MMI3,
2373 /* global register indices */
2374 static TCGv cpu_gpr[32], cpu_PC;
2375 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2376 static TCGv cpu_dspctrl, btarget, bcond;
2377 static TCGv_i32 hflags;
2378 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2379 static TCGv_i64 fpu_f64[32];
2380 static TCGv_i64 msa_wr_d[64];
2382 #include "exec/gen-icount.h"
2384 #define gen_helper_0e0i(name, arg) do { \
2385 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2386 gen_helper_##name(cpu_env, helper_tmp); \
2387 tcg_temp_free_i32(helper_tmp); \
2388 } while(0)
2390 #define gen_helper_0e1i(name, arg1, arg2) do { \
2391 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2392 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2393 tcg_temp_free_i32(helper_tmp); \
2394 } while(0)
2396 #define gen_helper_1e0i(name, ret, arg1) do { \
2397 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2398 gen_helper_##name(ret, cpu_env, helper_tmp); \
2399 tcg_temp_free_i32(helper_tmp); \
2400 } while(0)
2402 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2403 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2404 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2405 tcg_temp_free_i32(helper_tmp); \
2406 } while(0)
2408 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2409 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2410 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2411 tcg_temp_free_i32(helper_tmp); \
2412 } while(0)
2414 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2415 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2416 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2417 tcg_temp_free_i32(helper_tmp); \
2418 } while(0)
2420 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2421 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2422 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2423 tcg_temp_free_i32(helper_tmp); \
2424 } while(0)
2426 typedef struct DisasContext {
2427 DisasContextBase base;
2428 target_ulong saved_pc;
2429 target_ulong page_start;
2430 uint32_t opcode;
2431 uint64_t insn_flags;
2432 int32_t CP0_Config1;
2433 int32_t CP0_Config2;
2434 int32_t CP0_Config3;
2435 int32_t CP0_Config5;
2436 /* Routine used to access memory */
2437 int mem_idx;
2438 TCGMemOp default_tcg_memop_mask;
2439 uint32_t hflags, saved_hflags;
2440 target_ulong btarget;
2441 bool ulri;
2442 int kscrexist;
2443 bool rxi;
2444 int ie;
2445 bool bi;
2446 bool bp;
2447 uint64_t PAMask;
2448 bool mvh;
2449 bool eva;
2450 bool sc;
2451 int CP0_LLAddr_shift;
2452 bool ps;
2453 bool vp;
2454 bool cmgcr;
2455 bool mrp;
2456 bool nan2008;
2457 bool abs2008;
2458 } DisasContext;
2460 #define DISAS_STOP DISAS_TARGET_0
2461 #define DISAS_EXIT DISAS_TARGET_1
2463 static const char * const regnames[] = {
2464 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2465 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2466 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2467 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2470 static const char * const regnames_HI[] = {
2471 "HI0", "HI1", "HI2", "HI3",
2474 static const char * const regnames_LO[] = {
2475 "LO0", "LO1", "LO2", "LO3",
2478 static const char * const fregnames[] = {
2479 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2480 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2481 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2482 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2485 static const char * const msaregnames[] = {
2486 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2487 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2488 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2489 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2490 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2491 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2492 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2493 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2494 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2495 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2496 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2497 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2498 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2499 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2500 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2501 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2504 #define LOG_DISAS(...) \
2505 do { \
2506 if (MIPS_DEBUG_DISAS) { \
2507 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2509 } while (0)
2511 #define MIPS_INVAL(op) \
2512 do { \
2513 if (MIPS_DEBUG_DISAS) { \
2514 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2515 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2516 ctx->base.pc_next, ctx->opcode, op, \
2517 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2518 ((ctx->opcode >> 16) & 0x1F)); \
2520 } while (0)
2522 /* General purpose registers moves. */
2523 static inline void gen_load_gpr (TCGv t, int reg)
2525 if (reg == 0)
2526 tcg_gen_movi_tl(t, 0);
2527 else
2528 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2531 static inline void gen_store_gpr (TCGv t, int reg)
2533 if (reg != 0)
2534 tcg_gen_mov_tl(cpu_gpr[reg], t);
2537 /* Moves to/from shadow registers. */
2538 static inline void gen_load_srsgpr (int from, int to)
2540 TCGv t0 = tcg_temp_new();
2542 if (from == 0)
2543 tcg_gen_movi_tl(t0, 0);
2544 else {
2545 TCGv_i32 t2 = tcg_temp_new_i32();
2546 TCGv_ptr addr = tcg_temp_new_ptr();
2548 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2549 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2550 tcg_gen_andi_i32(t2, t2, 0xf);
2551 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2552 tcg_gen_ext_i32_ptr(addr, t2);
2553 tcg_gen_add_ptr(addr, cpu_env, addr);
2555 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2556 tcg_temp_free_ptr(addr);
2557 tcg_temp_free_i32(t2);
2559 gen_store_gpr(t0, to);
2560 tcg_temp_free(t0);
2563 static inline void gen_store_srsgpr (int from, int to)
2565 if (to != 0) {
2566 TCGv t0 = tcg_temp_new();
2567 TCGv_i32 t2 = tcg_temp_new_i32();
2568 TCGv_ptr addr = tcg_temp_new_ptr();
2570 gen_load_gpr(t0, from);
2571 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2572 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2573 tcg_gen_andi_i32(t2, t2, 0xf);
2574 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2575 tcg_gen_ext_i32_ptr(addr, t2);
2576 tcg_gen_add_ptr(addr, cpu_env, addr);
2578 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2579 tcg_temp_free_ptr(addr);
2580 tcg_temp_free_i32(t2);
2581 tcg_temp_free(t0);
2585 /* Tests */
2586 static inline void gen_save_pc(target_ulong pc)
2588 tcg_gen_movi_tl(cpu_PC, pc);
2591 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2593 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2594 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2595 gen_save_pc(ctx->base.pc_next);
2596 ctx->saved_pc = ctx->base.pc_next;
2598 if (ctx->hflags != ctx->saved_hflags) {
2599 tcg_gen_movi_i32(hflags, ctx->hflags);
2600 ctx->saved_hflags = ctx->hflags;
2601 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2602 case MIPS_HFLAG_BR:
2603 break;
2604 case MIPS_HFLAG_BC:
2605 case MIPS_HFLAG_BL:
2606 case MIPS_HFLAG_B:
2607 tcg_gen_movi_tl(btarget, ctx->btarget);
2608 break;
2613 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2615 ctx->saved_hflags = ctx->hflags;
2616 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2617 case MIPS_HFLAG_BR:
2618 break;
2619 case MIPS_HFLAG_BC:
2620 case MIPS_HFLAG_BL:
2621 case MIPS_HFLAG_B:
2622 ctx->btarget = env->btarget;
2623 break;
2627 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2629 TCGv_i32 texcp = tcg_const_i32(excp);
2630 TCGv_i32 terr = tcg_const_i32(err);
2631 save_cpu_state(ctx, 1);
2632 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2633 tcg_temp_free_i32(terr);
2634 tcg_temp_free_i32(texcp);
2635 ctx->base.is_jmp = DISAS_NORETURN;
2638 static inline void generate_exception(DisasContext *ctx, int excp)
2640 gen_helper_0e0i(raise_exception, excp);
2643 static inline void generate_exception_end(DisasContext *ctx, int excp)
2645 generate_exception_err(ctx, excp, 0);
2648 /* Floating point register moves. */
2649 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2651 if (ctx->hflags & MIPS_HFLAG_FRE) {
2652 generate_exception(ctx, EXCP_RI);
2654 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2657 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2659 TCGv_i64 t64;
2660 if (ctx->hflags & MIPS_HFLAG_FRE) {
2661 generate_exception(ctx, EXCP_RI);
2663 t64 = tcg_temp_new_i64();
2664 tcg_gen_extu_i32_i64(t64, t);
2665 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2666 tcg_temp_free_i64(t64);
2669 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2671 if (ctx->hflags & MIPS_HFLAG_F64) {
2672 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2673 } else {
2674 gen_load_fpr32(ctx, t, reg | 1);
2678 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2680 if (ctx->hflags & MIPS_HFLAG_F64) {
2681 TCGv_i64 t64 = tcg_temp_new_i64();
2682 tcg_gen_extu_i32_i64(t64, t);
2683 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2684 tcg_temp_free_i64(t64);
2685 } else {
2686 gen_store_fpr32(ctx, t, reg | 1);
2690 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2692 if (ctx->hflags & MIPS_HFLAG_F64) {
2693 tcg_gen_mov_i64(t, fpu_f64[reg]);
2694 } else {
2695 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2699 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2701 if (ctx->hflags & MIPS_HFLAG_F64) {
2702 tcg_gen_mov_i64(fpu_f64[reg], t);
2703 } else {
2704 TCGv_i64 t0;
2705 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2706 t0 = tcg_temp_new_i64();
2707 tcg_gen_shri_i64(t0, t, 32);
2708 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2709 tcg_temp_free_i64(t0);
2713 static inline int get_fp_bit (int cc)
2715 if (cc)
2716 return 24 + cc;
2717 else
2718 return 23;
2721 /* Addresses computation */
2722 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2724 tcg_gen_add_tl(ret, arg0, arg1);
2726 #if defined(TARGET_MIPS64)
2727 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2728 tcg_gen_ext32s_i64(ret, ret);
2730 #endif
2733 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2734 target_long ofs)
2736 tcg_gen_addi_tl(ret, base, ofs);
2738 #if defined(TARGET_MIPS64)
2739 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2740 tcg_gen_ext32s_i64(ret, ret);
2742 #endif
2745 /* Addresses computation (translation time) */
2746 static target_long addr_add(DisasContext *ctx, target_long base,
2747 target_long offset)
2749 target_long sum = base + offset;
2751 #if defined(TARGET_MIPS64)
2752 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2753 sum = (int32_t)sum;
2755 #endif
2756 return sum;
2759 /* Sign-extract the low 32-bits to a target_long. */
2760 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2762 #if defined(TARGET_MIPS64)
2763 tcg_gen_ext32s_i64(ret, arg);
2764 #else
2765 tcg_gen_extrl_i64_i32(ret, arg);
2766 #endif
2769 /* Sign-extract the high 32-bits to a target_long. */
2770 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2772 #if defined(TARGET_MIPS64)
2773 tcg_gen_sari_i64(ret, arg, 32);
2774 #else
2775 tcg_gen_extrh_i64_i32(ret, arg);
2776 #endif
2779 static inline void check_cp0_enabled(DisasContext *ctx)
2781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2782 generate_exception_err(ctx, EXCP_CpU, 0);
2785 static inline void check_cp1_enabled(DisasContext *ctx)
2787 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2788 generate_exception_err(ctx, EXCP_CpU, 1);
2791 /* Verify that the processor is running with COP1X instructions enabled.
2792 This is associated with the nabla symbol in the MIPS32 and MIPS64
2793 opcode tables. */
2795 static inline void check_cop1x(DisasContext *ctx)
2797 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2798 generate_exception_end(ctx, EXCP_RI);
2801 /* Verify that the processor is running with 64-bit floating-point
2802 operations enabled. */
2804 static inline void check_cp1_64bitmode(DisasContext *ctx)
2806 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2807 generate_exception_end(ctx, EXCP_RI);
2811 * Verify if floating point register is valid; an operation is not defined
2812 * if bit 0 of any register specification is set and the FR bit in the
2813 * Status register equals zero, since the register numbers specify an
2814 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2815 * in the Status register equals one, both even and odd register numbers
2816 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2818 * Multiple 64 bit wide registers can be checked by calling
2819 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2821 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2823 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2824 generate_exception_end(ctx, EXCP_RI);
2827 /* Verify that the processor is running with DSP instructions enabled.
2828 This is enabled by CP0 Status register MX(24) bit.
2831 static inline void check_dsp(DisasContext *ctx)
2833 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2834 if (ctx->insn_flags & ASE_DSP) {
2835 generate_exception_end(ctx, EXCP_DSPDIS);
2836 } else {
2837 generate_exception_end(ctx, EXCP_RI);
2842 static inline void check_dsp_r2(DisasContext *ctx)
2844 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2845 if (ctx->insn_flags & ASE_DSP) {
2846 generate_exception_end(ctx, EXCP_DSPDIS);
2847 } else {
2848 generate_exception_end(ctx, EXCP_RI);
2853 static inline void check_dsp_r3(DisasContext *ctx)
2855 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2856 if (ctx->insn_flags & ASE_DSP) {
2857 generate_exception_end(ctx, EXCP_DSPDIS);
2858 } else {
2859 generate_exception_end(ctx, EXCP_RI);
2864 /* This code generates a "reserved instruction" exception if the
2865 CPU does not support the instruction set corresponding to flags. */
2866 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2868 if (unlikely(!(ctx->insn_flags & flags))) {
2869 generate_exception_end(ctx, EXCP_RI);
2873 /* This code generates a "reserved instruction" exception if the
2874 CPU has corresponding flag set which indicates that the instruction
2875 has been removed. */
2876 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2878 if (unlikely(ctx->insn_flags & flags)) {
2879 generate_exception_end(ctx, EXCP_RI);
2884 * The Linux kernel traps certain reserved instruction exceptions to
2885 * emulate the corresponding instructions. QEMU is the kernel in user
2886 * mode, so those traps are emulated by accepting the instructions.
2888 * A reserved instruction exception is generated for flagged CPUs if
2889 * QEMU runs in system mode.
2891 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2893 #ifndef CONFIG_USER_ONLY
2894 check_insn_opc_removed(ctx, flags);
2895 #endif
2898 /* This code generates a "reserved instruction" exception if the
2899 CPU does not support 64-bit paired-single (PS) floating point data type */
2900 static inline void check_ps(DisasContext *ctx)
2902 if (unlikely(!ctx->ps)) {
2903 generate_exception(ctx, EXCP_RI);
2905 check_cp1_64bitmode(ctx);
2908 #ifdef TARGET_MIPS64
2909 /* This code generates a "reserved instruction" exception if 64-bit
2910 instructions are not enabled. */
2911 static inline void check_mips_64(DisasContext *ctx)
2913 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2914 generate_exception_end(ctx, EXCP_RI);
2916 #endif
2918 #ifndef CONFIG_USER_ONLY
2919 static inline void check_mvh(DisasContext *ctx)
2921 if (unlikely(!ctx->mvh)) {
2922 generate_exception(ctx, EXCP_RI);
2925 #endif
2928 * This code generates a "reserved instruction" exception if the
2929 * Config5 XNP bit is set.
2931 static inline void check_xnp(DisasContext *ctx)
2933 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2934 generate_exception_end(ctx, EXCP_RI);
2938 #ifndef CONFIG_USER_ONLY
2940 * This code generates a "reserved instruction" exception if the
2941 * Config3 PW bit is NOT set.
2943 static inline void check_pw(DisasContext *ctx)
2945 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2946 generate_exception_end(ctx, EXCP_RI);
2949 #endif
2952 * This code generates a "reserved instruction" exception if the
2953 * Config3 MT bit is NOT set.
2955 static inline void check_mt(DisasContext *ctx)
2957 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2958 generate_exception_end(ctx, EXCP_RI);
2962 #ifndef CONFIG_USER_ONLY
2964 * This code generates a "coprocessor unusable" exception if CP0 is not
2965 * available, and, if that is not the case, generates a "reserved instruction"
2966 * exception if the Config5 MT bit is NOT set. This is needed for availability
2967 * control of some of MT ASE instructions.
2969 static inline void check_cp0_mt(DisasContext *ctx)
2971 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2972 generate_exception_err(ctx, EXCP_CpU, 0);
2973 } else {
2974 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2975 generate_exception_err(ctx, EXCP_RI, 0);
2979 #endif
2982 * This code generates a "reserved instruction" exception if the
2983 * Config5 NMS bit is set.
2985 static inline void check_nms(DisasContext *ctx)
2987 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2988 generate_exception_end(ctx, EXCP_RI);
2993 /* Define small wrappers for gen_load_fpr* so that we have a uniform
2994 calling interface for 32 and 64-bit FPRs. No sense in changing
2995 all callers for gen_load_fpr32 when we need the CTX parameter for
2996 this one use. */
2997 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2998 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2999 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3000 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3001 int ft, int fs, int cc) \
3003 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
3004 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
3005 switch (ifmt) { \
3006 case FMT_PS: \
3007 check_ps(ctx); \
3008 break; \
3009 case FMT_D: \
3010 if (abs) { \
3011 check_cop1x(ctx); \
3013 check_cp1_registers(ctx, fs | ft); \
3014 break; \
3015 case FMT_S: \
3016 if (abs) { \
3017 check_cop1x(ctx); \
3019 break; \
3021 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
3022 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3023 switch (n) { \
3024 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3025 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3026 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3027 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3028 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3029 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3030 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3031 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3032 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3033 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3034 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3035 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3036 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3037 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3038 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3039 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3040 default: abort(); \
3042 tcg_temp_free_i##bits (fp0); \
3043 tcg_temp_free_i##bits (fp1); \
3046 FOP_CONDS(, 0, d, FMT_D, 64)
3047 FOP_CONDS(abs, 1, d, FMT_D, 64)
3048 FOP_CONDS(, 0, s, FMT_S, 32)
3049 FOP_CONDS(abs, 1, s, FMT_S, 32)
3050 FOP_CONDS(, 0, ps, FMT_PS, 64)
3051 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3052 #undef FOP_CONDS
3054 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3055 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3056 int ft, int fs, int fd) \
3058 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3059 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3060 if (ifmt == FMT_D) { \
3061 check_cp1_registers(ctx, fs | ft | fd); \
3063 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3064 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3065 switch (n) { \
3066 case 0: \
3067 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3068 break; \
3069 case 1: \
3070 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3071 break; \
3072 case 2: \
3073 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3074 break; \
3075 case 3: \
3076 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3077 break; \
3078 case 4: \
3079 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3080 break; \
3081 case 5: \
3082 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3083 break; \
3084 case 6: \
3085 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3086 break; \
3087 case 7: \
3088 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3089 break; \
3090 case 8: \
3091 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3092 break; \
3093 case 9: \
3094 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3095 break; \
3096 case 10: \
3097 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3098 break; \
3099 case 11: \
3100 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3101 break; \
3102 case 12: \
3103 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3104 break; \
3105 case 13: \
3106 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3107 break; \
3108 case 14: \
3109 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3110 break; \
3111 case 15: \
3112 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3113 break; \
3114 case 17: \
3115 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3116 break; \
3117 case 18: \
3118 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3119 break; \
3120 case 19: \
3121 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3122 break; \
3123 case 25: \
3124 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3125 break; \
3126 case 26: \
3127 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3128 break; \
3129 case 27: \
3130 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3131 break; \
3132 default: \
3133 abort(); \
3135 STORE; \
3136 tcg_temp_free_i ## bits (fp0); \
3137 tcg_temp_free_i ## bits (fp1); \
3140 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3141 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3142 #undef FOP_CONDNS
3143 #undef gen_ldcmp_fpr32
3144 #undef gen_ldcmp_fpr64
3146 /* load/store instructions. */
3147 #ifdef CONFIG_USER_ONLY
3148 #define OP_LD_ATOMIC(insn,fname) \
3149 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3150 DisasContext *ctx) \
3152 TCGv t0 = tcg_temp_new(); \
3153 tcg_gen_mov_tl(t0, arg1); \
3154 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3155 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3156 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3157 tcg_temp_free(t0); \
3159 #else
3160 #define OP_LD_ATOMIC(insn,fname) \
3161 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3162 DisasContext *ctx) \
3164 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3166 #endif
3167 OP_LD_ATOMIC(ll,ld32s);
3168 #if defined(TARGET_MIPS64)
3169 OP_LD_ATOMIC(lld,ld64);
3170 #endif
3171 #undef OP_LD_ATOMIC
3173 #ifdef CONFIG_USER_ONLY
3174 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3175 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3176 DisasContext *ctx) \
3178 TCGv t0 = tcg_temp_new(); \
3179 TCGLabel *l1 = gen_new_label(); \
3180 TCGLabel *l2 = gen_new_label(); \
3182 tcg_gen_andi_tl(t0, arg2, almask); \
3183 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
3184 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
3185 generate_exception(ctx, EXCP_AdES); \
3186 gen_set_label(l1); \
3187 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3188 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3189 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
3190 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3191 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
3192 generate_exception_end(ctx, EXCP_SC); \
3193 gen_set_label(l2); \
3194 tcg_gen_movi_tl(t0, 0); \
3195 gen_store_gpr(t0, rt); \
3196 tcg_temp_free(t0); \
3198 #else
3199 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3200 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3201 DisasContext *ctx) \
3203 TCGv t0 = tcg_temp_new(); \
3204 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3205 gen_store_gpr(t0, rt); \
3206 tcg_temp_free(t0); \
3208 #endif
3209 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3210 #if defined(TARGET_MIPS64)
3211 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3212 #endif
3213 #undef OP_ST_ATOMIC
3215 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3216 int base, int offset)
3218 if (base == 0) {
3219 tcg_gen_movi_tl(addr, offset);
3220 } else if (offset == 0) {
3221 gen_load_gpr(addr, base);
3222 } else {
3223 tcg_gen_movi_tl(addr, offset);
3224 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3228 static target_ulong pc_relative_pc (DisasContext *ctx)
3230 target_ulong pc = ctx->base.pc_next;
3232 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3233 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3235 pc -= branch_bytes;
3238 pc &= ~(target_ulong)3;
3239 return pc;
3242 /* Load */
3243 static void gen_ld(DisasContext *ctx, uint32_t opc,
3244 int rt, int base, int offset)
3246 TCGv t0, t1, t2;
3247 int mem_idx = ctx->mem_idx;
3249 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3250 /* Loongson CPU uses a load to zero register for prefetch.
3251 We emulate it as a NOP. On other CPU we must perform the
3252 actual memory access. */
3253 return;
3256 t0 = tcg_temp_new();
3257 gen_base_offset_addr(ctx, t0, base, offset);
3259 switch (opc) {
3260 #if defined(TARGET_MIPS64)
3261 case OPC_LWU:
3262 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3263 ctx->default_tcg_memop_mask);
3264 gen_store_gpr(t0, rt);
3265 break;
3266 case OPC_LD:
3267 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3268 ctx->default_tcg_memop_mask);
3269 gen_store_gpr(t0, rt);
3270 break;
3271 case OPC_LLD:
3272 case R6_OPC_LLD:
3273 op_ld_lld(t0, t0, mem_idx, ctx);
3274 gen_store_gpr(t0, rt);
3275 break;
3276 case OPC_LDL:
3277 t1 = tcg_temp_new();
3278 /* Do a byte access to possibly trigger a page
3279 fault with the unaligned address. */
3280 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3281 tcg_gen_andi_tl(t1, t0, 7);
3282 #ifndef TARGET_WORDS_BIGENDIAN
3283 tcg_gen_xori_tl(t1, t1, 7);
3284 #endif
3285 tcg_gen_shli_tl(t1, t1, 3);
3286 tcg_gen_andi_tl(t0, t0, ~7);
3287 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3288 tcg_gen_shl_tl(t0, t0, t1);
3289 t2 = tcg_const_tl(-1);
3290 tcg_gen_shl_tl(t2, t2, t1);
3291 gen_load_gpr(t1, rt);
3292 tcg_gen_andc_tl(t1, t1, t2);
3293 tcg_temp_free(t2);
3294 tcg_gen_or_tl(t0, t0, t1);
3295 tcg_temp_free(t1);
3296 gen_store_gpr(t0, rt);
3297 break;
3298 case OPC_LDR:
3299 t1 = tcg_temp_new();
3300 /* Do a byte access to possibly trigger a page
3301 fault with the unaligned address. */
3302 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3303 tcg_gen_andi_tl(t1, t0, 7);
3304 #ifdef TARGET_WORDS_BIGENDIAN
3305 tcg_gen_xori_tl(t1, t1, 7);
3306 #endif
3307 tcg_gen_shli_tl(t1, t1, 3);
3308 tcg_gen_andi_tl(t0, t0, ~7);
3309 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3310 tcg_gen_shr_tl(t0, t0, t1);
3311 tcg_gen_xori_tl(t1, t1, 63);
3312 t2 = tcg_const_tl(0xfffffffffffffffeull);
3313 tcg_gen_shl_tl(t2, t2, t1);
3314 gen_load_gpr(t1, rt);
3315 tcg_gen_and_tl(t1, t1, t2);
3316 tcg_temp_free(t2);
3317 tcg_gen_or_tl(t0, t0, t1);
3318 tcg_temp_free(t1);
3319 gen_store_gpr(t0, rt);
3320 break;
3321 case OPC_LDPC:
3322 t1 = tcg_const_tl(pc_relative_pc(ctx));
3323 gen_op_addr_add(ctx, t0, t0, t1);
3324 tcg_temp_free(t1);
3325 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3326 gen_store_gpr(t0, rt);
3327 break;
3328 #endif
3329 case OPC_LWPC:
3330 t1 = tcg_const_tl(pc_relative_pc(ctx));
3331 gen_op_addr_add(ctx, t0, t0, t1);
3332 tcg_temp_free(t1);
3333 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3334 gen_store_gpr(t0, rt);
3335 break;
3336 case OPC_LWE:
3337 mem_idx = MIPS_HFLAG_UM;
3338 /* fall through */
3339 case OPC_LW:
3340 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3341 ctx->default_tcg_memop_mask);
3342 gen_store_gpr(t0, rt);
3343 break;
3344 case OPC_LHE:
3345 mem_idx = MIPS_HFLAG_UM;
3346 /* fall through */
3347 case OPC_LH:
3348 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3349 ctx->default_tcg_memop_mask);
3350 gen_store_gpr(t0, rt);
3351 break;
3352 case OPC_LHUE:
3353 mem_idx = MIPS_HFLAG_UM;
3354 /* fall through */
3355 case OPC_LHU:
3356 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3357 ctx->default_tcg_memop_mask);
3358 gen_store_gpr(t0, rt);
3359 break;
3360 case OPC_LBE:
3361 mem_idx = MIPS_HFLAG_UM;
3362 /* fall through */
3363 case OPC_LB:
3364 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3365 gen_store_gpr(t0, rt);
3366 break;
3367 case OPC_LBUE:
3368 mem_idx = MIPS_HFLAG_UM;
3369 /* fall through */
3370 case OPC_LBU:
3371 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3372 gen_store_gpr(t0, rt);
3373 break;
3374 case OPC_LWLE:
3375 mem_idx = MIPS_HFLAG_UM;
3376 /* fall through */
3377 case OPC_LWL:
3378 t1 = tcg_temp_new();
3379 /* Do a byte access to possibly trigger a page
3380 fault with the unaligned address. */
3381 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3382 tcg_gen_andi_tl(t1, t0, 3);
3383 #ifndef TARGET_WORDS_BIGENDIAN
3384 tcg_gen_xori_tl(t1, t1, 3);
3385 #endif
3386 tcg_gen_shli_tl(t1, t1, 3);
3387 tcg_gen_andi_tl(t0, t0, ~3);
3388 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3389 tcg_gen_shl_tl(t0, t0, t1);
3390 t2 = tcg_const_tl(-1);
3391 tcg_gen_shl_tl(t2, t2, t1);
3392 gen_load_gpr(t1, rt);
3393 tcg_gen_andc_tl(t1, t1, t2);
3394 tcg_temp_free(t2);
3395 tcg_gen_or_tl(t0, t0, t1);
3396 tcg_temp_free(t1);
3397 tcg_gen_ext32s_tl(t0, t0);
3398 gen_store_gpr(t0, rt);
3399 break;
3400 case OPC_LWRE:
3401 mem_idx = MIPS_HFLAG_UM;
3402 /* fall through */
3403 case OPC_LWR:
3404 t1 = tcg_temp_new();
3405 /* Do a byte access to possibly trigger a page
3406 fault with the unaligned address. */
3407 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3408 tcg_gen_andi_tl(t1, t0, 3);
3409 #ifdef TARGET_WORDS_BIGENDIAN
3410 tcg_gen_xori_tl(t1, t1, 3);
3411 #endif
3412 tcg_gen_shli_tl(t1, t1, 3);
3413 tcg_gen_andi_tl(t0, t0, ~3);
3414 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3415 tcg_gen_shr_tl(t0, t0, t1);
3416 tcg_gen_xori_tl(t1, t1, 31);
3417 t2 = tcg_const_tl(0xfffffffeull);
3418 tcg_gen_shl_tl(t2, t2, t1);
3419 gen_load_gpr(t1, rt);
3420 tcg_gen_and_tl(t1, t1, t2);
3421 tcg_temp_free(t2);
3422 tcg_gen_or_tl(t0, t0, t1);
3423 tcg_temp_free(t1);
3424 tcg_gen_ext32s_tl(t0, t0);
3425 gen_store_gpr(t0, rt);
3426 break;
3427 case OPC_LLE:
3428 mem_idx = MIPS_HFLAG_UM;
3429 /* fall through */
3430 case OPC_LL:
3431 case R6_OPC_LL:
3432 op_ld_ll(t0, t0, mem_idx, ctx);
3433 gen_store_gpr(t0, rt);
3434 break;
3436 tcg_temp_free(t0);
3439 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3440 uint32_t reg1, uint32_t reg2)
3442 TCGv taddr = tcg_temp_new();
3443 TCGv_i64 tval = tcg_temp_new_i64();
3444 TCGv tmp1 = tcg_temp_new();
3445 TCGv tmp2 = tcg_temp_new();
3447 gen_base_offset_addr(ctx, taddr, base, offset);
3448 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3449 #ifdef TARGET_WORDS_BIGENDIAN
3450 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3451 #else
3452 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3453 #endif
3454 gen_store_gpr(tmp1, reg1);
3455 tcg_temp_free(tmp1);
3456 gen_store_gpr(tmp2, reg2);
3457 tcg_temp_free(tmp2);
3458 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3459 tcg_temp_free_i64(tval);
3460 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3461 tcg_temp_free(taddr);
3464 /* Store */
3465 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3466 int base, int offset)
3468 TCGv t0 = tcg_temp_new();
3469 TCGv t1 = tcg_temp_new();
3470 int mem_idx = ctx->mem_idx;
3472 gen_base_offset_addr(ctx, t0, base, offset);
3473 gen_load_gpr(t1, rt);
3474 switch (opc) {
3475 #if defined(TARGET_MIPS64)
3476 case OPC_SD:
3477 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3478 ctx->default_tcg_memop_mask);
3479 break;
3480 case OPC_SDL:
3481 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3482 break;
3483 case OPC_SDR:
3484 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3485 break;
3486 #endif
3487 case OPC_SWE:
3488 mem_idx = MIPS_HFLAG_UM;
3489 /* fall through */
3490 case OPC_SW:
3491 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3492 ctx->default_tcg_memop_mask);
3493 break;
3494 case OPC_SHE:
3495 mem_idx = MIPS_HFLAG_UM;
3496 /* fall through */
3497 case OPC_SH:
3498 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3499 ctx->default_tcg_memop_mask);
3500 break;
3501 case OPC_SBE:
3502 mem_idx = MIPS_HFLAG_UM;
3503 /* fall through */
3504 case OPC_SB:
3505 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3506 break;
3507 case OPC_SWLE:
3508 mem_idx = MIPS_HFLAG_UM;
3509 /* fall through */
3510 case OPC_SWL:
3511 gen_helper_0e2i(swl, t1, t0, mem_idx);
3512 break;
3513 case OPC_SWRE:
3514 mem_idx = MIPS_HFLAG_UM;
3515 /* fall through */
3516 case OPC_SWR:
3517 gen_helper_0e2i(swr, t1, t0, mem_idx);
3518 break;
3520 tcg_temp_free(t0);
3521 tcg_temp_free(t1);
3525 /* Store conditional */
3526 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3527 int base, int16_t offset)
3529 TCGv t0, t1;
3530 int mem_idx = ctx->mem_idx;
3532 #ifdef CONFIG_USER_ONLY
3533 t0 = tcg_temp_local_new();
3534 t1 = tcg_temp_local_new();
3535 #else
3536 t0 = tcg_temp_new();
3537 t1 = tcg_temp_new();
3538 #endif
3539 gen_base_offset_addr(ctx, t0, base, offset);
3540 gen_load_gpr(t1, rt);
3541 switch (opc) {
3542 #if defined(TARGET_MIPS64)
3543 case OPC_SCD:
3544 case R6_OPC_SCD:
3545 op_st_scd(t1, t0, rt, mem_idx, ctx);
3546 break;
3547 #endif
3548 case OPC_SCE:
3549 mem_idx = MIPS_HFLAG_UM;
3550 /* fall through */
3551 case OPC_SC:
3552 case R6_OPC_SC:
3553 op_st_sc(t1, t0, rt, mem_idx, ctx);
3554 break;
3556 tcg_temp_free(t1);
3557 tcg_temp_free(t0);
3560 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3561 uint32_t reg1, uint32_t reg2)
3563 TCGv taddr = tcg_temp_local_new();
3564 TCGv lladdr = tcg_temp_local_new();
3565 TCGv_i64 tval = tcg_temp_new_i64();
3566 TCGv_i64 llval = tcg_temp_new_i64();
3567 TCGv_i64 val = tcg_temp_new_i64();
3568 TCGv tmp1 = tcg_temp_new();
3569 TCGv tmp2 = tcg_temp_new();
3570 TCGLabel *lab_fail = gen_new_label();
3571 TCGLabel *lab_done = gen_new_label();
3573 gen_base_offset_addr(ctx, taddr, base, offset);
3575 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3576 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3578 gen_load_gpr(tmp1, reg1);
3579 gen_load_gpr(tmp2, reg2);
3581 #ifdef TARGET_WORDS_BIGENDIAN
3582 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3583 #else
3584 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3585 #endif
3587 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3588 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3589 ctx->mem_idx, MO_64);
3590 if (reg1 != 0) {
3591 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3593 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3595 gen_set_label(lab_fail);
3597 if (reg1 != 0) {
3598 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3600 gen_set_label(lab_done);
3601 tcg_gen_movi_tl(lladdr, -1);
3602 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3605 /* Load and store */
3606 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3607 TCGv t0)
3609 /* Don't do NOP if destination is zero: we must perform the actual
3610 memory access. */
3611 switch (opc) {
3612 case OPC_LWC1:
3614 TCGv_i32 fp0 = tcg_temp_new_i32();
3615 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3616 ctx->default_tcg_memop_mask);
3617 gen_store_fpr32(ctx, fp0, ft);
3618 tcg_temp_free_i32(fp0);
3620 break;
3621 case OPC_SWC1:
3623 TCGv_i32 fp0 = tcg_temp_new_i32();
3624 gen_load_fpr32(ctx, fp0, ft);
3625 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3626 ctx->default_tcg_memop_mask);
3627 tcg_temp_free_i32(fp0);
3629 break;
3630 case OPC_LDC1:
3632 TCGv_i64 fp0 = tcg_temp_new_i64();
3633 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3634 ctx->default_tcg_memop_mask);
3635 gen_store_fpr64(ctx, fp0, ft);
3636 tcg_temp_free_i64(fp0);
3638 break;
3639 case OPC_SDC1:
3641 TCGv_i64 fp0 = tcg_temp_new_i64();
3642 gen_load_fpr64(ctx, fp0, ft);
3643 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3644 ctx->default_tcg_memop_mask);
3645 tcg_temp_free_i64(fp0);
3647 break;
3648 default:
3649 MIPS_INVAL("flt_ldst");
3650 generate_exception_end(ctx, EXCP_RI);
3651 break;
3655 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3656 int rs, int16_t imm)
3658 TCGv t0 = tcg_temp_new();
3660 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3661 check_cp1_enabled(ctx);
3662 switch (op) {
3663 case OPC_LDC1:
3664 case OPC_SDC1:
3665 check_insn(ctx, ISA_MIPS2);
3666 /* Fallthrough */
3667 default:
3668 gen_base_offset_addr(ctx, t0, rs, imm);
3669 gen_flt_ldst(ctx, op, rt, t0);
3671 } else {
3672 generate_exception_err(ctx, EXCP_CpU, 1);
3674 tcg_temp_free(t0);
3677 /* Arithmetic with immediate operand */
3678 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3679 int rt, int rs, int imm)
3681 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3683 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3684 /* If no destination, treat it as a NOP.
3685 For addi, we must generate the overflow exception when needed. */
3686 return;
3688 switch (opc) {
3689 case OPC_ADDI:
3691 TCGv t0 = tcg_temp_local_new();
3692 TCGv t1 = tcg_temp_new();
3693 TCGv t2 = tcg_temp_new();
3694 TCGLabel *l1 = gen_new_label();
3696 gen_load_gpr(t1, rs);
3697 tcg_gen_addi_tl(t0, t1, uimm);
3698 tcg_gen_ext32s_tl(t0, t0);
3700 tcg_gen_xori_tl(t1, t1, ~uimm);
3701 tcg_gen_xori_tl(t2, t0, uimm);
3702 tcg_gen_and_tl(t1, t1, t2);
3703 tcg_temp_free(t2);
3704 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3705 tcg_temp_free(t1);
3706 /* operands of same sign, result different sign */
3707 generate_exception(ctx, EXCP_OVERFLOW);
3708 gen_set_label(l1);
3709 tcg_gen_ext32s_tl(t0, t0);
3710 gen_store_gpr(t0, rt);
3711 tcg_temp_free(t0);
3713 break;
3714 case OPC_ADDIU:
3715 if (rs != 0) {
3716 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3717 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3718 } else {
3719 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3721 break;
3722 #if defined(TARGET_MIPS64)
3723 case OPC_DADDI:
3725 TCGv t0 = tcg_temp_local_new();
3726 TCGv t1 = tcg_temp_new();
3727 TCGv t2 = tcg_temp_new();
3728 TCGLabel *l1 = gen_new_label();
3730 gen_load_gpr(t1, rs);
3731 tcg_gen_addi_tl(t0, t1, uimm);
3733 tcg_gen_xori_tl(t1, t1, ~uimm);
3734 tcg_gen_xori_tl(t2, t0, uimm);
3735 tcg_gen_and_tl(t1, t1, t2);
3736 tcg_temp_free(t2);
3737 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3738 tcg_temp_free(t1);
3739 /* operands of same sign, result different sign */
3740 generate_exception(ctx, EXCP_OVERFLOW);
3741 gen_set_label(l1);
3742 gen_store_gpr(t0, rt);
3743 tcg_temp_free(t0);
3745 break;
3746 case OPC_DADDIU:
3747 if (rs != 0) {
3748 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3749 } else {
3750 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3752 break;
3753 #endif
3757 /* Logic with immediate operand */
3758 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3759 int rt, int rs, int16_t imm)
3761 target_ulong uimm;
3763 if (rt == 0) {
3764 /* If no destination, treat it as a NOP. */
3765 return;
3767 uimm = (uint16_t)imm;
3768 switch (opc) {
3769 case OPC_ANDI:
3770 if (likely(rs != 0))
3771 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3772 else
3773 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3774 break;
3775 case OPC_ORI:
3776 if (rs != 0)
3777 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3778 else
3779 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3780 break;
3781 case OPC_XORI:
3782 if (likely(rs != 0))
3783 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3784 else
3785 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3786 break;
3787 case OPC_LUI:
3788 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3789 /* OPC_AUI */
3790 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3791 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3792 } else {
3793 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3795 break;
3797 default:
3798 break;
3802 /* Set on less than with immediate operand */
3803 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3804 int rt, int rs, int16_t imm)
3806 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3807 TCGv t0;
3809 if (rt == 0) {
3810 /* If no destination, treat it as a NOP. */
3811 return;
3813 t0 = tcg_temp_new();
3814 gen_load_gpr(t0, rs);
3815 switch (opc) {
3816 case OPC_SLTI:
3817 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3818 break;
3819 case OPC_SLTIU:
3820 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3821 break;
3823 tcg_temp_free(t0);
3826 /* Shifts with immediate operand */
3827 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3828 int rt, int rs, int16_t imm)
3830 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3831 TCGv t0;
3833 if (rt == 0) {
3834 /* If no destination, treat it as a NOP. */
3835 return;
3838 t0 = tcg_temp_new();
3839 gen_load_gpr(t0, rs);
3840 switch (opc) {
3841 case OPC_SLL:
3842 tcg_gen_shli_tl(t0, t0, uimm);
3843 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3844 break;
3845 case OPC_SRA:
3846 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3847 break;
3848 case OPC_SRL:
3849 if (uimm != 0) {
3850 tcg_gen_ext32u_tl(t0, t0);
3851 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3852 } else {
3853 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3855 break;
3856 case OPC_ROTR:
3857 if (uimm != 0) {
3858 TCGv_i32 t1 = tcg_temp_new_i32();
3860 tcg_gen_trunc_tl_i32(t1, t0);
3861 tcg_gen_rotri_i32(t1, t1, uimm);
3862 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3863 tcg_temp_free_i32(t1);
3864 } else {
3865 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3867 break;
3868 #if defined(TARGET_MIPS64)
3869 case OPC_DSLL:
3870 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3871 break;
3872 case OPC_DSRA:
3873 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3874 break;
3875 case OPC_DSRL:
3876 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3877 break;
3878 case OPC_DROTR:
3879 if (uimm != 0) {
3880 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3881 } else {
3882 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3884 break;
3885 case OPC_DSLL32:
3886 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3887 break;
3888 case OPC_DSRA32:
3889 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3890 break;
3891 case OPC_DSRL32:
3892 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3893 break;
3894 case OPC_DROTR32:
3895 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3896 break;
3897 #endif
3899 tcg_temp_free(t0);
3902 /* Arithmetic */
3903 static void gen_arith(DisasContext *ctx, uint32_t opc,
3904 int rd, int rs, int rt)
3906 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3907 && opc != OPC_DADD && opc != OPC_DSUB) {
3908 /* If no destination, treat it as a NOP.
3909 For add & sub, we must generate the overflow exception when needed. */
3910 return;
3913 switch (opc) {
3914 case OPC_ADD:
3916 TCGv t0 = tcg_temp_local_new();
3917 TCGv t1 = tcg_temp_new();
3918 TCGv t2 = tcg_temp_new();
3919 TCGLabel *l1 = gen_new_label();
3921 gen_load_gpr(t1, rs);
3922 gen_load_gpr(t2, rt);
3923 tcg_gen_add_tl(t0, t1, t2);
3924 tcg_gen_ext32s_tl(t0, t0);
3925 tcg_gen_xor_tl(t1, t1, t2);
3926 tcg_gen_xor_tl(t2, t0, t2);
3927 tcg_gen_andc_tl(t1, t2, t1);
3928 tcg_temp_free(t2);
3929 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3930 tcg_temp_free(t1);
3931 /* operands of same sign, result different sign */
3932 generate_exception(ctx, EXCP_OVERFLOW);
3933 gen_set_label(l1);
3934 gen_store_gpr(t0, rd);
3935 tcg_temp_free(t0);
3937 break;
3938 case OPC_ADDU:
3939 if (rs != 0 && rt != 0) {
3940 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3941 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3942 } else if (rs == 0 && rt != 0) {
3943 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3944 } else if (rs != 0 && rt == 0) {
3945 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3946 } else {
3947 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3949 break;
3950 case OPC_SUB:
3952 TCGv t0 = tcg_temp_local_new();
3953 TCGv t1 = tcg_temp_new();
3954 TCGv t2 = tcg_temp_new();
3955 TCGLabel *l1 = gen_new_label();
3957 gen_load_gpr(t1, rs);
3958 gen_load_gpr(t2, rt);
3959 tcg_gen_sub_tl(t0, t1, t2);
3960 tcg_gen_ext32s_tl(t0, t0);
3961 tcg_gen_xor_tl(t2, t1, t2);
3962 tcg_gen_xor_tl(t1, t0, t1);
3963 tcg_gen_and_tl(t1, t1, t2);
3964 tcg_temp_free(t2);
3965 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3966 tcg_temp_free(t1);
3967 /* operands of different sign, first operand and result different sign */
3968 generate_exception(ctx, EXCP_OVERFLOW);
3969 gen_set_label(l1);
3970 gen_store_gpr(t0, rd);
3971 tcg_temp_free(t0);
3973 break;
3974 case OPC_SUBU:
3975 if (rs != 0 && rt != 0) {
3976 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3977 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3978 } else if (rs == 0 && rt != 0) {
3979 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3980 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3981 } else if (rs != 0 && rt == 0) {
3982 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3983 } else {
3984 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3986 break;
3987 #if defined(TARGET_MIPS64)
3988 case OPC_DADD:
3990 TCGv t0 = tcg_temp_local_new();
3991 TCGv t1 = tcg_temp_new();
3992 TCGv t2 = tcg_temp_new();
3993 TCGLabel *l1 = gen_new_label();
3995 gen_load_gpr(t1, rs);
3996 gen_load_gpr(t2, rt);
3997 tcg_gen_add_tl(t0, t1, t2);
3998 tcg_gen_xor_tl(t1, t1, t2);
3999 tcg_gen_xor_tl(t2, t0, t2);
4000 tcg_gen_andc_tl(t1, t2, t1);
4001 tcg_temp_free(t2);
4002 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4003 tcg_temp_free(t1);
4004 /* operands of same sign, result different sign */
4005 generate_exception(ctx, EXCP_OVERFLOW);
4006 gen_set_label(l1);
4007 gen_store_gpr(t0, rd);
4008 tcg_temp_free(t0);
4010 break;
4011 case OPC_DADDU:
4012 if (rs != 0 && rt != 0) {
4013 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4014 } else if (rs == 0 && rt != 0) {
4015 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4016 } else if (rs != 0 && rt == 0) {
4017 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4018 } else {
4019 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4021 break;
4022 case OPC_DSUB:
4024 TCGv t0 = tcg_temp_local_new();
4025 TCGv t1 = tcg_temp_new();
4026 TCGv t2 = tcg_temp_new();
4027 TCGLabel *l1 = gen_new_label();
4029 gen_load_gpr(t1, rs);
4030 gen_load_gpr(t2, rt);
4031 tcg_gen_sub_tl(t0, t1, t2);
4032 tcg_gen_xor_tl(t2, t1, t2);
4033 tcg_gen_xor_tl(t1, t0, t1);
4034 tcg_gen_and_tl(t1, t1, t2);
4035 tcg_temp_free(t2);
4036 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4037 tcg_temp_free(t1);
4038 /* operands of different sign, first operand and result different sign */
4039 generate_exception(ctx, EXCP_OVERFLOW);
4040 gen_set_label(l1);
4041 gen_store_gpr(t0, rd);
4042 tcg_temp_free(t0);
4044 break;
4045 case OPC_DSUBU:
4046 if (rs != 0 && rt != 0) {
4047 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4048 } else if (rs == 0 && rt != 0) {
4049 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4050 } else if (rs != 0 && rt == 0) {
4051 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4052 } else {
4053 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4055 break;
4056 #endif
4057 case OPC_MUL:
4058 if (likely(rs != 0 && rt != 0)) {
4059 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4060 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4061 } else {
4062 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4064 break;
4068 /* Conditional move */
4069 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4070 int rd, int rs, int rt)
4072 TCGv t0, t1, t2;
4074 if (rd == 0) {
4075 /* If no destination, treat it as a NOP. */
4076 return;
4079 t0 = tcg_temp_new();
4080 gen_load_gpr(t0, rt);
4081 t1 = tcg_const_tl(0);
4082 t2 = tcg_temp_new();
4083 gen_load_gpr(t2, rs);
4084 switch (opc) {
4085 case OPC_MOVN:
4086 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4087 break;
4088 case OPC_MOVZ:
4089 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4090 break;
4091 case OPC_SELNEZ:
4092 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4093 break;
4094 case OPC_SELEQZ:
4095 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4096 break;
4098 tcg_temp_free(t2);
4099 tcg_temp_free(t1);
4100 tcg_temp_free(t0);
4103 /* Logic */
4104 static void gen_logic(DisasContext *ctx, uint32_t opc,
4105 int rd, int rs, int rt)
4107 if (rd == 0) {
4108 /* If no destination, treat it as a NOP. */
4109 return;
4112 switch (opc) {
4113 case OPC_AND:
4114 if (likely(rs != 0 && rt != 0)) {
4115 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4116 } else {
4117 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4119 break;
4120 case OPC_NOR:
4121 if (rs != 0 && rt != 0) {
4122 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4123 } else if (rs == 0 && rt != 0) {
4124 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4125 } else if (rs != 0 && rt == 0) {
4126 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4127 } else {
4128 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4130 break;
4131 case OPC_OR:
4132 if (likely(rs != 0 && rt != 0)) {
4133 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
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_XOR:
4143 if (likely(rs != 0 && rt != 0)) {
4144 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4145 } else if (rs == 0 && rt != 0) {
4146 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4147 } else if (rs != 0 && rt == 0) {
4148 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4149 } else {
4150 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4152 break;
4156 /* Set on lower than */
4157 static void gen_slt(DisasContext *ctx, uint32_t opc,
4158 int rd, int rs, int rt)
4160 TCGv t0, t1;
4162 if (rd == 0) {
4163 /* If no destination, treat it as a NOP. */
4164 return;
4167 t0 = tcg_temp_new();
4168 t1 = tcg_temp_new();
4169 gen_load_gpr(t0, rs);
4170 gen_load_gpr(t1, rt);
4171 switch (opc) {
4172 case OPC_SLT:
4173 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4174 break;
4175 case OPC_SLTU:
4176 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4177 break;
4179 tcg_temp_free(t0);
4180 tcg_temp_free(t1);
4183 /* Shifts */
4184 static void gen_shift(DisasContext *ctx, uint32_t opc,
4185 int rd, int rs, int rt)
4187 TCGv t0, t1;
4189 if (rd == 0) {
4190 /* If no destination, treat it as a NOP.
4191 For add & sub, we must generate the overflow exception when needed. */
4192 return;
4195 t0 = tcg_temp_new();
4196 t1 = tcg_temp_new();
4197 gen_load_gpr(t0, rs);
4198 gen_load_gpr(t1, rt);
4199 switch (opc) {
4200 case OPC_SLLV:
4201 tcg_gen_andi_tl(t0, t0, 0x1f);
4202 tcg_gen_shl_tl(t0, t1, t0);
4203 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4204 break;
4205 case OPC_SRAV:
4206 tcg_gen_andi_tl(t0, t0, 0x1f);
4207 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4208 break;
4209 case OPC_SRLV:
4210 tcg_gen_ext32u_tl(t1, t1);
4211 tcg_gen_andi_tl(t0, t0, 0x1f);
4212 tcg_gen_shr_tl(t0, t1, t0);
4213 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4214 break;
4215 case OPC_ROTRV:
4217 TCGv_i32 t2 = tcg_temp_new_i32();
4218 TCGv_i32 t3 = tcg_temp_new_i32();
4220 tcg_gen_trunc_tl_i32(t2, t0);
4221 tcg_gen_trunc_tl_i32(t3, t1);
4222 tcg_gen_andi_i32(t2, t2, 0x1f);
4223 tcg_gen_rotr_i32(t2, t3, t2);
4224 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4225 tcg_temp_free_i32(t2);
4226 tcg_temp_free_i32(t3);
4228 break;
4229 #if defined(TARGET_MIPS64)
4230 case OPC_DSLLV:
4231 tcg_gen_andi_tl(t0, t0, 0x3f);
4232 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4233 break;
4234 case OPC_DSRAV:
4235 tcg_gen_andi_tl(t0, t0, 0x3f);
4236 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4237 break;
4238 case OPC_DSRLV:
4239 tcg_gen_andi_tl(t0, t0, 0x3f);
4240 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4241 break;
4242 case OPC_DROTRV:
4243 tcg_gen_andi_tl(t0, t0, 0x3f);
4244 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4245 break;
4246 #endif
4248 tcg_temp_free(t0);
4249 tcg_temp_free(t1);
4252 /* Arithmetic on HI/LO registers */
4253 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4255 if (reg == 0 && (opc == OPC_MFHI || opc == TX79_MMI_MFHI1 ||
4256 opc == OPC_MFLO || opc == TX79_MMI_MFLO1)) {
4257 /* Treat as NOP. */
4258 return;
4261 if (acc != 0) {
4262 if (!(ctx->insn_flags & INSN_R5900)) {
4263 check_dsp(ctx);
4267 switch (opc) {
4268 case OPC_MFHI:
4269 case TX79_MMI_MFHI1:
4270 #if defined(TARGET_MIPS64)
4271 if (acc != 0) {
4272 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4273 } else
4274 #endif
4276 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4278 break;
4279 case OPC_MFLO:
4280 case TX79_MMI_MFLO1:
4281 #if defined(TARGET_MIPS64)
4282 if (acc != 0) {
4283 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4284 } else
4285 #endif
4287 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4289 break;
4290 case OPC_MTHI:
4291 case TX79_MMI_MTHI1:
4292 if (reg != 0) {
4293 #if defined(TARGET_MIPS64)
4294 if (acc != 0) {
4295 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4296 } else
4297 #endif
4299 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4301 } else {
4302 tcg_gen_movi_tl(cpu_HI[acc], 0);
4304 break;
4305 case OPC_MTLO:
4306 case TX79_MMI_MTLO1:
4307 if (reg != 0) {
4308 #if defined(TARGET_MIPS64)
4309 if (acc != 0) {
4310 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4311 } else
4312 #endif
4314 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4316 } else {
4317 tcg_gen_movi_tl(cpu_LO[acc], 0);
4319 break;
4323 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4324 TCGMemOp memop)
4326 TCGv t0 = tcg_const_tl(addr);
4327 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4328 gen_store_gpr(t0, reg);
4329 tcg_temp_free(t0);
4332 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4333 int rs)
4335 target_long offset;
4336 target_long addr;
4338 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4339 case OPC_ADDIUPC:
4340 if (rs != 0) {
4341 offset = sextract32(ctx->opcode << 2, 0, 21);
4342 addr = addr_add(ctx, pc, offset);
4343 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4345 break;
4346 case R6_OPC_LWPC:
4347 offset = sextract32(ctx->opcode << 2, 0, 21);
4348 addr = addr_add(ctx, pc, offset);
4349 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4350 break;
4351 #if defined(TARGET_MIPS64)
4352 case OPC_LWUPC:
4353 check_mips_64(ctx);
4354 offset = sextract32(ctx->opcode << 2, 0, 21);
4355 addr = addr_add(ctx, pc, offset);
4356 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4357 break;
4358 #endif
4359 default:
4360 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4361 case OPC_AUIPC:
4362 if (rs != 0) {
4363 offset = sextract32(ctx->opcode, 0, 16) << 16;
4364 addr = addr_add(ctx, pc, offset);
4365 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4367 break;
4368 case OPC_ALUIPC:
4369 if (rs != 0) {
4370 offset = sextract32(ctx->opcode, 0, 16) << 16;
4371 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4372 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4374 break;
4375 #if defined(TARGET_MIPS64)
4376 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4377 case R6_OPC_LDPC + (1 << 16):
4378 case R6_OPC_LDPC + (2 << 16):
4379 case R6_OPC_LDPC + (3 << 16):
4380 check_mips_64(ctx);
4381 offset = sextract32(ctx->opcode << 3, 0, 21);
4382 addr = addr_add(ctx, (pc & ~0x7), offset);
4383 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4384 break;
4385 #endif
4386 default:
4387 MIPS_INVAL("OPC_PCREL");
4388 generate_exception_end(ctx, EXCP_RI);
4389 break;
4391 break;
4395 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4397 TCGv t0, t1;
4399 if (rd == 0) {
4400 /* Treat as NOP. */
4401 return;
4404 t0 = tcg_temp_new();
4405 t1 = tcg_temp_new();
4407 gen_load_gpr(t0, rs);
4408 gen_load_gpr(t1, rt);
4410 switch (opc) {
4411 case R6_OPC_DIV:
4413 TCGv t2 = tcg_temp_new();
4414 TCGv t3 = tcg_temp_new();
4415 tcg_gen_ext32s_tl(t0, t0);
4416 tcg_gen_ext32s_tl(t1, t1);
4417 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4418 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4419 tcg_gen_and_tl(t2, t2, t3);
4420 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4421 tcg_gen_or_tl(t2, t2, t3);
4422 tcg_gen_movi_tl(t3, 0);
4423 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4424 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4425 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4426 tcg_temp_free(t3);
4427 tcg_temp_free(t2);
4429 break;
4430 case R6_OPC_MOD:
4432 TCGv t2 = tcg_temp_new();
4433 TCGv t3 = tcg_temp_new();
4434 tcg_gen_ext32s_tl(t0, t0);
4435 tcg_gen_ext32s_tl(t1, t1);
4436 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4437 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4438 tcg_gen_and_tl(t2, t2, t3);
4439 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4440 tcg_gen_or_tl(t2, t2, t3);
4441 tcg_gen_movi_tl(t3, 0);
4442 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4443 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4444 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4445 tcg_temp_free(t3);
4446 tcg_temp_free(t2);
4448 break;
4449 case R6_OPC_DIVU:
4451 TCGv t2 = tcg_const_tl(0);
4452 TCGv t3 = tcg_const_tl(1);
4453 tcg_gen_ext32u_tl(t0, t0);
4454 tcg_gen_ext32u_tl(t1, t1);
4455 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4456 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4457 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4458 tcg_temp_free(t3);
4459 tcg_temp_free(t2);
4461 break;
4462 case R6_OPC_MODU:
4464 TCGv t2 = tcg_const_tl(0);
4465 TCGv t3 = tcg_const_tl(1);
4466 tcg_gen_ext32u_tl(t0, t0);
4467 tcg_gen_ext32u_tl(t1, t1);
4468 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4469 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4470 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4471 tcg_temp_free(t3);
4472 tcg_temp_free(t2);
4474 break;
4475 case R6_OPC_MUL:
4477 TCGv_i32 t2 = tcg_temp_new_i32();
4478 TCGv_i32 t3 = tcg_temp_new_i32();
4479 tcg_gen_trunc_tl_i32(t2, t0);
4480 tcg_gen_trunc_tl_i32(t3, t1);
4481 tcg_gen_mul_i32(t2, t2, t3);
4482 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4483 tcg_temp_free_i32(t2);
4484 tcg_temp_free_i32(t3);
4486 break;
4487 case R6_OPC_MUH:
4489 TCGv_i32 t2 = tcg_temp_new_i32();
4490 TCGv_i32 t3 = tcg_temp_new_i32();
4491 tcg_gen_trunc_tl_i32(t2, t0);
4492 tcg_gen_trunc_tl_i32(t3, t1);
4493 tcg_gen_muls2_i32(t2, t3, t2, t3);
4494 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4495 tcg_temp_free_i32(t2);
4496 tcg_temp_free_i32(t3);
4498 break;
4499 case R6_OPC_MULU:
4501 TCGv_i32 t2 = tcg_temp_new_i32();
4502 TCGv_i32 t3 = tcg_temp_new_i32();
4503 tcg_gen_trunc_tl_i32(t2, t0);
4504 tcg_gen_trunc_tl_i32(t3, t1);
4505 tcg_gen_mul_i32(t2, t2, t3);
4506 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4507 tcg_temp_free_i32(t2);
4508 tcg_temp_free_i32(t3);
4510 break;
4511 case R6_OPC_MUHU:
4513 TCGv_i32 t2 = tcg_temp_new_i32();
4514 TCGv_i32 t3 = tcg_temp_new_i32();
4515 tcg_gen_trunc_tl_i32(t2, t0);
4516 tcg_gen_trunc_tl_i32(t3, t1);
4517 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4518 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4519 tcg_temp_free_i32(t2);
4520 tcg_temp_free_i32(t3);
4522 break;
4523 #if defined(TARGET_MIPS64)
4524 case R6_OPC_DDIV:
4526 TCGv t2 = tcg_temp_new();
4527 TCGv t3 = tcg_temp_new();
4528 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4529 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4530 tcg_gen_and_tl(t2, t2, t3);
4531 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4532 tcg_gen_or_tl(t2, t2, t3);
4533 tcg_gen_movi_tl(t3, 0);
4534 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4535 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4536 tcg_temp_free(t3);
4537 tcg_temp_free(t2);
4539 break;
4540 case R6_OPC_DMOD:
4542 TCGv t2 = tcg_temp_new();
4543 TCGv t3 = tcg_temp_new();
4544 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4545 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4546 tcg_gen_and_tl(t2, t2, t3);
4547 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4548 tcg_gen_or_tl(t2, t2, t3);
4549 tcg_gen_movi_tl(t3, 0);
4550 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4551 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4552 tcg_temp_free(t3);
4553 tcg_temp_free(t2);
4555 break;
4556 case R6_OPC_DDIVU:
4558 TCGv t2 = tcg_const_tl(0);
4559 TCGv t3 = tcg_const_tl(1);
4560 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4561 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4562 tcg_temp_free(t3);
4563 tcg_temp_free(t2);
4565 break;
4566 case R6_OPC_DMODU:
4568 TCGv t2 = tcg_const_tl(0);
4569 TCGv t3 = tcg_const_tl(1);
4570 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4571 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4572 tcg_temp_free(t3);
4573 tcg_temp_free(t2);
4575 break;
4576 case R6_OPC_DMUL:
4577 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4578 break;
4579 case R6_OPC_DMUH:
4581 TCGv t2 = tcg_temp_new();
4582 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4583 tcg_temp_free(t2);
4585 break;
4586 case R6_OPC_DMULU:
4587 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4588 break;
4589 case R6_OPC_DMUHU:
4591 TCGv t2 = tcg_temp_new();
4592 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4593 tcg_temp_free(t2);
4595 break;
4596 #endif
4597 default:
4598 MIPS_INVAL("r6 mul/div");
4599 generate_exception_end(ctx, EXCP_RI);
4600 goto out;
4602 out:
4603 tcg_temp_free(t0);
4604 tcg_temp_free(t1);
4607 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4608 int acc, int rs, int rt)
4610 TCGv t0, t1;
4612 t0 = tcg_temp_new();
4613 t1 = tcg_temp_new();
4615 gen_load_gpr(t0, rs);
4616 gen_load_gpr(t1, rt);
4618 if (acc != 0) {
4619 if (!(ctx->insn_flags & INSN_R5900)) {
4620 check_dsp(ctx);
4624 switch (opc) {
4625 case OPC_DIV:
4626 case TX79_MMI_DIV1:
4628 TCGv t2 = tcg_temp_new();
4629 TCGv t3 = tcg_temp_new();
4630 tcg_gen_ext32s_tl(t0, t0);
4631 tcg_gen_ext32s_tl(t1, t1);
4632 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4633 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4634 tcg_gen_and_tl(t2, t2, t3);
4635 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4636 tcg_gen_or_tl(t2, t2, t3);
4637 tcg_gen_movi_tl(t3, 0);
4638 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4639 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4640 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4641 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4642 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4643 tcg_temp_free(t3);
4644 tcg_temp_free(t2);
4646 break;
4647 case OPC_DIVU:
4648 case TX79_MMI_DIVU1:
4650 TCGv t2 = tcg_const_tl(0);
4651 TCGv t3 = tcg_const_tl(1);
4652 tcg_gen_ext32u_tl(t0, t0);
4653 tcg_gen_ext32u_tl(t1, t1);
4654 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4655 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4656 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4657 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4658 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4659 tcg_temp_free(t3);
4660 tcg_temp_free(t2);
4662 break;
4663 case OPC_MULT:
4665 TCGv_i32 t2 = tcg_temp_new_i32();
4666 TCGv_i32 t3 = tcg_temp_new_i32();
4667 tcg_gen_trunc_tl_i32(t2, t0);
4668 tcg_gen_trunc_tl_i32(t3, t1);
4669 tcg_gen_muls2_i32(t2, t3, t2, t3);
4670 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4671 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4672 tcg_temp_free_i32(t2);
4673 tcg_temp_free_i32(t3);
4675 break;
4676 case OPC_MULTU:
4678 TCGv_i32 t2 = tcg_temp_new_i32();
4679 TCGv_i32 t3 = tcg_temp_new_i32();
4680 tcg_gen_trunc_tl_i32(t2, t0);
4681 tcg_gen_trunc_tl_i32(t3, t1);
4682 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4683 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4684 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4685 tcg_temp_free_i32(t2);
4686 tcg_temp_free_i32(t3);
4688 break;
4689 #if defined(TARGET_MIPS64)
4690 case OPC_DDIV:
4692 TCGv t2 = tcg_temp_new();
4693 TCGv t3 = tcg_temp_new();
4694 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4695 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4696 tcg_gen_and_tl(t2, t2, t3);
4697 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4698 tcg_gen_or_tl(t2, t2, t3);
4699 tcg_gen_movi_tl(t3, 0);
4700 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4701 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4702 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4703 tcg_temp_free(t3);
4704 tcg_temp_free(t2);
4706 break;
4707 case OPC_DDIVU:
4709 TCGv t2 = tcg_const_tl(0);
4710 TCGv t3 = tcg_const_tl(1);
4711 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4712 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4713 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4714 tcg_temp_free(t3);
4715 tcg_temp_free(t2);
4717 break;
4718 case OPC_DMULT:
4719 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4720 break;
4721 case OPC_DMULTU:
4722 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4723 break;
4724 #endif
4725 case OPC_MADD:
4727 TCGv_i64 t2 = tcg_temp_new_i64();
4728 TCGv_i64 t3 = tcg_temp_new_i64();
4730 tcg_gen_ext_tl_i64(t2, t0);
4731 tcg_gen_ext_tl_i64(t3, t1);
4732 tcg_gen_mul_i64(t2, t2, t3);
4733 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4734 tcg_gen_add_i64(t2, t2, t3);
4735 tcg_temp_free_i64(t3);
4736 gen_move_low32(cpu_LO[acc], t2);
4737 gen_move_high32(cpu_HI[acc], t2);
4738 tcg_temp_free_i64(t2);
4740 break;
4741 case OPC_MADDU:
4743 TCGv_i64 t2 = tcg_temp_new_i64();
4744 TCGv_i64 t3 = tcg_temp_new_i64();
4746 tcg_gen_ext32u_tl(t0, t0);
4747 tcg_gen_ext32u_tl(t1, t1);
4748 tcg_gen_extu_tl_i64(t2, t0);
4749 tcg_gen_extu_tl_i64(t3, t1);
4750 tcg_gen_mul_i64(t2, t2, t3);
4751 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4752 tcg_gen_add_i64(t2, t2, t3);
4753 tcg_temp_free_i64(t3);
4754 gen_move_low32(cpu_LO[acc], t2);
4755 gen_move_high32(cpu_HI[acc], t2);
4756 tcg_temp_free_i64(t2);
4758 break;
4759 case OPC_MSUB:
4761 TCGv_i64 t2 = tcg_temp_new_i64();
4762 TCGv_i64 t3 = tcg_temp_new_i64();
4764 tcg_gen_ext_tl_i64(t2, t0);
4765 tcg_gen_ext_tl_i64(t3, t1);
4766 tcg_gen_mul_i64(t2, t2, t3);
4767 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4768 tcg_gen_sub_i64(t2, t3, t2);
4769 tcg_temp_free_i64(t3);
4770 gen_move_low32(cpu_LO[acc], t2);
4771 gen_move_high32(cpu_HI[acc], t2);
4772 tcg_temp_free_i64(t2);
4774 break;
4775 case OPC_MSUBU:
4777 TCGv_i64 t2 = tcg_temp_new_i64();
4778 TCGv_i64 t3 = tcg_temp_new_i64();
4780 tcg_gen_ext32u_tl(t0, t0);
4781 tcg_gen_ext32u_tl(t1, t1);
4782 tcg_gen_extu_tl_i64(t2, t0);
4783 tcg_gen_extu_tl_i64(t3, t1);
4784 tcg_gen_mul_i64(t2, t2, t3);
4785 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4786 tcg_gen_sub_i64(t2, t3, t2);
4787 tcg_temp_free_i64(t3);
4788 gen_move_low32(cpu_LO[acc], t2);
4789 gen_move_high32(cpu_HI[acc], t2);
4790 tcg_temp_free_i64(t2);
4792 break;
4793 default:
4794 MIPS_INVAL("mul/div");
4795 generate_exception_end(ctx, EXCP_RI);
4796 goto out;
4798 out:
4799 tcg_temp_free(t0);
4800 tcg_temp_free(t1);
4804 * These MULT and MULTU instructions implemented in for example the
4805 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4806 * architectures are special three-operand variants with the syntax
4808 * MULT[U][1] rd, rs, rt
4810 * such that
4812 * (rd, LO, HI) <- rs * rt
4814 * where the low-order 32-bits of the result is placed into both the
4815 * GPR rd and the special register LO. The high-order 32-bits of the
4816 * result is placed into the special register HI.
4818 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4819 * which is the zero register that always reads as 0.
4821 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4822 int rd, int rs, int rt)
4824 TCGv t0 = tcg_temp_new();
4825 TCGv t1 = tcg_temp_new();
4826 int acc = 0;
4828 gen_load_gpr(t0, rs);
4829 gen_load_gpr(t1, rt);
4831 switch (opc) {
4832 case TX79_MMI_MULT1:
4833 acc = 1;
4834 /* Fall through */
4835 case OPC_MULT:
4837 TCGv_i32 t2 = tcg_temp_new_i32();
4838 TCGv_i32 t3 = tcg_temp_new_i32();
4839 tcg_gen_trunc_tl_i32(t2, t0);
4840 tcg_gen_trunc_tl_i32(t3, t1);
4841 tcg_gen_muls2_i32(t2, t3, t2, t3);
4842 if (rd) {
4843 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4845 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4846 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4847 tcg_temp_free_i32(t2);
4848 tcg_temp_free_i32(t3);
4850 break;
4851 case TX79_MMI_MULTU1:
4852 acc = 1;
4853 /* Fall through */
4854 case OPC_MULTU:
4856 TCGv_i32 t2 = tcg_temp_new_i32();
4857 TCGv_i32 t3 = tcg_temp_new_i32();
4858 tcg_gen_trunc_tl_i32(t2, t0);
4859 tcg_gen_trunc_tl_i32(t3, t1);
4860 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4861 if (rd) {
4862 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4864 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4865 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4866 tcg_temp_free_i32(t2);
4867 tcg_temp_free_i32(t3);
4869 break;
4870 default:
4871 MIPS_INVAL("mul TXx9");
4872 generate_exception_end(ctx, EXCP_RI);
4873 goto out;
4876 out:
4877 tcg_temp_free(t0);
4878 tcg_temp_free(t1);
4881 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4882 int rd, int rs, int rt)
4884 TCGv t0 = tcg_temp_new();
4885 TCGv t1 = tcg_temp_new();
4887 gen_load_gpr(t0, rs);
4888 gen_load_gpr(t1, rt);
4890 switch (opc) {
4891 case OPC_VR54XX_MULS:
4892 gen_helper_muls(t0, cpu_env, t0, t1);
4893 break;
4894 case OPC_VR54XX_MULSU:
4895 gen_helper_mulsu(t0, cpu_env, t0, t1);
4896 break;
4897 case OPC_VR54XX_MACC:
4898 gen_helper_macc(t0, cpu_env, t0, t1);
4899 break;
4900 case OPC_VR54XX_MACCU:
4901 gen_helper_maccu(t0, cpu_env, t0, t1);
4902 break;
4903 case OPC_VR54XX_MSAC:
4904 gen_helper_msac(t0, cpu_env, t0, t1);
4905 break;
4906 case OPC_VR54XX_MSACU:
4907 gen_helper_msacu(t0, cpu_env, t0, t1);
4908 break;
4909 case OPC_VR54XX_MULHI:
4910 gen_helper_mulhi(t0, cpu_env, t0, t1);
4911 break;
4912 case OPC_VR54XX_MULHIU:
4913 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4914 break;
4915 case OPC_VR54XX_MULSHI:
4916 gen_helper_mulshi(t0, cpu_env, t0, t1);
4917 break;
4918 case OPC_VR54XX_MULSHIU:
4919 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4920 break;
4921 case OPC_VR54XX_MACCHI:
4922 gen_helper_macchi(t0, cpu_env, t0, t1);
4923 break;
4924 case OPC_VR54XX_MACCHIU:
4925 gen_helper_macchiu(t0, cpu_env, t0, t1);
4926 break;
4927 case OPC_VR54XX_MSACHI:
4928 gen_helper_msachi(t0, cpu_env, t0, t1);
4929 break;
4930 case OPC_VR54XX_MSACHIU:
4931 gen_helper_msachiu(t0, cpu_env, t0, t1);
4932 break;
4933 default:
4934 MIPS_INVAL("mul vr54xx");
4935 generate_exception_end(ctx, EXCP_RI);
4936 goto out;
4938 gen_store_gpr(t0, rd);
4940 out:
4941 tcg_temp_free(t0);
4942 tcg_temp_free(t1);
4945 static void gen_cl (DisasContext *ctx, uint32_t opc,
4946 int rd, int rs)
4948 TCGv t0;
4950 if (rd == 0) {
4951 /* Treat as NOP. */
4952 return;
4954 t0 = cpu_gpr[rd];
4955 gen_load_gpr(t0, rs);
4957 switch (opc) {
4958 case OPC_CLO:
4959 case R6_OPC_CLO:
4960 #if defined(TARGET_MIPS64)
4961 case OPC_DCLO:
4962 case R6_OPC_DCLO:
4963 #endif
4964 tcg_gen_not_tl(t0, t0);
4965 break;
4968 switch (opc) {
4969 case OPC_CLO:
4970 case R6_OPC_CLO:
4971 case OPC_CLZ:
4972 case R6_OPC_CLZ:
4973 tcg_gen_ext32u_tl(t0, t0);
4974 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4975 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4976 break;
4977 #if defined(TARGET_MIPS64)
4978 case OPC_DCLO:
4979 case R6_OPC_DCLO:
4980 case OPC_DCLZ:
4981 case R6_OPC_DCLZ:
4982 tcg_gen_clzi_i64(t0, t0, 64);
4983 break;
4984 #endif
4988 /* Godson integer instructions */
4989 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4990 int rd, int rs, int rt)
4992 TCGv t0, t1;
4994 if (rd == 0) {
4995 /* Treat as NOP. */
4996 return;
4999 switch (opc) {
5000 case OPC_MULT_G_2E:
5001 case OPC_MULT_G_2F:
5002 case OPC_MULTU_G_2E:
5003 case OPC_MULTU_G_2F:
5004 #if defined(TARGET_MIPS64)
5005 case OPC_DMULT_G_2E:
5006 case OPC_DMULT_G_2F:
5007 case OPC_DMULTU_G_2E:
5008 case OPC_DMULTU_G_2F:
5009 #endif
5010 t0 = tcg_temp_new();
5011 t1 = tcg_temp_new();
5012 break;
5013 default:
5014 t0 = tcg_temp_local_new();
5015 t1 = tcg_temp_local_new();
5016 break;
5019 gen_load_gpr(t0, rs);
5020 gen_load_gpr(t1, rt);
5022 switch (opc) {
5023 case OPC_MULT_G_2E:
5024 case OPC_MULT_G_2F:
5025 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5026 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5027 break;
5028 case OPC_MULTU_G_2E:
5029 case OPC_MULTU_G_2F:
5030 tcg_gen_ext32u_tl(t0, t0);
5031 tcg_gen_ext32u_tl(t1, t1);
5032 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5033 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5034 break;
5035 case OPC_DIV_G_2E:
5036 case OPC_DIV_G_2F:
5038 TCGLabel *l1 = gen_new_label();
5039 TCGLabel *l2 = gen_new_label();
5040 TCGLabel *l3 = gen_new_label();
5041 tcg_gen_ext32s_tl(t0, t0);
5042 tcg_gen_ext32s_tl(t1, t1);
5043 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5044 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5045 tcg_gen_br(l3);
5046 gen_set_label(l1);
5047 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5048 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5049 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5050 tcg_gen_br(l3);
5051 gen_set_label(l2);
5052 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5053 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5054 gen_set_label(l3);
5056 break;
5057 case OPC_DIVU_G_2E:
5058 case OPC_DIVU_G_2F:
5060 TCGLabel *l1 = gen_new_label();
5061 TCGLabel *l2 = gen_new_label();
5062 tcg_gen_ext32u_tl(t0, t0);
5063 tcg_gen_ext32u_tl(t1, t1);
5064 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5065 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5066 tcg_gen_br(l2);
5067 gen_set_label(l1);
5068 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5069 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5070 gen_set_label(l2);
5072 break;
5073 case OPC_MOD_G_2E:
5074 case OPC_MOD_G_2F:
5076 TCGLabel *l1 = gen_new_label();
5077 TCGLabel *l2 = gen_new_label();
5078 TCGLabel *l3 = gen_new_label();
5079 tcg_gen_ext32u_tl(t0, t0);
5080 tcg_gen_ext32u_tl(t1, t1);
5081 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5082 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5083 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5084 gen_set_label(l1);
5085 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5086 tcg_gen_br(l3);
5087 gen_set_label(l2);
5088 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5089 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5090 gen_set_label(l3);
5092 break;
5093 case OPC_MODU_G_2E:
5094 case OPC_MODU_G_2F:
5096 TCGLabel *l1 = gen_new_label();
5097 TCGLabel *l2 = gen_new_label();
5098 tcg_gen_ext32u_tl(t0, t0);
5099 tcg_gen_ext32u_tl(t1, t1);
5100 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5101 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5102 tcg_gen_br(l2);
5103 gen_set_label(l1);
5104 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5105 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5106 gen_set_label(l2);
5108 break;
5109 #if defined(TARGET_MIPS64)
5110 case OPC_DMULT_G_2E:
5111 case OPC_DMULT_G_2F:
5112 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5113 break;
5114 case OPC_DMULTU_G_2E:
5115 case OPC_DMULTU_G_2F:
5116 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5117 break;
5118 case OPC_DDIV_G_2E:
5119 case OPC_DDIV_G_2F:
5121 TCGLabel *l1 = gen_new_label();
5122 TCGLabel *l2 = gen_new_label();
5123 TCGLabel *l3 = gen_new_label();
5124 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5125 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5126 tcg_gen_br(l3);
5127 gen_set_label(l1);
5128 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5129 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5130 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5131 tcg_gen_br(l3);
5132 gen_set_label(l2);
5133 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5134 gen_set_label(l3);
5136 break;
5137 case OPC_DDIVU_G_2E:
5138 case OPC_DDIVU_G_2F:
5140 TCGLabel *l1 = gen_new_label();
5141 TCGLabel *l2 = gen_new_label();
5142 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5143 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5144 tcg_gen_br(l2);
5145 gen_set_label(l1);
5146 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5147 gen_set_label(l2);
5149 break;
5150 case OPC_DMOD_G_2E:
5151 case OPC_DMOD_G_2F:
5153 TCGLabel *l1 = gen_new_label();
5154 TCGLabel *l2 = gen_new_label();
5155 TCGLabel *l3 = gen_new_label();
5156 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5157 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5158 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5159 gen_set_label(l1);
5160 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5161 tcg_gen_br(l3);
5162 gen_set_label(l2);
5163 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5164 gen_set_label(l3);
5166 break;
5167 case OPC_DMODU_G_2E:
5168 case OPC_DMODU_G_2F:
5170 TCGLabel *l1 = gen_new_label();
5171 TCGLabel *l2 = gen_new_label();
5172 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5173 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5174 tcg_gen_br(l2);
5175 gen_set_label(l1);
5176 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5177 gen_set_label(l2);
5179 break;
5180 #endif
5183 tcg_temp_free(t0);
5184 tcg_temp_free(t1);
5187 /* Loongson multimedia instructions */
5188 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5190 uint32_t opc, shift_max;
5191 TCGv_i64 t0, t1;
5193 opc = MASK_LMI(ctx->opcode);
5194 switch (opc) {
5195 case OPC_ADD_CP2:
5196 case OPC_SUB_CP2:
5197 case OPC_DADD_CP2:
5198 case OPC_DSUB_CP2:
5199 t0 = tcg_temp_local_new_i64();
5200 t1 = tcg_temp_local_new_i64();
5201 break;
5202 default:
5203 t0 = tcg_temp_new_i64();
5204 t1 = tcg_temp_new_i64();
5205 break;
5208 check_cp1_enabled(ctx);
5209 gen_load_fpr64(ctx, t0, rs);
5210 gen_load_fpr64(ctx, t1, rt);
5212 #define LMI_HELPER(UP, LO) \
5213 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5214 #define LMI_HELPER_1(UP, LO) \
5215 case OPC_##UP: gen_helper_##LO(t0, t0); break
5216 #define LMI_DIRECT(UP, LO, OP) \
5217 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5219 switch (opc) {
5220 LMI_HELPER(PADDSH, paddsh);
5221 LMI_HELPER(PADDUSH, paddush);
5222 LMI_HELPER(PADDH, paddh);
5223 LMI_HELPER(PADDW, paddw);
5224 LMI_HELPER(PADDSB, paddsb);
5225 LMI_HELPER(PADDUSB, paddusb);
5226 LMI_HELPER(PADDB, paddb);
5228 LMI_HELPER(PSUBSH, psubsh);
5229 LMI_HELPER(PSUBUSH, psubush);
5230 LMI_HELPER(PSUBH, psubh);
5231 LMI_HELPER(PSUBW, psubw);
5232 LMI_HELPER(PSUBSB, psubsb);
5233 LMI_HELPER(PSUBUSB, psubusb);
5234 LMI_HELPER(PSUBB, psubb);
5236 LMI_HELPER(PSHUFH, pshufh);
5237 LMI_HELPER(PACKSSWH, packsswh);
5238 LMI_HELPER(PACKSSHB, packsshb);
5239 LMI_HELPER(PACKUSHB, packushb);
5241 LMI_HELPER(PUNPCKLHW, punpcklhw);
5242 LMI_HELPER(PUNPCKHHW, punpckhhw);
5243 LMI_HELPER(PUNPCKLBH, punpcklbh);
5244 LMI_HELPER(PUNPCKHBH, punpckhbh);
5245 LMI_HELPER(PUNPCKLWD, punpcklwd);
5246 LMI_HELPER(PUNPCKHWD, punpckhwd);
5248 LMI_HELPER(PAVGH, pavgh);
5249 LMI_HELPER(PAVGB, pavgb);
5250 LMI_HELPER(PMAXSH, pmaxsh);
5251 LMI_HELPER(PMINSH, pminsh);
5252 LMI_HELPER(PMAXUB, pmaxub);
5253 LMI_HELPER(PMINUB, pminub);
5255 LMI_HELPER(PCMPEQW, pcmpeqw);
5256 LMI_HELPER(PCMPGTW, pcmpgtw);
5257 LMI_HELPER(PCMPEQH, pcmpeqh);
5258 LMI_HELPER(PCMPGTH, pcmpgth);
5259 LMI_HELPER(PCMPEQB, pcmpeqb);
5260 LMI_HELPER(PCMPGTB, pcmpgtb);
5262 LMI_HELPER(PSLLW, psllw);
5263 LMI_HELPER(PSLLH, psllh);
5264 LMI_HELPER(PSRLW, psrlw);
5265 LMI_HELPER(PSRLH, psrlh);
5266 LMI_HELPER(PSRAW, psraw);
5267 LMI_HELPER(PSRAH, psrah);
5269 LMI_HELPER(PMULLH, pmullh);
5270 LMI_HELPER(PMULHH, pmulhh);
5271 LMI_HELPER(PMULHUH, pmulhuh);
5272 LMI_HELPER(PMADDHW, pmaddhw);
5274 LMI_HELPER(PASUBUB, pasubub);
5275 LMI_HELPER_1(BIADD, biadd);
5276 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5278 LMI_DIRECT(PADDD, paddd, add);
5279 LMI_DIRECT(PSUBD, psubd, sub);
5280 LMI_DIRECT(XOR_CP2, xor, xor);
5281 LMI_DIRECT(NOR_CP2, nor, nor);
5282 LMI_DIRECT(AND_CP2, and, and);
5283 LMI_DIRECT(OR_CP2, or, or);
5285 case OPC_PANDN:
5286 tcg_gen_andc_i64(t0, t1, t0);
5287 break;
5289 case OPC_PINSRH_0:
5290 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5291 break;
5292 case OPC_PINSRH_1:
5293 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5294 break;
5295 case OPC_PINSRH_2:
5296 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5297 break;
5298 case OPC_PINSRH_3:
5299 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5300 break;
5302 case OPC_PEXTRH:
5303 tcg_gen_andi_i64(t1, t1, 3);
5304 tcg_gen_shli_i64(t1, t1, 4);
5305 tcg_gen_shr_i64(t0, t0, t1);
5306 tcg_gen_ext16u_i64(t0, t0);
5307 break;
5309 case OPC_ADDU_CP2:
5310 tcg_gen_add_i64(t0, t0, t1);
5311 tcg_gen_ext32s_i64(t0, t0);
5312 break;
5313 case OPC_SUBU_CP2:
5314 tcg_gen_sub_i64(t0, t0, t1);
5315 tcg_gen_ext32s_i64(t0, t0);
5316 break;
5318 case OPC_SLL_CP2:
5319 shift_max = 32;
5320 goto do_shift;
5321 case OPC_SRL_CP2:
5322 shift_max = 32;
5323 goto do_shift;
5324 case OPC_SRA_CP2:
5325 shift_max = 32;
5326 goto do_shift;
5327 case OPC_DSLL_CP2:
5328 shift_max = 64;
5329 goto do_shift;
5330 case OPC_DSRL_CP2:
5331 shift_max = 64;
5332 goto do_shift;
5333 case OPC_DSRA_CP2:
5334 shift_max = 64;
5335 goto do_shift;
5336 do_shift:
5337 /* Make sure shift count isn't TCG undefined behaviour. */
5338 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5340 switch (opc) {
5341 case OPC_SLL_CP2:
5342 case OPC_DSLL_CP2:
5343 tcg_gen_shl_i64(t0, t0, t1);
5344 break;
5345 case OPC_SRA_CP2:
5346 case OPC_DSRA_CP2:
5347 /* Since SRA is UndefinedResult without sign-extended inputs,
5348 we can treat SRA and DSRA the same. */
5349 tcg_gen_sar_i64(t0, t0, t1);
5350 break;
5351 case OPC_SRL_CP2:
5352 /* We want to shift in zeros for SRL; zero-extend first. */
5353 tcg_gen_ext32u_i64(t0, t0);
5354 /* FALLTHRU */
5355 case OPC_DSRL_CP2:
5356 tcg_gen_shr_i64(t0, t0, t1);
5357 break;
5360 if (shift_max == 32) {
5361 tcg_gen_ext32s_i64(t0, t0);
5364 /* Shifts larger than MAX produce zero. */
5365 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5366 tcg_gen_neg_i64(t1, t1);
5367 tcg_gen_and_i64(t0, t0, t1);
5368 break;
5370 case OPC_ADD_CP2:
5371 case OPC_DADD_CP2:
5373 TCGv_i64 t2 = tcg_temp_new_i64();
5374 TCGLabel *lab = gen_new_label();
5376 tcg_gen_mov_i64(t2, t0);
5377 tcg_gen_add_i64(t0, t1, t2);
5378 if (opc == OPC_ADD_CP2) {
5379 tcg_gen_ext32s_i64(t0, t0);
5381 tcg_gen_xor_i64(t1, t1, t2);
5382 tcg_gen_xor_i64(t2, t2, t0);
5383 tcg_gen_andc_i64(t1, t2, t1);
5384 tcg_temp_free_i64(t2);
5385 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5386 generate_exception(ctx, EXCP_OVERFLOW);
5387 gen_set_label(lab);
5388 break;
5391 case OPC_SUB_CP2:
5392 case OPC_DSUB_CP2:
5394 TCGv_i64 t2 = tcg_temp_new_i64();
5395 TCGLabel *lab = gen_new_label();
5397 tcg_gen_mov_i64(t2, t0);
5398 tcg_gen_sub_i64(t0, t1, t2);
5399 if (opc == OPC_SUB_CP2) {
5400 tcg_gen_ext32s_i64(t0, t0);
5402 tcg_gen_xor_i64(t1, t1, t2);
5403 tcg_gen_xor_i64(t2, t2, t0);
5404 tcg_gen_and_i64(t1, t1, t2);
5405 tcg_temp_free_i64(t2);
5406 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5407 generate_exception(ctx, EXCP_OVERFLOW);
5408 gen_set_label(lab);
5409 break;
5412 case OPC_PMULUW:
5413 tcg_gen_ext32u_i64(t0, t0);
5414 tcg_gen_ext32u_i64(t1, t1);
5415 tcg_gen_mul_i64(t0, t0, t1);
5416 break;
5418 case OPC_SEQU_CP2:
5419 case OPC_SEQ_CP2:
5420 case OPC_SLTU_CP2:
5421 case OPC_SLT_CP2:
5422 case OPC_SLEU_CP2:
5423 case OPC_SLE_CP2:
5424 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5425 FD field is the CC field? */
5426 default:
5427 MIPS_INVAL("loongson_cp2");
5428 generate_exception_end(ctx, EXCP_RI);
5429 return;
5432 #undef LMI_HELPER
5433 #undef LMI_DIRECT
5435 gen_store_fpr64(ctx, t0, rd);
5437 tcg_temp_free_i64(t0);
5438 tcg_temp_free_i64(t1);
5441 /* Traps */
5442 static void gen_trap (DisasContext *ctx, uint32_t opc,
5443 int rs, int rt, int16_t imm)
5445 int cond;
5446 TCGv t0 = tcg_temp_new();
5447 TCGv t1 = tcg_temp_new();
5449 cond = 0;
5450 /* Load needed operands */
5451 switch (opc) {
5452 case OPC_TEQ:
5453 case OPC_TGE:
5454 case OPC_TGEU:
5455 case OPC_TLT:
5456 case OPC_TLTU:
5457 case OPC_TNE:
5458 /* Compare two registers */
5459 if (rs != rt) {
5460 gen_load_gpr(t0, rs);
5461 gen_load_gpr(t1, rt);
5462 cond = 1;
5464 break;
5465 case OPC_TEQI:
5466 case OPC_TGEI:
5467 case OPC_TGEIU:
5468 case OPC_TLTI:
5469 case OPC_TLTIU:
5470 case OPC_TNEI:
5471 /* Compare register to immediate */
5472 if (rs != 0 || imm != 0) {
5473 gen_load_gpr(t0, rs);
5474 tcg_gen_movi_tl(t1, (int32_t)imm);
5475 cond = 1;
5477 break;
5479 if (cond == 0) {
5480 switch (opc) {
5481 case OPC_TEQ: /* rs == rs */
5482 case OPC_TEQI: /* r0 == 0 */
5483 case OPC_TGE: /* rs >= rs */
5484 case OPC_TGEI: /* r0 >= 0 */
5485 case OPC_TGEU: /* rs >= rs unsigned */
5486 case OPC_TGEIU: /* r0 >= 0 unsigned */
5487 /* Always trap */
5488 generate_exception_end(ctx, EXCP_TRAP);
5489 break;
5490 case OPC_TLT: /* rs < rs */
5491 case OPC_TLTI: /* r0 < 0 */
5492 case OPC_TLTU: /* rs < rs unsigned */
5493 case OPC_TLTIU: /* r0 < 0 unsigned */
5494 case OPC_TNE: /* rs != rs */
5495 case OPC_TNEI: /* r0 != 0 */
5496 /* Never trap: treat as NOP. */
5497 break;
5499 } else {
5500 TCGLabel *l1 = gen_new_label();
5502 switch (opc) {
5503 case OPC_TEQ:
5504 case OPC_TEQI:
5505 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5506 break;
5507 case OPC_TGE:
5508 case OPC_TGEI:
5509 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5510 break;
5511 case OPC_TGEU:
5512 case OPC_TGEIU:
5513 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5514 break;
5515 case OPC_TLT:
5516 case OPC_TLTI:
5517 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5518 break;
5519 case OPC_TLTU:
5520 case OPC_TLTIU:
5521 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5522 break;
5523 case OPC_TNE:
5524 case OPC_TNEI:
5525 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5526 break;
5528 generate_exception(ctx, EXCP_TRAP);
5529 gen_set_label(l1);
5531 tcg_temp_free(t0);
5532 tcg_temp_free(t1);
5535 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5537 if (unlikely(ctx->base.singlestep_enabled)) {
5538 return false;
5541 #ifndef CONFIG_USER_ONLY
5542 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5543 #else
5544 return true;
5545 #endif
5548 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5550 if (use_goto_tb(ctx, dest)) {
5551 tcg_gen_goto_tb(n);
5552 gen_save_pc(dest);
5553 tcg_gen_exit_tb(ctx->base.tb, n);
5554 } else {
5555 gen_save_pc(dest);
5556 if (ctx->base.singlestep_enabled) {
5557 save_cpu_state(ctx, 0);
5558 gen_helper_raise_exception_debug(cpu_env);
5560 tcg_gen_lookup_and_goto_ptr();
5564 /* Branches (before delay slot) */
5565 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5566 int insn_bytes,
5567 int rs, int rt, int32_t offset,
5568 int delayslot_size)
5570 target_ulong btgt = -1;
5571 int blink = 0;
5572 int bcond_compute = 0;
5573 TCGv t0 = tcg_temp_new();
5574 TCGv t1 = tcg_temp_new();
5576 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5577 #ifdef MIPS_DEBUG_DISAS
5578 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5579 TARGET_FMT_lx "\n", ctx->base.pc_next);
5580 #endif
5581 generate_exception_end(ctx, EXCP_RI);
5582 goto out;
5585 /* Load needed operands */
5586 switch (opc) {
5587 case OPC_BEQ:
5588 case OPC_BEQL:
5589 case OPC_BNE:
5590 case OPC_BNEL:
5591 /* Compare two registers */
5592 if (rs != rt) {
5593 gen_load_gpr(t0, rs);
5594 gen_load_gpr(t1, rt);
5595 bcond_compute = 1;
5597 btgt = ctx->base.pc_next + insn_bytes + offset;
5598 break;
5599 case OPC_BGEZ:
5600 case OPC_BGEZAL:
5601 case OPC_BGEZALL:
5602 case OPC_BGEZL:
5603 case OPC_BGTZ:
5604 case OPC_BGTZL:
5605 case OPC_BLEZ:
5606 case OPC_BLEZL:
5607 case OPC_BLTZ:
5608 case OPC_BLTZAL:
5609 case OPC_BLTZALL:
5610 case OPC_BLTZL:
5611 /* Compare to zero */
5612 if (rs != 0) {
5613 gen_load_gpr(t0, rs);
5614 bcond_compute = 1;
5616 btgt = ctx->base.pc_next + insn_bytes + offset;
5617 break;
5618 case OPC_BPOSGE32:
5619 #if defined(TARGET_MIPS64)
5620 case OPC_BPOSGE64:
5621 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5622 #else
5623 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5624 #endif
5625 bcond_compute = 1;
5626 btgt = ctx->base.pc_next + insn_bytes + offset;
5627 break;
5628 case OPC_J:
5629 case OPC_JAL:
5630 case OPC_JALX:
5631 /* Jump to immediate */
5632 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5633 (uint32_t)offset;
5634 break;
5635 case OPC_JR:
5636 case OPC_JALR:
5637 /* Jump to register */
5638 if (offset != 0 && offset != 16) {
5639 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5640 others are reserved. */
5641 MIPS_INVAL("jump hint");
5642 generate_exception_end(ctx, EXCP_RI);
5643 goto out;
5645 gen_load_gpr(btarget, rs);
5646 break;
5647 default:
5648 MIPS_INVAL("branch/jump");
5649 generate_exception_end(ctx, EXCP_RI);
5650 goto out;
5652 if (bcond_compute == 0) {
5653 /* No condition to be computed */
5654 switch (opc) {
5655 case OPC_BEQ: /* rx == rx */
5656 case OPC_BEQL: /* rx == rx likely */
5657 case OPC_BGEZ: /* 0 >= 0 */
5658 case OPC_BGEZL: /* 0 >= 0 likely */
5659 case OPC_BLEZ: /* 0 <= 0 */
5660 case OPC_BLEZL: /* 0 <= 0 likely */
5661 /* Always take */
5662 ctx->hflags |= MIPS_HFLAG_B;
5663 break;
5664 case OPC_BGEZAL: /* 0 >= 0 */
5665 case OPC_BGEZALL: /* 0 >= 0 likely */
5666 /* Always take and link */
5667 blink = 31;
5668 ctx->hflags |= MIPS_HFLAG_B;
5669 break;
5670 case OPC_BNE: /* rx != rx */
5671 case OPC_BGTZ: /* 0 > 0 */
5672 case OPC_BLTZ: /* 0 < 0 */
5673 /* Treat as NOP. */
5674 goto out;
5675 case OPC_BLTZAL: /* 0 < 0 */
5676 /* Handle as an unconditional branch to get correct delay
5677 slot checking. */
5678 blink = 31;
5679 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5680 ctx->hflags |= MIPS_HFLAG_B;
5681 break;
5682 case OPC_BLTZALL: /* 0 < 0 likely */
5683 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5684 /* Skip the instruction in the delay slot */
5685 ctx->base.pc_next += 4;
5686 goto out;
5687 case OPC_BNEL: /* rx != rx likely */
5688 case OPC_BGTZL: /* 0 > 0 likely */
5689 case OPC_BLTZL: /* 0 < 0 likely */
5690 /* Skip the instruction in the delay slot */
5691 ctx->base.pc_next += 4;
5692 goto out;
5693 case OPC_J:
5694 ctx->hflags |= MIPS_HFLAG_B;
5695 break;
5696 case OPC_JALX:
5697 ctx->hflags |= MIPS_HFLAG_BX;
5698 /* Fallthrough */
5699 case OPC_JAL:
5700 blink = 31;
5701 ctx->hflags |= MIPS_HFLAG_B;
5702 break;
5703 case OPC_JR:
5704 ctx->hflags |= MIPS_HFLAG_BR;
5705 break;
5706 case OPC_JALR:
5707 blink = rt;
5708 ctx->hflags |= MIPS_HFLAG_BR;
5709 break;
5710 default:
5711 MIPS_INVAL("branch/jump");
5712 generate_exception_end(ctx, EXCP_RI);
5713 goto out;
5715 } else {
5716 switch (opc) {
5717 case OPC_BEQ:
5718 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5719 goto not_likely;
5720 case OPC_BEQL:
5721 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5722 goto likely;
5723 case OPC_BNE:
5724 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5725 goto not_likely;
5726 case OPC_BNEL:
5727 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5728 goto likely;
5729 case OPC_BGEZ:
5730 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5731 goto not_likely;
5732 case OPC_BGEZL:
5733 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5734 goto likely;
5735 case OPC_BGEZAL:
5736 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5737 blink = 31;
5738 goto not_likely;
5739 case OPC_BGEZALL:
5740 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5741 blink = 31;
5742 goto likely;
5743 case OPC_BGTZ:
5744 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5745 goto not_likely;
5746 case OPC_BGTZL:
5747 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5748 goto likely;
5749 case OPC_BLEZ:
5750 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5751 goto not_likely;
5752 case OPC_BLEZL:
5753 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5754 goto likely;
5755 case OPC_BLTZ:
5756 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5757 goto not_likely;
5758 case OPC_BLTZL:
5759 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5760 goto likely;
5761 case OPC_BPOSGE32:
5762 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5763 goto not_likely;
5764 #if defined(TARGET_MIPS64)
5765 case OPC_BPOSGE64:
5766 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5767 goto not_likely;
5768 #endif
5769 case OPC_BLTZAL:
5770 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5771 blink = 31;
5772 not_likely:
5773 ctx->hflags |= MIPS_HFLAG_BC;
5774 break;
5775 case OPC_BLTZALL:
5776 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5777 blink = 31;
5778 likely:
5779 ctx->hflags |= MIPS_HFLAG_BL;
5780 break;
5781 default:
5782 MIPS_INVAL("conditional branch/jump");
5783 generate_exception_end(ctx, EXCP_RI);
5784 goto out;
5788 ctx->btarget = btgt;
5790 switch (delayslot_size) {
5791 case 2:
5792 ctx->hflags |= MIPS_HFLAG_BDS16;
5793 break;
5794 case 4:
5795 ctx->hflags |= MIPS_HFLAG_BDS32;
5796 break;
5799 if (blink > 0) {
5800 int post_delay = insn_bytes + delayslot_size;
5801 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5803 tcg_gen_movi_tl(cpu_gpr[blink],
5804 ctx->base.pc_next + post_delay + lowbit);
5807 out:
5808 if (insn_bytes == 2)
5809 ctx->hflags |= MIPS_HFLAG_B16;
5810 tcg_temp_free(t0);
5811 tcg_temp_free(t1);
5815 /* nanoMIPS Branches */
5816 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5817 int insn_bytes,
5818 int rs, int rt, int32_t offset)
5820 target_ulong btgt = -1;
5821 int bcond_compute = 0;
5822 TCGv t0 = tcg_temp_new();
5823 TCGv t1 = tcg_temp_new();
5825 /* Load needed operands */
5826 switch (opc) {
5827 case OPC_BEQ:
5828 case OPC_BNE:
5829 /* Compare two registers */
5830 if (rs != rt) {
5831 gen_load_gpr(t0, rs);
5832 gen_load_gpr(t1, rt);
5833 bcond_compute = 1;
5835 btgt = ctx->base.pc_next + insn_bytes + offset;
5836 break;
5837 case OPC_BGEZAL:
5838 /* Compare to zero */
5839 if (rs != 0) {
5840 gen_load_gpr(t0, rs);
5841 bcond_compute = 1;
5843 btgt = ctx->base.pc_next + insn_bytes + offset;
5844 break;
5845 case OPC_BPOSGE32:
5846 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5847 bcond_compute = 1;
5848 btgt = ctx->base.pc_next + insn_bytes + offset;
5849 break;
5850 case OPC_JR:
5851 case OPC_JALR:
5852 /* Jump to register */
5853 if (offset != 0 && offset != 16) {
5854 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5855 others are reserved. */
5856 MIPS_INVAL("jump hint");
5857 generate_exception_end(ctx, EXCP_RI);
5858 goto out;
5860 gen_load_gpr(btarget, rs);
5861 break;
5862 default:
5863 MIPS_INVAL("branch/jump");
5864 generate_exception_end(ctx, EXCP_RI);
5865 goto out;
5867 if (bcond_compute == 0) {
5868 /* No condition to be computed */
5869 switch (opc) {
5870 case OPC_BEQ: /* rx == rx */
5871 /* Always take */
5872 ctx->hflags |= MIPS_HFLAG_B;
5873 break;
5874 case OPC_BGEZAL: /* 0 >= 0 */
5875 /* Always take and link */
5876 tcg_gen_movi_tl(cpu_gpr[31],
5877 ctx->base.pc_next + insn_bytes);
5878 ctx->hflags |= MIPS_HFLAG_B;
5879 break;
5880 case OPC_BNE: /* rx != rx */
5881 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5882 /* Skip the instruction in the delay slot */
5883 ctx->base.pc_next += 4;
5884 goto out;
5885 case OPC_JR:
5886 ctx->hflags |= MIPS_HFLAG_BR;
5887 break;
5888 case OPC_JALR:
5889 if (rt > 0) {
5890 tcg_gen_movi_tl(cpu_gpr[rt],
5891 ctx->base.pc_next + insn_bytes);
5893 ctx->hflags |= MIPS_HFLAG_BR;
5894 break;
5895 default:
5896 MIPS_INVAL("branch/jump");
5897 generate_exception_end(ctx, EXCP_RI);
5898 goto out;
5900 } else {
5901 switch (opc) {
5902 case OPC_BEQ:
5903 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5904 goto not_likely;
5905 case OPC_BNE:
5906 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5907 goto not_likely;
5908 case OPC_BGEZAL:
5909 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5910 tcg_gen_movi_tl(cpu_gpr[31],
5911 ctx->base.pc_next + insn_bytes);
5912 goto not_likely;
5913 case OPC_BPOSGE32:
5914 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5915 not_likely:
5916 ctx->hflags |= MIPS_HFLAG_BC;
5917 break;
5918 default:
5919 MIPS_INVAL("conditional branch/jump");
5920 generate_exception_end(ctx, EXCP_RI);
5921 goto out;
5925 ctx->btarget = btgt;
5927 out:
5928 if (insn_bytes == 2) {
5929 ctx->hflags |= MIPS_HFLAG_B16;
5931 tcg_temp_free(t0);
5932 tcg_temp_free(t1);
5936 /* special3 bitfield operations */
5937 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5938 int rs, int lsb, int msb)
5940 TCGv t0 = tcg_temp_new();
5941 TCGv t1 = tcg_temp_new();
5943 gen_load_gpr(t1, rs);
5944 switch (opc) {
5945 case OPC_EXT:
5946 if (lsb + msb > 31) {
5947 goto fail;
5949 if (msb != 31) {
5950 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5951 } else {
5952 /* The two checks together imply that lsb == 0,
5953 so this is a simple sign-extension. */
5954 tcg_gen_ext32s_tl(t0, t1);
5956 break;
5957 #if defined(TARGET_MIPS64)
5958 case OPC_DEXTU:
5959 lsb += 32;
5960 goto do_dext;
5961 case OPC_DEXTM:
5962 msb += 32;
5963 goto do_dext;
5964 case OPC_DEXT:
5965 do_dext:
5966 if (lsb + msb > 63) {
5967 goto fail;
5969 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5970 break;
5971 #endif
5972 case OPC_INS:
5973 if (lsb > msb) {
5974 goto fail;
5976 gen_load_gpr(t0, rt);
5977 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5978 tcg_gen_ext32s_tl(t0, t0);
5979 break;
5980 #if defined(TARGET_MIPS64)
5981 case OPC_DINSU:
5982 lsb += 32;
5983 /* FALLTHRU */
5984 case OPC_DINSM:
5985 msb += 32;
5986 /* FALLTHRU */
5987 case OPC_DINS:
5988 if (lsb > msb) {
5989 goto fail;
5991 gen_load_gpr(t0, rt);
5992 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5993 break;
5994 #endif
5995 default:
5996 fail:
5997 MIPS_INVAL("bitops");
5998 generate_exception_end(ctx, EXCP_RI);
5999 tcg_temp_free(t0);
6000 tcg_temp_free(t1);
6001 return;
6003 gen_store_gpr(t0, rt);
6004 tcg_temp_free(t0);
6005 tcg_temp_free(t1);
6008 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
6010 TCGv t0;
6012 if (rd == 0) {
6013 /* If no destination, treat it as a NOP. */
6014 return;
6017 t0 = tcg_temp_new();
6018 gen_load_gpr(t0, rt);
6019 switch (op2) {
6020 case OPC_WSBH:
6022 TCGv t1 = tcg_temp_new();
6023 TCGv t2 = tcg_const_tl(0x00FF00FF);
6025 tcg_gen_shri_tl(t1, t0, 8);
6026 tcg_gen_and_tl(t1, t1, t2);
6027 tcg_gen_and_tl(t0, t0, t2);
6028 tcg_gen_shli_tl(t0, t0, 8);
6029 tcg_gen_or_tl(t0, t0, t1);
6030 tcg_temp_free(t2);
6031 tcg_temp_free(t1);
6032 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6034 break;
6035 case OPC_SEB:
6036 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6037 break;
6038 case OPC_SEH:
6039 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6040 break;
6041 #if defined(TARGET_MIPS64)
6042 case OPC_DSBH:
6044 TCGv t1 = tcg_temp_new();
6045 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6047 tcg_gen_shri_tl(t1, t0, 8);
6048 tcg_gen_and_tl(t1, t1, t2);
6049 tcg_gen_and_tl(t0, t0, t2);
6050 tcg_gen_shli_tl(t0, t0, 8);
6051 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6052 tcg_temp_free(t2);
6053 tcg_temp_free(t1);
6055 break;
6056 case OPC_DSHD:
6058 TCGv t1 = tcg_temp_new();
6059 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6061 tcg_gen_shri_tl(t1, t0, 16);
6062 tcg_gen_and_tl(t1, t1, t2);
6063 tcg_gen_and_tl(t0, t0, t2);
6064 tcg_gen_shli_tl(t0, t0, 16);
6065 tcg_gen_or_tl(t0, t0, t1);
6066 tcg_gen_shri_tl(t1, t0, 32);
6067 tcg_gen_shli_tl(t0, t0, 32);
6068 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6069 tcg_temp_free(t2);
6070 tcg_temp_free(t1);
6072 break;
6073 #endif
6074 default:
6075 MIPS_INVAL("bsfhl");
6076 generate_exception_end(ctx, EXCP_RI);
6077 tcg_temp_free(t0);
6078 return;
6080 tcg_temp_free(t0);
6083 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6084 int imm2)
6086 TCGv t0;
6087 TCGv t1;
6088 if (rd == 0) {
6089 /* Treat as NOP. */
6090 return;
6092 t0 = tcg_temp_new();
6093 t1 = tcg_temp_new();
6094 gen_load_gpr(t0, rs);
6095 gen_load_gpr(t1, rt);
6096 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6097 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6098 if (opc == OPC_LSA) {
6099 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6102 tcg_temp_free(t1);
6103 tcg_temp_free(t0);
6105 return;
6108 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6109 int rt, int bits)
6111 TCGv t0;
6112 if (rd == 0) {
6113 /* Treat as NOP. */
6114 return;
6116 t0 = tcg_temp_new();
6117 if (bits == 0 || bits == wordsz) {
6118 if (bits == 0) {
6119 gen_load_gpr(t0, rt);
6120 } else {
6121 gen_load_gpr(t0, rs);
6123 switch (wordsz) {
6124 case 32:
6125 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6126 break;
6127 #if defined(TARGET_MIPS64)
6128 case 64:
6129 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6130 break;
6131 #endif
6133 } else {
6134 TCGv t1 = tcg_temp_new();
6135 gen_load_gpr(t0, rt);
6136 gen_load_gpr(t1, rs);
6137 switch (wordsz) {
6138 case 32:
6140 TCGv_i64 t2 = tcg_temp_new_i64();
6141 tcg_gen_concat_tl_i64(t2, t1, t0);
6142 tcg_gen_shri_i64(t2, t2, 32 - bits);
6143 gen_move_low32(cpu_gpr[rd], t2);
6144 tcg_temp_free_i64(t2);
6146 break;
6147 #if defined(TARGET_MIPS64)
6148 case 64:
6149 tcg_gen_shli_tl(t0, t0, bits);
6150 tcg_gen_shri_tl(t1, t1, 64 - bits);
6151 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6152 break;
6153 #endif
6155 tcg_temp_free(t1);
6158 tcg_temp_free(t0);
6161 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6162 int bp)
6164 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6167 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6168 int shift)
6170 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6173 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6175 TCGv t0;
6176 if (rd == 0) {
6177 /* Treat as NOP. */
6178 return;
6180 t0 = tcg_temp_new();
6181 gen_load_gpr(t0, rt);
6182 switch (opc) {
6183 case OPC_BITSWAP:
6184 gen_helper_bitswap(cpu_gpr[rd], t0);
6185 break;
6186 #if defined(TARGET_MIPS64)
6187 case OPC_DBITSWAP:
6188 gen_helper_dbitswap(cpu_gpr[rd], t0);
6189 break;
6190 #endif
6192 tcg_temp_free(t0);
6195 #ifndef CONFIG_USER_ONLY
6196 /* CP0 (MMU and control) */
6197 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6199 TCGv_i64 t0 = tcg_temp_new_i64();
6200 TCGv_i64 t1 = tcg_temp_new_i64();
6202 tcg_gen_ext_tl_i64(t0, arg);
6203 tcg_gen_ld_i64(t1, cpu_env, off);
6204 #if defined(TARGET_MIPS64)
6205 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6206 #else
6207 tcg_gen_concat32_i64(t1, t1, t0);
6208 #endif
6209 tcg_gen_st_i64(t1, cpu_env, off);
6210 tcg_temp_free_i64(t1);
6211 tcg_temp_free_i64(t0);
6214 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6216 TCGv_i64 t0 = tcg_temp_new_i64();
6217 TCGv_i64 t1 = tcg_temp_new_i64();
6219 tcg_gen_ext_tl_i64(t0, arg);
6220 tcg_gen_ld_i64(t1, cpu_env, off);
6221 tcg_gen_concat32_i64(t1, t1, t0);
6222 tcg_gen_st_i64(t1, cpu_env, off);
6223 tcg_temp_free_i64(t1);
6224 tcg_temp_free_i64(t0);
6227 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6229 TCGv_i64 t0 = tcg_temp_new_i64();
6231 tcg_gen_ld_i64(t0, cpu_env, off);
6232 #if defined(TARGET_MIPS64)
6233 tcg_gen_shri_i64(t0, t0, 30);
6234 #else
6235 tcg_gen_shri_i64(t0, t0, 32);
6236 #endif
6237 gen_move_low32(arg, t0);
6238 tcg_temp_free_i64(t0);
6241 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6243 TCGv_i64 t0 = tcg_temp_new_i64();
6245 tcg_gen_ld_i64(t0, cpu_env, off);
6246 tcg_gen_shri_i64(t0, t0, 32 + shift);
6247 gen_move_low32(arg, t0);
6248 tcg_temp_free_i64(t0);
6251 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6253 TCGv_i32 t0 = tcg_temp_new_i32();
6255 tcg_gen_ld_i32(t0, cpu_env, off);
6256 tcg_gen_ext_i32_tl(arg, t0);
6257 tcg_temp_free_i32(t0);
6260 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6262 tcg_gen_ld_tl(arg, cpu_env, off);
6263 tcg_gen_ext32s_tl(arg, arg);
6266 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6268 TCGv_i32 t0 = tcg_temp_new_i32();
6270 tcg_gen_trunc_tl_i32(t0, arg);
6271 tcg_gen_st_i32(t0, cpu_env, off);
6272 tcg_temp_free_i32(t0);
6275 #define CP0_CHECK(c) \
6276 do { \
6277 if (!(c)) { \
6278 goto cp0_unimplemented; \
6280 } while (0)
6282 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6284 const char *rn = "invalid";
6286 switch (reg) {
6287 case 2:
6288 switch (sel) {
6289 case 0:
6290 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6291 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6292 rn = "EntryLo0";
6293 break;
6294 default:
6295 goto cp0_unimplemented;
6297 break;
6298 case 3:
6299 switch (sel) {
6300 case 0:
6301 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6302 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6303 rn = "EntryLo1";
6304 break;
6305 default:
6306 goto cp0_unimplemented;
6308 break;
6309 case 17:
6310 switch (sel) {
6311 case 0:
6312 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6313 ctx->CP0_LLAddr_shift);
6314 rn = "LLAddr";
6315 break;
6316 case 1:
6317 CP0_CHECK(ctx->mrp);
6318 gen_helper_mfhc0_maar(arg, cpu_env);
6319 rn = "MAAR";
6320 break;
6321 default:
6322 goto cp0_unimplemented;
6324 break;
6325 case 28:
6326 switch (sel) {
6327 case 0:
6328 case 2:
6329 case 4:
6330 case 6:
6331 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6332 rn = "TagLo";
6333 break;
6334 default:
6335 goto cp0_unimplemented;
6337 break;
6338 default:
6339 goto cp0_unimplemented;
6341 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6342 return;
6344 cp0_unimplemented:
6345 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6346 tcg_gen_movi_tl(arg, 0);
6349 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6351 const char *rn = "invalid";
6352 uint64_t mask = ctx->PAMask >> 36;
6354 switch (reg) {
6355 case 2:
6356 switch (sel) {
6357 case 0:
6358 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6359 tcg_gen_andi_tl(arg, arg, mask);
6360 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6361 rn = "EntryLo0";
6362 break;
6363 default:
6364 goto cp0_unimplemented;
6366 break;
6367 case 3:
6368 switch (sel) {
6369 case 0:
6370 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6371 tcg_gen_andi_tl(arg, arg, mask);
6372 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6373 rn = "EntryLo1";
6374 break;
6375 default:
6376 goto cp0_unimplemented;
6378 break;
6379 case 17:
6380 switch (sel) {
6381 case 0:
6382 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6383 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6384 relevant for modern MIPS cores supporting MTHC0, therefore
6385 treating MTHC0 to LLAddr as NOP. */
6386 rn = "LLAddr";
6387 break;
6388 case 1:
6389 CP0_CHECK(ctx->mrp);
6390 gen_helper_mthc0_maar(cpu_env, arg);
6391 rn = "MAAR";
6392 break;
6393 default:
6394 goto cp0_unimplemented;
6396 break;
6397 case 28:
6398 switch (sel) {
6399 case 0:
6400 case 2:
6401 case 4:
6402 case 6:
6403 tcg_gen_andi_tl(arg, arg, mask);
6404 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6405 rn = "TagLo";
6406 break;
6407 default:
6408 goto cp0_unimplemented;
6410 break;
6411 default:
6412 goto cp0_unimplemented;
6414 trace_mips_translate_c0("mthc0", rn, reg, sel);
6416 cp0_unimplemented:
6417 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6420 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6422 if (ctx->insn_flags & ISA_MIPS32R6) {
6423 tcg_gen_movi_tl(arg, 0);
6424 } else {
6425 tcg_gen_movi_tl(arg, ~0);
6429 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6431 const char *rn = "invalid";
6433 if (sel != 0)
6434 check_insn(ctx, ISA_MIPS32);
6436 switch (reg) {
6437 case 0:
6438 switch (sel) {
6439 case 0:
6440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6441 rn = "Index";
6442 break;
6443 case 1:
6444 CP0_CHECK(ctx->insn_flags & ASE_MT);
6445 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6446 rn = "MVPControl";
6447 break;
6448 case 2:
6449 CP0_CHECK(ctx->insn_flags & ASE_MT);
6450 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6451 rn = "MVPConf0";
6452 break;
6453 case 3:
6454 CP0_CHECK(ctx->insn_flags & ASE_MT);
6455 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6456 rn = "MVPConf1";
6457 break;
6458 case 4:
6459 CP0_CHECK(ctx->vp);
6460 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6461 rn = "VPControl";
6462 break;
6463 default:
6464 goto cp0_unimplemented;
6466 break;
6467 case 1:
6468 switch (sel) {
6469 case 0:
6470 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6471 gen_helper_mfc0_random(arg, cpu_env);
6472 rn = "Random";
6473 break;
6474 case 1:
6475 CP0_CHECK(ctx->insn_flags & ASE_MT);
6476 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6477 rn = "VPEControl";
6478 break;
6479 case 2:
6480 CP0_CHECK(ctx->insn_flags & ASE_MT);
6481 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6482 rn = "VPEConf0";
6483 break;
6484 case 3:
6485 CP0_CHECK(ctx->insn_flags & ASE_MT);
6486 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6487 rn = "VPEConf1";
6488 break;
6489 case 4:
6490 CP0_CHECK(ctx->insn_flags & ASE_MT);
6491 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6492 rn = "YQMask";
6493 break;
6494 case 5:
6495 CP0_CHECK(ctx->insn_flags & ASE_MT);
6496 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6497 rn = "VPESchedule";
6498 break;
6499 case 6:
6500 CP0_CHECK(ctx->insn_flags & ASE_MT);
6501 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6502 rn = "VPEScheFBack";
6503 break;
6504 case 7:
6505 CP0_CHECK(ctx->insn_flags & ASE_MT);
6506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6507 rn = "VPEOpt";
6508 break;
6509 default:
6510 goto cp0_unimplemented;
6512 break;
6513 case 2:
6514 switch (sel) {
6515 case 0:
6517 TCGv_i64 tmp = tcg_temp_new_i64();
6518 tcg_gen_ld_i64(tmp, cpu_env,
6519 offsetof(CPUMIPSState, CP0_EntryLo0));
6520 #if defined(TARGET_MIPS64)
6521 if (ctx->rxi) {
6522 /* Move RI/XI fields to bits 31:30 */
6523 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6524 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6526 #endif
6527 gen_move_low32(arg, tmp);
6528 tcg_temp_free_i64(tmp);
6530 rn = "EntryLo0";
6531 break;
6532 case 1:
6533 CP0_CHECK(ctx->insn_flags & ASE_MT);
6534 gen_helper_mfc0_tcstatus(arg, cpu_env);
6535 rn = "TCStatus";
6536 break;
6537 case 2:
6538 CP0_CHECK(ctx->insn_flags & ASE_MT);
6539 gen_helper_mfc0_tcbind(arg, cpu_env);
6540 rn = "TCBind";
6541 break;
6542 case 3:
6543 CP0_CHECK(ctx->insn_flags & ASE_MT);
6544 gen_helper_mfc0_tcrestart(arg, cpu_env);
6545 rn = "TCRestart";
6546 break;
6547 case 4:
6548 CP0_CHECK(ctx->insn_flags & ASE_MT);
6549 gen_helper_mfc0_tchalt(arg, cpu_env);
6550 rn = "TCHalt";
6551 break;
6552 case 5:
6553 CP0_CHECK(ctx->insn_flags & ASE_MT);
6554 gen_helper_mfc0_tccontext(arg, cpu_env);
6555 rn = "TCContext";
6556 break;
6557 case 6:
6558 CP0_CHECK(ctx->insn_flags & ASE_MT);
6559 gen_helper_mfc0_tcschedule(arg, cpu_env);
6560 rn = "TCSchedule";
6561 break;
6562 case 7:
6563 CP0_CHECK(ctx->insn_flags & ASE_MT);
6564 gen_helper_mfc0_tcschefback(arg, cpu_env);
6565 rn = "TCScheFBack";
6566 break;
6567 default:
6568 goto cp0_unimplemented;
6570 break;
6571 case 3:
6572 switch (sel) {
6573 case 0:
6575 TCGv_i64 tmp = tcg_temp_new_i64();
6576 tcg_gen_ld_i64(tmp, cpu_env,
6577 offsetof(CPUMIPSState, CP0_EntryLo1));
6578 #if defined(TARGET_MIPS64)
6579 if (ctx->rxi) {
6580 /* Move RI/XI fields to bits 31:30 */
6581 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6582 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6584 #endif
6585 gen_move_low32(arg, tmp);
6586 tcg_temp_free_i64(tmp);
6588 rn = "EntryLo1";
6589 break;
6590 case 1:
6591 CP0_CHECK(ctx->vp);
6592 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6593 rn = "GlobalNumber";
6594 break;
6595 default:
6596 goto cp0_unimplemented;
6598 break;
6599 case 4:
6600 switch (sel) {
6601 case 0:
6602 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6603 tcg_gen_ext32s_tl(arg, arg);
6604 rn = "Context";
6605 break;
6606 case 1:
6607 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6608 rn = "ContextConfig";
6609 goto cp0_unimplemented;
6610 case 2:
6611 CP0_CHECK(ctx->ulri);
6612 tcg_gen_ld_tl(arg, cpu_env,
6613 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6614 tcg_gen_ext32s_tl(arg, arg);
6615 rn = "UserLocal";
6616 break;
6617 default:
6618 goto cp0_unimplemented;
6620 break;
6621 case 5:
6622 switch (sel) {
6623 case 0:
6624 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6625 rn = "PageMask";
6626 break;
6627 case 1:
6628 check_insn(ctx, ISA_MIPS32R2);
6629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6630 rn = "PageGrain";
6631 break;
6632 case 2:
6633 CP0_CHECK(ctx->sc);
6634 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6635 tcg_gen_ext32s_tl(arg, arg);
6636 rn = "SegCtl0";
6637 break;
6638 case 3:
6639 CP0_CHECK(ctx->sc);
6640 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6641 tcg_gen_ext32s_tl(arg, arg);
6642 rn = "SegCtl1";
6643 break;
6644 case 4:
6645 CP0_CHECK(ctx->sc);
6646 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6647 tcg_gen_ext32s_tl(arg, arg);
6648 rn = "SegCtl2";
6649 break;
6650 case 5:
6651 check_pw(ctx);
6652 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6653 rn = "PWBase";
6654 break;
6655 case 6:
6656 check_pw(ctx);
6657 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6658 rn = "PWField";
6659 break;
6660 case 7:
6661 check_pw(ctx);
6662 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6663 rn = "PWSize";
6664 break;
6665 default:
6666 goto cp0_unimplemented;
6668 break;
6669 case 6:
6670 switch (sel) {
6671 case 0:
6672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6673 rn = "Wired";
6674 break;
6675 case 1:
6676 check_insn(ctx, ISA_MIPS32R2);
6677 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6678 rn = "SRSConf0";
6679 break;
6680 case 2:
6681 check_insn(ctx, ISA_MIPS32R2);
6682 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6683 rn = "SRSConf1";
6684 break;
6685 case 3:
6686 check_insn(ctx, ISA_MIPS32R2);
6687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6688 rn = "SRSConf2";
6689 break;
6690 case 4:
6691 check_insn(ctx, ISA_MIPS32R2);
6692 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6693 rn = "SRSConf3";
6694 break;
6695 case 5:
6696 check_insn(ctx, ISA_MIPS32R2);
6697 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6698 rn = "SRSConf4";
6699 break;
6700 case 6:
6701 check_pw(ctx);
6702 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6703 rn = "PWCtl";
6704 break;
6705 default:
6706 goto cp0_unimplemented;
6708 break;
6709 case 7:
6710 switch (sel) {
6711 case 0:
6712 check_insn(ctx, ISA_MIPS32R2);
6713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6714 rn = "HWREna";
6715 break;
6716 default:
6717 goto cp0_unimplemented;
6719 break;
6720 case 8:
6721 switch (sel) {
6722 case 0:
6723 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6724 tcg_gen_ext32s_tl(arg, arg);
6725 rn = "BadVAddr";
6726 break;
6727 case 1:
6728 CP0_CHECK(ctx->bi);
6729 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6730 rn = "BadInstr";
6731 break;
6732 case 2:
6733 CP0_CHECK(ctx->bp);
6734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6735 rn = "BadInstrP";
6736 break;
6737 case 3:
6738 CP0_CHECK(ctx->bi);
6739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6740 tcg_gen_andi_tl(arg, arg, ~0xffff);
6741 rn = "BadInstrX";
6742 break;
6743 default:
6744 goto cp0_unimplemented;
6746 break;
6747 case 9:
6748 switch (sel) {
6749 case 0:
6750 /* Mark as an IO operation because we read the time. */
6751 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6752 gen_io_start();
6754 gen_helper_mfc0_count(arg, cpu_env);
6755 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6756 gen_io_end();
6758 /* Break the TB to be able to take timer interrupts immediately
6759 after reading count. DISAS_STOP isn't sufficient, we need to
6760 ensure we break completely out of translated code. */
6761 gen_save_pc(ctx->base.pc_next + 4);
6762 ctx->base.is_jmp = DISAS_EXIT;
6763 rn = "Count";
6764 break;
6765 /* 6,7 are implementation dependent */
6766 default:
6767 goto cp0_unimplemented;
6769 break;
6770 case 10:
6771 switch (sel) {
6772 case 0:
6773 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6774 tcg_gen_ext32s_tl(arg, arg);
6775 rn = "EntryHi";
6776 break;
6777 default:
6778 goto cp0_unimplemented;
6780 break;
6781 case 11:
6782 switch (sel) {
6783 case 0:
6784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6785 rn = "Compare";
6786 break;
6787 /* 6,7 are implementation dependent */
6788 default:
6789 goto cp0_unimplemented;
6791 break;
6792 case 12:
6793 switch (sel) {
6794 case 0:
6795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6796 rn = "Status";
6797 break;
6798 case 1:
6799 check_insn(ctx, ISA_MIPS32R2);
6800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6801 rn = "IntCtl";
6802 break;
6803 case 2:
6804 check_insn(ctx, ISA_MIPS32R2);
6805 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6806 rn = "SRSCtl";
6807 break;
6808 case 3:
6809 check_insn(ctx, ISA_MIPS32R2);
6810 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6811 rn = "SRSMap";
6812 break;
6813 default:
6814 goto cp0_unimplemented;
6816 break;
6817 case 13:
6818 switch (sel) {
6819 case 0:
6820 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6821 rn = "Cause";
6822 break;
6823 default:
6824 goto cp0_unimplemented;
6826 break;
6827 case 14:
6828 switch (sel) {
6829 case 0:
6830 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6831 tcg_gen_ext32s_tl(arg, arg);
6832 rn = "EPC";
6833 break;
6834 default:
6835 goto cp0_unimplemented;
6837 break;
6838 case 15:
6839 switch (sel) {
6840 case 0:
6841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6842 rn = "PRid";
6843 break;
6844 case 1:
6845 check_insn(ctx, ISA_MIPS32R2);
6846 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6847 tcg_gen_ext32s_tl(arg, arg);
6848 rn = "EBase";
6849 break;
6850 case 3:
6851 check_insn(ctx, ISA_MIPS32R2);
6852 CP0_CHECK(ctx->cmgcr);
6853 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6854 tcg_gen_ext32s_tl(arg, arg);
6855 rn = "CMGCRBase";
6856 break;
6857 default:
6858 goto cp0_unimplemented;
6860 break;
6861 case 16:
6862 switch (sel) {
6863 case 0:
6864 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6865 rn = "Config";
6866 break;
6867 case 1:
6868 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6869 rn = "Config1";
6870 break;
6871 case 2:
6872 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6873 rn = "Config2";
6874 break;
6875 case 3:
6876 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6877 rn = "Config3";
6878 break;
6879 case 4:
6880 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6881 rn = "Config4";
6882 break;
6883 case 5:
6884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6885 rn = "Config5";
6886 break;
6887 /* 6,7 are implementation dependent */
6888 case 6:
6889 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6890 rn = "Config6";
6891 break;
6892 case 7:
6893 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6894 rn = "Config7";
6895 break;
6896 default:
6897 goto cp0_unimplemented;
6899 break;
6900 case 17:
6901 switch (sel) {
6902 case 0:
6903 gen_helper_mfc0_lladdr(arg, cpu_env);
6904 rn = "LLAddr";
6905 break;
6906 case 1:
6907 CP0_CHECK(ctx->mrp);
6908 gen_helper_mfc0_maar(arg, cpu_env);
6909 rn = "MAAR";
6910 break;
6911 case 2:
6912 CP0_CHECK(ctx->mrp);
6913 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6914 rn = "MAARI";
6915 break;
6916 default:
6917 goto cp0_unimplemented;
6919 break;
6920 case 18:
6921 switch (sel) {
6922 case 0:
6923 case 1:
6924 case 2:
6925 case 3:
6926 case 4:
6927 case 5:
6928 case 6:
6929 case 7:
6930 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6931 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6932 rn = "WatchLo";
6933 break;
6934 default:
6935 goto cp0_unimplemented;
6937 break;
6938 case 19:
6939 switch (sel) {
6940 case 0:
6941 case 1:
6942 case 2:
6943 case 3:
6944 case 4:
6945 case 5:
6946 case 6:
6947 case 7:
6948 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6949 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6950 rn = "WatchHi";
6951 break;
6952 default:
6953 goto cp0_unimplemented;
6955 break;
6956 case 20:
6957 switch (sel) {
6958 case 0:
6959 #if defined(TARGET_MIPS64)
6960 check_insn(ctx, ISA_MIPS3);
6961 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6962 tcg_gen_ext32s_tl(arg, arg);
6963 rn = "XContext";
6964 break;
6965 #endif
6966 default:
6967 goto cp0_unimplemented;
6969 break;
6970 case 21:
6971 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6972 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6973 switch (sel) {
6974 case 0:
6975 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6976 rn = "Framemask";
6977 break;
6978 default:
6979 goto cp0_unimplemented;
6981 break;
6982 case 22:
6983 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6984 rn = "'Diagnostic"; /* implementation dependent */
6985 break;
6986 case 23:
6987 switch (sel) {
6988 case 0:
6989 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6990 rn = "Debug";
6991 break;
6992 case 1:
6993 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
6994 rn = "TraceControl";
6995 goto cp0_unimplemented;
6996 case 2:
6997 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
6998 rn = "TraceControl2";
6999 goto cp0_unimplemented;
7000 case 3:
7001 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
7002 rn = "UserTraceData";
7003 goto cp0_unimplemented;
7004 case 4:
7005 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
7006 rn = "TraceBPC";
7007 goto cp0_unimplemented;
7008 default:
7009 goto cp0_unimplemented;
7011 break;
7012 case 24:
7013 switch (sel) {
7014 case 0:
7015 /* EJTAG support */
7016 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7017 tcg_gen_ext32s_tl(arg, arg);
7018 rn = "DEPC";
7019 break;
7020 default:
7021 goto cp0_unimplemented;
7023 break;
7024 case 25:
7025 switch (sel) {
7026 case 0:
7027 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7028 rn = "Performance0";
7029 break;
7030 case 1:
7031 // gen_helper_mfc0_performance1(arg);
7032 rn = "Performance1";
7033 goto cp0_unimplemented;
7034 case 2:
7035 // gen_helper_mfc0_performance2(arg);
7036 rn = "Performance2";
7037 goto cp0_unimplemented;
7038 case 3:
7039 // gen_helper_mfc0_performance3(arg);
7040 rn = "Performance3";
7041 goto cp0_unimplemented;
7042 case 4:
7043 // gen_helper_mfc0_performance4(arg);
7044 rn = "Performance4";
7045 goto cp0_unimplemented;
7046 case 5:
7047 // gen_helper_mfc0_performance5(arg);
7048 rn = "Performance5";
7049 goto cp0_unimplemented;
7050 case 6:
7051 // gen_helper_mfc0_performance6(arg);
7052 rn = "Performance6";
7053 goto cp0_unimplemented;
7054 case 7:
7055 // gen_helper_mfc0_performance7(arg);
7056 rn = "Performance7";
7057 goto cp0_unimplemented;
7058 default:
7059 goto cp0_unimplemented;
7061 break;
7062 case 26:
7063 switch (sel) {
7064 case 0:
7065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7066 rn = "ErrCtl";
7067 break;
7068 default:
7069 goto cp0_unimplemented;
7071 break;
7072 case 27:
7073 switch (sel) {
7074 case 0:
7075 case 1:
7076 case 2:
7077 case 3:
7078 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7079 rn = "CacheErr";
7080 break;
7081 default:
7082 goto cp0_unimplemented;
7084 break;
7085 case 28:
7086 switch (sel) {
7087 case 0:
7088 case 2:
7089 case 4:
7090 case 6:
7092 TCGv_i64 tmp = tcg_temp_new_i64();
7093 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7094 gen_move_low32(arg, tmp);
7095 tcg_temp_free_i64(tmp);
7097 rn = "TagLo";
7098 break;
7099 case 1:
7100 case 3:
7101 case 5:
7102 case 7:
7103 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7104 rn = "DataLo";
7105 break;
7106 default:
7107 goto cp0_unimplemented;
7109 break;
7110 case 29:
7111 switch (sel) {
7112 case 0:
7113 case 2:
7114 case 4:
7115 case 6:
7116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7117 rn = "TagHi";
7118 break;
7119 case 1:
7120 case 3:
7121 case 5:
7122 case 7:
7123 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7124 rn = "DataHi";
7125 break;
7126 default:
7127 goto cp0_unimplemented;
7129 break;
7130 case 30:
7131 switch (sel) {
7132 case 0:
7133 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7134 tcg_gen_ext32s_tl(arg, arg);
7135 rn = "ErrorEPC";
7136 break;
7137 default:
7138 goto cp0_unimplemented;
7140 break;
7141 case 31:
7142 switch (sel) {
7143 case 0:
7144 /* EJTAG support */
7145 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7146 rn = "DESAVE";
7147 break;
7148 case 2:
7149 case 3:
7150 case 4:
7151 case 5:
7152 case 6:
7153 case 7:
7154 CP0_CHECK(ctx->kscrexist & (1 << sel));
7155 tcg_gen_ld_tl(arg, cpu_env,
7156 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7157 tcg_gen_ext32s_tl(arg, arg);
7158 rn = "KScratch";
7159 break;
7160 default:
7161 goto cp0_unimplemented;
7163 break;
7164 default:
7165 goto cp0_unimplemented;
7167 trace_mips_translate_c0("mfc0", rn, reg, sel);
7168 return;
7170 cp0_unimplemented:
7171 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7172 gen_mfc0_unimplemented(ctx, arg);
7175 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7177 const char *rn = "invalid";
7179 if (sel != 0)
7180 check_insn(ctx, ISA_MIPS32);
7182 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7183 gen_io_start();
7186 switch (reg) {
7187 case 0:
7188 switch (sel) {
7189 case 0:
7190 gen_helper_mtc0_index(cpu_env, arg);
7191 rn = "Index";
7192 break;
7193 case 1:
7194 CP0_CHECK(ctx->insn_flags & ASE_MT);
7195 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7196 rn = "MVPControl";
7197 break;
7198 case 2:
7199 CP0_CHECK(ctx->insn_flags & ASE_MT);
7200 /* ignored */
7201 rn = "MVPConf0";
7202 break;
7203 case 3:
7204 CP0_CHECK(ctx->insn_flags & ASE_MT);
7205 /* ignored */
7206 rn = "MVPConf1";
7207 break;
7208 case 4:
7209 CP0_CHECK(ctx->vp);
7210 /* ignored */
7211 rn = "VPControl";
7212 break;
7213 default:
7214 goto cp0_unimplemented;
7216 break;
7217 case 1:
7218 switch (sel) {
7219 case 0:
7220 /* ignored */
7221 rn = "Random";
7222 break;
7223 case 1:
7224 CP0_CHECK(ctx->insn_flags & ASE_MT);
7225 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7226 rn = "VPEControl";
7227 break;
7228 case 2:
7229 CP0_CHECK(ctx->insn_flags & ASE_MT);
7230 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7231 rn = "VPEConf0";
7232 break;
7233 case 3:
7234 CP0_CHECK(ctx->insn_flags & ASE_MT);
7235 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7236 rn = "VPEConf1";
7237 break;
7238 case 4:
7239 CP0_CHECK(ctx->insn_flags & ASE_MT);
7240 gen_helper_mtc0_yqmask(cpu_env, arg);
7241 rn = "YQMask";
7242 break;
7243 case 5:
7244 CP0_CHECK(ctx->insn_flags & ASE_MT);
7245 tcg_gen_st_tl(arg, cpu_env,
7246 offsetof(CPUMIPSState, CP0_VPESchedule));
7247 rn = "VPESchedule";
7248 break;
7249 case 6:
7250 CP0_CHECK(ctx->insn_flags & ASE_MT);
7251 tcg_gen_st_tl(arg, cpu_env,
7252 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7253 rn = "VPEScheFBack";
7254 break;
7255 case 7:
7256 CP0_CHECK(ctx->insn_flags & ASE_MT);
7257 gen_helper_mtc0_vpeopt(cpu_env, arg);
7258 rn = "VPEOpt";
7259 break;
7260 default:
7261 goto cp0_unimplemented;
7263 break;
7264 case 2:
7265 switch (sel) {
7266 case 0:
7267 gen_helper_mtc0_entrylo0(cpu_env, arg);
7268 rn = "EntryLo0";
7269 break;
7270 case 1:
7271 CP0_CHECK(ctx->insn_flags & ASE_MT);
7272 gen_helper_mtc0_tcstatus(cpu_env, arg);
7273 rn = "TCStatus";
7274 break;
7275 case 2:
7276 CP0_CHECK(ctx->insn_flags & ASE_MT);
7277 gen_helper_mtc0_tcbind(cpu_env, arg);
7278 rn = "TCBind";
7279 break;
7280 case 3:
7281 CP0_CHECK(ctx->insn_flags & ASE_MT);
7282 gen_helper_mtc0_tcrestart(cpu_env, arg);
7283 rn = "TCRestart";
7284 break;
7285 case 4:
7286 CP0_CHECK(ctx->insn_flags & ASE_MT);
7287 gen_helper_mtc0_tchalt(cpu_env, arg);
7288 rn = "TCHalt";
7289 break;
7290 case 5:
7291 CP0_CHECK(ctx->insn_flags & ASE_MT);
7292 gen_helper_mtc0_tccontext(cpu_env, arg);
7293 rn = "TCContext";
7294 break;
7295 case 6:
7296 CP0_CHECK(ctx->insn_flags & ASE_MT);
7297 gen_helper_mtc0_tcschedule(cpu_env, arg);
7298 rn = "TCSchedule";
7299 break;
7300 case 7:
7301 CP0_CHECK(ctx->insn_flags & ASE_MT);
7302 gen_helper_mtc0_tcschefback(cpu_env, arg);
7303 rn = "TCScheFBack";
7304 break;
7305 default:
7306 goto cp0_unimplemented;
7308 break;
7309 case 3:
7310 switch (sel) {
7311 case 0:
7312 gen_helper_mtc0_entrylo1(cpu_env, arg);
7313 rn = "EntryLo1";
7314 break;
7315 case 1:
7316 CP0_CHECK(ctx->vp);
7317 /* ignored */
7318 rn = "GlobalNumber";
7319 break;
7320 default:
7321 goto cp0_unimplemented;
7323 break;
7324 case 4:
7325 switch (sel) {
7326 case 0:
7327 gen_helper_mtc0_context(cpu_env, arg);
7328 rn = "Context";
7329 break;
7330 case 1:
7331 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7332 rn = "ContextConfig";
7333 goto cp0_unimplemented;
7334 case 2:
7335 CP0_CHECK(ctx->ulri);
7336 tcg_gen_st_tl(arg, cpu_env,
7337 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7338 rn = "UserLocal";
7339 break;
7340 default:
7341 goto cp0_unimplemented;
7343 break;
7344 case 5:
7345 switch (sel) {
7346 case 0:
7347 gen_helper_mtc0_pagemask(cpu_env, arg);
7348 rn = "PageMask";
7349 break;
7350 case 1:
7351 check_insn(ctx, ISA_MIPS32R2);
7352 gen_helper_mtc0_pagegrain(cpu_env, arg);
7353 rn = "PageGrain";
7354 ctx->base.is_jmp = DISAS_STOP;
7355 break;
7356 case 2:
7357 CP0_CHECK(ctx->sc);
7358 gen_helper_mtc0_segctl0(cpu_env, arg);
7359 rn = "SegCtl0";
7360 break;
7361 case 3:
7362 CP0_CHECK(ctx->sc);
7363 gen_helper_mtc0_segctl1(cpu_env, arg);
7364 rn = "SegCtl1";
7365 break;
7366 case 4:
7367 CP0_CHECK(ctx->sc);
7368 gen_helper_mtc0_segctl2(cpu_env, arg);
7369 rn = "SegCtl2";
7370 break;
7371 case 5:
7372 check_pw(ctx);
7373 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7374 rn = "PWBase";
7375 break;
7376 case 6:
7377 check_pw(ctx);
7378 gen_helper_mtc0_pwfield(cpu_env, arg);
7379 rn = "PWField";
7380 break;
7381 case 7:
7382 check_pw(ctx);
7383 gen_helper_mtc0_pwsize(cpu_env, arg);
7384 rn = "PWSize";
7385 break;
7386 default:
7387 goto cp0_unimplemented;
7389 break;
7390 case 6:
7391 switch (sel) {
7392 case 0:
7393 gen_helper_mtc0_wired(cpu_env, arg);
7394 rn = "Wired";
7395 break;
7396 case 1:
7397 check_insn(ctx, ISA_MIPS32R2);
7398 gen_helper_mtc0_srsconf0(cpu_env, arg);
7399 rn = "SRSConf0";
7400 break;
7401 case 2:
7402 check_insn(ctx, ISA_MIPS32R2);
7403 gen_helper_mtc0_srsconf1(cpu_env, arg);
7404 rn = "SRSConf1";
7405 break;
7406 case 3:
7407 check_insn(ctx, ISA_MIPS32R2);
7408 gen_helper_mtc0_srsconf2(cpu_env, arg);
7409 rn = "SRSConf2";
7410 break;
7411 case 4:
7412 check_insn(ctx, ISA_MIPS32R2);
7413 gen_helper_mtc0_srsconf3(cpu_env, arg);
7414 rn = "SRSConf3";
7415 break;
7416 case 5:
7417 check_insn(ctx, ISA_MIPS32R2);
7418 gen_helper_mtc0_srsconf4(cpu_env, arg);
7419 rn = "SRSConf4";
7420 break;
7421 case 6:
7422 check_pw(ctx);
7423 gen_helper_mtc0_pwctl(cpu_env, arg);
7424 rn = "PWCtl";
7425 break;
7426 default:
7427 goto cp0_unimplemented;
7429 break;
7430 case 7:
7431 switch (sel) {
7432 case 0:
7433 check_insn(ctx, ISA_MIPS32R2);
7434 gen_helper_mtc0_hwrena(cpu_env, arg);
7435 ctx->base.is_jmp = DISAS_STOP;
7436 rn = "HWREna";
7437 break;
7438 default:
7439 goto cp0_unimplemented;
7441 break;
7442 case 8:
7443 switch (sel) {
7444 case 0:
7445 /* ignored */
7446 rn = "BadVAddr";
7447 break;
7448 case 1:
7449 /* ignored */
7450 rn = "BadInstr";
7451 break;
7452 case 2:
7453 /* ignored */
7454 rn = "BadInstrP";
7455 break;
7456 case 3:
7457 /* ignored */
7458 rn = "BadInstrX";
7459 break;
7460 default:
7461 goto cp0_unimplemented;
7463 break;
7464 case 9:
7465 switch (sel) {
7466 case 0:
7467 gen_helper_mtc0_count(cpu_env, arg);
7468 rn = "Count";
7469 break;
7470 /* 6,7 are implementation dependent */
7471 default:
7472 goto cp0_unimplemented;
7474 break;
7475 case 10:
7476 switch (sel) {
7477 case 0:
7478 gen_helper_mtc0_entryhi(cpu_env, arg);
7479 rn = "EntryHi";
7480 break;
7481 default:
7482 goto cp0_unimplemented;
7484 break;
7485 case 11:
7486 switch (sel) {
7487 case 0:
7488 gen_helper_mtc0_compare(cpu_env, arg);
7489 rn = "Compare";
7490 break;
7491 /* 6,7 are implementation dependent */
7492 default:
7493 goto cp0_unimplemented;
7495 break;
7496 case 12:
7497 switch (sel) {
7498 case 0:
7499 save_cpu_state(ctx, 1);
7500 gen_helper_mtc0_status(cpu_env, arg);
7501 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7502 gen_save_pc(ctx->base.pc_next + 4);
7503 ctx->base.is_jmp = DISAS_EXIT;
7504 rn = "Status";
7505 break;
7506 case 1:
7507 check_insn(ctx, ISA_MIPS32R2);
7508 gen_helper_mtc0_intctl(cpu_env, arg);
7509 /* Stop translation as we may have switched the execution mode */
7510 ctx->base.is_jmp = DISAS_STOP;
7511 rn = "IntCtl";
7512 break;
7513 case 2:
7514 check_insn(ctx, ISA_MIPS32R2);
7515 gen_helper_mtc0_srsctl(cpu_env, arg);
7516 /* Stop translation as we may have switched the execution mode */
7517 ctx->base.is_jmp = DISAS_STOP;
7518 rn = "SRSCtl";
7519 break;
7520 case 3:
7521 check_insn(ctx, ISA_MIPS32R2);
7522 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7523 /* Stop translation as we may have switched the execution mode */
7524 ctx->base.is_jmp = DISAS_STOP;
7525 rn = "SRSMap";
7526 break;
7527 default:
7528 goto cp0_unimplemented;
7530 break;
7531 case 13:
7532 switch (sel) {
7533 case 0:
7534 save_cpu_state(ctx, 1);
7535 gen_helper_mtc0_cause(cpu_env, arg);
7536 /* Stop translation as we may have triggered an interrupt.
7537 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7538 * translated code to check for pending interrupts. */
7539 gen_save_pc(ctx->base.pc_next + 4);
7540 ctx->base.is_jmp = DISAS_EXIT;
7541 rn = "Cause";
7542 break;
7543 default:
7544 goto cp0_unimplemented;
7546 break;
7547 case 14:
7548 switch (sel) {
7549 case 0:
7550 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7551 rn = "EPC";
7552 break;
7553 default:
7554 goto cp0_unimplemented;
7556 break;
7557 case 15:
7558 switch (sel) {
7559 case 0:
7560 /* ignored */
7561 rn = "PRid";
7562 break;
7563 case 1:
7564 check_insn(ctx, ISA_MIPS32R2);
7565 gen_helper_mtc0_ebase(cpu_env, arg);
7566 rn = "EBase";
7567 break;
7568 default:
7569 goto cp0_unimplemented;
7571 break;
7572 case 16:
7573 switch (sel) {
7574 case 0:
7575 gen_helper_mtc0_config0(cpu_env, arg);
7576 rn = "Config";
7577 /* Stop translation as we may have switched the execution mode */
7578 ctx->base.is_jmp = DISAS_STOP;
7579 break;
7580 case 1:
7581 /* ignored, read only */
7582 rn = "Config1";
7583 break;
7584 case 2:
7585 gen_helper_mtc0_config2(cpu_env, arg);
7586 rn = "Config2";
7587 /* Stop translation as we may have switched the execution mode */
7588 ctx->base.is_jmp = DISAS_STOP;
7589 break;
7590 case 3:
7591 gen_helper_mtc0_config3(cpu_env, arg);
7592 rn = "Config3";
7593 /* Stop translation as we may have switched the execution mode */
7594 ctx->base.is_jmp = DISAS_STOP;
7595 break;
7596 case 4:
7597 gen_helper_mtc0_config4(cpu_env, arg);
7598 rn = "Config4";
7599 ctx->base.is_jmp = DISAS_STOP;
7600 break;
7601 case 5:
7602 gen_helper_mtc0_config5(cpu_env, arg);
7603 rn = "Config5";
7604 /* Stop translation as we may have switched the execution mode */
7605 ctx->base.is_jmp = DISAS_STOP;
7606 break;
7607 /* 6,7 are implementation dependent */
7608 case 6:
7609 /* ignored */
7610 rn = "Config6";
7611 break;
7612 case 7:
7613 /* ignored */
7614 rn = "Config7";
7615 break;
7616 default:
7617 rn = "Invalid config selector";
7618 goto cp0_unimplemented;
7620 break;
7621 case 17:
7622 switch (sel) {
7623 case 0:
7624 gen_helper_mtc0_lladdr(cpu_env, arg);
7625 rn = "LLAddr";
7626 break;
7627 case 1:
7628 CP0_CHECK(ctx->mrp);
7629 gen_helper_mtc0_maar(cpu_env, arg);
7630 rn = "MAAR";
7631 break;
7632 case 2:
7633 CP0_CHECK(ctx->mrp);
7634 gen_helper_mtc0_maari(cpu_env, arg);
7635 rn = "MAARI";
7636 break;
7637 default:
7638 goto cp0_unimplemented;
7640 break;
7641 case 18:
7642 switch (sel) {
7643 case 0:
7644 case 1:
7645 case 2:
7646 case 3:
7647 case 4:
7648 case 5:
7649 case 6:
7650 case 7:
7651 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7652 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7653 rn = "WatchLo";
7654 break;
7655 default:
7656 goto cp0_unimplemented;
7658 break;
7659 case 19:
7660 switch (sel) {
7661 case 0:
7662 case 1:
7663 case 2:
7664 case 3:
7665 case 4:
7666 case 5:
7667 case 6:
7668 case 7:
7669 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7670 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7671 rn = "WatchHi";
7672 break;
7673 default:
7674 goto cp0_unimplemented;
7676 break;
7677 case 20:
7678 switch (sel) {
7679 case 0:
7680 #if defined(TARGET_MIPS64)
7681 check_insn(ctx, ISA_MIPS3);
7682 gen_helper_mtc0_xcontext(cpu_env, arg);
7683 rn = "XContext";
7684 break;
7685 #endif
7686 default:
7687 goto cp0_unimplemented;
7689 break;
7690 case 21:
7691 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7692 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7693 switch (sel) {
7694 case 0:
7695 gen_helper_mtc0_framemask(cpu_env, arg);
7696 rn = "Framemask";
7697 break;
7698 default:
7699 goto cp0_unimplemented;
7701 break;
7702 case 22:
7703 /* ignored */
7704 rn = "Diagnostic"; /* implementation dependent */
7705 break;
7706 case 23:
7707 switch (sel) {
7708 case 0:
7709 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7710 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7711 gen_save_pc(ctx->base.pc_next + 4);
7712 ctx->base.is_jmp = DISAS_EXIT;
7713 rn = "Debug";
7714 break;
7715 case 1:
7716 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7717 rn = "TraceControl";
7718 /* Stop translation as we may have switched the execution mode */
7719 ctx->base.is_jmp = DISAS_STOP;
7720 goto cp0_unimplemented;
7721 case 2:
7722 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7723 rn = "TraceControl2";
7724 /* Stop translation as we may have switched the execution mode */
7725 ctx->base.is_jmp = DISAS_STOP;
7726 goto cp0_unimplemented;
7727 case 3:
7728 /* Stop translation as we may have switched the execution mode */
7729 ctx->base.is_jmp = DISAS_STOP;
7730 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7731 rn = "UserTraceData";
7732 /* Stop translation as we may have switched the execution mode */
7733 ctx->base.is_jmp = DISAS_STOP;
7734 goto cp0_unimplemented;
7735 case 4:
7736 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7737 /* Stop translation as we may have switched the execution mode */
7738 ctx->base.is_jmp = DISAS_STOP;
7739 rn = "TraceBPC";
7740 goto cp0_unimplemented;
7741 default:
7742 goto cp0_unimplemented;
7744 break;
7745 case 24:
7746 switch (sel) {
7747 case 0:
7748 /* EJTAG support */
7749 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7750 rn = "DEPC";
7751 break;
7752 default:
7753 goto cp0_unimplemented;
7755 break;
7756 case 25:
7757 switch (sel) {
7758 case 0:
7759 gen_helper_mtc0_performance0(cpu_env, arg);
7760 rn = "Performance0";
7761 break;
7762 case 1:
7763 // gen_helper_mtc0_performance1(arg);
7764 rn = "Performance1";
7765 goto cp0_unimplemented;
7766 case 2:
7767 // gen_helper_mtc0_performance2(arg);
7768 rn = "Performance2";
7769 goto cp0_unimplemented;
7770 case 3:
7771 // gen_helper_mtc0_performance3(arg);
7772 rn = "Performance3";
7773 goto cp0_unimplemented;
7774 case 4:
7775 // gen_helper_mtc0_performance4(arg);
7776 rn = "Performance4";
7777 goto cp0_unimplemented;
7778 case 5:
7779 // gen_helper_mtc0_performance5(arg);
7780 rn = "Performance5";
7781 goto cp0_unimplemented;
7782 case 6:
7783 // gen_helper_mtc0_performance6(arg);
7784 rn = "Performance6";
7785 goto cp0_unimplemented;
7786 case 7:
7787 // gen_helper_mtc0_performance7(arg);
7788 rn = "Performance7";
7789 goto cp0_unimplemented;
7790 default:
7791 goto cp0_unimplemented;
7793 break;
7794 case 26:
7795 switch (sel) {
7796 case 0:
7797 gen_helper_mtc0_errctl(cpu_env, arg);
7798 ctx->base.is_jmp = DISAS_STOP;
7799 rn = "ErrCtl";
7800 break;
7801 default:
7802 goto cp0_unimplemented;
7804 break;
7805 case 27:
7806 switch (sel) {
7807 case 0:
7808 case 1:
7809 case 2:
7810 case 3:
7811 /* ignored */
7812 rn = "CacheErr";
7813 break;
7814 default:
7815 goto cp0_unimplemented;
7817 break;
7818 case 28:
7819 switch (sel) {
7820 case 0:
7821 case 2:
7822 case 4:
7823 case 6:
7824 gen_helper_mtc0_taglo(cpu_env, arg);
7825 rn = "TagLo";
7826 break;
7827 case 1:
7828 case 3:
7829 case 5:
7830 case 7:
7831 gen_helper_mtc0_datalo(cpu_env, arg);
7832 rn = "DataLo";
7833 break;
7834 default:
7835 goto cp0_unimplemented;
7837 break;
7838 case 29:
7839 switch (sel) {
7840 case 0:
7841 case 2:
7842 case 4:
7843 case 6:
7844 gen_helper_mtc0_taghi(cpu_env, arg);
7845 rn = "TagHi";
7846 break;
7847 case 1:
7848 case 3:
7849 case 5:
7850 case 7:
7851 gen_helper_mtc0_datahi(cpu_env, arg);
7852 rn = "DataHi";
7853 break;
7854 default:
7855 rn = "invalid sel";
7856 goto cp0_unimplemented;
7858 break;
7859 case 30:
7860 switch (sel) {
7861 case 0:
7862 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7863 rn = "ErrorEPC";
7864 break;
7865 default:
7866 goto cp0_unimplemented;
7868 break;
7869 case 31:
7870 switch (sel) {
7871 case 0:
7872 /* EJTAG support */
7873 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7874 rn = "DESAVE";
7875 break;
7876 case 2:
7877 case 3:
7878 case 4:
7879 case 5:
7880 case 6:
7881 case 7:
7882 CP0_CHECK(ctx->kscrexist & (1 << sel));
7883 tcg_gen_st_tl(arg, cpu_env,
7884 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7885 rn = "KScratch";
7886 break;
7887 default:
7888 goto cp0_unimplemented;
7890 break;
7891 default:
7892 goto cp0_unimplemented;
7894 trace_mips_translate_c0("mtc0", rn, reg, sel);
7896 /* For simplicity assume that all writes can cause interrupts. */
7897 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7898 gen_io_end();
7899 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7900 * translated code to check for pending interrupts. */
7901 gen_save_pc(ctx->base.pc_next + 4);
7902 ctx->base.is_jmp = DISAS_EXIT;
7904 return;
7906 cp0_unimplemented:
7907 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7910 #if defined(TARGET_MIPS64)
7911 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7913 const char *rn = "invalid";
7915 if (sel != 0)
7916 check_insn(ctx, ISA_MIPS64);
7918 switch (reg) {
7919 case 0:
7920 switch (sel) {
7921 case 0:
7922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7923 rn = "Index";
7924 break;
7925 case 1:
7926 CP0_CHECK(ctx->insn_flags & ASE_MT);
7927 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7928 rn = "MVPControl";
7929 break;
7930 case 2:
7931 CP0_CHECK(ctx->insn_flags & ASE_MT);
7932 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7933 rn = "MVPConf0";
7934 break;
7935 case 3:
7936 CP0_CHECK(ctx->insn_flags & ASE_MT);
7937 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7938 rn = "MVPConf1";
7939 break;
7940 case 4:
7941 CP0_CHECK(ctx->vp);
7942 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7943 rn = "VPControl";
7944 break;
7945 default:
7946 goto cp0_unimplemented;
7948 break;
7949 case 1:
7950 switch (sel) {
7951 case 0:
7952 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7953 gen_helper_mfc0_random(arg, cpu_env);
7954 rn = "Random";
7955 break;
7956 case 1:
7957 CP0_CHECK(ctx->insn_flags & ASE_MT);
7958 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7959 rn = "VPEControl";
7960 break;
7961 case 2:
7962 CP0_CHECK(ctx->insn_flags & ASE_MT);
7963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7964 rn = "VPEConf0";
7965 break;
7966 case 3:
7967 CP0_CHECK(ctx->insn_flags & ASE_MT);
7968 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7969 rn = "VPEConf1";
7970 break;
7971 case 4:
7972 CP0_CHECK(ctx->insn_flags & ASE_MT);
7973 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7974 rn = "YQMask";
7975 break;
7976 case 5:
7977 CP0_CHECK(ctx->insn_flags & ASE_MT);
7978 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7979 rn = "VPESchedule";
7980 break;
7981 case 6:
7982 CP0_CHECK(ctx->insn_flags & ASE_MT);
7983 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7984 rn = "VPEScheFBack";
7985 break;
7986 case 7:
7987 CP0_CHECK(ctx->insn_flags & ASE_MT);
7988 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7989 rn = "VPEOpt";
7990 break;
7991 default:
7992 goto cp0_unimplemented;
7994 break;
7995 case 2:
7996 switch (sel) {
7997 case 0:
7998 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7999 rn = "EntryLo0";
8000 break;
8001 case 1:
8002 CP0_CHECK(ctx->insn_flags & ASE_MT);
8003 gen_helper_mfc0_tcstatus(arg, cpu_env);
8004 rn = "TCStatus";
8005 break;
8006 case 2:
8007 CP0_CHECK(ctx->insn_flags & ASE_MT);
8008 gen_helper_mfc0_tcbind(arg, cpu_env);
8009 rn = "TCBind";
8010 break;
8011 case 3:
8012 CP0_CHECK(ctx->insn_flags & ASE_MT);
8013 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8014 rn = "TCRestart";
8015 break;
8016 case 4:
8017 CP0_CHECK(ctx->insn_flags & ASE_MT);
8018 gen_helper_dmfc0_tchalt(arg, cpu_env);
8019 rn = "TCHalt";
8020 break;
8021 case 5:
8022 CP0_CHECK(ctx->insn_flags & ASE_MT);
8023 gen_helper_dmfc0_tccontext(arg, cpu_env);
8024 rn = "TCContext";
8025 break;
8026 case 6:
8027 CP0_CHECK(ctx->insn_flags & ASE_MT);
8028 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8029 rn = "TCSchedule";
8030 break;
8031 case 7:
8032 CP0_CHECK(ctx->insn_flags & ASE_MT);
8033 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8034 rn = "TCScheFBack";
8035 break;
8036 default:
8037 goto cp0_unimplemented;
8039 break;
8040 case 3:
8041 switch (sel) {
8042 case 0:
8043 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8044 rn = "EntryLo1";
8045 break;
8046 case 1:
8047 CP0_CHECK(ctx->vp);
8048 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8049 rn = "GlobalNumber";
8050 break;
8051 default:
8052 goto cp0_unimplemented;
8054 break;
8055 case 4:
8056 switch (sel) {
8057 case 0:
8058 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8059 rn = "Context";
8060 break;
8061 case 1:
8062 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8063 rn = "ContextConfig";
8064 goto cp0_unimplemented;
8065 case 2:
8066 CP0_CHECK(ctx->ulri);
8067 tcg_gen_ld_tl(arg, cpu_env,
8068 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8069 rn = "UserLocal";
8070 break;
8071 default:
8072 goto cp0_unimplemented;
8074 break;
8075 case 5:
8076 switch (sel) {
8077 case 0:
8078 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8079 rn = "PageMask";
8080 break;
8081 case 1:
8082 check_insn(ctx, ISA_MIPS32R2);
8083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8084 rn = "PageGrain";
8085 break;
8086 case 2:
8087 CP0_CHECK(ctx->sc);
8088 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8089 rn = "SegCtl0";
8090 break;
8091 case 3:
8092 CP0_CHECK(ctx->sc);
8093 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8094 rn = "SegCtl1";
8095 break;
8096 case 4:
8097 CP0_CHECK(ctx->sc);
8098 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8099 rn = "SegCtl2";
8100 break;
8101 case 5:
8102 check_pw(ctx);
8103 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8104 rn = "PWBase";
8105 break;
8106 case 6:
8107 check_pw(ctx);
8108 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8109 rn = "PWField";
8110 break;
8111 case 7:
8112 check_pw(ctx);
8113 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8114 rn = "PWSize";
8115 break;
8116 default:
8117 goto cp0_unimplemented;
8119 break;
8120 case 6:
8121 switch (sel) {
8122 case 0:
8123 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8124 rn = "Wired";
8125 break;
8126 case 1:
8127 check_insn(ctx, ISA_MIPS32R2);
8128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8129 rn = "SRSConf0";
8130 break;
8131 case 2:
8132 check_insn(ctx, ISA_MIPS32R2);
8133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8134 rn = "SRSConf1";
8135 break;
8136 case 3:
8137 check_insn(ctx, ISA_MIPS32R2);
8138 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8139 rn = "SRSConf2";
8140 break;
8141 case 4:
8142 check_insn(ctx, ISA_MIPS32R2);
8143 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8144 rn = "SRSConf3";
8145 break;
8146 case 5:
8147 check_insn(ctx, ISA_MIPS32R2);
8148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8149 rn = "SRSConf4";
8150 break;
8151 case 6:
8152 check_pw(ctx);
8153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8154 rn = "PWCtl";
8155 break;
8156 default:
8157 goto cp0_unimplemented;
8159 break;
8160 case 7:
8161 switch (sel) {
8162 case 0:
8163 check_insn(ctx, ISA_MIPS32R2);
8164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8165 rn = "HWREna";
8166 break;
8167 default:
8168 goto cp0_unimplemented;
8170 break;
8171 case 8:
8172 switch (sel) {
8173 case 0:
8174 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8175 rn = "BadVAddr";
8176 break;
8177 case 1:
8178 CP0_CHECK(ctx->bi);
8179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8180 rn = "BadInstr";
8181 break;
8182 case 2:
8183 CP0_CHECK(ctx->bp);
8184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8185 rn = "BadInstrP";
8186 break;
8187 case 3:
8188 CP0_CHECK(ctx->bi);
8189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8190 tcg_gen_andi_tl(arg, arg, ~0xffff);
8191 rn = "BadInstrX";
8192 break;
8193 default:
8194 goto cp0_unimplemented;
8196 break;
8197 case 9:
8198 switch (sel) {
8199 case 0:
8200 /* Mark as an IO operation because we read the time. */
8201 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8202 gen_io_start();
8204 gen_helper_mfc0_count(arg, cpu_env);
8205 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8206 gen_io_end();
8208 /* Break the TB to be able to take timer interrupts immediately
8209 after reading count. DISAS_STOP isn't sufficient, we need to
8210 ensure we break completely out of translated code. */
8211 gen_save_pc(ctx->base.pc_next + 4);
8212 ctx->base.is_jmp = DISAS_EXIT;
8213 rn = "Count";
8214 break;
8215 /* 6,7 are implementation dependent */
8216 default:
8217 goto cp0_unimplemented;
8219 break;
8220 case 10:
8221 switch (sel) {
8222 case 0:
8223 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8224 rn = "EntryHi";
8225 break;
8226 default:
8227 goto cp0_unimplemented;
8229 break;
8230 case 11:
8231 switch (sel) {
8232 case 0:
8233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8234 rn = "Compare";
8235 break;
8236 /* 6,7 are implementation dependent */
8237 default:
8238 goto cp0_unimplemented;
8240 break;
8241 case 12:
8242 switch (sel) {
8243 case 0:
8244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8245 rn = "Status";
8246 break;
8247 case 1:
8248 check_insn(ctx, ISA_MIPS32R2);
8249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8250 rn = "IntCtl";
8251 break;
8252 case 2:
8253 check_insn(ctx, ISA_MIPS32R2);
8254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8255 rn = "SRSCtl";
8256 break;
8257 case 3:
8258 check_insn(ctx, ISA_MIPS32R2);
8259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8260 rn = "SRSMap";
8261 break;
8262 default:
8263 goto cp0_unimplemented;
8265 break;
8266 case 13:
8267 switch (sel) {
8268 case 0:
8269 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8270 rn = "Cause";
8271 break;
8272 default:
8273 goto cp0_unimplemented;
8275 break;
8276 case 14:
8277 switch (sel) {
8278 case 0:
8279 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8280 rn = "EPC";
8281 break;
8282 default:
8283 goto cp0_unimplemented;
8285 break;
8286 case 15:
8287 switch (sel) {
8288 case 0:
8289 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8290 rn = "PRid";
8291 break;
8292 case 1:
8293 check_insn(ctx, ISA_MIPS32R2);
8294 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8295 rn = "EBase";
8296 break;
8297 case 3:
8298 check_insn(ctx, ISA_MIPS32R2);
8299 CP0_CHECK(ctx->cmgcr);
8300 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8301 rn = "CMGCRBase";
8302 break;
8303 default:
8304 goto cp0_unimplemented;
8306 break;
8307 case 16:
8308 switch (sel) {
8309 case 0:
8310 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8311 rn = "Config";
8312 break;
8313 case 1:
8314 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8315 rn = "Config1";
8316 break;
8317 case 2:
8318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8319 rn = "Config2";
8320 break;
8321 case 3:
8322 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8323 rn = "Config3";
8324 break;
8325 case 4:
8326 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8327 rn = "Config4";
8328 break;
8329 case 5:
8330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8331 rn = "Config5";
8332 break;
8333 /* 6,7 are implementation dependent */
8334 case 6:
8335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8336 rn = "Config6";
8337 break;
8338 case 7:
8339 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8340 rn = "Config7";
8341 break;
8342 default:
8343 goto cp0_unimplemented;
8345 break;
8346 case 17:
8347 switch (sel) {
8348 case 0:
8349 gen_helper_dmfc0_lladdr(arg, cpu_env);
8350 rn = "LLAddr";
8351 break;
8352 case 1:
8353 CP0_CHECK(ctx->mrp);
8354 gen_helper_dmfc0_maar(arg, cpu_env);
8355 rn = "MAAR";
8356 break;
8357 case 2:
8358 CP0_CHECK(ctx->mrp);
8359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8360 rn = "MAARI";
8361 break;
8362 default:
8363 goto cp0_unimplemented;
8365 break;
8366 case 18:
8367 switch (sel) {
8368 case 0:
8369 case 1:
8370 case 2:
8371 case 3:
8372 case 4:
8373 case 5:
8374 case 6:
8375 case 7:
8376 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8377 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8378 rn = "WatchLo";
8379 break;
8380 default:
8381 goto cp0_unimplemented;
8383 break;
8384 case 19:
8385 switch (sel) {
8386 case 0:
8387 case 1:
8388 case 2:
8389 case 3:
8390 case 4:
8391 case 5:
8392 case 6:
8393 case 7:
8394 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8395 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8396 rn = "WatchHi";
8397 break;
8398 default:
8399 goto cp0_unimplemented;
8401 break;
8402 case 20:
8403 switch (sel) {
8404 case 0:
8405 check_insn(ctx, ISA_MIPS3);
8406 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8407 rn = "XContext";
8408 break;
8409 default:
8410 goto cp0_unimplemented;
8412 break;
8413 case 21:
8414 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8415 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8416 switch (sel) {
8417 case 0:
8418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8419 rn = "Framemask";
8420 break;
8421 default:
8422 goto cp0_unimplemented;
8424 break;
8425 case 22:
8426 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8427 rn = "'Diagnostic"; /* implementation dependent */
8428 break;
8429 case 23:
8430 switch (sel) {
8431 case 0:
8432 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8433 rn = "Debug";
8434 break;
8435 case 1:
8436 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8437 rn = "TraceControl";
8438 goto cp0_unimplemented;
8439 case 2:
8440 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8441 rn = "TraceControl2";
8442 goto cp0_unimplemented;
8443 case 3:
8444 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8445 rn = "UserTraceData";
8446 goto cp0_unimplemented;
8447 case 4:
8448 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8449 rn = "TraceBPC";
8450 goto cp0_unimplemented;
8451 default:
8452 goto cp0_unimplemented;
8454 break;
8455 case 24:
8456 switch (sel) {
8457 case 0:
8458 /* EJTAG support */
8459 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8460 rn = "DEPC";
8461 break;
8462 default:
8463 goto cp0_unimplemented;
8465 break;
8466 case 25:
8467 switch (sel) {
8468 case 0:
8469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8470 rn = "Performance0";
8471 break;
8472 case 1:
8473 // gen_helper_dmfc0_performance1(arg);
8474 rn = "Performance1";
8475 goto cp0_unimplemented;
8476 case 2:
8477 // gen_helper_dmfc0_performance2(arg);
8478 rn = "Performance2";
8479 goto cp0_unimplemented;
8480 case 3:
8481 // gen_helper_dmfc0_performance3(arg);
8482 rn = "Performance3";
8483 goto cp0_unimplemented;
8484 case 4:
8485 // gen_helper_dmfc0_performance4(arg);
8486 rn = "Performance4";
8487 goto cp0_unimplemented;
8488 case 5:
8489 // gen_helper_dmfc0_performance5(arg);
8490 rn = "Performance5";
8491 goto cp0_unimplemented;
8492 case 6:
8493 // gen_helper_dmfc0_performance6(arg);
8494 rn = "Performance6";
8495 goto cp0_unimplemented;
8496 case 7:
8497 // gen_helper_dmfc0_performance7(arg);
8498 rn = "Performance7";
8499 goto cp0_unimplemented;
8500 default:
8501 goto cp0_unimplemented;
8503 break;
8504 case 26:
8505 switch (sel) {
8506 case 0:
8507 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8508 rn = "ErrCtl";
8509 break;
8510 default:
8511 goto cp0_unimplemented;
8513 break;
8514 case 27:
8515 switch (sel) {
8516 /* ignored */
8517 case 0:
8518 case 1:
8519 case 2:
8520 case 3:
8521 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8522 rn = "CacheErr";
8523 break;
8524 default:
8525 goto cp0_unimplemented;
8527 break;
8528 case 28:
8529 switch (sel) {
8530 case 0:
8531 case 2:
8532 case 4:
8533 case 6:
8534 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8535 rn = "TagLo";
8536 break;
8537 case 1:
8538 case 3:
8539 case 5:
8540 case 7:
8541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8542 rn = "DataLo";
8543 break;
8544 default:
8545 goto cp0_unimplemented;
8547 break;
8548 case 29:
8549 switch (sel) {
8550 case 0:
8551 case 2:
8552 case 4:
8553 case 6:
8554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8555 rn = "TagHi";
8556 break;
8557 case 1:
8558 case 3:
8559 case 5:
8560 case 7:
8561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8562 rn = "DataHi";
8563 break;
8564 default:
8565 goto cp0_unimplemented;
8567 break;
8568 case 30:
8569 switch (sel) {
8570 case 0:
8571 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8572 rn = "ErrorEPC";
8573 break;
8574 default:
8575 goto cp0_unimplemented;
8577 break;
8578 case 31:
8579 switch (sel) {
8580 case 0:
8581 /* EJTAG support */
8582 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8583 rn = "DESAVE";
8584 break;
8585 case 2:
8586 case 3:
8587 case 4:
8588 case 5:
8589 case 6:
8590 case 7:
8591 CP0_CHECK(ctx->kscrexist & (1 << sel));
8592 tcg_gen_ld_tl(arg, cpu_env,
8593 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8594 rn = "KScratch";
8595 break;
8596 default:
8597 goto cp0_unimplemented;
8599 break;
8600 default:
8601 goto cp0_unimplemented;
8603 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8604 return;
8606 cp0_unimplemented:
8607 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8608 gen_mfc0_unimplemented(ctx, arg);
8611 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8613 const char *rn = "invalid";
8615 if (sel != 0)
8616 check_insn(ctx, ISA_MIPS64);
8618 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8619 gen_io_start();
8622 switch (reg) {
8623 case 0:
8624 switch (sel) {
8625 case 0:
8626 gen_helper_mtc0_index(cpu_env, arg);
8627 rn = "Index";
8628 break;
8629 case 1:
8630 CP0_CHECK(ctx->insn_flags & ASE_MT);
8631 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8632 rn = "MVPControl";
8633 break;
8634 case 2:
8635 CP0_CHECK(ctx->insn_flags & ASE_MT);
8636 /* ignored */
8637 rn = "MVPConf0";
8638 break;
8639 case 3:
8640 CP0_CHECK(ctx->insn_flags & ASE_MT);
8641 /* ignored */
8642 rn = "MVPConf1";
8643 break;
8644 case 4:
8645 CP0_CHECK(ctx->vp);
8646 /* ignored */
8647 rn = "VPControl";
8648 break;
8649 default:
8650 goto cp0_unimplemented;
8652 break;
8653 case 1:
8654 switch (sel) {
8655 case 0:
8656 /* ignored */
8657 rn = "Random";
8658 break;
8659 case 1:
8660 CP0_CHECK(ctx->insn_flags & ASE_MT);
8661 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8662 rn = "VPEControl";
8663 break;
8664 case 2:
8665 CP0_CHECK(ctx->insn_flags & ASE_MT);
8666 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8667 rn = "VPEConf0";
8668 break;
8669 case 3:
8670 CP0_CHECK(ctx->insn_flags & ASE_MT);
8671 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8672 rn = "VPEConf1";
8673 break;
8674 case 4:
8675 CP0_CHECK(ctx->insn_flags & ASE_MT);
8676 gen_helper_mtc0_yqmask(cpu_env, arg);
8677 rn = "YQMask";
8678 break;
8679 case 5:
8680 CP0_CHECK(ctx->insn_flags & ASE_MT);
8681 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8682 rn = "VPESchedule";
8683 break;
8684 case 6:
8685 CP0_CHECK(ctx->insn_flags & ASE_MT);
8686 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8687 rn = "VPEScheFBack";
8688 break;
8689 case 7:
8690 CP0_CHECK(ctx->insn_flags & ASE_MT);
8691 gen_helper_mtc0_vpeopt(cpu_env, arg);
8692 rn = "VPEOpt";
8693 break;
8694 default:
8695 goto cp0_unimplemented;
8697 break;
8698 case 2:
8699 switch (sel) {
8700 case 0:
8701 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8702 rn = "EntryLo0";
8703 break;
8704 case 1:
8705 CP0_CHECK(ctx->insn_flags & ASE_MT);
8706 gen_helper_mtc0_tcstatus(cpu_env, arg);
8707 rn = "TCStatus";
8708 break;
8709 case 2:
8710 CP0_CHECK(ctx->insn_flags & ASE_MT);
8711 gen_helper_mtc0_tcbind(cpu_env, arg);
8712 rn = "TCBind";
8713 break;
8714 case 3:
8715 CP0_CHECK(ctx->insn_flags & ASE_MT);
8716 gen_helper_mtc0_tcrestart(cpu_env, arg);
8717 rn = "TCRestart";
8718 break;
8719 case 4:
8720 CP0_CHECK(ctx->insn_flags & ASE_MT);
8721 gen_helper_mtc0_tchalt(cpu_env, arg);
8722 rn = "TCHalt";
8723 break;
8724 case 5:
8725 CP0_CHECK(ctx->insn_flags & ASE_MT);
8726 gen_helper_mtc0_tccontext(cpu_env, arg);
8727 rn = "TCContext";
8728 break;
8729 case 6:
8730 CP0_CHECK(ctx->insn_flags & ASE_MT);
8731 gen_helper_mtc0_tcschedule(cpu_env, arg);
8732 rn = "TCSchedule";
8733 break;
8734 case 7:
8735 CP0_CHECK(ctx->insn_flags & ASE_MT);
8736 gen_helper_mtc0_tcschefback(cpu_env, arg);
8737 rn = "TCScheFBack";
8738 break;
8739 default:
8740 goto cp0_unimplemented;
8742 break;
8743 case 3:
8744 switch (sel) {
8745 case 0:
8746 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8747 rn = "EntryLo1";
8748 break;
8749 case 1:
8750 CP0_CHECK(ctx->vp);
8751 /* ignored */
8752 rn = "GlobalNumber";
8753 break;
8754 default:
8755 goto cp0_unimplemented;
8757 break;
8758 case 4:
8759 switch (sel) {
8760 case 0:
8761 gen_helper_mtc0_context(cpu_env, arg);
8762 rn = "Context";
8763 break;
8764 case 1:
8765 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8766 rn = "ContextConfig";
8767 goto cp0_unimplemented;
8768 case 2:
8769 CP0_CHECK(ctx->ulri);
8770 tcg_gen_st_tl(arg, cpu_env,
8771 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8772 rn = "UserLocal";
8773 break;
8774 default:
8775 goto cp0_unimplemented;
8777 break;
8778 case 5:
8779 switch (sel) {
8780 case 0:
8781 gen_helper_mtc0_pagemask(cpu_env, arg);
8782 rn = "PageMask";
8783 break;
8784 case 1:
8785 check_insn(ctx, ISA_MIPS32R2);
8786 gen_helper_mtc0_pagegrain(cpu_env, arg);
8787 rn = "PageGrain";
8788 break;
8789 case 2:
8790 CP0_CHECK(ctx->sc);
8791 gen_helper_mtc0_segctl0(cpu_env, arg);
8792 rn = "SegCtl0";
8793 break;
8794 case 3:
8795 CP0_CHECK(ctx->sc);
8796 gen_helper_mtc0_segctl1(cpu_env, arg);
8797 rn = "SegCtl1";
8798 break;
8799 case 4:
8800 CP0_CHECK(ctx->sc);
8801 gen_helper_mtc0_segctl2(cpu_env, arg);
8802 rn = "SegCtl2";
8803 break;
8804 case 5:
8805 check_pw(ctx);
8806 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8807 rn = "PWBase";
8808 break;
8809 case 6:
8810 check_pw(ctx);
8811 gen_helper_mtc0_pwfield(cpu_env, arg);
8812 rn = "PWField";
8813 break;
8814 case 7:
8815 check_pw(ctx);
8816 gen_helper_mtc0_pwsize(cpu_env, arg);
8817 rn = "PWSize";
8818 break;
8819 default:
8820 goto cp0_unimplemented;
8822 break;
8823 case 6:
8824 switch (sel) {
8825 case 0:
8826 gen_helper_mtc0_wired(cpu_env, arg);
8827 rn = "Wired";
8828 break;
8829 case 1:
8830 check_insn(ctx, ISA_MIPS32R2);
8831 gen_helper_mtc0_srsconf0(cpu_env, arg);
8832 rn = "SRSConf0";
8833 break;
8834 case 2:
8835 check_insn(ctx, ISA_MIPS32R2);
8836 gen_helper_mtc0_srsconf1(cpu_env, arg);
8837 rn = "SRSConf1";
8838 break;
8839 case 3:
8840 check_insn(ctx, ISA_MIPS32R2);
8841 gen_helper_mtc0_srsconf2(cpu_env, arg);
8842 rn = "SRSConf2";
8843 break;
8844 case 4:
8845 check_insn(ctx, ISA_MIPS32R2);
8846 gen_helper_mtc0_srsconf3(cpu_env, arg);
8847 rn = "SRSConf3";
8848 break;
8849 case 5:
8850 check_insn(ctx, ISA_MIPS32R2);
8851 gen_helper_mtc0_srsconf4(cpu_env, arg);
8852 rn = "SRSConf4";
8853 break;
8854 case 6:
8855 check_pw(ctx);
8856 gen_helper_mtc0_pwctl(cpu_env, arg);
8857 rn = "PWCtl";
8858 break;
8859 default:
8860 goto cp0_unimplemented;
8862 break;
8863 case 7:
8864 switch (sel) {
8865 case 0:
8866 check_insn(ctx, ISA_MIPS32R2);
8867 gen_helper_mtc0_hwrena(cpu_env, arg);
8868 ctx->base.is_jmp = DISAS_STOP;
8869 rn = "HWREna";
8870 break;
8871 default:
8872 goto cp0_unimplemented;
8874 break;
8875 case 8:
8876 switch (sel) {
8877 case 0:
8878 /* ignored */
8879 rn = "BadVAddr";
8880 break;
8881 case 1:
8882 /* ignored */
8883 rn = "BadInstr";
8884 break;
8885 case 2:
8886 /* ignored */
8887 rn = "BadInstrP";
8888 break;
8889 case 3:
8890 /* ignored */
8891 rn = "BadInstrX";
8892 break;
8893 default:
8894 goto cp0_unimplemented;
8896 break;
8897 case 9:
8898 switch (sel) {
8899 case 0:
8900 gen_helper_mtc0_count(cpu_env, arg);
8901 rn = "Count";
8902 break;
8903 /* 6,7 are implementation dependent */
8904 default:
8905 goto cp0_unimplemented;
8907 /* Stop translation as we may have switched the execution mode */
8908 ctx->base.is_jmp = DISAS_STOP;
8909 break;
8910 case 10:
8911 switch (sel) {
8912 case 0:
8913 gen_helper_mtc0_entryhi(cpu_env, arg);
8914 rn = "EntryHi";
8915 break;
8916 default:
8917 goto cp0_unimplemented;
8919 break;
8920 case 11:
8921 switch (sel) {
8922 case 0:
8923 gen_helper_mtc0_compare(cpu_env, arg);
8924 rn = "Compare";
8925 break;
8926 /* 6,7 are implementation dependent */
8927 default:
8928 goto cp0_unimplemented;
8930 /* Stop translation as we may have switched the execution mode */
8931 ctx->base.is_jmp = DISAS_STOP;
8932 break;
8933 case 12:
8934 switch (sel) {
8935 case 0:
8936 save_cpu_state(ctx, 1);
8937 gen_helper_mtc0_status(cpu_env, arg);
8938 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8939 gen_save_pc(ctx->base.pc_next + 4);
8940 ctx->base.is_jmp = DISAS_EXIT;
8941 rn = "Status";
8942 break;
8943 case 1:
8944 check_insn(ctx, ISA_MIPS32R2);
8945 gen_helper_mtc0_intctl(cpu_env, arg);
8946 /* Stop translation as we may have switched the execution mode */
8947 ctx->base.is_jmp = DISAS_STOP;
8948 rn = "IntCtl";
8949 break;
8950 case 2:
8951 check_insn(ctx, ISA_MIPS32R2);
8952 gen_helper_mtc0_srsctl(cpu_env, arg);
8953 /* Stop translation as we may have switched the execution mode */
8954 ctx->base.is_jmp = DISAS_STOP;
8955 rn = "SRSCtl";
8956 break;
8957 case 3:
8958 check_insn(ctx, ISA_MIPS32R2);
8959 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8960 /* Stop translation as we may have switched the execution mode */
8961 ctx->base.is_jmp = DISAS_STOP;
8962 rn = "SRSMap";
8963 break;
8964 default:
8965 goto cp0_unimplemented;
8967 break;
8968 case 13:
8969 switch (sel) {
8970 case 0:
8971 save_cpu_state(ctx, 1);
8972 gen_helper_mtc0_cause(cpu_env, arg);
8973 /* Stop translation as we may have triggered an interrupt.
8974 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8975 * translated code to check for pending interrupts. */
8976 gen_save_pc(ctx->base.pc_next + 4);
8977 ctx->base.is_jmp = DISAS_EXIT;
8978 rn = "Cause";
8979 break;
8980 default:
8981 goto cp0_unimplemented;
8983 break;
8984 case 14:
8985 switch (sel) {
8986 case 0:
8987 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8988 rn = "EPC";
8989 break;
8990 default:
8991 goto cp0_unimplemented;
8993 break;
8994 case 15:
8995 switch (sel) {
8996 case 0:
8997 /* ignored */
8998 rn = "PRid";
8999 break;
9000 case 1:
9001 check_insn(ctx, ISA_MIPS32R2);
9002 gen_helper_mtc0_ebase(cpu_env, arg);
9003 rn = "EBase";
9004 break;
9005 default:
9006 goto cp0_unimplemented;
9008 break;
9009 case 16:
9010 switch (sel) {
9011 case 0:
9012 gen_helper_mtc0_config0(cpu_env, arg);
9013 rn = "Config";
9014 /* Stop translation as we may have switched the execution mode */
9015 ctx->base.is_jmp = DISAS_STOP;
9016 break;
9017 case 1:
9018 /* ignored, read only */
9019 rn = "Config1";
9020 break;
9021 case 2:
9022 gen_helper_mtc0_config2(cpu_env, arg);
9023 rn = "Config2";
9024 /* Stop translation as we may have switched the execution mode */
9025 ctx->base.is_jmp = DISAS_STOP;
9026 break;
9027 case 3:
9028 gen_helper_mtc0_config3(cpu_env, arg);
9029 rn = "Config3";
9030 /* Stop translation as we may have switched the execution mode */
9031 ctx->base.is_jmp = DISAS_STOP;
9032 break;
9033 case 4:
9034 /* currently ignored */
9035 rn = "Config4";
9036 break;
9037 case 5:
9038 gen_helper_mtc0_config5(cpu_env, arg);
9039 rn = "Config5";
9040 /* Stop translation as we may have switched the execution mode */
9041 ctx->base.is_jmp = DISAS_STOP;
9042 break;
9043 /* 6,7 are implementation dependent */
9044 default:
9045 rn = "Invalid config selector";
9046 goto cp0_unimplemented;
9048 break;
9049 case 17:
9050 switch (sel) {
9051 case 0:
9052 gen_helper_mtc0_lladdr(cpu_env, arg);
9053 rn = "LLAddr";
9054 break;
9055 case 1:
9056 CP0_CHECK(ctx->mrp);
9057 gen_helper_mtc0_maar(cpu_env, arg);
9058 rn = "MAAR";
9059 break;
9060 case 2:
9061 CP0_CHECK(ctx->mrp);
9062 gen_helper_mtc0_maari(cpu_env, arg);
9063 rn = "MAARI";
9064 break;
9065 default:
9066 goto cp0_unimplemented;
9068 break;
9069 case 18:
9070 switch (sel) {
9071 case 0:
9072 case 1:
9073 case 2:
9074 case 3:
9075 case 4:
9076 case 5:
9077 case 6:
9078 case 7:
9079 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9080 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9081 rn = "WatchLo";
9082 break;
9083 default:
9084 goto cp0_unimplemented;
9086 break;
9087 case 19:
9088 switch (sel) {
9089 case 0:
9090 case 1:
9091 case 2:
9092 case 3:
9093 case 4:
9094 case 5:
9095 case 6:
9096 case 7:
9097 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9098 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9099 rn = "WatchHi";
9100 break;
9101 default:
9102 goto cp0_unimplemented;
9104 break;
9105 case 20:
9106 switch (sel) {
9107 case 0:
9108 check_insn(ctx, ISA_MIPS3);
9109 gen_helper_mtc0_xcontext(cpu_env, arg);
9110 rn = "XContext";
9111 break;
9112 default:
9113 goto cp0_unimplemented;
9115 break;
9116 case 21:
9117 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9118 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9119 switch (sel) {
9120 case 0:
9121 gen_helper_mtc0_framemask(cpu_env, arg);
9122 rn = "Framemask";
9123 break;
9124 default:
9125 goto cp0_unimplemented;
9127 break;
9128 case 22:
9129 /* ignored */
9130 rn = "Diagnostic"; /* implementation dependent */
9131 break;
9132 case 23:
9133 switch (sel) {
9134 case 0:
9135 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9136 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9137 gen_save_pc(ctx->base.pc_next + 4);
9138 ctx->base.is_jmp = DISAS_EXIT;
9139 rn = "Debug";
9140 break;
9141 case 1:
9142 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9143 /* Stop translation as we may have switched the execution mode */
9144 ctx->base.is_jmp = DISAS_STOP;
9145 rn = "TraceControl";
9146 goto cp0_unimplemented;
9147 case 2:
9148 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9149 /* Stop translation as we may have switched the execution mode */
9150 ctx->base.is_jmp = DISAS_STOP;
9151 rn = "TraceControl2";
9152 goto cp0_unimplemented;
9153 case 3:
9154 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9155 /* Stop translation as we may have switched the execution mode */
9156 ctx->base.is_jmp = DISAS_STOP;
9157 rn = "UserTraceData";
9158 goto cp0_unimplemented;
9159 case 4:
9160 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9161 /* Stop translation as we may have switched the execution mode */
9162 ctx->base.is_jmp = DISAS_STOP;
9163 rn = "TraceBPC";
9164 goto cp0_unimplemented;
9165 default:
9166 goto cp0_unimplemented;
9168 break;
9169 case 24:
9170 switch (sel) {
9171 case 0:
9172 /* EJTAG support */
9173 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9174 rn = "DEPC";
9175 break;
9176 default:
9177 goto cp0_unimplemented;
9179 break;
9180 case 25:
9181 switch (sel) {
9182 case 0:
9183 gen_helper_mtc0_performance0(cpu_env, arg);
9184 rn = "Performance0";
9185 break;
9186 case 1:
9187 // gen_helper_mtc0_performance1(cpu_env, arg);
9188 rn = "Performance1";
9189 goto cp0_unimplemented;
9190 case 2:
9191 // gen_helper_mtc0_performance2(cpu_env, arg);
9192 rn = "Performance2";
9193 goto cp0_unimplemented;
9194 case 3:
9195 // gen_helper_mtc0_performance3(cpu_env, arg);
9196 rn = "Performance3";
9197 goto cp0_unimplemented;
9198 case 4:
9199 // gen_helper_mtc0_performance4(cpu_env, arg);
9200 rn = "Performance4";
9201 goto cp0_unimplemented;
9202 case 5:
9203 // gen_helper_mtc0_performance5(cpu_env, arg);
9204 rn = "Performance5";
9205 goto cp0_unimplemented;
9206 case 6:
9207 // gen_helper_mtc0_performance6(cpu_env, arg);
9208 rn = "Performance6";
9209 goto cp0_unimplemented;
9210 case 7:
9211 // gen_helper_mtc0_performance7(cpu_env, arg);
9212 rn = "Performance7";
9213 goto cp0_unimplemented;
9214 default:
9215 goto cp0_unimplemented;
9217 break;
9218 case 26:
9219 switch (sel) {
9220 case 0:
9221 gen_helper_mtc0_errctl(cpu_env, arg);
9222 ctx->base.is_jmp = DISAS_STOP;
9223 rn = "ErrCtl";
9224 break;
9225 default:
9226 goto cp0_unimplemented;
9228 break;
9229 case 27:
9230 switch (sel) {
9231 case 0:
9232 case 1:
9233 case 2:
9234 case 3:
9235 /* ignored */
9236 rn = "CacheErr";
9237 break;
9238 default:
9239 goto cp0_unimplemented;
9241 break;
9242 case 28:
9243 switch (sel) {
9244 case 0:
9245 case 2:
9246 case 4:
9247 case 6:
9248 gen_helper_mtc0_taglo(cpu_env, arg);
9249 rn = "TagLo";
9250 break;
9251 case 1:
9252 case 3:
9253 case 5:
9254 case 7:
9255 gen_helper_mtc0_datalo(cpu_env, arg);
9256 rn = "DataLo";
9257 break;
9258 default:
9259 goto cp0_unimplemented;
9261 break;
9262 case 29:
9263 switch (sel) {
9264 case 0:
9265 case 2:
9266 case 4:
9267 case 6:
9268 gen_helper_mtc0_taghi(cpu_env, arg);
9269 rn = "TagHi";
9270 break;
9271 case 1:
9272 case 3:
9273 case 5:
9274 case 7:
9275 gen_helper_mtc0_datahi(cpu_env, arg);
9276 rn = "DataHi";
9277 break;
9278 default:
9279 rn = "invalid sel";
9280 goto cp0_unimplemented;
9282 break;
9283 case 30:
9284 switch (sel) {
9285 case 0:
9286 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9287 rn = "ErrorEPC";
9288 break;
9289 default:
9290 goto cp0_unimplemented;
9292 break;
9293 case 31:
9294 switch (sel) {
9295 case 0:
9296 /* EJTAG support */
9297 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9298 rn = "DESAVE";
9299 break;
9300 case 2:
9301 case 3:
9302 case 4:
9303 case 5:
9304 case 6:
9305 case 7:
9306 CP0_CHECK(ctx->kscrexist & (1 << sel));
9307 tcg_gen_st_tl(arg, cpu_env,
9308 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9309 rn = "KScratch";
9310 break;
9311 default:
9312 goto cp0_unimplemented;
9314 break;
9315 default:
9316 goto cp0_unimplemented;
9318 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9320 /* For simplicity assume that all writes can cause interrupts. */
9321 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9322 gen_io_end();
9323 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9324 * translated code to check for pending interrupts. */
9325 gen_save_pc(ctx->base.pc_next + 4);
9326 ctx->base.is_jmp = DISAS_EXIT;
9328 return;
9330 cp0_unimplemented:
9331 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9333 #endif /* TARGET_MIPS64 */
9335 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9336 int u, int sel, int h)
9338 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9339 TCGv t0 = tcg_temp_local_new();
9341 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9342 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9343 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9344 tcg_gen_movi_tl(t0, -1);
9345 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9346 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9347 tcg_gen_movi_tl(t0, -1);
9348 else if (u == 0) {
9349 switch (rt) {
9350 case 1:
9351 switch (sel) {
9352 case 1:
9353 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9354 break;
9355 case 2:
9356 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9357 break;
9358 default:
9359 goto die;
9360 break;
9362 break;
9363 case 2:
9364 switch (sel) {
9365 case 1:
9366 gen_helper_mftc0_tcstatus(t0, cpu_env);
9367 break;
9368 case 2:
9369 gen_helper_mftc0_tcbind(t0, cpu_env);
9370 break;
9371 case 3:
9372 gen_helper_mftc0_tcrestart(t0, cpu_env);
9373 break;
9374 case 4:
9375 gen_helper_mftc0_tchalt(t0, cpu_env);
9376 break;
9377 case 5:
9378 gen_helper_mftc0_tccontext(t0, cpu_env);
9379 break;
9380 case 6:
9381 gen_helper_mftc0_tcschedule(t0, cpu_env);
9382 break;
9383 case 7:
9384 gen_helper_mftc0_tcschefback(t0, cpu_env);
9385 break;
9386 default:
9387 gen_mfc0(ctx, t0, rt, sel);
9388 break;
9390 break;
9391 case 10:
9392 switch (sel) {
9393 case 0:
9394 gen_helper_mftc0_entryhi(t0, cpu_env);
9395 break;
9396 default:
9397 gen_mfc0(ctx, t0, rt, sel);
9398 break;
9400 case 12:
9401 switch (sel) {
9402 case 0:
9403 gen_helper_mftc0_status(t0, cpu_env);
9404 break;
9405 default:
9406 gen_mfc0(ctx, t0, rt, sel);
9407 break;
9409 case 13:
9410 switch (sel) {
9411 case 0:
9412 gen_helper_mftc0_cause(t0, cpu_env);
9413 break;
9414 default:
9415 goto die;
9416 break;
9418 break;
9419 case 14:
9420 switch (sel) {
9421 case 0:
9422 gen_helper_mftc0_epc(t0, cpu_env);
9423 break;
9424 default:
9425 goto die;
9426 break;
9428 break;
9429 case 15:
9430 switch (sel) {
9431 case 1:
9432 gen_helper_mftc0_ebase(t0, cpu_env);
9433 break;
9434 default:
9435 goto die;
9436 break;
9438 break;
9439 case 16:
9440 switch (sel) {
9441 case 0:
9442 case 1:
9443 case 2:
9444 case 3:
9445 case 4:
9446 case 5:
9447 case 6:
9448 case 7:
9449 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9450 break;
9451 default:
9452 goto die;
9453 break;
9455 break;
9456 case 23:
9457 switch (sel) {
9458 case 0:
9459 gen_helper_mftc0_debug(t0, cpu_env);
9460 break;
9461 default:
9462 gen_mfc0(ctx, t0, rt, sel);
9463 break;
9465 break;
9466 default:
9467 gen_mfc0(ctx, t0, rt, sel);
9469 } else switch (sel) {
9470 /* GPR registers. */
9471 case 0:
9472 gen_helper_1e0i(mftgpr, t0, rt);
9473 break;
9474 /* Auxiliary CPU registers */
9475 case 1:
9476 switch (rt) {
9477 case 0:
9478 gen_helper_1e0i(mftlo, t0, 0);
9479 break;
9480 case 1:
9481 gen_helper_1e0i(mfthi, t0, 0);
9482 break;
9483 case 2:
9484 gen_helper_1e0i(mftacx, t0, 0);
9485 break;
9486 case 4:
9487 gen_helper_1e0i(mftlo, t0, 1);
9488 break;
9489 case 5:
9490 gen_helper_1e0i(mfthi, t0, 1);
9491 break;
9492 case 6:
9493 gen_helper_1e0i(mftacx, t0, 1);
9494 break;
9495 case 8:
9496 gen_helper_1e0i(mftlo, t0, 2);
9497 break;
9498 case 9:
9499 gen_helper_1e0i(mfthi, t0, 2);
9500 break;
9501 case 10:
9502 gen_helper_1e0i(mftacx, t0, 2);
9503 break;
9504 case 12:
9505 gen_helper_1e0i(mftlo, t0, 3);
9506 break;
9507 case 13:
9508 gen_helper_1e0i(mfthi, t0, 3);
9509 break;
9510 case 14:
9511 gen_helper_1e0i(mftacx, t0, 3);
9512 break;
9513 case 16:
9514 gen_helper_mftdsp(t0, cpu_env);
9515 break;
9516 default:
9517 goto die;
9519 break;
9520 /* Floating point (COP1). */
9521 case 2:
9522 /* XXX: For now we support only a single FPU context. */
9523 if (h == 0) {
9524 TCGv_i32 fp0 = tcg_temp_new_i32();
9526 gen_load_fpr32(ctx, fp0, rt);
9527 tcg_gen_ext_i32_tl(t0, fp0);
9528 tcg_temp_free_i32(fp0);
9529 } else {
9530 TCGv_i32 fp0 = tcg_temp_new_i32();
9532 gen_load_fpr32h(ctx, fp0, rt);
9533 tcg_gen_ext_i32_tl(t0, fp0);
9534 tcg_temp_free_i32(fp0);
9536 break;
9537 case 3:
9538 /* XXX: For now we support only a single FPU context. */
9539 gen_helper_1e0i(cfc1, t0, rt);
9540 break;
9541 /* COP2: Not implemented. */
9542 case 4:
9543 case 5:
9544 /* fall through */
9545 default:
9546 goto die;
9548 trace_mips_translate_tr("mftr", rt, u, sel, h);
9549 gen_store_gpr(t0, rd);
9550 tcg_temp_free(t0);
9551 return;
9553 die:
9554 tcg_temp_free(t0);
9555 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9556 generate_exception_end(ctx, EXCP_RI);
9559 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9560 int u, int sel, int h)
9562 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9563 TCGv t0 = tcg_temp_local_new();
9565 gen_load_gpr(t0, rt);
9566 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9567 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9568 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9569 /* NOP */ ;
9570 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9571 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9572 /* NOP */ ;
9573 else if (u == 0) {
9574 switch (rd) {
9575 case 1:
9576 switch (sel) {
9577 case 1:
9578 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9579 break;
9580 case 2:
9581 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9582 break;
9583 default:
9584 goto die;
9585 break;
9587 break;
9588 case 2:
9589 switch (sel) {
9590 case 1:
9591 gen_helper_mttc0_tcstatus(cpu_env, t0);
9592 break;
9593 case 2:
9594 gen_helper_mttc0_tcbind(cpu_env, t0);
9595 break;
9596 case 3:
9597 gen_helper_mttc0_tcrestart(cpu_env, t0);
9598 break;
9599 case 4:
9600 gen_helper_mttc0_tchalt(cpu_env, t0);
9601 break;
9602 case 5:
9603 gen_helper_mttc0_tccontext(cpu_env, t0);
9604 break;
9605 case 6:
9606 gen_helper_mttc0_tcschedule(cpu_env, t0);
9607 break;
9608 case 7:
9609 gen_helper_mttc0_tcschefback(cpu_env, t0);
9610 break;
9611 default:
9612 gen_mtc0(ctx, t0, rd, sel);
9613 break;
9615 break;
9616 case 10:
9617 switch (sel) {
9618 case 0:
9619 gen_helper_mttc0_entryhi(cpu_env, t0);
9620 break;
9621 default:
9622 gen_mtc0(ctx, t0, rd, sel);
9623 break;
9625 case 12:
9626 switch (sel) {
9627 case 0:
9628 gen_helper_mttc0_status(cpu_env, t0);
9629 break;
9630 default:
9631 gen_mtc0(ctx, t0, rd, sel);
9632 break;
9634 case 13:
9635 switch (sel) {
9636 case 0:
9637 gen_helper_mttc0_cause(cpu_env, t0);
9638 break;
9639 default:
9640 goto die;
9641 break;
9643 break;
9644 case 15:
9645 switch (sel) {
9646 case 1:
9647 gen_helper_mttc0_ebase(cpu_env, t0);
9648 break;
9649 default:
9650 goto die;
9651 break;
9653 break;
9654 case 23:
9655 switch (sel) {
9656 case 0:
9657 gen_helper_mttc0_debug(cpu_env, t0);
9658 break;
9659 default:
9660 gen_mtc0(ctx, t0, rd, sel);
9661 break;
9663 break;
9664 default:
9665 gen_mtc0(ctx, t0, rd, sel);
9667 } else switch (sel) {
9668 /* GPR registers. */
9669 case 0:
9670 gen_helper_0e1i(mttgpr, t0, rd);
9671 break;
9672 /* Auxiliary CPU registers */
9673 case 1:
9674 switch (rd) {
9675 case 0:
9676 gen_helper_0e1i(mttlo, t0, 0);
9677 break;
9678 case 1:
9679 gen_helper_0e1i(mtthi, t0, 0);
9680 break;
9681 case 2:
9682 gen_helper_0e1i(mttacx, t0, 0);
9683 break;
9684 case 4:
9685 gen_helper_0e1i(mttlo, t0, 1);
9686 break;
9687 case 5:
9688 gen_helper_0e1i(mtthi, t0, 1);
9689 break;
9690 case 6:
9691 gen_helper_0e1i(mttacx, t0, 1);
9692 break;
9693 case 8:
9694 gen_helper_0e1i(mttlo, t0, 2);
9695 break;
9696 case 9:
9697 gen_helper_0e1i(mtthi, t0, 2);
9698 break;
9699 case 10:
9700 gen_helper_0e1i(mttacx, t0, 2);
9701 break;
9702 case 12:
9703 gen_helper_0e1i(mttlo, t0, 3);
9704 break;
9705 case 13:
9706 gen_helper_0e1i(mtthi, t0, 3);
9707 break;
9708 case 14:
9709 gen_helper_0e1i(mttacx, t0, 3);
9710 break;
9711 case 16:
9712 gen_helper_mttdsp(cpu_env, t0);
9713 break;
9714 default:
9715 goto die;
9717 break;
9718 /* Floating point (COP1). */
9719 case 2:
9720 /* XXX: For now we support only a single FPU context. */
9721 if (h == 0) {
9722 TCGv_i32 fp0 = tcg_temp_new_i32();
9724 tcg_gen_trunc_tl_i32(fp0, t0);
9725 gen_store_fpr32(ctx, fp0, rd);
9726 tcg_temp_free_i32(fp0);
9727 } else {
9728 TCGv_i32 fp0 = tcg_temp_new_i32();
9730 tcg_gen_trunc_tl_i32(fp0, t0);
9731 gen_store_fpr32h(ctx, fp0, rd);
9732 tcg_temp_free_i32(fp0);
9734 break;
9735 case 3:
9736 /* XXX: For now we support only a single FPU context. */
9738 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9740 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9741 tcg_temp_free_i32(fs_tmp);
9743 /* Stop translation as we may have changed hflags */
9744 ctx->base.is_jmp = DISAS_STOP;
9745 break;
9746 /* COP2: Not implemented. */
9747 case 4:
9748 case 5:
9749 /* fall through */
9750 default:
9751 goto die;
9753 trace_mips_translate_tr("mttr", rd, u, sel, h);
9754 tcg_temp_free(t0);
9755 return;
9757 die:
9758 tcg_temp_free(t0);
9759 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9760 generate_exception_end(ctx, EXCP_RI);
9763 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9765 const char *opn = "ldst";
9767 check_cp0_enabled(ctx);
9768 switch (opc) {
9769 case OPC_MFC0:
9770 if (rt == 0) {
9771 /* Treat as NOP. */
9772 return;
9774 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9775 opn = "mfc0";
9776 break;
9777 case OPC_MTC0:
9779 TCGv t0 = tcg_temp_new();
9781 gen_load_gpr(t0, rt);
9782 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9783 tcg_temp_free(t0);
9785 opn = "mtc0";
9786 break;
9787 #if defined(TARGET_MIPS64)
9788 case OPC_DMFC0:
9789 check_insn(ctx, ISA_MIPS3);
9790 if (rt == 0) {
9791 /* Treat as NOP. */
9792 return;
9794 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9795 opn = "dmfc0";
9796 break;
9797 case OPC_DMTC0:
9798 check_insn(ctx, ISA_MIPS3);
9800 TCGv t0 = tcg_temp_new();
9802 gen_load_gpr(t0, rt);
9803 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9804 tcg_temp_free(t0);
9806 opn = "dmtc0";
9807 break;
9808 #endif
9809 case OPC_MFHC0:
9810 check_mvh(ctx);
9811 if (rt == 0) {
9812 /* Treat as NOP. */
9813 return;
9815 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9816 opn = "mfhc0";
9817 break;
9818 case OPC_MTHC0:
9819 check_mvh(ctx);
9821 TCGv t0 = tcg_temp_new();
9822 gen_load_gpr(t0, rt);
9823 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9824 tcg_temp_free(t0);
9826 opn = "mthc0";
9827 break;
9828 case OPC_MFTR:
9829 check_cp0_enabled(ctx);
9830 if (rd == 0) {
9831 /* Treat as NOP. */
9832 return;
9834 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9835 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9836 opn = "mftr";
9837 break;
9838 case OPC_MTTR:
9839 check_cp0_enabled(ctx);
9840 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9841 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9842 opn = "mttr";
9843 break;
9844 case OPC_TLBWI:
9845 opn = "tlbwi";
9846 if (!env->tlb->helper_tlbwi)
9847 goto die;
9848 gen_helper_tlbwi(cpu_env);
9849 break;
9850 case OPC_TLBINV:
9851 opn = "tlbinv";
9852 if (ctx->ie >= 2) {
9853 if (!env->tlb->helper_tlbinv) {
9854 goto die;
9856 gen_helper_tlbinv(cpu_env);
9857 } /* treat as nop if TLBINV not supported */
9858 break;
9859 case OPC_TLBINVF:
9860 opn = "tlbinvf";
9861 if (ctx->ie >= 2) {
9862 if (!env->tlb->helper_tlbinvf) {
9863 goto die;
9865 gen_helper_tlbinvf(cpu_env);
9866 } /* treat as nop if TLBINV not supported */
9867 break;
9868 case OPC_TLBWR:
9869 opn = "tlbwr";
9870 if (!env->tlb->helper_tlbwr)
9871 goto die;
9872 gen_helper_tlbwr(cpu_env);
9873 break;
9874 case OPC_TLBP:
9875 opn = "tlbp";
9876 if (!env->tlb->helper_tlbp)
9877 goto die;
9878 gen_helper_tlbp(cpu_env);
9879 break;
9880 case OPC_TLBR:
9881 opn = "tlbr";
9882 if (!env->tlb->helper_tlbr)
9883 goto die;
9884 gen_helper_tlbr(cpu_env);
9885 break;
9886 case OPC_ERET: /* OPC_ERETNC */
9887 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9888 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9889 goto die;
9890 } else {
9891 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9892 if (ctx->opcode & (1 << bit_shift)) {
9893 /* OPC_ERETNC */
9894 opn = "eretnc";
9895 check_insn(ctx, ISA_MIPS32R5);
9896 gen_helper_eretnc(cpu_env);
9897 } else {
9898 /* OPC_ERET */
9899 opn = "eret";
9900 check_insn(ctx, ISA_MIPS2);
9901 gen_helper_eret(cpu_env);
9903 ctx->base.is_jmp = DISAS_EXIT;
9905 break;
9906 case OPC_DERET:
9907 opn = "deret";
9908 check_insn(ctx, ISA_MIPS32);
9909 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9910 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9911 goto die;
9913 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9914 MIPS_INVAL(opn);
9915 generate_exception_end(ctx, EXCP_RI);
9916 } else {
9917 gen_helper_deret(cpu_env);
9918 ctx->base.is_jmp = DISAS_EXIT;
9920 break;
9921 case OPC_WAIT:
9922 opn = "wait";
9923 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9924 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9925 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9926 goto die;
9928 /* If we get an exception, we want to restart at next instruction */
9929 ctx->base.pc_next += 4;
9930 save_cpu_state(ctx, 1);
9931 ctx->base.pc_next -= 4;
9932 gen_helper_wait(cpu_env);
9933 ctx->base.is_jmp = DISAS_NORETURN;
9934 break;
9935 default:
9936 die:
9937 MIPS_INVAL(opn);
9938 generate_exception_end(ctx, EXCP_RI);
9939 return;
9941 (void)opn; /* avoid a compiler warning */
9943 #endif /* !CONFIG_USER_ONLY */
9945 /* CP1 Branches (before delay slot) */
9946 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9947 int32_t cc, int32_t offset)
9949 target_ulong btarget;
9950 TCGv_i32 t0 = tcg_temp_new_i32();
9952 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9953 generate_exception_end(ctx, EXCP_RI);
9954 goto out;
9957 if (cc != 0)
9958 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9960 btarget = ctx->base.pc_next + 4 + offset;
9962 switch (op) {
9963 case OPC_BC1F:
9964 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9965 tcg_gen_not_i32(t0, t0);
9966 tcg_gen_andi_i32(t0, t0, 1);
9967 tcg_gen_extu_i32_tl(bcond, t0);
9968 goto not_likely;
9969 case OPC_BC1FL:
9970 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9971 tcg_gen_not_i32(t0, t0);
9972 tcg_gen_andi_i32(t0, t0, 1);
9973 tcg_gen_extu_i32_tl(bcond, t0);
9974 goto likely;
9975 case OPC_BC1T:
9976 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9977 tcg_gen_andi_i32(t0, t0, 1);
9978 tcg_gen_extu_i32_tl(bcond, t0);
9979 goto not_likely;
9980 case OPC_BC1TL:
9981 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9982 tcg_gen_andi_i32(t0, t0, 1);
9983 tcg_gen_extu_i32_tl(bcond, t0);
9984 likely:
9985 ctx->hflags |= MIPS_HFLAG_BL;
9986 break;
9987 case OPC_BC1FANY2:
9989 TCGv_i32 t1 = tcg_temp_new_i32();
9990 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9991 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9992 tcg_gen_nand_i32(t0, t0, t1);
9993 tcg_temp_free_i32(t1);
9994 tcg_gen_andi_i32(t0, t0, 1);
9995 tcg_gen_extu_i32_tl(bcond, t0);
9997 goto not_likely;
9998 case OPC_BC1TANY2:
10000 TCGv_i32 t1 = tcg_temp_new_i32();
10001 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10002 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10003 tcg_gen_or_i32(t0, t0, t1);
10004 tcg_temp_free_i32(t1);
10005 tcg_gen_andi_i32(t0, t0, 1);
10006 tcg_gen_extu_i32_tl(bcond, t0);
10008 goto not_likely;
10009 case OPC_BC1FANY4:
10011 TCGv_i32 t1 = tcg_temp_new_i32();
10012 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10013 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10014 tcg_gen_and_i32(t0, t0, t1);
10015 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10016 tcg_gen_and_i32(t0, t0, t1);
10017 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10018 tcg_gen_nand_i32(t0, t0, t1);
10019 tcg_temp_free_i32(t1);
10020 tcg_gen_andi_i32(t0, t0, 1);
10021 tcg_gen_extu_i32_tl(bcond, t0);
10023 goto not_likely;
10024 case OPC_BC1TANY4:
10026 TCGv_i32 t1 = tcg_temp_new_i32();
10027 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10028 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10029 tcg_gen_or_i32(t0, t0, t1);
10030 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10031 tcg_gen_or_i32(t0, t0, t1);
10032 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10033 tcg_gen_or_i32(t0, t0, t1);
10034 tcg_temp_free_i32(t1);
10035 tcg_gen_andi_i32(t0, t0, 1);
10036 tcg_gen_extu_i32_tl(bcond, t0);
10038 not_likely:
10039 ctx->hflags |= MIPS_HFLAG_BC;
10040 break;
10041 default:
10042 MIPS_INVAL("cp1 cond branch");
10043 generate_exception_end(ctx, EXCP_RI);
10044 goto out;
10046 ctx->btarget = btarget;
10047 ctx->hflags |= MIPS_HFLAG_BDS32;
10048 out:
10049 tcg_temp_free_i32(t0);
10052 /* R6 CP1 Branches */
10053 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10054 int32_t ft, int32_t offset,
10055 int delayslot_size)
10057 target_ulong btarget;
10058 TCGv_i64 t0 = tcg_temp_new_i64();
10060 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10061 #ifdef MIPS_DEBUG_DISAS
10062 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10063 "\n", ctx->base.pc_next);
10064 #endif
10065 generate_exception_end(ctx, EXCP_RI);
10066 goto out;
10069 gen_load_fpr64(ctx, t0, ft);
10070 tcg_gen_andi_i64(t0, t0, 1);
10072 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10074 switch (op) {
10075 case OPC_BC1EQZ:
10076 tcg_gen_xori_i64(t0, t0, 1);
10077 ctx->hflags |= MIPS_HFLAG_BC;
10078 break;
10079 case OPC_BC1NEZ:
10080 /* t0 already set */
10081 ctx->hflags |= MIPS_HFLAG_BC;
10082 break;
10083 default:
10084 MIPS_INVAL("cp1 cond branch");
10085 generate_exception_end(ctx, EXCP_RI);
10086 goto out;
10089 tcg_gen_trunc_i64_tl(bcond, t0);
10091 ctx->btarget = btarget;
10093 switch (delayslot_size) {
10094 case 2:
10095 ctx->hflags |= MIPS_HFLAG_BDS16;
10096 break;
10097 case 4:
10098 ctx->hflags |= MIPS_HFLAG_BDS32;
10099 break;
10102 out:
10103 tcg_temp_free_i64(t0);
10106 /* Coprocessor 1 (FPU) */
10108 #define FOP(func, fmt) (((fmt) << 21) | (func))
10110 enum fopcode {
10111 OPC_ADD_S = FOP(0, FMT_S),
10112 OPC_SUB_S = FOP(1, FMT_S),
10113 OPC_MUL_S = FOP(2, FMT_S),
10114 OPC_DIV_S = FOP(3, FMT_S),
10115 OPC_SQRT_S = FOP(4, FMT_S),
10116 OPC_ABS_S = FOP(5, FMT_S),
10117 OPC_MOV_S = FOP(6, FMT_S),
10118 OPC_NEG_S = FOP(7, FMT_S),
10119 OPC_ROUND_L_S = FOP(8, FMT_S),
10120 OPC_TRUNC_L_S = FOP(9, FMT_S),
10121 OPC_CEIL_L_S = FOP(10, FMT_S),
10122 OPC_FLOOR_L_S = FOP(11, FMT_S),
10123 OPC_ROUND_W_S = FOP(12, FMT_S),
10124 OPC_TRUNC_W_S = FOP(13, FMT_S),
10125 OPC_CEIL_W_S = FOP(14, FMT_S),
10126 OPC_FLOOR_W_S = FOP(15, FMT_S),
10127 OPC_SEL_S = FOP(16, FMT_S),
10128 OPC_MOVCF_S = FOP(17, FMT_S),
10129 OPC_MOVZ_S = FOP(18, FMT_S),
10130 OPC_MOVN_S = FOP(19, FMT_S),
10131 OPC_SELEQZ_S = FOP(20, FMT_S),
10132 OPC_RECIP_S = FOP(21, FMT_S),
10133 OPC_RSQRT_S = FOP(22, FMT_S),
10134 OPC_SELNEZ_S = FOP(23, FMT_S),
10135 OPC_MADDF_S = FOP(24, FMT_S),
10136 OPC_MSUBF_S = FOP(25, FMT_S),
10137 OPC_RINT_S = FOP(26, FMT_S),
10138 OPC_CLASS_S = FOP(27, FMT_S),
10139 OPC_MIN_S = FOP(28, FMT_S),
10140 OPC_RECIP2_S = FOP(28, FMT_S),
10141 OPC_MINA_S = FOP(29, FMT_S),
10142 OPC_RECIP1_S = FOP(29, FMT_S),
10143 OPC_MAX_S = FOP(30, FMT_S),
10144 OPC_RSQRT1_S = FOP(30, FMT_S),
10145 OPC_MAXA_S = FOP(31, FMT_S),
10146 OPC_RSQRT2_S = FOP(31, FMT_S),
10147 OPC_CVT_D_S = FOP(33, FMT_S),
10148 OPC_CVT_W_S = FOP(36, FMT_S),
10149 OPC_CVT_L_S = FOP(37, FMT_S),
10150 OPC_CVT_PS_S = FOP(38, FMT_S),
10151 OPC_CMP_F_S = FOP (48, FMT_S),
10152 OPC_CMP_UN_S = FOP (49, FMT_S),
10153 OPC_CMP_EQ_S = FOP (50, FMT_S),
10154 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10155 OPC_CMP_OLT_S = FOP (52, FMT_S),
10156 OPC_CMP_ULT_S = FOP (53, FMT_S),
10157 OPC_CMP_OLE_S = FOP (54, FMT_S),
10158 OPC_CMP_ULE_S = FOP (55, FMT_S),
10159 OPC_CMP_SF_S = FOP (56, FMT_S),
10160 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10161 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10162 OPC_CMP_NGL_S = FOP (59, FMT_S),
10163 OPC_CMP_LT_S = FOP (60, FMT_S),
10164 OPC_CMP_NGE_S = FOP (61, FMT_S),
10165 OPC_CMP_LE_S = FOP (62, FMT_S),
10166 OPC_CMP_NGT_S = FOP (63, FMT_S),
10168 OPC_ADD_D = FOP(0, FMT_D),
10169 OPC_SUB_D = FOP(1, FMT_D),
10170 OPC_MUL_D = FOP(2, FMT_D),
10171 OPC_DIV_D = FOP(3, FMT_D),
10172 OPC_SQRT_D = FOP(4, FMT_D),
10173 OPC_ABS_D = FOP(5, FMT_D),
10174 OPC_MOV_D = FOP(6, FMT_D),
10175 OPC_NEG_D = FOP(7, FMT_D),
10176 OPC_ROUND_L_D = FOP(8, FMT_D),
10177 OPC_TRUNC_L_D = FOP(9, FMT_D),
10178 OPC_CEIL_L_D = FOP(10, FMT_D),
10179 OPC_FLOOR_L_D = FOP(11, FMT_D),
10180 OPC_ROUND_W_D = FOP(12, FMT_D),
10181 OPC_TRUNC_W_D = FOP(13, FMT_D),
10182 OPC_CEIL_W_D = FOP(14, FMT_D),
10183 OPC_FLOOR_W_D = FOP(15, FMT_D),
10184 OPC_SEL_D = FOP(16, FMT_D),
10185 OPC_MOVCF_D = FOP(17, FMT_D),
10186 OPC_MOVZ_D = FOP(18, FMT_D),
10187 OPC_MOVN_D = FOP(19, FMT_D),
10188 OPC_SELEQZ_D = FOP(20, FMT_D),
10189 OPC_RECIP_D = FOP(21, FMT_D),
10190 OPC_RSQRT_D = FOP(22, FMT_D),
10191 OPC_SELNEZ_D = FOP(23, FMT_D),
10192 OPC_MADDF_D = FOP(24, FMT_D),
10193 OPC_MSUBF_D = FOP(25, FMT_D),
10194 OPC_RINT_D = FOP(26, FMT_D),
10195 OPC_CLASS_D = FOP(27, FMT_D),
10196 OPC_MIN_D = FOP(28, FMT_D),
10197 OPC_RECIP2_D = FOP(28, FMT_D),
10198 OPC_MINA_D = FOP(29, FMT_D),
10199 OPC_RECIP1_D = FOP(29, FMT_D),
10200 OPC_MAX_D = FOP(30, FMT_D),
10201 OPC_RSQRT1_D = FOP(30, FMT_D),
10202 OPC_MAXA_D = FOP(31, FMT_D),
10203 OPC_RSQRT2_D = FOP(31, FMT_D),
10204 OPC_CVT_S_D = FOP(32, FMT_D),
10205 OPC_CVT_W_D = FOP(36, FMT_D),
10206 OPC_CVT_L_D = FOP(37, FMT_D),
10207 OPC_CMP_F_D = FOP (48, FMT_D),
10208 OPC_CMP_UN_D = FOP (49, FMT_D),
10209 OPC_CMP_EQ_D = FOP (50, FMT_D),
10210 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10211 OPC_CMP_OLT_D = FOP (52, FMT_D),
10212 OPC_CMP_ULT_D = FOP (53, FMT_D),
10213 OPC_CMP_OLE_D = FOP (54, FMT_D),
10214 OPC_CMP_ULE_D = FOP (55, FMT_D),
10215 OPC_CMP_SF_D = FOP (56, FMT_D),
10216 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10217 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10218 OPC_CMP_NGL_D = FOP (59, FMT_D),
10219 OPC_CMP_LT_D = FOP (60, FMT_D),
10220 OPC_CMP_NGE_D = FOP (61, FMT_D),
10221 OPC_CMP_LE_D = FOP (62, FMT_D),
10222 OPC_CMP_NGT_D = FOP (63, FMT_D),
10224 OPC_CVT_S_W = FOP(32, FMT_W),
10225 OPC_CVT_D_W = FOP(33, FMT_W),
10226 OPC_CVT_S_L = FOP(32, FMT_L),
10227 OPC_CVT_D_L = FOP(33, FMT_L),
10228 OPC_CVT_PS_PW = FOP(38, FMT_W),
10230 OPC_ADD_PS = FOP(0, FMT_PS),
10231 OPC_SUB_PS = FOP(1, FMT_PS),
10232 OPC_MUL_PS = FOP(2, FMT_PS),
10233 OPC_DIV_PS = FOP(3, FMT_PS),
10234 OPC_ABS_PS = FOP(5, FMT_PS),
10235 OPC_MOV_PS = FOP(6, FMT_PS),
10236 OPC_NEG_PS = FOP(7, FMT_PS),
10237 OPC_MOVCF_PS = FOP(17, FMT_PS),
10238 OPC_MOVZ_PS = FOP(18, FMT_PS),
10239 OPC_MOVN_PS = FOP(19, FMT_PS),
10240 OPC_ADDR_PS = FOP(24, FMT_PS),
10241 OPC_MULR_PS = FOP(26, FMT_PS),
10242 OPC_RECIP2_PS = FOP(28, FMT_PS),
10243 OPC_RECIP1_PS = FOP(29, FMT_PS),
10244 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10245 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10247 OPC_CVT_S_PU = FOP(32, FMT_PS),
10248 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10249 OPC_CVT_S_PL = FOP(40, FMT_PS),
10250 OPC_PLL_PS = FOP(44, FMT_PS),
10251 OPC_PLU_PS = FOP(45, FMT_PS),
10252 OPC_PUL_PS = FOP(46, FMT_PS),
10253 OPC_PUU_PS = FOP(47, FMT_PS),
10254 OPC_CMP_F_PS = FOP (48, FMT_PS),
10255 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10256 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10257 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10258 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10259 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10260 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10261 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10262 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10263 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10264 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10265 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10266 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10267 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10268 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10269 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10272 enum r6_f_cmp_op {
10273 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10274 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10275 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10276 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10277 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10278 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10279 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10280 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10281 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10282 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10283 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10284 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10285 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10286 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10287 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10288 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10289 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10290 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10291 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10292 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10293 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10294 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10296 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10297 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10298 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10299 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10300 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10301 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10302 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10303 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10304 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10305 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10306 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10307 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10308 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10309 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10310 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10311 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10312 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10313 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10314 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10315 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10316 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10317 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10319 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10321 TCGv t0 = tcg_temp_new();
10323 switch (opc) {
10324 case OPC_MFC1:
10326 TCGv_i32 fp0 = tcg_temp_new_i32();
10328 gen_load_fpr32(ctx, fp0, fs);
10329 tcg_gen_ext_i32_tl(t0, fp0);
10330 tcg_temp_free_i32(fp0);
10332 gen_store_gpr(t0, rt);
10333 break;
10334 case OPC_MTC1:
10335 gen_load_gpr(t0, rt);
10337 TCGv_i32 fp0 = tcg_temp_new_i32();
10339 tcg_gen_trunc_tl_i32(fp0, t0);
10340 gen_store_fpr32(ctx, fp0, fs);
10341 tcg_temp_free_i32(fp0);
10343 break;
10344 case OPC_CFC1:
10345 gen_helper_1e0i(cfc1, t0, fs);
10346 gen_store_gpr(t0, rt);
10347 break;
10348 case OPC_CTC1:
10349 gen_load_gpr(t0, rt);
10350 save_cpu_state(ctx, 0);
10352 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10354 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10355 tcg_temp_free_i32(fs_tmp);
10357 /* Stop translation as we may have changed hflags */
10358 ctx->base.is_jmp = DISAS_STOP;
10359 break;
10360 #if defined(TARGET_MIPS64)
10361 case OPC_DMFC1:
10362 gen_load_fpr64(ctx, t0, fs);
10363 gen_store_gpr(t0, rt);
10364 break;
10365 case OPC_DMTC1:
10366 gen_load_gpr(t0, rt);
10367 gen_store_fpr64(ctx, t0, fs);
10368 break;
10369 #endif
10370 case OPC_MFHC1:
10372 TCGv_i32 fp0 = tcg_temp_new_i32();
10374 gen_load_fpr32h(ctx, fp0, fs);
10375 tcg_gen_ext_i32_tl(t0, fp0);
10376 tcg_temp_free_i32(fp0);
10378 gen_store_gpr(t0, rt);
10379 break;
10380 case OPC_MTHC1:
10381 gen_load_gpr(t0, rt);
10383 TCGv_i32 fp0 = tcg_temp_new_i32();
10385 tcg_gen_trunc_tl_i32(fp0, t0);
10386 gen_store_fpr32h(ctx, fp0, fs);
10387 tcg_temp_free_i32(fp0);
10389 break;
10390 default:
10391 MIPS_INVAL("cp1 move");
10392 generate_exception_end(ctx, EXCP_RI);
10393 goto out;
10396 out:
10397 tcg_temp_free(t0);
10400 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10402 TCGLabel *l1;
10403 TCGCond cond;
10404 TCGv_i32 t0;
10406 if (rd == 0) {
10407 /* Treat as NOP. */
10408 return;
10411 if (tf)
10412 cond = TCG_COND_EQ;
10413 else
10414 cond = TCG_COND_NE;
10416 l1 = gen_new_label();
10417 t0 = tcg_temp_new_i32();
10418 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10419 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10420 tcg_temp_free_i32(t0);
10421 if (rs == 0) {
10422 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10423 } else {
10424 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10426 gen_set_label(l1);
10429 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10430 int tf)
10432 int cond;
10433 TCGv_i32 t0 = tcg_temp_new_i32();
10434 TCGLabel *l1 = gen_new_label();
10436 if (tf)
10437 cond = TCG_COND_EQ;
10438 else
10439 cond = TCG_COND_NE;
10441 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10442 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10443 gen_load_fpr32(ctx, t0, fs);
10444 gen_store_fpr32(ctx, t0, fd);
10445 gen_set_label(l1);
10446 tcg_temp_free_i32(t0);
10449 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10451 int cond;
10452 TCGv_i32 t0 = tcg_temp_new_i32();
10453 TCGv_i64 fp0;
10454 TCGLabel *l1 = gen_new_label();
10456 if (tf)
10457 cond = TCG_COND_EQ;
10458 else
10459 cond = TCG_COND_NE;
10461 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10462 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10463 tcg_temp_free_i32(t0);
10464 fp0 = tcg_temp_new_i64();
10465 gen_load_fpr64(ctx, fp0, fs);
10466 gen_store_fpr64(ctx, fp0, fd);
10467 tcg_temp_free_i64(fp0);
10468 gen_set_label(l1);
10471 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10472 int cc, int tf)
10474 int cond;
10475 TCGv_i32 t0 = tcg_temp_new_i32();
10476 TCGLabel *l1 = gen_new_label();
10477 TCGLabel *l2 = gen_new_label();
10479 if (tf)
10480 cond = TCG_COND_EQ;
10481 else
10482 cond = TCG_COND_NE;
10484 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10485 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10486 gen_load_fpr32(ctx, t0, fs);
10487 gen_store_fpr32(ctx, t0, fd);
10488 gen_set_label(l1);
10490 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10491 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10492 gen_load_fpr32h(ctx, t0, fs);
10493 gen_store_fpr32h(ctx, t0, fd);
10494 tcg_temp_free_i32(t0);
10495 gen_set_label(l2);
10498 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10499 int fs)
10501 TCGv_i32 t1 = tcg_const_i32(0);
10502 TCGv_i32 fp0 = tcg_temp_new_i32();
10503 TCGv_i32 fp1 = tcg_temp_new_i32();
10504 TCGv_i32 fp2 = tcg_temp_new_i32();
10505 gen_load_fpr32(ctx, fp0, fd);
10506 gen_load_fpr32(ctx, fp1, ft);
10507 gen_load_fpr32(ctx, fp2, fs);
10509 switch (op1) {
10510 case OPC_SEL_S:
10511 tcg_gen_andi_i32(fp0, fp0, 1);
10512 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10513 break;
10514 case OPC_SELEQZ_S:
10515 tcg_gen_andi_i32(fp1, fp1, 1);
10516 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10517 break;
10518 case OPC_SELNEZ_S:
10519 tcg_gen_andi_i32(fp1, fp1, 1);
10520 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10521 break;
10522 default:
10523 MIPS_INVAL("gen_sel_s");
10524 generate_exception_end(ctx, EXCP_RI);
10525 break;
10528 gen_store_fpr32(ctx, fp0, fd);
10529 tcg_temp_free_i32(fp2);
10530 tcg_temp_free_i32(fp1);
10531 tcg_temp_free_i32(fp0);
10532 tcg_temp_free_i32(t1);
10535 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10536 int fs)
10538 TCGv_i64 t1 = tcg_const_i64(0);
10539 TCGv_i64 fp0 = tcg_temp_new_i64();
10540 TCGv_i64 fp1 = tcg_temp_new_i64();
10541 TCGv_i64 fp2 = tcg_temp_new_i64();
10542 gen_load_fpr64(ctx, fp0, fd);
10543 gen_load_fpr64(ctx, fp1, ft);
10544 gen_load_fpr64(ctx, fp2, fs);
10546 switch (op1) {
10547 case OPC_SEL_D:
10548 tcg_gen_andi_i64(fp0, fp0, 1);
10549 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10550 break;
10551 case OPC_SELEQZ_D:
10552 tcg_gen_andi_i64(fp1, fp1, 1);
10553 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10554 break;
10555 case OPC_SELNEZ_D:
10556 tcg_gen_andi_i64(fp1, fp1, 1);
10557 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10558 break;
10559 default:
10560 MIPS_INVAL("gen_sel_d");
10561 generate_exception_end(ctx, EXCP_RI);
10562 break;
10565 gen_store_fpr64(ctx, fp0, fd);
10566 tcg_temp_free_i64(fp2);
10567 tcg_temp_free_i64(fp1);
10568 tcg_temp_free_i64(fp0);
10569 tcg_temp_free_i64(t1);
10572 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10573 int ft, int fs, int fd, int cc)
10575 uint32_t func = ctx->opcode & 0x3f;
10576 switch (op1) {
10577 case OPC_ADD_S:
10579 TCGv_i32 fp0 = tcg_temp_new_i32();
10580 TCGv_i32 fp1 = tcg_temp_new_i32();
10582 gen_load_fpr32(ctx, fp0, fs);
10583 gen_load_fpr32(ctx, fp1, ft);
10584 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10585 tcg_temp_free_i32(fp1);
10586 gen_store_fpr32(ctx, fp0, fd);
10587 tcg_temp_free_i32(fp0);
10589 break;
10590 case OPC_SUB_S:
10592 TCGv_i32 fp0 = tcg_temp_new_i32();
10593 TCGv_i32 fp1 = tcg_temp_new_i32();
10595 gen_load_fpr32(ctx, fp0, fs);
10596 gen_load_fpr32(ctx, fp1, ft);
10597 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10598 tcg_temp_free_i32(fp1);
10599 gen_store_fpr32(ctx, fp0, fd);
10600 tcg_temp_free_i32(fp0);
10602 break;
10603 case OPC_MUL_S:
10605 TCGv_i32 fp0 = tcg_temp_new_i32();
10606 TCGv_i32 fp1 = tcg_temp_new_i32();
10608 gen_load_fpr32(ctx, fp0, fs);
10609 gen_load_fpr32(ctx, fp1, ft);
10610 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10611 tcg_temp_free_i32(fp1);
10612 gen_store_fpr32(ctx, fp0, fd);
10613 tcg_temp_free_i32(fp0);
10615 break;
10616 case OPC_DIV_S:
10618 TCGv_i32 fp0 = tcg_temp_new_i32();
10619 TCGv_i32 fp1 = tcg_temp_new_i32();
10621 gen_load_fpr32(ctx, fp0, fs);
10622 gen_load_fpr32(ctx, fp1, ft);
10623 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10624 tcg_temp_free_i32(fp1);
10625 gen_store_fpr32(ctx, fp0, fd);
10626 tcg_temp_free_i32(fp0);
10628 break;
10629 case OPC_SQRT_S:
10631 TCGv_i32 fp0 = tcg_temp_new_i32();
10633 gen_load_fpr32(ctx, fp0, fs);
10634 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10635 gen_store_fpr32(ctx, fp0, fd);
10636 tcg_temp_free_i32(fp0);
10638 break;
10639 case OPC_ABS_S:
10641 TCGv_i32 fp0 = tcg_temp_new_i32();
10643 gen_load_fpr32(ctx, fp0, fs);
10644 if (ctx->abs2008) {
10645 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10646 } else {
10647 gen_helper_float_abs_s(fp0, fp0);
10649 gen_store_fpr32(ctx, fp0, fd);
10650 tcg_temp_free_i32(fp0);
10652 break;
10653 case OPC_MOV_S:
10655 TCGv_i32 fp0 = tcg_temp_new_i32();
10657 gen_load_fpr32(ctx, fp0, fs);
10658 gen_store_fpr32(ctx, fp0, fd);
10659 tcg_temp_free_i32(fp0);
10661 break;
10662 case OPC_NEG_S:
10664 TCGv_i32 fp0 = tcg_temp_new_i32();
10666 gen_load_fpr32(ctx, fp0, fs);
10667 if (ctx->abs2008) {
10668 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10669 } else {
10670 gen_helper_float_chs_s(fp0, fp0);
10672 gen_store_fpr32(ctx, fp0, fd);
10673 tcg_temp_free_i32(fp0);
10675 break;
10676 case OPC_ROUND_L_S:
10677 check_cp1_64bitmode(ctx);
10679 TCGv_i32 fp32 = tcg_temp_new_i32();
10680 TCGv_i64 fp64 = tcg_temp_new_i64();
10682 gen_load_fpr32(ctx, fp32, fs);
10683 if (ctx->nan2008) {
10684 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10685 } else {
10686 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10688 tcg_temp_free_i32(fp32);
10689 gen_store_fpr64(ctx, fp64, fd);
10690 tcg_temp_free_i64(fp64);
10692 break;
10693 case OPC_TRUNC_L_S:
10694 check_cp1_64bitmode(ctx);
10696 TCGv_i32 fp32 = tcg_temp_new_i32();
10697 TCGv_i64 fp64 = tcg_temp_new_i64();
10699 gen_load_fpr32(ctx, fp32, fs);
10700 if (ctx->nan2008) {
10701 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10702 } else {
10703 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10705 tcg_temp_free_i32(fp32);
10706 gen_store_fpr64(ctx, fp64, fd);
10707 tcg_temp_free_i64(fp64);
10709 break;
10710 case OPC_CEIL_L_S:
10711 check_cp1_64bitmode(ctx);
10713 TCGv_i32 fp32 = tcg_temp_new_i32();
10714 TCGv_i64 fp64 = tcg_temp_new_i64();
10716 gen_load_fpr32(ctx, fp32, fs);
10717 if (ctx->nan2008) {
10718 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10719 } else {
10720 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10722 tcg_temp_free_i32(fp32);
10723 gen_store_fpr64(ctx, fp64, fd);
10724 tcg_temp_free_i64(fp64);
10726 break;
10727 case OPC_FLOOR_L_S:
10728 check_cp1_64bitmode(ctx);
10730 TCGv_i32 fp32 = tcg_temp_new_i32();
10731 TCGv_i64 fp64 = tcg_temp_new_i64();
10733 gen_load_fpr32(ctx, fp32, fs);
10734 if (ctx->nan2008) {
10735 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10736 } else {
10737 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10739 tcg_temp_free_i32(fp32);
10740 gen_store_fpr64(ctx, fp64, fd);
10741 tcg_temp_free_i64(fp64);
10743 break;
10744 case OPC_ROUND_W_S:
10746 TCGv_i32 fp0 = tcg_temp_new_i32();
10748 gen_load_fpr32(ctx, fp0, fs);
10749 if (ctx->nan2008) {
10750 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10751 } else {
10752 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10754 gen_store_fpr32(ctx, fp0, fd);
10755 tcg_temp_free_i32(fp0);
10757 break;
10758 case OPC_TRUNC_W_S:
10760 TCGv_i32 fp0 = tcg_temp_new_i32();
10762 gen_load_fpr32(ctx, fp0, fs);
10763 if (ctx->nan2008) {
10764 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10765 } else {
10766 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10768 gen_store_fpr32(ctx, fp0, fd);
10769 tcg_temp_free_i32(fp0);
10771 break;
10772 case OPC_CEIL_W_S:
10774 TCGv_i32 fp0 = tcg_temp_new_i32();
10776 gen_load_fpr32(ctx, fp0, fs);
10777 if (ctx->nan2008) {
10778 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10779 } else {
10780 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10782 gen_store_fpr32(ctx, fp0, fd);
10783 tcg_temp_free_i32(fp0);
10785 break;
10786 case OPC_FLOOR_W_S:
10788 TCGv_i32 fp0 = tcg_temp_new_i32();
10790 gen_load_fpr32(ctx, fp0, fs);
10791 if (ctx->nan2008) {
10792 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10793 } else {
10794 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10796 gen_store_fpr32(ctx, fp0, fd);
10797 tcg_temp_free_i32(fp0);
10799 break;
10800 case OPC_SEL_S:
10801 check_insn(ctx, ISA_MIPS32R6);
10802 gen_sel_s(ctx, op1, fd, ft, fs);
10803 break;
10804 case OPC_SELEQZ_S:
10805 check_insn(ctx, ISA_MIPS32R6);
10806 gen_sel_s(ctx, op1, fd, ft, fs);
10807 break;
10808 case OPC_SELNEZ_S:
10809 check_insn(ctx, ISA_MIPS32R6);
10810 gen_sel_s(ctx, op1, fd, ft, fs);
10811 break;
10812 case OPC_MOVCF_S:
10813 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10814 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10815 break;
10816 case OPC_MOVZ_S:
10817 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10819 TCGLabel *l1 = gen_new_label();
10820 TCGv_i32 fp0;
10822 if (ft != 0) {
10823 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10825 fp0 = tcg_temp_new_i32();
10826 gen_load_fpr32(ctx, fp0, fs);
10827 gen_store_fpr32(ctx, fp0, fd);
10828 tcg_temp_free_i32(fp0);
10829 gen_set_label(l1);
10831 break;
10832 case OPC_MOVN_S:
10833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10835 TCGLabel *l1 = gen_new_label();
10836 TCGv_i32 fp0;
10838 if (ft != 0) {
10839 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10840 fp0 = tcg_temp_new_i32();
10841 gen_load_fpr32(ctx, fp0, fs);
10842 gen_store_fpr32(ctx, fp0, fd);
10843 tcg_temp_free_i32(fp0);
10844 gen_set_label(l1);
10847 break;
10848 case OPC_RECIP_S:
10850 TCGv_i32 fp0 = tcg_temp_new_i32();
10852 gen_load_fpr32(ctx, fp0, fs);
10853 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10854 gen_store_fpr32(ctx, fp0, fd);
10855 tcg_temp_free_i32(fp0);
10857 break;
10858 case OPC_RSQRT_S:
10860 TCGv_i32 fp0 = tcg_temp_new_i32();
10862 gen_load_fpr32(ctx, fp0, fs);
10863 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10864 gen_store_fpr32(ctx, fp0, fd);
10865 tcg_temp_free_i32(fp0);
10867 break;
10868 case OPC_MADDF_S:
10869 check_insn(ctx, ISA_MIPS32R6);
10871 TCGv_i32 fp0 = tcg_temp_new_i32();
10872 TCGv_i32 fp1 = tcg_temp_new_i32();
10873 TCGv_i32 fp2 = tcg_temp_new_i32();
10874 gen_load_fpr32(ctx, fp0, fs);
10875 gen_load_fpr32(ctx, fp1, ft);
10876 gen_load_fpr32(ctx, fp2, fd);
10877 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10878 gen_store_fpr32(ctx, fp2, fd);
10879 tcg_temp_free_i32(fp2);
10880 tcg_temp_free_i32(fp1);
10881 tcg_temp_free_i32(fp0);
10883 break;
10884 case OPC_MSUBF_S:
10885 check_insn(ctx, ISA_MIPS32R6);
10887 TCGv_i32 fp0 = tcg_temp_new_i32();
10888 TCGv_i32 fp1 = tcg_temp_new_i32();
10889 TCGv_i32 fp2 = tcg_temp_new_i32();
10890 gen_load_fpr32(ctx, fp0, fs);
10891 gen_load_fpr32(ctx, fp1, ft);
10892 gen_load_fpr32(ctx, fp2, fd);
10893 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10894 gen_store_fpr32(ctx, fp2, fd);
10895 tcg_temp_free_i32(fp2);
10896 tcg_temp_free_i32(fp1);
10897 tcg_temp_free_i32(fp0);
10899 break;
10900 case OPC_RINT_S:
10901 check_insn(ctx, ISA_MIPS32R6);
10903 TCGv_i32 fp0 = tcg_temp_new_i32();
10904 gen_load_fpr32(ctx, fp0, fs);
10905 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10906 gen_store_fpr32(ctx, fp0, fd);
10907 tcg_temp_free_i32(fp0);
10909 break;
10910 case OPC_CLASS_S:
10911 check_insn(ctx, ISA_MIPS32R6);
10913 TCGv_i32 fp0 = tcg_temp_new_i32();
10914 gen_load_fpr32(ctx, fp0, fs);
10915 gen_helper_float_class_s(fp0, cpu_env, fp0);
10916 gen_store_fpr32(ctx, fp0, fd);
10917 tcg_temp_free_i32(fp0);
10919 break;
10920 case OPC_MIN_S: /* OPC_RECIP2_S */
10921 if (ctx->insn_flags & ISA_MIPS32R6) {
10922 /* OPC_MIN_S */
10923 TCGv_i32 fp0 = tcg_temp_new_i32();
10924 TCGv_i32 fp1 = tcg_temp_new_i32();
10925 TCGv_i32 fp2 = tcg_temp_new_i32();
10926 gen_load_fpr32(ctx, fp0, fs);
10927 gen_load_fpr32(ctx, fp1, ft);
10928 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10929 gen_store_fpr32(ctx, fp2, fd);
10930 tcg_temp_free_i32(fp2);
10931 tcg_temp_free_i32(fp1);
10932 tcg_temp_free_i32(fp0);
10933 } else {
10934 /* OPC_RECIP2_S */
10935 check_cp1_64bitmode(ctx);
10937 TCGv_i32 fp0 = tcg_temp_new_i32();
10938 TCGv_i32 fp1 = tcg_temp_new_i32();
10940 gen_load_fpr32(ctx, fp0, fs);
10941 gen_load_fpr32(ctx, fp1, ft);
10942 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10943 tcg_temp_free_i32(fp1);
10944 gen_store_fpr32(ctx, fp0, fd);
10945 tcg_temp_free_i32(fp0);
10948 break;
10949 case OPC_MINA_S: /* OPC_RECIP1_S */
10950 if (ctx->insn_flags & ISA_MIPS32R6) {
10951 /* OPC_MINA_S */
10952 TCGv_i32 fp0 = tcg_temp_new_i32();
10953 TCGv_i32 fp1 = tcg_temp_new_i32();
10954 TCGv_i32 fp2 = tcg_temp_new_i32();
10955 gen_load_fpr32(ctx, fp0, fs);
10956 gen_load_fpr32(ctx, fp1, ft);
10957 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10958 gen_store_fpr32(ctx, fp2, fd);
10959 tcg_temp_free_i32(fp2);
10960 tcg_temp_free_i32(fp1);
10961 tcg_temp_free_i32(fp0);
10962 } else {
10963 /* OPC_RECIP1_S */
10964 check_cp1_64bitmode(ctx);
10966 TCGv_i32 fp0 = tcg_temp_new_i32();
10968 gen_load_fpr32(ctx, fp0, fs);
10969 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10970 gen_store_fpr32(ctx, fp0, fd);
10971 tcg_temp_free_i32(fp0);
10974 break;
10975 case OPC_MAX_S: /* OPC_RSQRT1_S */
10976 if (ctx->insn_flags & ISA_MIPS32R6) {
10977 /* OPC_MAX_S */
10978 TCGv_i32 fp0 = tcg_temp_new_i32();
10979 TCGv_i32 fp1 = tcg_temp_new_i32();
10980 gen_load_fpr32(ctx, fp0, fs);
10981 gen_load_fpr32(ctx, fp1, ft);
10982 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10983 gen_store_fpr32(ctx, fp1, fd);
10984 tcg_temp_free_i32(fp1);
10985 tcg_temp_free_i32(fp0);
10986 } else {
10987 /* OPC_RSQRT1_S */
10988 check_cp1_64bitmode(ctx);
10990 TCGv_i32 fp0 = tcg_temp_new_i32();
10992 gen_load_fpr32(ctx, fp0, fs);
10993 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10994 gen_store_fpr32(ctx, fp0, fd);
10995 tcg_temp_free_i32(fp0);
10998 break;
10999 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11000 if (ctx->insn_flags & ISA_MIPS32R6) {
11001 /* OPC_MAXA_S */
11002 TCGv_i32 fp0 = tcg_temp_new_i32();
11003 TCGv_i32 fp1 = tcg_temp_new_i32();
11004 gen_load_fpr32(ctx, fp0, fs);
11005 gen_load_fpr32(ctx, fp1, ft);
11006 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11007 gen_store_fpr32(ctx, fp1, fd);
11008 tcg_temp_free_i32(fp1);
11009 tcg_temp_free_i32(fp0);
11010 } else {
11011 /* OPC_RSQRT2_S */
11012 check_cp1_64bitmode(ctx);
11014 TCGv_i32 fp0 = tcg_temp_new_i32();
11015 TCGv_i32 fp1 = tcg_temp_new_i32();
11017 gen_load_fpr32(ctx, fp0, fs);
11018 gen_load_fpr32(ctx, fp1, ft);
11019 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
11020 tcg_temp_free_i32(fp1);
11021 gen_store_fpr32(ctx, fp0, fd);
11022 tcg_temp_free_i32(fp0);
11025 break;
11026 case OPC_CVT_D_S:
11027 check_cp1_registers(ctx, fd);
11029 TCGv_i32 fp32 = tcg_temp_new_i32();
11030 TCGv_i64 fp64 = tcg_temp_new_i64();
11032 gen_load_fpr32(ctx, fp32, fs);
11033 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11034 tcg_temp_free_i32(fp32);
11035 gen_store_fpr64(ctx, fp64, fd);
11036 tcg_temp_free_i64(fp64);
11038 break;
11039 case OPC_CVT_W_S:
11041 TCGv_i32 fp0 = tcg_temp_new_i32();
11043 gen_load_fpr32(ctx, fp0, fs);
11044 if (ctx->nan2008) {
11045 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11046 } else {
11047 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11049 gen_store_fpr32(ctx, fp0, fd);
11050 tcg_temp_free_i32(fp0);
11052 break;
11053 case OPC_CVT_L_S:
11054 check_cp1_64bitmode(ctx);
11056 TCGv_i32 fp32 = tcg_temp_new_i32();
11057 TCGv_i64 fp64 = tcg_temp_new_i64();
11059 gen_load_fpr32(ctx, fp32, fs);
11060 if (ctx->nan2008) {
11061 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11062 } else {
11063 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11065 tcg_temp_free_i32(fp32);
11066 gen_store_fpr64(ctx, fp64, fd);
11067 tcg_temp_free_i64(fp64);
11069 break;
11070 case OPC_CVT_PS_S:
11071 check_ps(ctx);
11073 TCGv_i64 fp64 = tcg_temp_new_i64();
11074 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11075 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11077 gen_load_fpr32(ctx, fp32_0, fs);
11078 gen_load_fpr32(ctx, fp32_1, ft);
11079 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11080 tcg_temp_free_i32(fp32_1);
11081 tcg_temp_free_i32(fp32_0);
11082 gen_store_fpr64(ctx, fp64, fd);
11083 tcg_temp_free_i64(fp64);
11085 break;
11086 case OPC_CMP_F_S:
11087 case OPC_CMP_UN_S:
11088 case OPC_CMP_EQ_S:
11089 case OPC_CMP_UEQ_S:
11090 case OPC_CMP_OLT_S:
11091 case OPC_CMP_ULT_S:
11092 case OPC_CMP_OLE_S:
11093 case OPC_CMP_ULE_S:
11094 case OPC_CMP_SF_S:
11095 case OPC_CMP_NGLE_S:
11096 case OPC_CMP_SEQ_S:
11097 case OPC_CMP_NGL_S:
11098 case OPC_CMP_LT_S:
11099 case OPC_CMP_NGE_S:
11100 case OPC_CMP_LE_S:
11101 case OPC_CMP_NGT_S:
11102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11103 if (ctx->opcode & (1 << 6)) {
11104 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11105 } else {
11106 gen_cmp_s(ctx, func-48, ft, fs, cc);
11108 break;
11109 case OPC_ADD_D:
11110 check_cp1_registers(ctx, fs | ft | fd);
11112 TCGv_i64 fp0 = tcg_temp_new_i64();
11113 TCGv_i64 fp1 = tcg_temp_new_i64();
11115 gen_load_fpr64(ctx, fp0, fs);
11116 gen_load_fpr64(ctx, fp1, ft);
11117 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11118 tcg_temp_free_i64(fp1);
11119 gen_store_fpr64(ctx, fp0, fd);
11120 tcg_temp_free_i64(fp0);
11122 break;
11123 case OPC_SUB_D:
11124 check_cp1_registers(ctx, fs | ft | fd);
11126 TCGv_i64 fp0 = tcg_temp_new_i64();
11127 TCGv_i64 fp1 = tcg_temp_new_i64();
11129 gen_load_fpr64(ctx, fp0, fs);
11130 gen_load_fpr64(ctx, fp1, ft);
11131 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11132 tcg_temp_free_i64(fp1);
11133 gen_store_fpr64(ctx, fp0, fd);
11134 tcg_temp_free_i64(fp0);
11136 break;
11137 case OPC_MUL_D:
11138 check_cp1_registers(ctx, fs | ft | fd);
11140 TCGv_i64 fp0 = tcg_temp_new_i64();
11141 TCGv_i64 fp1 = tcg_temp_new_i64();
11143 gen_load_fpr64(ctx, fp0, fs);
11144 gen_load_fpr64(ctx, fp1, ft);
11145 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11146 tcg_temp_free_i64(fp1);
11147 gen_store_fpr64(ctx, fp0, fd);
11148 tcg_temp_free_i64(fp0);
11150 break;
11151 case OPC_DIV_D:
11152 check_cp1_registers(ctx, fs | ft | fd);
11154 TCGv_i64 fp0 = tcg_temp_new_i64();
11155 TCGv_i64 fp1 = tcg_temp_new_i64();
11157 gen_load_fpr64(ctx, fp0, fs);
11158 gen_load_fpr64(ctx, fp1, ft);
11159 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11160 tcg_temp_free_i64(fp1);
11161 gen_store_fpr64(ctx, fp0, fd);
11162 tcg_temp_free_i64(fp0);
11164 break;
11165 case OPC_SQRT_D:
11166 check_cp1_registers(ctx, fs | fd);
11168 TCGv_i64 fp0 = tcg_temp_new_i64();
11170 gen_load_fpr64(ctx, fp0, fs);
11171 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11172 gen_store_fpr64(ctx, fp0, fd);
11173 tcg_temp_free_i64(fp0);
11175 break;
11176 case OPC_ABS_D:
11177 check_cp1_registers(ctx, fs | fd);
11179 TCGv_i64 fp0 = tcg_temp_new_i64();
11181 gen_load_fpr64(ctx, fp0, fs);
11182 if (ctx->abs2008) {
11183 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11184 } else {
11185 gen_helper_float_abs_d(fp0, fp0);
11187 gen_store_fpr64(ctx, fp0, fd);
11188 tcg_temp_free_i64(fp0);
11190 break;
11191 case OPC_MOV_D:
11192 check_cp1_registers(ctx, fs | fd);
11194 TCGv_i64 fp0 = tcg_temp_new_i64();
11196 gen_load_fpr64(ctx, fp0, fs);
11197 gen_store_fpr64(ctx, fp0, fd);
11198 tcg_temp_free_i64(fp0);
11200 break;
11201 case OPC_NEG_D:
11202 check_cp1_registers(ctx, fs | fd);
11204 TCGv_i64 fp0 = tcg_temp_new_i64();
11206 gen_load_fpr64(ctx, fp0, fs);
11207 if (ctx->abs2008) {
11208 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11209 } else {
11210 gen_helper_float_chs_d(fp0, fp0);
11212 gen_store_fpr64(ctx, fp0, fd);
11213 tcg_temp_free_i64(fp0);
11215 break;
11216 case OPC_ROUND_L_D:
11217 check_cp1_64bitmode(ctx);
11219 TCGv_i64 fp0 = tcg_temp_new_i64();
11221 gen_load_fpr64(ctx, fp0, fs);
11222 if (ctx->nan2008) {
11223 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11224 } else {
11225 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11227 gen_store_fpr64(ctx, fp0, fd);
11228 tcg_temp_free_i64(fp0);
11230 break;
11231 case OPC_TRUNC_L_D:
11232 check_cp1_64bitmode(ctx);
11234 TCGv_i64 fp0 = tcg_temp_new_i64();
11236 gen_load_fpr64(ctx, fp0, fs);
11237 if (ctx->nan2008) {
11238 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11239 } else {
11240 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11242 gen_store_fpr64(ctx, fp0, fd);
11243 tcg_temp_free_i64(fp0);
11245 break;
11246 case OPC_CEIL_L_D:
11247 check_cp1_64bitmode(ctx);
11249 TCGv_i64 fp0 = tcg_temp_new_i64();
11251 gen_load_fpr64(ctx, fp0, fs);
11252 if (ctx->nan2008) {
11253 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11254 } else {
11255 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11257 gen_store_fpr64(ctx, fp0, fd);
11258 tcg_temp_free_i64(fp0);
11260 break;
11261 case OPC_FLOOR_L_D:
11262 check_cp1_64bitmode(ctx);
11264 TCGv_i64 fp0 = tcg_temp_new_i64();
11266 gen_load_fpr64(ctx, fp0, fs);
11267 if (ctx->nan2008) {
11268 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11269 } else {
11270 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11272 gen_store_fpr64(ctx, fp0, fd);
11273 tcg_temp_free_i64(fp0);
11275 break;
11276 case OPC_ROUND_W_D:
11277 check_cp1_registers(ctx, fs);
11279 TCGv_i32 fp32 = tcg_temp_new_i32();
11280 TCGv_i64 fp64 = tcg_temp_new_i64();
11282 gen_load_fpr64(ctx, fp64, fs);
11283 if (ctx->nan2008) {
11284 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11285 } else {
11286 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11288 tcg_temp_free_i64(fp64);
11289 gen_store_fpr32(ctx, fp32, fd);
11290 tcg_temp_free_i32(fp32);
11292 break;
11293 case OPC_TRUNC_W_D:
11294 check_cp1_registers(ctx, fs);
11296 TCGv_i32 fp32 = tcg_temp_new_i32();
11297 TCGv_i64 fp64 = tcg_temp_new_i64();
11299 gen_load_fpr64(ctx, fp64, fs);
11300 if (ctx->nan2008) {
11301 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11302 } else {
11303 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11305 tcg_temp_free_i64(fp64);
11306 gen_store_fpr32(ctx, fp32, fd);
11307 tcg_temp_free_i32(fp32);
11309 break;
11310 case OPC_CEIL_W_D:
11311 check_cp1_registers(ctx, fs);
11313 TCGv_i32 fp32 = tcg_temp_new_i32();
11314 TCGv_i64 fp64 = tcg_temp_new_i64();
11316 gen_load_fpr64(ctx, fp64, fs);
11317 if (ctx->nan2008) {
11318 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11319 } else {
11320 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11322 tcg_temp_free_i64(fp64);
11323 gen_store_fpr32(ctx, fp32, fd);
11324 tcg_temp_free_i32(fp32);
11326 break;
11327 case OPC_FLOOR_W_D:
11328 check_cp1_registers(ctx, fs);
11330 TCGv_i32 fp32 = tcg_temp_new_i32();
11331 TCGv_i64 fp64 = tcg_temp_new_i64();
11333 gen_load_fpr64(ctx, fp64, fs);
11334 if (ctx->nan2008) {
11335 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11336 } else {
11337 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11339 tcg_temp_free_i64(fp64);
11340 gen_store_fpr32(ctx, fp32, fd);
11341 tcg_temp_free_i32(fp32);
11343 break;
11344 case OPC_SEL_D:
11345 check_insn(ctx, ISA_MIPS32R6);
11346 gen_sel_d(ctx, op1, fd, ft, fs);
11347 break;
11348 case OPC_SELEQZ_D:
11349 check_insn(ctx, ISA_MIPS32R6);
11350 gen_sel_d(ctx, op1, fd, ft, fs);
11351 break;
11352 case OPC_SELNEZ_D:
11353 check_insn(ctx, ISA_MIPS32R6);
11354 gen_sel_d(ctx, op1, fd, ft, fs);
11355 break;
11356 case OPC_MOVCF_D:
11357 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11358 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11359 break;
11360 case OPC_MOVZ_D:
11361 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11363 TCGLabel *l1 = gen_new_label();
11364 TCGv_i64 fp0;
11366 if (ft != 0) {
11367 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11369 fp0 = tcg_temp_new_i64();
11370 gen_load_fpr64(ctx, fp0, fs);
11371 gen_store_fpr64(ctx, fp0, fd);
11372 tcg_temp_free_i64(fp0);
11373 gen_set_label(l1);
11375 break;
11376 case OPC_MOVN_D:
11377 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11379 TCGLabel *l1 = gen_new_label();
11380 TCGv_i64 fp0;
11382 if (ft != 0) {
11383 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11384 fp0 = tcg_temp_new_i64();
11385 gen_load_fpr64(ctx, fp0, fs);
11386 gen_store_fpr64(ctx, fp0, fd);
11387 tcg_temp_free_i64(fp0);
11388 gen_set_label(l1);
11391 break;
11392 case OPC_RECIP_D:
11393 check_cp1_registers(ctx, fs | fd);
11395 TCGv_i64 fp0 = tcg_temp_new_i64();
11397 gen_load_fpr64(ctx, fp0, fs);
11398 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11399 gen_store_fpr64(ctx, fp0, fd);
11400 tcg_temp_free_i64(fp0);
11402 break;
11403 case OPC_RSQRT_D:
11404 check_cp1_registers(ctx, fs | fd);
11406 TCGv_i64 fp0 = tcg_temp_new_i64();
11408 gen_load_fpr64(ctx, fp0, fs);
11409 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11410 gen_store_fpr64(ctx, fp0, fd);
11411 tcg_temp_free_i64(fp0);
11413 break;
11414 case OPC_MADDF_D:
11415 check_insn(ctx, ISA_MIPS32R6);
11417 TCGv_i64 fp0 = tcg_temp_new_i64();
11418 TCGv_i64 fp1 = tcg_temp_new_i64();
11419 TCGv_i64 fp2 = tcg_temp_new_i64();
11420 gen_load_fpr64(ctx, fp0, fs);
11421 gen_load_fpr64(ctx, fp1, ft);
11422 gen_load_fpr64(ctx, fp2, fd);
11423 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11424 gen_store_fpr64(ctx, fp2, fd);
11425 tcg_temp_free_i64(fp2);
11426 tcg_temp_free_i64(fp1);
11427 tcg_temp_free_i64(fp0);
11429 break;
11430 case OPC_MSUBF_D:
11431 check_insn(ctx, ISA_MIPS32R6);
11433 TCGv_i64 fp0 = tcg_temp_new_i64();
11434 TCGv_i64 fp1 = tcg_temp_new_i64();
11435 TCGv_i64 fp2 = tcg_temp_new_i64();
11436 gen_load_fpr64(ctx, fp0, fs);
11437 gen_load_fpr64(ctx, fp1, ft);
11438 gen_load_fpr64(ctx, fp2, fd);
11439 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11440 gen_store_fpr64(ctx, fp2, fd);
11441 tcg_temp_free_i64(fp2);
11442 tcg_temp_free_i64(fp1);
11443 tcg_temp_free_i64(fp0);
11445 break;
11446 case OPC_RINT_D:
11447 check_insn(ctx, ISA_MIPS32R6);
11449 TCGv_i64 fp0 = tcg_temp_new_i64();
11450 gen_load_fpr64(ctx, fp0, fs);
11451 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11452 gen_store_fpr64(ctx, fp0, fd);
11453 tcg_temp_free_i64(fp0);
11455 break;
11456 case OPC_CLASS_D:
11457 check_insn(ctx, ISA_MIPS32R6);
11459 TCGv_i64 fp0 = tcg_temp_new_i64();
11460 gen_load_fpr64(ctx, fp0, fs);
11461 gen_helper_float_class_d(fp0, cpu_env, fp0);
11462 gen_store_fpr64(ctx, fp0, fd);
11463 tcg_temp_free_i64(fp0);
11465 break;
11466 case OPC_MIN_D: /* OPC_RECIP2_D */
11467 if (ctx->insn_flags & ISA_MIPS32R6) {
11468 /* OPC_MIN_D */
11469 TCGv_i64 fp0 = tcg_temp_new_i64();
11470 TCGv_i64 fp1 = tcg_temp_new_i64();
11471 gen_load_fpr64(ctx, fp0, fs);
11472 gen_load_fpr64(ctx, fp1, ft);
11473 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11474 gen_store_fpr64(ctx, fp1, fd);
11475 tcg_temp_free_i64(fp1);
11476 tcg_temp_free_i64(fp0);
11477 } else {
11478 /* OPC_RECIP2_D */
11479 check_cp1_64bitmode(ctx);
11481 TCGv_i64 fp0 = tcg_temp_new_i64();
11482 TCGv_i64 fp1 = tcg_temp_new_i64();
11484 gen_load_fpr64(ctx, fp0, fs);
11485 gen_load_fpr64(ctx, fp1, ft);
11486 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11487 tcg_temp_free_i64(fp1);
11488 gen_store_fpr64(ctx, fp0, fd);
11489 tcg_temp_free_i64(fp0);
11492 break;
11493 case OPC_MINA_D: /* OPC_RECIP1_D */
11494 if (ctx->insn_flags & ISA_MIPS32R6) {
11495 /* OPC_MINA_D */
11496 TCGv_i64 fp0 = tcg_temp_new_i64();
11497 TCGv_i64 fp1 = tcg_temp_new_i64();
11498 gen_load_fpr64(ctx, fp0, fs);
11499 gen_load_fpr64(ctx, fp1, ft);
11500 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11501 gen_store_fpr64(ctx, fp1, fd);
11502 tcg_temp_free_i64(fp1);
11503 tcg_temp_free_i64(fp0);
11504 } else {
11505 /* OPC_RECIP1_D */
11506 check_cp1_64bitmode(ctx);
11508 TCGv_i64 fp0 = tcg_temp_new_i64();
11510 gen_load_fpr64(ctx, fp0, fs);
11511 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11512 gen_store_fpr64(ctx, fp0, fd);
11513 tcg_temp_free_i64(fp0);
11516 break;
11517 case OPC_MAX_D: /* OPC_RSQRT1_D */
11518 if (ctx->insn_flags & ISA_MIPS32R6) {
11519 /* OPC_MAX_D */
11520 TCGv_i64 fp0 = tcg_temp_new_i64();
11521 TCGv_i64 fp1 = tcg_temp_new_i64();
11522 gen_load_fpr64(ctx, fp0, fs);
11523 gen_load_fpr64(ctx, fp1, ft);
11524 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11525 gen_store_fpr64(ctx, fp1, fd);
11526 tcg_temp_free_i64(fp1);
11527 tcg_temp_free_i64(fp0);
11528 } else {
11529 /* OPC_RSQRT1_D */
11530 check_cp1_64bitmode(ctx);
11532 TCGv_i64 fp0 = tcg_temp_new_i64();
11534 gen_load_fpr64(ctx, fp0, fs);
11535 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11536 gen_store_fpr64(ctx, fp0, fd);
11537 tcg_temp_free_i64(fp0);
11540 break;
11541 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11542 if (ctx->insn_flags & ISA_MIPS32R6) {
11543 /* OPC_MAXA_D */
11544 TCGv_i64 fp0 = tcg_temp_new_i64();
11545 TCGv_i64 fp1 = tcg_temp_new_i64();
11546 gen_load_fpr64(ctx, fp0, fs);
11547 gen_load_fpr64(ctx, fp1, ft);
11548 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11549 gen_store_fpr64(ctx, fp1, fd);
11550 tcg_temp_free_i64(fp1);
11551 tcg_temp_free_i64(fp0);
11552 } else {
11553 /* OPC_RSQRT2_D */
11554 check_cp1_64bitmode(ctx);
11556 TCGv_i64 fp0 = tcg_temp_new_i64();
11557 TCGv_i64 fp1 = tcg_temp_new_i64();
11559 gen_load_fpr64(ctx, fp0, fs);
11560 gen_load_fpr64(ctx, fp1, ft);
11561 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11562 tcg_temp_free_i64(fp1);
11563 gen_store_fpr64(ctx, fp0, fd);
11564 tcg_temp_free_i64(fp0);
11567 break;
11568 case OPC_CMP_F_D:
11569 case OPC_CMP_UN_D:
11570 case OPC_CMP_EQ_D:
11571 case OPC_CMP_UEQ_D:
11572 case OPC_CMP_OLT_D:
11573 case OPC_CMP_ULT_D:
11574 case OPC_CMP_OLE_D:
11575 case OPC_CMP_ULE_D:
11576 case OPC_CMP_SF_D:
11577 case OPC_CMP_NGLE_D:
11578 case OPC_CMP_SEQ_D:
11579 case OPC_CMP_NGL_D:
11580 case OPC_CMP_LT_D:
11581 case OPC_CMP_NGE_D:
11582 case OPC_CMP_LE_D:
11583 case OPC_CMP_NGT_D:
11584 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11585 if (ctx->opcode & (1 << 6)) {
11586 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11587 } else {
11588 gen_cmp_d(ctx, func-48, ft, fs, cc);
11590 break;
11591 case OPC_CVT_S_D:
11592 check_cp1_registers(ctx, fs);
11594 TCGv_i32 fp32 = tcg_temp_new_i32();
11595 TCGv_i64 fp64 = tcg_temp_new_i64();
11597 gen_load_fpr64(ctx, fp64, fs);
11598 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11599 tcg_temp_free_i64(fp64);
11600 gen_store_fpr32(ctx, fp32, fd);
11601 tcg_temp_free_i32(fp32);
11603 break;
11604 case OPC_CVT_W_D:
11605 check_cp1_registers(ctx, fs);
11607 TCGv_i32 fp32 = tcg_temp_new_i32();
11608 TCGv_i64 fp64 = tcg_temp_new_i64();
11610 gen_load_fpr64(ctx, fp64, fs);
11611 if (ctx->nan2008) {
11612 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11613 } else {
11614 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11616 tcg_temp_free_i64(fp64);
11617 gen_store_fpr32(ctx, fp32, fd);
11618 tcg_temp_free_i32(fp32);
11620 break;
11621 case OPC_CVT_L_D:
11622 check_cp1_64bitmode(ctx);
11624 TCGv_i64 fp0 = tcg_temp_new_i64();
11626 gen_load_fpr64(ctx, fp0, fs);
11627 if (ctx->nan2008) {
11628 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11629 } else {
11630 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11632 gen_store_fpr64(ctx, fp0, fd);
11633 tcg_temp_free_i64(fp0);
11635 break;
11636 case OPC_CVT_S_W:
11638 TCGv_i32 fp0 = tcg_temp_new_i32();
11640 gen_load_fpr32(ctx, fp0, fs);
11641 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11642 gen_store_fpr32(ctx, fp0, fd);
11643 tcg_temp_free_i32(fp0);
11645 break;
11646 case OPC_CVT_D_W:
11647 check_cp1_registers(ctx, fd);
11649 TCGv_i32 fp32 = tcg_temp_new_i32();
11650 TCGv_i64 fp64 = tcg_temp_new_i64();
11652 gen_load_fpr32(ctx, fp32, fs);
11653 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11654 tcg_temp_free_i32(fp32);
11655 gen_store_fpr64(ctx, fp64, fd);
11656 tcg_temp_free_i64(fp64);
11658 break;
11659 case OPC_CVT_S_L:
11660 check_cp1_64bitmode(ctx);
11662 TCGv_i32 fp32 = tcg_temp_new_i32();
11663 TCGv_i64 fp64 = tcg_temp_new_i64();
11665 gen_load_fpr64(ctx, fp64, fs);
11666 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11667 tcg_temp_free_i64(fp64);
11668 gen_store_fpr32(ctx, fp32, fd);
11669 tcg_temp_free_i32(fp32);
11671 break;
11672 case OPC_CVT_D_L:
11673 check_cp1_64bitmode(ctx);
11675 TCGv_i64 fp0 = tcg_temp_new_i64();
11677 gen_load_fpr64(ctx, fp0, fs);
11678 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11679 gen_store_fpr64(ctx, fp0, fd);
11680 tcg_temp_free_i64(fp0);
11682 break;
11683 case OPC_CVT_PS_PW:
11684 check_ps(ctx);
11686 TCGv_i64 fp0 = tcg_temp_new_i64();
11688 gen_load_fpr64(ctx, fp0, fs);
11689 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11690 gen_store_fpr64(ctx, fp0, fd);
11691 tcg_temp_free_i64(fp0);
11693 break;
11694 case OPC_ADD_PS:
11695 check_ps(ctx);
11697 TCGv_i64 fp0 = tcg_temp_new_i64();
11698 TCGv_i64 fp1 = tcg_temp_new_i64();
11700 gen_load_fpr64(ctx, fp0, fs);
11701 gen_load_fpr64(ctx, fp1, ft);
11702 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11703 tcg_temp_free_i64(fp1);
11704 gen_store_fpr64(ctx, fp0, fd);
11705 tcg_temp_free_i64(fp0);
11707 break;
11708 case OPC_SUB_PS:
11709 check_ps(ctx);
11711 TCGv_i64 fp0 = tcg_temp_new_i64();
11712 TCGv_i64 fp1 = tcg_temp_new_i64();
11714 gen_load_fpr64(ctx, fp0, fs);
11715 gen_load_fpr64(ctx, fp1, ft);
11716 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11717 tcg_temp_free_i64(fp1);
11718 gen_store_fpr64(ctx, fp0, fd);
11719 tcg_temp_free_i64(fp0);
11721 break;
11722 case OPC_MUL_PS:
11723 check_ps(ctx);
11725 TCGv_i64 fp0 = tcg_temp_new_i64();
11726 TCGv_i64 fp1 = tcg_temp_new_i64();
11728 gen_load_fpr64(ctx, fp0, fs);
11729 gen_load_fpr64(ctx, fp1, ft);
11730 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11731 tcg_temp_free_i64(fp1);
11732 gen_store_fpr64(ctx, fp0, fd);
11733 tcg_temp_free_i64(fp0);
11735 break;
11736 case OPC_ABS_PS:
11737 check_ps(ctx);
11739 TCGv_i64 fp0 = tcg_temp_new_i64();
11741 gen_load_fpr64(ctx, fp0, fs);
11742 gen_helper_float_abs_ps(fp0, fp0);
11743 gen_store_fpr64(ctx, fp0, fd);
11744 tcg_temp_free_i64(fp0);
11746 break;
11747 case OPC_MOV_PS:
11748 check_ps(ctx);
11750 TCGv_i64 fp0 = tcg_temp_new_i64();
11752 gen_load_fpr64(ctx, fp0, fs);
11753 gen_store_fpr64(ctx, fp0, fd);
11754 tcg_temp_free_i64(fp0);
11756 break;
11757 case OPC_NEG_PS:
11758 check_ps(ctx);
11760 TCGv_i64 fp0 = tcg_temp_new_i64();
11762 gen_load_fpr64(ctx, fp0, fs);
11763 gen_helper_float_chs_ps(fp0, fp0);
11764 gen_store_fpr64(ctx, fp0, fd);
11765 tcg_temp_free_i64(fp0);
11767 break;
11768 case OPC_MOVCF_PS:
11769 check_ps(ctx);
11770 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11771 break;
11772 case OPC_MOVZ_PS:
11773 check_ps(ctx);
11775 TCGLabel *l1 = gen_new_label();
11776 TCGv_i64 fp0;
11778 if (ft != 0)
11779 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11780 fp0 = tcg_temp_new_i64();
11781 gen_load_fpr64(ctx, fp0, fs);
11782 gen_store_fpr64(ctx, fp0, fd);
11783 tcg_temp_free_i64(fp0);
11784 gen_set_label(l1);
11786 break;
11787 case OPC_MOVN_PS:
11788 check_ps(ctx);
11790 TCGLabel *l1 = gen_new_label();
11791 TCGv_i64 fp0;
11793 if (ft != 0) {
11794 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11795 fp0 = tcg_temp_new_i64();
11796 gen_load_fpr64(ctx, fp0, fs);
11797 gen_store_fpr64(ctx, fp0, fd);
11798 tcg_temp_free_i64(fp0);
11799 gen_set_label(l1);
11802 break;
11803 case OPC_ADDR_PS:
11804 check_ps(ctx);
11806 TCGv_i64 fp0 = tcg_temp_new_i64();
11807 TCGv_i64 fp1 = tcg_temp_new_i64();
11809 gen_load_fpr64(ctx, fp0, ft);
11810 gen_load_fpr64(ctx, fp1, fs);
11811 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11812 tcg_temp_free_i64(fp1);
11813 gen_store_fpr64(ctx, fp0, fd);
11814 tcg_temp_free_i64(fp0);
11816 break;
11817 case OPC_MULR_PS:
11818 check_ps(ctx);
11820 TCGv_i64 fp0 = tcg_temp_new_i64();
11821 TCGv_i64 fp1 = tcg_temp_new_i64();
11823 gen_load_fpr64(ctx, fp0, ft);
11824 gen_load_fpr64(ctx, fp1, fs);
11825 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11826 tcg_temp_free_i64(fp1);
11827 gen_store_fpr64(ctx, fp0, fd);
11828 tcg_temp_free_i64(fp0);
11830 break;
11831 case OPC_RECIP2_PS:
11832 check_ps(ctx);
11834 TCGv_i64 fp0 = tcg_temp_new_i64();
11835 TCGv_i64 fp1 = tcg_temp_new_i64();
11837 gen_load_fpr64(ctx, fp0, fs);
11838 gen_load_fpr64(ctx, fp1, ft);
11839 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11840 tcg_temp_free_i64(fp1);
11841 gen_store_fpr64(ctx, fp0, fd);
11842 tcg_temp_free_i64(fp0);
11844 break;
11845 case OPC_RECIP1_PS:
11846 check_ps(ctx);
11848 TCGv_i64 fp0 = tcg_temp_new_i64();
11850 gen_load_fpr64(ctx, fp0, fs);
11851 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11852 gen_store_fpr64(ctx, fp0, fd);
11853 tcg_temp_free_i64(fp0);
11855 break;
11856 case OPC_RSQRT1_PS:
11857 check_ps(ctx);
11859 TCGv_i64 fp0 = tcg_temp_new_i64();
11861 gen_load_fpr64(ctx, fp0, fs);
11862 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11863 gen_store_fpr64(ctx, fp0, fd);
11864 tcg_temp_free_i64(fp0);
11866 break;
11867 case OPC_RSQRT2_PS:
11868 check_ps(ctx);
11870 TCGv_i64 fp0 = tcg_temp_new_i64();
11871 TCGv_i64 fp1 = tcg_temp_new_i64();
11873 gen_load_fpr64(ctx, fp0, fs);
11874 gen_load_fpr64(ctx, fp1, ft);
11875 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11876 tcg_temp_free_i64(fp1);
11877 gen_store_fpr64(ctx, fp0, fd);
11878 tcg_temp_free_i64(fp0);
11880 break;
11881 case OPC_CVT_S_PU:
11882 check_cp1_64bitmode(ctx);
11884 TCGv_i32 fp0 = tcg_temp_new_i32();
11886 gen_load_fpr32h(ctx, fp0, fs);
11887 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11888 gen_store_fpr32(ctx, fp0, fd);
11889 tcg_temp_free_i32(fp0);
11891 break;
11892 case OPC_CVT_PW_PS:
11893 check_ps(ctx);
11895 TCGv_i64 fp0 = tcg_temp_new_i64();
11897 gen_load_fpr64(ctx, fp0, fs);
11898 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11899 gen_store_fpr64(ctx, fp0, fd);
11900 tcg_temp_free_i64(fp0);
11902 break;
11903 case OPC_CVT_S_PL:
11904 check_cp1_64bitmode(ctx);
11906 TCGv_i32 fp0 = tcg_temp_new_i32();
11908 gen_load_fpr32(ctx, fp0, fs);
11909 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11910 gen_store_fpr32(ctx, fp0, fd);
11911 tcg_temp_free_i32(fp0);
11913 break;
11914 case OPC_PLL_PS:
11915 check_ps(ctx);
11917 TCGv_i32 fp0 = tcg_temp_new_i32();
11918 TCGv_i32 fp1 = tcg_temp_new_i32();
11920 gen_load_fpr32(ctx, fp0, fs);
11921 gen_load_fpr32(ctx, fp1, ft);
11922 gen_store_fpr32h(ctx, fp0, fd);
11923 gen_store_fpr32(ctx, fp1, fd);
11924 tcg_temp_free_i32(fp0);
11925 tcg_temp_free_i32(fp1);
11927 break;
11928 case OPC_PLU_PS:
11929 check_ps(ctx);
11931 TCGv_i32 fp0 = tcg_temp_new_i32();
11932 TCGv_i32 fp1 = tcg_temp_new_i32();
11934 gen_load_fpr32(ctx, fp0, fs);
11935 gen_load_fpr32h(ctx, fp1, ft);
11936 gen_store_fpr32(ctx, fp1, fd);
11937 gen_store_fpr32h(ctx, fp0, fd);
11938 tcg_temp_free_i32(fp0);
11939 tcg_temp_free_i32(fp1);
11941 break;
11942 case OPC_PUL_PS:
11943 check_ps(ctx);
11945 TCGv_i32 fp0 = tcg_temp_new_i32();
11946 TCGv_i32 fp1 = tcg_temp_new_i32();
11948 gen_load_fpr32h(ctx, fp0, fs);
11949 gen_load_fpr32(ctx, fp1, ft);
11950 gen_store_fpr32(ctx, fp1, fd);
11951 gen_store_fpr32h(ctx, fp0, fd);
11952 tcg_temp_free_i32(fp0);
11953 tcg_temp_free_i32(fp1);
11955 break;
11956 case OPC_PUU_PS:
11957 check_ps(ctx);
11959 TCGv_i32 fp0 = tcg_temp_new_i32();
11960 TCGv_i32 fp1 = tcg_temp_new_i32();
11962 gen_load_fpr32h(ctx, fp0, fs);
11963 gen_load_fpr32h(ctx, fp1, ft);
11964 gen_store_fpr32(ctx, fp1, fd);
11965 gen_store_fpr32h(ctx, fp0, fd);
11966 tcg_temp_free_i32(fp0);
11967 tcg_temp_free_i32(fp1);
11969 break;
11970 case OPC_CMP_F_PS:
11971 case OPC_CMP_UN_PS:
11972 case OPC_CMP_EQ_PS:
11973 case OPC_CMP_UEQ_PS:
11974 case OPC_CMP_OLT_PS:
11975 case OPC_CMP_ULT_PS:
11976 case OPC_CMP_OLE_PS:
11977 case OPC_CMP_ULE_PS:
11978 case OPC_CMP_SF_PS:
11979 case OPC_CMP_NGLE_PS:
11980 case OPC_CMP_SEQ_PS:
11981 case OPC_CMP_NGL_PS:
11982 case OPC_CMP_LT_PS:
11983 case OPC_CMP_NGE_PS:
11984 case OPC_CMP_LE_PS:
11985 case OPC_CMP_NGT_PS:
11986 if (ctx->opcode & (1 << 6)) {
11987 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
11988 } else {
11989 gen_cmp_ps(ctx, func-48, ft, fs, cc);
11991 break;
11992 default:
11993 MIPS_INVAL("farith");
11994 generate_exception_end(ctx, EXCP_RI);
11995 return;
11999 /* Coprocessor 3 (FPU) */
12000 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
12001 int fd, int fs, int base, int index)
12003 TCGv t0 = tcg_temp_new();
12005 if (base == 0) {
12006 gen_load_gpr(t0, index);
12007 } else if (index == 0) {
12008 gen_load_gpr(t0, base);
12009 } else {
12010 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12012 /* Don't do NOP if destination is zero: we must perform the actual
12013 memory access. */
12014 switch (opc) {
12015 case OPC_LWXC1:
12016 check_cop1x(ctx);
12018 TCGv_i32 fp0 = tcg_temp_new_i32();
12020 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12021 tcg_gen_trunc_tl_i32(fp0, t0);
12022 gen_store_fpr32(ctx, fp0, fd);
12023 tcg_temp_free_i32(fp0);
12025 break;
12026 case OPC_LDXC1:
12027 check_cop1x(ctx);
12028 check_cp1_registers(ctx, fd);
12030 TCGv_i64 fp0 = tcg_temp_new_i64();
12031 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12032 gen_store_fpr64(ctx, fp0, fd);
12033 tcg_temp_free_i64(fp0);
12035 break;
12036 case OPC_LUXC1:
12037 check_cp1_64bitmode(ctx);
12038 tcg_gen_andi_tl(t0, t0, ~0x7);
12040 TCGv_i64 fp0 = tcg_temp_new_i64();
12042 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12043 gen_store_fpr64(ctx, fp0, fd);
12044 tcg_temp_free_i64(fp0);
12046 break;
12047 case OPC_SWXC1:
12048 check_cop1x(ctx);
12050 TCGv_i32 fp0 = tcg_temp_new_i32();
12051 gen_load_fpr32(ctx, fp0, fs);
12052 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12053 tcg_temp_free_i32(fp0);
12055 break;
12056 case OPC_SDXC1:
12057 check_cop1x(ctx);
12058 check_cp1_registers(ctx, fs);
12060 TCGv_i64 fp0 = tcg_temp_new_i64();
12061 gen_load_fpr64(ctx, fp0, fs);
12062 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12063 tcg_temp_free_i64(fp0);
12065 break;
12066 case OPC_SUXC1:
12067 check_cp1_64bitmode(ctx);
12068 tcg_gen_andi_tl(t0, t0, ~0x7);
12070 TCGv_i64 fp0 = tcg_temp_new_i64();
12071 gen_load_fpr64(ctx, fp0, fs);
12072 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12073 tcg_temp_free_i64(fp0);
12075 break;
12077 tcg_temp_free(t0);
12080 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12081 int fd, int fr, int fs, int ft)
12083 switch (opc) {
12084 case OPC_ALNV_PS:
12085 check_ps(ctx);
12087 TCGv t0 = tcg_temp_local_new();
12088 TCGv_i32 fp = tcg_temp_new_i32();
12089 TCGv_i32 fph = tcg_temp_new_i32();
12090 TCGLabel *l1 = gen_new_label();
12091 TCGLabel *l2 = gen_new_label();
12093 gen_load_gpr(t0, fr);
12094 tcg_gen_andi_tl(t0, t0, 0x7);
12096 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12097 gen_load_fpr32(ctx, fp, fs);
12098 gen_load_fpr32h(ctx, fph, fs);
12099 gen_store_fpr32(ctx, fp, fd);
12100 gen_store_fpr32h(ctx, fph, fd);
12101 tcg_gen_br(l2);
12102 gen_set_label(l1);
12103 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12104 tcg_temp_free(t0);
12105 #ifdef TARGET_WORDS_BIGENDIAN
12106 gen_load_fpr32(ctx, fp, fs);
12107 gen_load_fpr32h(ctx, fph, ft);
12108 gen_store_fpr32h(ctx, fp, fd);
12109 gen_store_fpr32(ctx, fph, fd);
12110 #else
12111 gen_load_fpr32h(ctx, fph, fs);
12112 gen_load_fpr32(ctx, fp, ft);
12113 gen_store_fpr32(ctx, fph, fd);
12114 gen_store_fpr32h(ctx, fp, fd);
12115 #endif
12116 gen_set_label(l2);
12117 tcg_temp_free_i32(fp);
12118 tcg_temp_free_i32(fph);
12120 break;
12121 case OPC_MADD_S:
12122 check_cop1x(ctx);
12124 TCGv_i32 fp0 = tcg_temp_new_i32();
12125 TCGv_i32 fp1 = tcg_temp_new_i32();
12126 TCGv_i32 fp2 = tcg_temp_new_i32();
12128 gen_load_fpr32(ctx, fp0, fs);
12129 gen_load_fpr32(ctx, fp1, ft);
12130 gen_load_fpr32(ctx, fp2, fr);
12131 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12132 tcg_temp_free_i32(fp0);
12133 tcg_temp_free_i32(fp1);
12134 gen_store_fpr32(ctx, fp2, fd);
12135 tcg_temp_free_i32(fp2);
12137 break;
12138 case OPC_MADD_D:
12139 check_cop1x(ctx);
12140 check_cp1_registers(ctx, fd | fs | ft | fr);
12142 TCGv_i64 fp0 = tcg_temp_new_i64();
12143 TCGv_i64 fp1 = tcg_temp_new_i64();
12144 TCGv_i64 fp2 = tcg_temp_new_i64();
12146 gen_load_fpr64(ctx, fp0, fs);
12147 gen_load_fpr64(ctx, fp1, ft);
12148 gen_load_fpr64(ctx, fp2, fr);
12149 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12150 tcg_temp_free_i64(fp0);
12151 tcg_temp_free_i64(fp1);
12152 gen_store_fpr64(ctx, fp2, fd);
12153 tcg_temp_free_i64(fp2);
12155 break;
12156 case OPC_MADD_PS:
12157 check_ps(ctx);
12159 TCGv_i64 fp0 = tcg_temp_new_i64();
12160 TCGv_i64 fp1 = tcg_temp_new_i64();
12161 TCGv_i64 fp2 = tcg_temp_new_i64();
12163 gen_load_fpr64(ctx, fp0, fs);
12164 gen_load_fpr64(ctx, fp1, ft);
12165 gen_load_fpr64(ctx, fp2, fr);
12166 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12167 tcg_temp_free_i64(fp0);
12168 tcg_temp_free_i64(fp1);
12169 gen_store_fpr64(ctx, fp2, fd);
12170 tcg_temp_free_i64(fp2);
12172 break;
12173 case OPC_MSUB_S:
12174 check_cop1x(ctx);
12176 TCGv_i32 fp0 = tcg_temp_new_i32();
12177 TCGv_i32 fp1 = tcg_temp_new_i32();
12178 TCGv_i32 fp2 = tcg_temp_new_i32();
12180 gen_load_fpr32(ctx, fp0, fs);
12181 gen_load_fpr32(ctx, fp1, ft);
12182 gen_load_fpr32(ctx, fp2, fr);
12183 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12184 tcg_temp_free_i32(fp0);
12185 tcg_temp_free_i32(fp1);
12186 gen_store_fpr32(ctx, fp2, fd);
12187 tcg_temp_free_i32(fp2);
12189 break;
12190 case OPC_MSUB_D:
12191 check_cop1x(ctx);
12192 check_cp1_registers(ctx, fd | fs | ft | fr);
12194 TCGv_i64 fp0 = tcg_temp_new_i64();
12195 TCGv_i64 fp1 = tcg_temp_new_i64();
12196 TCGv_i64 fp2 = tcg_temp_new_i64();
12198 gen_load_fpr64(ctx, fp0, fs);
12199 gen_load_fpr64(ctx, fp1, ft);
12200 gen_load_fpr64(ctx, fp2, fr);
12201 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12202 tcg_temp_free_i64(fp0);
12203 tcg_temp_free_i64(fp1);
12204 gen_store_fpr64(ctx, fp2, fd);
12205 tcg_temp_free_i64(fp2);
12207 break;
12208 case OPC_MSUB_PS:
12209 check_ps(ctx);
12211 TCGv_i64 fp0 = tcg_temp_new_i64();
12212 TCGv_i64 fp1 = tcg_temp_new_i64();
12213 TCGv_i64 fp2 = tcg_temp_new_i64();
12215 gen_load_fpr64(ctx, fp0, fs);
12216 gen_load_fpr64(ctx, fp1, ft);
12217 gen_load_fpr64(ctx, fp2, fr);
12218 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12219 tcg_temp_free_i64(fp0);
12220 tcg_temp_free_i64(fp1);
12221 gen_store_fpr64(ctx, fp2, fd);
12222 tcg_temp_free_i64(fp2);
12224 break;
12225 case OPC_NMADD_S:
12226 check_cop1x(ctx);
12228 TCGv_i32 fp0 = tcg_temp_new_i32();
12229 TCGv_i32 fp1 = tcg_temp_new_i32();
12230 TCGv_i32 fp2 = tcg_temp_new_i32();
12232 gen_load_fpr32(ctx, fp0, fs);
12233 gen_load_fpr32(ctx, fp1, ft);
12234 gen_load_fpr32(ctx, fp2, fr);
12235 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12236 tcg_temp_free_i32(fp0);
12237 tcg_temp_free_i32(fp1);
12238 gen_store_fpr32(ctx, fp2, fd);
12239 tcg_temp_free_i32(fp2);
12241 break;
12242 case OPC_NMADD_D:
12243 check_cop1x(ctx);
12244 check_cp1_registers(ctx, fd | fs | ft | fr);
12246 TCGv_i64 fp0 = tcg_temp_new_i64();
12247 TCGv_i64 fp1 = tcg_temp_new_i64();
12248 TCGv_i64 fp2 = tcg_temp_new_i64();
12250 gen_load_fpr64(ctx, fp0, fs);
12251 gen_load_fpr64(ctx, fp1, ft);
12252 gen_load_fpr64(ctx, fp2, fr);
12253 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12254 tcg_temp_free_i64(fp0);
12255 tcg_temp_free_i64(fp1);
12256 gen_store_fpr64(ctx, fp2, fd);
12257 tcg_temp_free_i64(fp2);
12259 break;
12260 case OPC_NMADD_PS:
12261 check_ps(ctx);
12263 TCGv_i64 fp0 = tcg_temp_new_i64();
12264 TCGv_i64 fp1 = tcg_temp_new_i64();
12265 TCGv_i64 fp2 = tcg_temp_new_i64();
12267 gen_load_fpr64(ctx, fp0, fs);
12268 gen_load_fpr64(ctx, fp1, ft);
12269 gen_load_fpr64(ctx, fp2, fr);
12270 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12271 tcg_temp_free_i64(fp0);
12272 tcg_temp_free_i64(fp1);
12273 gen_store_fpr64(ctx, fp2, fd);
12274 tcg_temp_free_i64(fp2);
12276 break;
12277 case OPC_NMSUB_S:
12278 check_cop1x(ctx);
12280 TCGv_i32 fp0 = tcg_temp_new_i32();
12281 TCGv_i32 fp1 = tcg_temp_new_i32();
12282 TCGv_i32 fp2 = tcg_temp_new_i32();
12284 gen_load_fpr32(ctx, fp0, fs);
12285 gen_load_fpr32(ctx, fp1, ft);
12286 gen_load_fpr32(ctx, fp2, fr);
12287 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12288 tcg_temp_free_i32(fp0);
12289 tcg_temp_free_i32(fp1);
12290 gen_store_fpr32(ctx, fp2, fd);
12291 tcg_temp_free_i32(fp2);
12293 break;
12294 case OPC_NMSUB_D:
12295 check_cop1x(ctx);
12296 check_cp1_registers(ctx, fd | fs | ft | fr);
12298 TCGv_i64 fp0 = tcg_temp_new_i64();
12299 TCGv_i64 fp1 = tcg_temp_new_i64();
12300 TCGv_i64 fp2 = tcg_temp_new_i64();
12302 gen_load_fpr64(ctx, fp0, fs);
12303 gen_load_fpr64(ctx, fp1, ft);
12304 gen_load_fpr64(ctx, fp2, fr);
12305 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12306 tcg_temp_free_i64(fp0);
12307 tcg_temp_free_i64(fp1);
12308 gen_store_fpr64(ctx, fp2, fd);
12309 tcg_temp_free_i64(fp2);
12311 break;
12312 case OPC_NMSUB_PS:
12313 check_ps(ctx);
12315 TCGv_i64 fp0 = tcg_temp_new_i64();
12316 TCGv_i64 fp1 = tcg_temp_new_i64();
12317 TCGv_i64 fp2 = tcg_temp_new_i64();
12319 gen_load_fpr64(ctx, fp0, fs);
12320 gen_load_fpr64(ctx, fp1, ft);
12321 gen_load_fpr64(ctx, fp2, fr);
12322 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12323 tcg_temp_free_i64(fp0);
12324 tcg_temp_free_i64(fp1);
12325 gen_store_fpr64(ctx, fp2, fd);
12326 tcg_temp_free_i64(fp2);
12328 break;
12329 default:
12330 MIPS_INVAL("flt3_arith");
12331 generate_exception_end(ctx, EXCP_RI);
12332 return;
12336 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12338 TCGv t0;
12340 #if !defined(CONFIG_USER_ONLY)
12341 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12342 Therefore only check the ISA in system mode. */
12343 check_insn(ctx, ISA_MIPS32R2);
12344 #endif
12345 t0 = tcg_temp_new();
12347 switch (rd) {
12348 case 0:
12349 gen_helper_rdhwr_cpunum(t0, cpu_env);
12350 gen_store_gpr(t0, rt);
12351 break;
12352 case 1:
12353 gen_helper_rdhwr_synci_step(t0, cpu_env);
12354 gen_store_gpr(t0, rt);
12355 break;
12356 case 2:
12357 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12358 gen_io_start();
12360 gen_helper_rdhwr_cc(t0, cpu_env);
12361 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12362 gen_io_end();
12364 gen_store_gpr(t0, rt);
12365 /* Break the TB to be able to take timer interrupts immediately
12366 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12367 we break completely out of translated code. */
12368 gen_save_pc(ctx->base.pc_next + 4);
12369 ctx->base.is_jmp = DISAS_EXIT;
12370 break;
12371 case 3:
12372 gen_helper_rdhwr_ccres(t0, cpu_env);
12373 gen_store_gpr(t0, rt);
12374 break;
12375 case 4:
12376 check_insn(ctx, ISA_MIPS32R6);
12377 if (sel != 0) {
12378 /* Performance counter registers are not implemented other than
12379 * control register 0.
12381 generate_exception(ctx, EXCP_RI);
12383 gen_helper_rdhwr_performance(t0, cpu_env);
12384 gen_store_gpr(t0, rt);
12385 break;
12386 case 5:
12387 check_insn(ctx, ISA_MIPS32R6);
12388 gen_helper_rdhwr_xnp(t0, cpu_env);
12389 gen_store_gpr(t0, rt);
12390 break;
12391 case 29:
12392 #if defined(CONFIG_USER_ONLY)
12393 tcg_gen_ld_tl(t0, cpu_env,
12394 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12395 gen_store_gpr(t0, rt);
12396 break;
12397 #else
12398 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12399 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12400 tcg_gen_ld_tl(t0, cpu_env,
12401 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12402 gen_store_gpr(t0, rt);
12403 } else {
12404 generate_exception_end(ctx, EXCP_RI);
12406 break;
12407 #endif
12408 default: /* Invalid */
12409 MIPS_INVAL("rdhwr");
12410 generate_exception_end(ctx, EXCP_RI);
12411 break;
12413 tcg_temp_free(t0);
12416 static inline void clear_branch_hflags(DisasContext *ctx)
12418 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12419 if (ctx->base.is_jmp == DISAS_NEXT) {
12420 save_cpu_state(ctx, 0);
12421 } else {
12422 /* it is not safe to save ctx->hflags as hflags may be changed
12423 in execution time by the instruction in delay / forbidden slot. */
12424 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12428 static void gen_branch(DisasContext *ctx, int insn_bytes)
12430 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12431 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12432 /* Branches completion */
12433 clear_branch_hflags(ctx);
12434 ctx->base.is_jmp = DISAS_NORETURN;
12435 /* FIXME: Need to clear can_do_io. */
12436 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12437 case MIPS_HFLAG_FBNSLOT:
12438 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12439 break;
12440 case MIPS_HFLAG_B:
12441 /* unconditional branch */
12442 if (proc_hflags & MIPS_HFLAG_BX) {
12443 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12445 gen_goto_tb(ctx, 0, ctx->btarget);
12446 break;
12447 case MIPS_HFLAG_BL:
12448 /* blikely taken case */
12449 gen_goto_tb(ctx, 0, ctx->btarget);
12450 break;
12451 case MIPS_HFLAG_BC:
12452 /* Conditional branch */
12454 TCGLabel *l1 = gen_new_label();
12456 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12457 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12458 gen_set_label(l1);
12459 gen_goto_tb(ctx, 0, ctx->btarget);
12461 break;
12462 case MIPS_HFLAG_BR:
12463 /* unconditional branch to register */
12464 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12465 TCGv t0 = tcg_temp_new();
12466 TCGv_i32 t1 = tcg_temp_new_i32();
12468 tcg_gen_andi_tl(t0, btarget, 0x1);
12469 tcg_gen_trunc_tl_i32(t1, t0);
12470 tcg_temp_free(t0);
12471 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12472 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12473 tcg_gen_or_i32(hflags, hflags, t1);
12474 tcg_temp_free_i32(t1);
12476 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12477 } else {
12478 tcg_gen_mov_tl(cpu_PC, btarget);
12480 if (ctx->base.singlestep_enabled) {
12481 save_cpu_state(ctx, 0);
12482 gen_helper_raise_exception_debug(cpu_env);
12484 tcg_gen_lookup_and_goto_ptr();
12485 break;
12486 default:
12487 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12488 abort();
12493 /* Compact Branches */
12494 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12495 int rs, int rt, int32_t offset)
12497 int bcond_compute = 0;
12498 TCGv t0 = tcg_temp_new();
12499 TCGv t1 = tcg_temp_new();
12500 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12502 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12503 #ifdef MIPS_DEBUG_DISAS
12504 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12505 "\n", ctx->base.pc_next);
12506 #endif
12507 generate_exception_end(ctx, EXCP_RI);
12508 goto out;
12511 /* Load needed operands and calculate btarget */
12512 switch (opc) {
12513 /* compact branch */
12514 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12515 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12516 gen_load_gpr(t0, rs);
12517 gen_load_gpr(t1, rt);
12518 bcond_compute = 1;
12519 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12520 if (rs <= rt && rs == 0) {
12521 /* OPC_BEQZALC, OPC_BNEZALC */
12522 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12524 break;
12525 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12526 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12527 gen_load_gpr(t0, rs);
12528 gen_load_gpr(t1, rt);
12529 bcond_compute = 1;
12530 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12531 break;
12532 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12533 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12534 if (rs == 0 || rs == rt) {
12535 /* OPC_BLEZALC, OPC_BGEZALC */
12536 /* OPC_BGTZALC, OPC_BLTZALC */
12537 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12539 gen_load_gpr(t0, rs);
12540 gen_load_gpr(t1, rt);
12541 bcond_compute = 1;
12542 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12543 break;
12544 case OPC_BC:
12545 case OPC_BALC:
12546 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12547 break;
12548 case OPC_BEQZC:
12549 case OPC_BNEZC:
12550 if (rs != 0) {
12551 /* OPC_BEQZC, OPC_BNEZC */
12552 gen_load_gpr(t0, rs);
12553 bcond_compute = 1;
12554 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12555 } else {
12556 /* OPC_JIC, OPC_JIALC */
12557 TCGv tbase = tcg_temp_new();
12558 TCGv toffset = tcg_temp_new();
12560 gen_load_gpr(tbase, rt);
12561 tcg_gen_movi_tl(toffset, offset);
12562 gen_op_addr_add(ctx, btarget, tbase, toffset);
12563 tcg_temp_free(tbase);
12564 tcg_temp_free(toffset);
12566 break;
12567 default:
12568 MIPS_INVAL("Compact branch/jump");
12569 generate_exception_end(ctx, EXCP_RI);
12570 goto out;
12573 if (bcond_compute == 0) {
12574 /* Uncoditional compact branch */
12575 switch (opc) {
12576 case OPC_JIALC:
12577 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12578 /* Fallthrough */
12579 case OPC_JIC:
12580 ctx->hflags |= MIPS_HFLAG_BR;
12581 break;
12582 case OPC_BALC:
12583 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12584 /* Fallthrough */
12585 case OPC_BC:
12586 ctx->hflags |= MIPS_HFLAG_B;
12587 break;
12588 default:
12589 MIPS_INVAL("Compact branch/jump");
12590 generate_exception_end(ctx, EXCP_RI);
12591 goto out;
12594 /* Generating branch here as compact branches don't have delay slot */
12595 gen_branch(ctx, 4);
12596 } else {
12597 /* Conditional compact branch */
12598 TCGLabel *fs = gen_new_label();
12599 save_cpu_state(ctx, 0);
12601 switch (opc) {
12602 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12603 if (rs == 0 && rt != 0) {
12604 /* OPC_BLEZALC */
12605 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12606 } else if (rs != 0 && rt != 0 && rs == rt) {
12607 /* OPC_BGEZALC */
12608 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12609 } else {
12610 /* OPC_BGEUC */
12611 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12613 break;
12614 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12615 if (rs == 0 && rt != 0) {
12616 /* OPC_BGTZALC */
12617 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12618 } else if (rs != 0 && rt != 0 && rs == rt) {
12619 /* OPC_BLTZALC */
12620 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12621 } else {
12622 /* OPC_BLTUC */
12623 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12625 break;
12626 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12627 if (rs == 0 && rt != 0) {
12628 /* OPC_BLEZC */
12629 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12630 } else if (rs != 0 && rt != 0 && rs == rt) {
12631 /* OPC_BGEZC */
12632 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12633 } else {
12634 /* OPC_BGEC */
12635 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12637 break;
12638 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12639 if (rs == 0 && rt != 0) {
12640 /* OPC_BGTZC */
12641 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12642 } else if (rs != 0 && rt != 0 && rs == rt) {
12643 /* OPC_BLTZC */
12644 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12645 } else {
12646 /* OPC_BLTC */
12647 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12649 break;
12650 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12651 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12652 if (rs >= rt) {
12653 /* OPC_BOVC, OPC_BNVC */
12654 TCGv t2 = tcg_temp_new();
12655 TCGv t3 = tcg_temp_new();
12656 TCGv t4 = tcg_temp_new();
12657 TCGv input_overflow = tcg_temp_new();
12659 gen_load_gpr(t0, rs);
12660 gen_load_gpr(t1, rt);
12661 tcg_gen_ext32s_tl(t2, t0);
12662 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12663 tcg_gen_ext32s_tl(t3, t1);
12664 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12665 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12667 tcg_gen_add_tl(t4, t2, t3);
12668 tcg_gen_ext32s_tl(t4, t4);
12669 tcg_gen_xor_tl(t2, t2, t3);
12670 tcg_gen_xor_tl(t3, t4, t3);
12671 tcg_gen_andc_tl(t2, t3, t2);
12672 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12673 tcg_gen_or_tl(t4, t4, input_overflow);
12674 if (opc == OPC_BOVC) {
12675 /* OPC_BOVC */
12676 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12677 } else {
12678 /* OPC_BNVC */
12679 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12681 tcg_temp_free(input_overflow);
12682 tcg_temp_free(t4);
12683 tcg_temp_free(t3);
12684 tcg_temp_free(t2);
12685 } else if (rs < rt && rs == 0) {
12686 /* OPC_BEQZALC, OPC_BNEZALC */
12687 if (opc == OPC_BEQZALC) {
12688 /* OPC_BEQZALC */
12689 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12690 } else {
12691 /* OPC_BNEZALC */
12692 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12694 } else {
12695 /* OPC_BEQC, OPC_BNEC */
12696 if (opc == OPC_BEQC) {
12697 /* OPC_BEQC */
12698 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12699 } else {
12700 /* OPC_BNEC */
12701 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12704 break;
12705 case OPC_BEQZC:
12706 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12707 break;
12708 case OPC_BNEZC:
12709 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12710 break;
12711 default:
12712 MIPS_INVAL("Compact conditional branch/jump");
12713 generate_exception_end(ctx, EXCP_RI);
12714 goto out;
12717 /* Generating branch here as compact branches don't have delay slot */
12718 gen_goto_tb(ctx, 1, ctx->btarget);
12719 gen_set_label(fs);
12721 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12724 out:
12725 tcg_temp_free(t0);
12726 tcg_temp_free(t1);
12729 /* ISA extensions (ASEs) */
12730 /* MIPS16 extension to MIPS32 */
12732 /* MIPS16 major opcodes */
12733 enum {
12734 M16_OPC_ADDIUSP = 0x00,
12735 M16_OPC_ADDIUPC = 0x01,
12736 M16_OPC_B = 0x02,
12737 M16_OPC_JAL = 0x03,
12738 M16_OPC_BEQZ = 0x04,
12739 M16_OPC_BNEQZ = 0x05,
12740 M16_OPC_SHIFT = 0x06,
12741 M16_OPC_LD = 0x07,
12742 M16_OPC_RRIA = 0x08,
12743 M16_OPC_ADDIU8 = 0x09,
12744 M16_OPC_SLTI = 0x0a,
12745 M16_OPC_SLTIU = 0x0b,
12746 M16_OPC_I8 = 0x0c,
12747 M16_OPC_LI = 0x0d,
12748 M16_OPC_CMPI = 0x0e,
12749 M16_OPC_SD = 0x0f,
12750 M16_OPC_LB = 0x10,
12751 M16_OPC_LH = 0x11,
12752 M16_OPC_LWSP = 0x12,
12753 M16_OPC_LW = 0x13,
12754 M16_OPC_LBU = 0x14,
12755 M16_OPC_LHU = 0x15,
12756 M16_OPC_LWPC = 0x16,
12757 M16_OPC_LWU = 0x17,
12758 M16_OPC_SB = 0x18,
12759 M16_OPC_SH = 0x19,
12760 M16_OPC_SWSP = 0x1a,
12761 M16_OPC_SW = 0x1b,
12762 M16_OPC_RRR = 0x1c,
12763 M16_OPC_RR = 0x1d,
12764 M16_OPC_EXTEND = 0x1e,
12765 M16_OPC_I64 = 0x1f
12768 /* I8 funct field */
12769 enum {
12770 I8_BTEQZ = 0x0,
12771 I8_BTNEZ = 0x1,
12772 I8_SWRASP = 0x2,
12773 I8_ADJSP = 0x3,
12774 I8_SVRS = 0x4,
12775 I8_MOV32R = 0x5,
12776 I8_MOVR32 = 0x7
12779 /* RRR f field */
12780 enum {
12781 RRR_DADDU = 0x0,
12782 RRR_ADDU = 0x1,
12783 RRR_DSUBU = 0x2,
12784 RRR_SUBU = 0x3
12787 /* RR funct field */
12788 enum {
12789 RR_JR = 0x00,
12790 RR_SDBBP = 0x01,
12791 RR_SLT = 0x02,
12792 RR_SLTU = 0x03,
12793 RR_SLLV = 0x04,
12794 RR_BREAK = 0x05,
12795 RR_SRLV = 0x06,
12796 RR_SRAV = 0x07,
12797 RR_DSRL = 0x08,
12798 RR_CMP = 0x0a,
12799 RR_NEG = 0x0b,
12800 RR_AND = 0x0c,
12801 RR_OR = 0x0d,
12802 RR_XOR = 0x0e,
12803 RR_NOT = 0x0f,
12804 RR_MFHI = 0x10,
12805 RR_CNVT = 0x11,
12806 RR_MFLO = 0x12,
12807 RR_DSRA = 0x13,
12808 RR_DSLLV = 0x14,
12809 RR_DSRLV = 0x16,
12810 RR_DSRAV = 0x17,
12811 RR_MULT = 0x18,
12812 RR_MULTU = 0x19,
12813 RR_DIV = 0x1a,
12814 RR_DIVU = 0x1b,
12815 RR_DMULT = 0x1c,
12816 RR_DMULTU = 0x1d,
12817 RR_DDIV = 0x1e,
12818 RR_DDIVU = 0x1f
12821 /* I64 funct field */
12822 enum {
12823 I64_LDSP = 0x0,
12824 I64_SDSP = 0x1,
12825 I64_SDRASP = 0x2,
12826 I64_DADJSP = 0x3,
12827 I64_LDPC = 0x4,
12828 I64_DADDIU5 = 0x5,
12829 I64_DADDIUPC = 0x6,
12830 I64_DADDIUSP = 0x7
12833 /* RR ry field for CNVT */
12834 enum {
12835 RR_RY_CNVT_ZEB = 0x0,
12836 RR_RY_CNVT_ZEH = 0x1,
12837 RR_RY_CNVT_ZEW = 0x2,
12838 RR_RY_CNVT_SEB = 0x4,
12839 RR_RY_CNVT_SEH = 0x5,
12840 RR_RY_CNVT_SEW = 0x6,
12843 static int xlat (int r)
12845 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12847 return map[r];
12850 static void gen_mips16_save (DisasContext *ctx,
12851 int xsregs, int aregs,
12852 int do_ra, int do_s0, int do_s1,
12853 int framesize)
12855 TCGv t0 = tcg_temp_new();
12856 TCGv t1 = tcg_temp_new();
12857 TCGv t2 = tcg_temp_new();
12858 int args, astatic;
12860 switch (aregs) {
12861 case 0:
12862 case 1:
12863 case 2:
12864 case 3:
12865 case 11:
12866 args = 0;
12867 break;
12868 case 4:
12869 case 5:
12870 case 6:
12871 case 7:
12872 args = 1;
12873 break;
12874 case 8:
12875 case 9:
12876 case 10:
12877 args = 2;
12878 break;
12879 case 12:
12880 case 13:
12881 args = 3;
12882 break;
12883 case 14:
12884 args = 4;
12885 break;
12886 default:
12887 generate_exception_end(ctx, EXCP_RI);
12888 return;
12891 switch (args) {
12892 case 4:
12893 gen_base_offset_addr(ctx, t0, 29, 12);
12894 gen_load_gpr(t1, 7);
12895 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12896 /* Fall through */
12897 case 3:
12898 gen_base_offset_addr(ctx, t0, 29, 8);
12899 gen_load_gpr(t1, 6);
12900 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12901 /* Fall through */
12902 case 2:
12903 gen_base_offset_addr(ctx, t0, 29, 4);
12904 gen_load_gpr(t1, 5);
12905 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12906 /* Fall through */
12907 case 1:
12908 gen_base_offset_addr(ctx, t0, 29, 0);
12909 gen_load_gpr(t1, 4);
12910 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12913 gen_load_gpr(t0, 29);
12915 #define DECR_AND_STORE(reg) do { \
12916 tcg_gen_movi_tl(t2, -4); \
12917 gen_op_addr_add(ctx, t0, t0, t2); \
12918 gen_load_gpr(t1, reg); \
12919 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12920 } while (0)
12922 if (do_ra) {
12923 DECR_AND_STORE(31);
12926 switch (xsregs) {
12927 case 7:
12928 DECR_AND_STORE(30);
12929 /* Fall through */
12930 case 6:
12931 DECR_AND_STORE(23);
12932 /* Fall through */
12933 case 5:
12934 DECR_AND_STORE(22);
12935 /* Fall through */
12936 case 4:
12937 DECR_AND_STORE(21);
12938 /* Fall through */
12939 case 3:
12940 DECR_AND_STORE(20);
12941 /* Fall through */
12942 case 2:
12943 DECR_AND_STORE(19);
12944 /* Fall through */
12945 case 1:
12946 DECR_AND_STORE(18);
12949 if (do_s1) {
12950 DECR_AND_STORE(17);
12952 if (do_s0) {
12953 DECR_AND_STORE(16);
12956 switch (aregs) {
12957 case 0:
12958 case 4:
12959 case 8:
12960 case 12:
12961 case 14:
12962 astatic = 0;
12963 break;
12964 case 1:
12965 case 5:
12966 case 9:
12967 case 13:
12968 astatic = 1;
12969 break;
12970 case 2:
12971 case 6:
12972 case 10:
12973 astatic = 2;
12974 break;
12975 case 3:
12976 case 7:
12977 astatic = 3;
12978 break;
12979 case 11:
12980 astatic = 4;
12981 break;
12982 default:
12983 generate_exception_end(ctx, EXCP_RI);
12984 return;
12987 if (astatic > 0) {
12988 DECR_AND_STORE(7);
12989 if (astatic > 1) {
12990 DECR_AND_STORE(6);
12991 if (astatic > 2) {
12992 DECR_AND_STORE(5);
12993 if (astatic > 3) {
12994 DECR_AND_STORE(4);
12999 #undef DECR_AND_STORE
13001 tcg_gen_movi_tl(t2, -framesize);
13002 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13003 tcg_temp_free(t0);
13004 tcg_temp_free(t1);
13005 tcg_temp_free(t2);
13008 static void gen_mips16_restore (DisasContext *ctx,
13009 int xsregs, int aregs,
13010 int do_ra, int do_s0, int do_s1,
13011 int framesize)
13013 int astatic;
13014 TCGv t0 = tcg_temp_new();
13015 TCGv t1 = tcg_temp_new();
13016 TCGv t2 = tcg_temp_new();
13018 tcg_gen_movi_tl(t2, framesize);
13019 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
13021 #define DECR_AND_LOAD(reg) do { \
13022 tcg_gen_movi_tl(t2, -4); \
13023 gen_op_addr_add(ctx, t0, t0, t2); \
13024 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13025 gen_store_gpr(t1, reg); \
13026 } while (0)
13028 if (do_ra) {
13029 DECR_AND_LOAD(31);
13032 switch (xsregs) {
13033 case 7:
13034 DECR_AND_LOAD(30);
13035 /* Fall through */
13036 case 6:
13037 DECR_AND_LOAD(23);
13038 /* Fall through */
13039 case 5:
13040 DECR_AND_LOAD(22);
13041 /* Fall through */
13042 case 4:
13043 DECR_AND_LOAD(21);
13044 /* Fall through */
13045 case 3:
13046 DECR_AND_LOAD(20);
13047 /* Fall through */
13048 case 2:
13049 DECR_AND_LOAD(19);
13050 /* Fall through */
13051 case 1:
13052 DECR_AND_LOAD(18);
13055 if (do_s1) {
13056 DECR_AND_LOAD(17);
13058 if (do_s0) {
13059 DECR_AND_LOAD(16);
13062 switch (aregs) {
13063 case 0:
13064 case 4:
13065 case 8:
13066 case 12:
13067 case 14:
13068 astatic = 0;
13069 break;
13070 case 1:
13071 case 5:
13072 case 9:
13073 case 13:
13074 astatic = 1;
13075 break;
13076 case 2:
13077 case 6:
13078 case 10:
13079 astatic = 2;
13080 break;
13081 case 3:
13082 case 7:
13083 astatic = 3;
13084 break;
13085 case 11:
13086 astatic = 4;
13087 break;
13088 default:
13089 generate_exception_end(ctx, EXCP_RI);
13090 return;
13093 if (astatic > 0) {
13094 DECR_AND_LOAD(7);
13095 if (astatic > 1) {
13096 DECR_AND_LOAD(6);
13097 if (astatic > 2) {
13098 DECR_AND_LOAD(5);
13099 if (astatic > 3) {
13100 DECR_AND_LOAD(4);
13105 #undef DECR_AND_LOAD
13107 tcg_gen_movi_tl(t2, framesize);
13108 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13109 tcg_temp_free(t0);
13110 tcg_temp_free(t1);
13111 tcg_temp_free(t2);
13114 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13115 int is_64_bit, int extended)
13117 TCGv t0;
13119 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13120 generate_exception_end(ctx, EXCP_RI);
13121 return;
13124 t0 = tcg_temp_new();
13126 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13127 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13128 if (!is_64_bit) {
13129 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13132 tcg_temp_free(t0);
13135 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13136 int16_t offset)
13138 TCGv_i32 t0 = tcg_const_i32(op);
13139 TCGv t1 = tcg_temp_new();
13140 gen_base_offset_addr(ctx, t1, base, offset);
13141 gen_helper_cache(cpu_env, t1, t0);
13144 #if defined(TARGET_MIPS64)
13145 static void decode_i64_mips16 (DisasContext *ctx,
13146 int ry, int funct, int16_t offset,
13147 int extended)
13149 switch (funct) {
13150 case I64_LDSP:
13151 check_insn(ctx, ISA_MIPS3);
13152 check_mips_64(ctx);
13153 offset = extended ? offset : offset << 3;
13154 gen_ld(ctx, OPC_LD, ry, 29, offset);
13155 break;
13156 case I64_SDSP:
13157 check_insn(ctx, ISA_MIPS3);
13158 check_mips_64(ctx);
13159 offset = extended ? offset : offset << 3;
13160 gen_st(ctx, OPC_SD, ry, 29, offset);
13161 break;
13162 case I64_SDRASP:
13163 check_insn(ctx, ISA_MIPS3);
13164 check_mips_64(ctx);
13165 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13166 gen_st(ctx, OPC_SD, 31, 29, offset);
13167 break;
13168 case I64_DADJSP:
13169 check_insn(ctx, ISA_MIPS3);
13170 check_mips_64(ctx);
13171 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13172 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13173 break;
13174 case I64_LDPC:
13175 check_insn(ctx, ISA_MIPS3);
13176 check_mips_64(ctx);
13177 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13178 generate_exception_end(ctx, EXCP_RI);
13179 } else {
13180 offset = extended ? offset : offset << 3;
13181 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13183 break;
13184 case I64_DADDIU5:
13185 check_insn(ctx, ISA_MIPS3);
13186 check_mips_64(ctx);
13187 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13188 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13189 break;
13190 case I64_DADDIUPC:
13191 check_insn(ctx, ISA_MIPS3);
13192 check_mips_64(ctx);
13193 offset = extended ? offset : offset << 2;
13194 gen_addiupc(ctx, ry, offset, 1, extended);
13195 break;
13196 case I64_DADDIUSP:
13197 check_insn(ctx, ISA_MIPS3);
13198 check_mips_64(ctx);
13199 offset = extended ? offset : offset << 2;
13200 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13201 break;
13204 #endif
13206 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13208 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13209 int op, rx, ry, funct, sa;
13210 int16_t imm, offset;
13212 ctx->opcode = (ctx->opcode << 16) | extend;
13213 op = (ctx->opcode >> 11) & 0x1f;
13214 sa = (ctx->opcode >> 22) & 0x1f;
13215 funct = (ctx->opcode >> 8) & 0x7;
13216 rx = xlat((ctx->opcode >> 8) & 0x7);
13217 ry = xlat((ctx->opcode >> 5) & 0x7);
13218 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13219 | ((ctx->opcode >> 21) & 0x3f) << 5
13220 | (ctx->opcode & 0x1f));
13222 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13223 counterparts. */
13224 switch (op) {
13225 case M16_OPC_ADDIUSP:
13226 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13227 break;
13228 case M16_OPC_ADDIUPC:
13229 gen_addiupc(ctx, rx, imm, 0, 1);
13230 break;
13231 case M16_OPC_B:
13232 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13233 /* No delay slot, so just process as a normal instruction */
13234 break;
13235 case M16_OPC_BEQZ:
13236 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13237 /* No delay slot, so just process as a normal instruction */
13238 break;
13239 case M16_OPC_BNEQZ:
13240 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13241 /* No delay slot, so just process as a normal instruction */
13242 break;
13243 case M16_OPC_SHIFT:
13244 switch (ctx->opcode & 0x3) {
13245 case 0x0:
13246 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13247 break;
13248 case 0x1:
13249 #if defined(TARGET_MIPS64)
13250 check_mips_64(ctx);
13251 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13252 #else
13253 generate_exception_end(ctx, EXCP_RI);
13254 #endif
13255 break;
13256 case 0x2:
13257 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13258 break;
13259 case 0x3:
13260 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13261 break;
13263 break;
13264 #if defined(TARGET_MIPS64)
13265 case M16_OPC_LD:
13266 check_insn(ctx, ISA_MIPS3);
13267 check_mips_64(ctx);
13268 gen_ld(ctx, OPC_LD, ry, rx, offset);
13269 break;
13270 #endif
13271 case M16_OPC_RRIA:
13272 imm = ctx->opcode & 0xf;
13273 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13274 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13275 imm = (int16_t) (imm << 1) >> 1;
13276 if ((ctx->opcode >> 4) & 0x1) {
13277 #if defined(TARGET_MIPS64)
13278 check_mips_64(ctx);
13279 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13280 #else
13281 generate_exception_end(ctx, EXCP_RI);
13282 #endif
13283 } else {
13284 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13286 break;
13287 case M16_OPC_ADDIU8:
13288 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13289 break;
13290 case M16_OPC_SLTI:
13291 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13292 break;
13293 case M16_OPC_SLTIU:
13294 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13295 break;
13296 case M16_OPC_I8:
13297 switch (funct) {
13298 case I8_BTEQZ:
13299 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13300 break;
13301 case I8_BTNEZ:
13302 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13303 break;
13304 case I8_SWRASP:
13305 gen_st(ctx, OPC_SW, 31, 29, imm);
13306 break;
13307 case I8_ADJSP:
13308 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13309 break;
13310 case I8_SVRS:
13311 check_insn(ctx, ISA_MIPS32);
13313 int xsregs = (ctx->opcode >> 24) & 0x7;
13314 int aregs = (ctx->opcode >> 16) & 0xf;
13315 int do_ra = (ctx->opcode >> 6) & 0x1;
13316 int do_s0 = (ctx->opcode >> 5) & 0x1;
13317 int do_s1 = (ctx->opcode >> 4) & 0x1;
13318 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13319 | (ctx->opcode & 0xf)) << 3;
13321 if (ctx->opcode & (1 << 7)) {
13322 gen_mips16_save(ctx, xsregs, aregs,
13323 do_ra, do_s0, do_s1,
13324 framesize);
13325 } else {
13326 gen_mips16_restore(ctx, xsregs, aregs,
13327 do_ra, do_s0, do_s1,
13328 framesize);
13331 break;
13332 default:
13333 generate_exception_end(ctx, EXCP_RI);
13334 break;
13336 break;
13337 case M16_OPC_LI:
13338 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13339 break;
13340 case M16_OPC_CMPI:
13341 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13342 break;
13343 #if defined(TARGET_MIPS64)
13344 case M16_OPC_SD:
13345 check_insn(ctx, ISA_MIPS3);
13346 check_mips_64(ctx);
13347 gen_st(ctx, OPC_SD, ry, rx, offset);
13348 break;
13349 #endif
13350 case M16_OPC_LB:
13351 gen_ld(ctx, OPC_LB, ry, rx, offset);
13352 break;
13353 case M16_OPC_LH:
13354 gen_ld(ctx, OPC_LH, ry, rx, offset);
13355 break;
13356 case M16_OPC_LWSP:
13357 gen_ld(ctx, OPC_LW, rx, 29, offset);
13358 break;
13359 case M16_OPC_LW:
13360 gen_ld(ctx, OPC_LW, ry, rx, offset);
13361 break;
13362 case M16_OPC_LBU:
13363 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13364 break;
13365 case M16_OPC_LHU:
13366 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13367 break;
13368 case M16_OPC_LWPC:
13369 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13370 break;
13371 #if defined(TARGET_MIPS64)
13372 case M16_OPC_LWU:
13373 check_insn(ctx, ISA_MIPS3);
13374 check_mips_64(ctx);
13375 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13376 break;
13377 #endif
13378 case M16_OPC_SB:
13379 gen_st(ctx, OPC_SB, ry, rx, offset);
13380 break;
13381 case M16_OPC_SH:
13382 gen_st(ctx, OPC_SH, ry, rx, offset);
13383 break;
13384 case M16_OPC_SWSP:
13385 gen_st(ctx, OPC_SW, rx, 29, offset);
13386 break;
13387 case M16_OPC_SW:
13388 gen_st(ctx, OPC_SW, ry, rx, offset);
13389 break;
13390 #if defined(TARGET_MIPS64)
13391 case M16_OPC_I64:
13392 decode_i64_mips16(ctx, ry, funct, offset, 1);
13393 break;
13394 #endif
13395 default:
13396 generate_exception_end(ctx, EXCP_RI);
13397 break;
13400 return 4;
13403 static inline bool is_uhi(int sdbbp_code)
13405 #ifdef CONFIG_USER_ONLY
13406 return false;
13407 #else
13408 return semihosting_enabled() && sdbbp_code == 1;
13409 #endif
13412 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13414 int rx, ry;
13415 int sa;
13416 int op, cnvt_op, op1, offset;
13417 int funct;
13418 int n_bytes;
13420 op = (ctx->opcode >> 11) & 0x1f;
13421 sa = (ctx->opcode >> 2) & 0x7;
13422 sa = sa == 0 ? 8 : sa;
13423 rx = xlat((ctx->opcode >> 8) & 0x7);
13424 cnvt_op = (ctx->opcode >> 5) & 0x7;
13425 ry = xlat((ctx->opcode >> 5) & 0x7);
13426 op1 = offset = ctx->opcode & 0x1f;
13428 n_bytes = 2;
13430 switch (op) {
13431 case M16_OPC_ADDIUSP:
13433 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13435 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13437 break;
13438 case M16_OPC_ADDIUPC:
13439 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13440 break;
13441 case M16_OPC_B:
13442 offset = (ctx->opcode & 0x7ff) << 1;
13443 offset = (int16_t)(offset << 4) >> 4;
13444 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13445 /* No delay slot, so just process as a normal instruction */
13446 break;
13447 case M16_OPC_JAL:
13448 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13449 offset = (((ctx->opcode & 0x1f) << 21)
13450 | ((ctx->opcode >> 5) & 0x1f) << 16
13451 | offset) << 2;
13452 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13453 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13454 n_bytes = 4;
13455 break;
13456 case M16_OPC_BEQZ:
13457 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13458 ((int8_t)ctx->opcode) << 1, 0);
13459 /* No delay slot, so just process as a normal instruction */
13460 break;
13461 case M16_OPC_BNEQZ:
13462 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13463 ((int8_t)ctx->opcode) << 1, 0);
13464 /* No delay slot, so just process as a normal instruction */
13465 break;
13466 case M16_OPC_SHIFT:
13467 switch (ctx->opcode & 0x3) {
13468 case 0x0:
13469 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13470 break;
13471 case 0x1:
13472 #if defined(TARGET_MIPS64)
13473 check_insn(ctx, ISA_MIPS3);
13474 check_mips_64(ctx);
13475 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13476 #else
13477 generate_exception_end(ctx, EXCP_RI);
13478 #endif
13479 break;
13480 case 0x2:
13481 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13482 break;
13483 case 0x3:
13484 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13485 break;
13487 break;
13488 #if defined(TARGET_MIPS64)
13489 case M16_OPC_LD:
13490 check_insn(ctx, ISA_MIPS3);
13491 check_mips_64(ctx);
13492 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13493 break;
13494 #endif
13495 case M16_OPC_RRIA:
13497 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13499 if ((ctx->opcode >> 4) & 1) {
13500 #if defined(TARGET_MIPS64)
13501 check_insn(ctx, ISA_MIPS3);
13502 check_mips_64(ctx);
13503 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13504 #else
13505 generate_exception_end(ctx, EXCP_RI);
13506 #endif
13507 } else {
13508 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13511 break;
13512 case M16_OPC_ADDIU8:
13514 int16_t imm = (int8_t) ctx->opcode;
13516 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13518 break;
13519 case M16_OPC_SLTI:
13521 int16_t imm = (uint8_t) ctx->opcode;
13522 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13524 break;
13525 case M16_OPC_SLTIU:
13527 int16_t imm = (uint8_t) ctx->opcode;
13528 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13530 break;
13531 case M16_OPC_I8:
13533 int reg32;
13535 funct = (ctx->opcode >> 8) & 0x7;
13536 switch (funct) {
13537 case I8_BTEQZ:
13538 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13539 ((int8_t)ctx->opcode) << 1, 0);
13540 break;
13541 case I8_BTNEZ:
13542 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13543 ((int8_t)ctx->opcode) << 1, 0);
13544 break;
13545 case I8_SWRASP:
13546 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13547 break;
13548 case I8_ADJSP:
13549 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13550 ((int8_t)ctx->opcode) << 3);
13551 break;
13552 case I8_SVRS:
13553 check_insn(ctx, ISA_MIPS32);
13555 int do_ra = ctx->opcode & (1 << 6);
13556 int do_s0 = ctx->opcode & (1 << 5);
13557 int do_s1 = ctx->opcode & (1 << 4);
13558 int framesize = ctx->opcode & 0xf;
13560 if (framesize == 0) {
13561 framesize = 128;
13562 } else {
13563 framesize = framesize << 3;
13566 if (ctx->opcode & (1 << 7)) {
13567 gen_mips16_save(ctx, 0, 0,
13568 do_ra, do_s0, do_s1, framesize);
13569 } else {
13570 gen_mips16_restore(ctx, 0, 0,
13571 do_ra, do_s0, do_s1, framesize);
13574 break;
13575 case I8_MOV32R:
13577 int rz = xlat(ctx->opcode & 0x7);
13579 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13580 ((ctx->opcode >> 5) & 0x7);
13581 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13583 break;
13584 case I8_MOVR32:
13585 reg32 = ctx->opcode & 0x1f;
13586 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13587 break;
13588 default:
13589 generate_exception_end(ctx, EXCP_RI);
13590 break;
13593 break;
13594 case M16_OPC_LI:
13596 int16_t imm = (uint8_t) ctx->opcode;
13598 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13600 break;
13601 case M16_OPC_CMPI:
13603 int16_t imm = (uint8_t) ctx->opcode;
13604 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13606 break;
13607 #if defined(TARGET_MIPS64)
13608 case M16_OPC_SD:
13609 check_insn(ctx, ISA_MIPS3);
13610 check_mips_64(ctx);
13611 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13612 break;
13613 #endif
13614 case M16_OPC_LB:
13615 gen_ld(ctx, OPC_LB, ry, rx, offset);
13616 break;
13617 case M16_OPC_LH:
13618 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13619 break;
13620 case M16_OPC_LWSP:
13621 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13622 break;
13623 case M16_OPC_LW:
13624 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13625 break;
13626 case M16_OPC_LBU:
13627 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13628 break;
13629 case M16_OPC_LHU:
13630 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13631 break;
13632 case M16_OPC_LWPC:
13633 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13634 break;
13635 #if defined (TARGET_MIPS64)
13636 case M16_OPC_LWU:
13637 check_insn(ctx, ISA_MIPS3);
13638 check_mips_64(ctx);
13639 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13640 break;
13641 #endif
13642 case M16_OPC_SB:
13643 gen_st(ctx, OPC_SB, ry, rx, offset);
13644 break;
13645 case M16_OPC_SH:
13646 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13647 break;
13648 case M16_OPC_SWSP:
13649 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13650 break;
13651 case M16_OPC_SW:
13652 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13653 break;
13654 case M16_OPC_RRR:
13656 int rz = xlat((ctx->opcode >> 2) & 0x7);
13657 int mips32_op;
13659 switch (ctx->opcode & 0x3) {
13660 case RRR_ADDU:
13661 mips32_op = OPC_ADDU;
13662 break;
13663 case RRR_SUBU:
13664 mips32_op = OPC_SUBU;
13665 break;
13666 #if defined(TARGET_MIPS64)
13667 case RRR_DADDU:
13668 mips32_op = OPC_DADDU;
13669 check_insn(ctx, ISA_MIPS3);
13670 check_mips_64(ctx);
13671 break;
13672 case RRR_DSUBU:
13673 mips32_op = OPC_DSUBU;
13674 check_insn(ctx, ISA_MIPS3);
13675 check_mips_64(ctx);
13676 break;
13677 #endif
13678 default:
13679 generate_exception_end(ctx, EXCP_RI);
13680 goto done;
13683 gen_arith(ctx, mips32_op, rz, rx, ry);
13684 done:
13687 break;
13688 case M16_OPC_RR:
13689 switch (op1) {
13690 case RR_JR:
13692 int nd = (ctx->opcode >> 7) & 0x1;
13693 int link = (ctx->opcode >> 6) & 0x1;
13694 int ra = (ctx->opcode >> 5) & 0x1;
13696 if (nd) {
13697 check_insn(ctx, ISA_MIPS32);
13700 if (link) {
13701 op = OPC_JALR;
13702 } else {
13703 op = OPC_JR;
13706 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13707 (nd ? 0 : 2));
13709 break;
13710 case RR_SDBBP:
13711 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13712 gen_helper_do_semihosting(cpu_env);
13713 } else {
13714 /* XXX: not clear which exception should be raised
13715 * when in debug mode...
13717 check_insn(ctx, ISA_MIPS32);
13718 generate_exception_end(ctx, EXCP_DBp);
13720 break;
13721 case RR_SLT:
13722 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13723 break;
13724 case RR_SLTU:
13725 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13726 break;
13727 case RR_BREAK:
13728 generate_exception_end(ctx, EXCP_BREAK);
13729 break;
13730 case RR_SLLV:
13731 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13732 break;
13733 case RR_SRLV:
13734 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13735 break;
13736 case RR_SRAV:
13737 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13738 break;
13739 #if defined (TARGET_MIPS64)
13740 case RR_DSRL:
13741 check_insn(ctx, ISA_MIPS3);
13742 check_mips_64(ctx);
13743 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13744 break;
13745 #endif
13746 case RR_CMP:
13747 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13748 break;
13749 case RR_NEG:
13750 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13751 break;
13752 case RR_AND:
13753 gen_logic(ctx, OPC_AND, rx, rx, ry);
13754 break;
13755 case RR_OR:
13756 gen_logic(ctx, OPC_OR, rx, rx, ry);
13757 break;
13758 case RR_XOR:
13759 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13760 break;
13761 case RR_NOT:
13762 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13763 break;
13764 case RR_MFHI:
13765 gen_HILO(ctx, OPC_MFHI, 0, rx);
13766 break;
13767 case RR_CNVT:
13768 check_insn(ctx, ISA_MIPS32);
13769 switch (cnvt_op) {
13770 case RR_RY_CNVT_ZEB:
13771 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13772 break;
13773 case RR_RY_CNVT_ZEH:
13774 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13775 break;
13776 case RR_RY_CNVT_SEB:
13777 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13778 break;
13779 case RR_RY_CNVT_SEH:
13780 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13781 break;
13782 #if defined (TARGET_MIPS64)
13783 case RR_RY_CNVT_ZEW:
13784 check_insn(ctx, ISA_MIPS64);
13785 check_mips_64(ctx);
13786 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13787 break;
13788 case RR_RY_CNVT_SEW:
13789 check_insn(ctx, ISA_MIPS64);
13790 check_mips_64(ctx);
13791 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13792 break;
13793 #endif
13794 default:
13795 generate_exception_end(ctx, EXCP_RI);
13796 break;
13798 break;
13799 case RR_MFLO:
13800 gen_HILO(ctx, OPC_MFLO, 0, rx);
13801 break;
13802 #if defined (TARGET_MIPS64)
13803 case RR_DSRA:
13804 check_insn(ctx, ISA_MIPS3);
13805 check_mips_64(ctx);
13806 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13807 break;
13808 case RR_DSLLV:
13809 check_insn(ctx, ISA_MIPS3);
13810 check_mips_64(ctx);
13811 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13812 break;
13813 case RR_DSRLV:
13814 check_insn(ctx, ISA_MIPS3);
13815 check_mips_64(ctx);
13816 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13817 break;
13818 case RR_DSRAV:
13819 check_insn(ctx, ISA_MIPS3);
13820 check_mips_64(ctx);
13821 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13822 break;
13823 #endif
13824 case RR_MULT:
13825 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13826 break;
13827 case RR_MULTU:
13828 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13829 break;
13830 case RR_DIV:
13831 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13832 break;
13833 case RR_DIVU:
13834 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13835 break;
13836 #if defined (TARGET_MIPS64)
13837 case RR_DMULT:
13838 check_insn(ctx, ISA_MIPS3);
13839 check_mips_64(ctx);
13840 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13841 break;
13842 case RR_DMULTU:
13843 check_insn(ctx, ISA_MIPS3);
13844 check_mips_64(ctx);
13845 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13846 break;
13847 case RR_DDIV:
13848 check_insn(ctx, ISA_MIPS3);
13849 check_mips_64(ctx);
13850 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13851 break;
13852 case RR_DDIVU:
13853 check_insn(ctx, ISA_MIPS3);
13854 check_mips_64(ctx);
13855 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13856 break;
13857 #endif
13858 default:
13859 generate_exception_end(ctx, EXCP_RI);
13860 break;
13862 break;
13863 case M16_OPC_EXTEND:
13864 decode_extended_mips16_opc(env, ctx);
13865 n_bytes = 4;
13866 break;
13867 #if defined(TARGET_MIPS64)
13868 case M16_OPC_I64:
13869 funct = (ctx->opcode >> 8) & 0x7;
13870 decode_i64_mips16(ctx, ry, funct, offset, 0);
13871 break;
13872 #endif
13873 default:
13874 generate_exception_end(ctx, EXCP_RI);
13875 break;
13878 return n_bytes;
13881 /* microMIPS extension to MIPS32/MIPS64 */
13884 * microMIPS32/microMIPS64 major opcodes
13886 * 1. MIPS Architecture for Programmers Volume II-B:
13887 * The microMIPS32 Instruction Set (Revision 3.05)
13889 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13891 * 2. MIPS Architecture For Programmers Volume II-A:
13892 * The MIPS64 Instruction Set (Revision 3.51)
13895 enum {
13896 POOL32A = 0x00,
13897 POOL16A = 0x01,
13898 LBU16 = 0x02,
13899 MOVE16 = 0x03,
13900 ADDI32 = 0x04,
13901 R6_LUI = 0x04,
13902 AUI = 0x04,
13903 LBU32 = 0x05,
13904 SB32 = 0x06,
13905 LB32 = 0x07,
13907 POOL32B = 0x08,
13908 POOL16B = 0x09,
13909 LHU16 = 0x0a,
13910 ANDI16 = 0x0b,
13911 ADDIU32 = 0x0c,
13912 LHU32 = 0x0d,
13913 SH32 = 0x0e,
13914 LH32 = 0x0f,
13916 POOL32I = 0x10,
13917 POOL16C = 0x11,
13918 LWSP16 = 0x12,
13919 POOL16D = 0x13,
13920 ORI32 = 0x14,
13921 POOL32F = 0x15,
13922 POOL32S = 0x16, /* MIPS64 */
13923 DADDIU32 = 0x17, /* MIPS64 */
13925 POOL32C = 0x18,
13926 LWGP16 = 0x19,
13927 LW16 = 0x1a,
13928 POOL16E = 0x1b,
13929 XORI32 = 0x1c,
13930 JALS32 = 0x1d,
13931 BOVC = 0x1d,
13932 BEQC = 0x1d,
13933 BEQZALC = 0x1d,
13934 ADDIUPC = 0x1e,
13935 PCREL = 0x1e,
13936 BNVC = 0x1f,
13937 BNEC = 0x1f,
13938 BNEZALC = 0x1f,
13940 R6_BEQZC = 0x20,
13941 JIC = 0x20,
13942 POOL16F = 0x21,
13943 SB16 = 0x22,
13944 BEQZ16 = 0x23,
13945 BEQZC16 = 0x23,
13946 SLTI32 = 0x24,
13947 BEQ32 = 0x25,
13948 BC = 0x25,
13949 SWC132 = 0x26,
13950 LWC132 = 0x27,
13952 /* 0x29 is reserved */
13953 RES_29 = 0x29,
13954 R6_BNEZC = 0x28,
13955 JIALC = 0x28,
13956 SH16 = 0x2a,
13957 BNEZ16 = 0x2b,
13958 BNEZC16 = 0x2b,
13959 SLTIU32 = 0x2c,
13960 BNE32 = 0x2d,
13961 BALC = 0x2d,
13962 SDC132 = 0x2e,
13963 LDC132 = 0x2f,
13965 /* 0x31 is reserved */
13966 RES_31 = 0x31,
13967 BLEZALC = 0x30,
13968 BGEZALC = 0x30,
13969 BGEUC = 0x30,
13970 SWSP16 = 0x32,
13971 B16 = 0x33,
13972 BC16 = 0x33,
13973 ANDI32 = 0x34,
13974 J32 = 0x35,
13975 BGTZC = 0x35,
13976 BLTZC = 0x35,
13977 BLTC = 0x35,
13978 SD32 = 0x36, /* MIPS64 */
13979 LD32 = 0x37, /* MIPS64 */
13981 /* 0x39 is reserved */
13982 RES_39 = 0x39,
13983 BGTZALC = 0x38,
13984 BLTZALC = 0x38,
13985 BLTUC = 0x38,
13986 SW16 = 0x3a,
13987 LI16 = 0x3b,
13988 JALX32 = 0x3c,
13989 JAL32 = 0x3d,
13990 BLEZC = 0x3d,
13991 BGEZC = 0x3d,
13992 BGEC = 0x3d,
13993 SW32 = 0x3e,
13994 LW32 = 0x3f
13997 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13998 enum {
13999 ADDIUPC_00 = 0x00,
14000 ADDIUPC_01 = 0x01,
14001 ADDIUPC_02 = 0x02,
14002 ADDIUPC_03 = 0x03,
14003 ADDIUPC_04 = 0x04,
14004 ADDIUPC_05 = 0x05,
14005 ADDIUPC_06 = 0x06,
14006 ADDIUPC_07 = 0x07,
14007 AUIPC = 0x1e,
14008 ALUIPC = 0x1f,
14009 LWPC_08 = 0x08,
14010 LWPC_09 = 0x09,
14011 LWPC_0A = 0x0A,
14012 LWPC_0B = 0x0B,
14013 LWPC_0C = 0x0C,
14014 LWPC_0D = 0x0D,
14015 LWPC_0E = 0x0E,
14016 LWPC_0F = 0x0F,
14019 /* POOL32A encoding of minor opcode field */
14021 enum {
14022 /* These opcodes are distinguished only by bits 9..6; those bits are
14023 * what are recorded below. */
14024 SLL32 = 0x0,
14025 SRL32 = 0x1,
14026 SRA = 0x2,
14027 ROTR = 0x3,
14028 SELEQZ = 0x5,
14029 SELNEZ = 0x6,
14030 R6_RDHWR = 0x7,
14032 SLLV = 0x0,
14033 SRLV = 0x1,
14034 SRAV = 0x2,
14035 ROTRV = 0x3,
14036 ADD = 0x4,
14037 ADDU32 = 0x5,
14038 SUB = 0x6,
14039 SUBU32 = 0x7,
14040 MUL = 0x8,
14041 AND = 0x9,
14042 OR32 = 0xa,
14043 NOR = 0xb,
14044 XOR32 = 0xc,
14045 SLT = 0xd,
14046 SLTU = 0xe,
14048 MOVN = 0x0,
14049 R6_MUL = 0x0,
14050 MOVZ = 0x1,
14051 MUH = 0x1,
14052 MULU = 0x2,
14053 MUHU = 0x3,
14054 LWXS = 0x4,
14055 R6_DIV = 0x4,
14056 MOD = 0x5,
14057 R6_DIVU = 0x6,
14058 MODU = 0x7,
14060 /* The following can be distinguished by their lower 6 bits. */
14061 BREAK32 = 0x07,
14062 INS = 0x0c,
14063 LSA = 0x0f,
14064 ALIGN = 0x1f,
14065 EXT = 0x2c,
14066 POOL32AXF = 0x3c,
14067 SIGRIE = 0x3f
14070 /* POOL32AXF encoding of minor opcode field extension */
14073 * 1. MIPS Architecture for Programmers Volume II-B:
14074 * The microMIPS32 Instruction Set (Revision 3.05)
14076 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14078 * 2. MIPS Architecture for Programmers VolumeIV-e:
14079 * The MIPS DSP Application-Specific Extension
14080 * to the microMIPS32 Architecture (Revision 2.34)
14082 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14085 enum {
14086 /* bits 11..6 */
14087 TEQ = 0x00,
14088 TGE = 0x08,
14089 TGEU = 0x10,
14090 TLT = 0x20,
14091 TLTU = 0x28,
14092 TNE = 0x30,
14094 MFC0 = 0x03,
14095 MTC0 = 0x0b,
14097 /* begin of microMIPS32 DSP */
14099 /* bits 13..12 for 0x01 */
14100 MFHI_ACC = 0x0,
14101 MFLO_ACC = 0x1,
14102 MTHI_ACC = 0x2,
14103 MTLO_ACC = 0x3,
14105 /* bits 13..12 for 0x2a */
14106 MADD_ACC = 0x0,
14107 MADDU_ACC = 0x1,
14108 MSUB_ACC = 0x2,
14109 MSUBU_ACC = 0x3,
14111 /* bits 13..12 for 0x32 */
14112 MULT_ACC = 0x0,
14113 MULTU_ACC = 0x1,
14115 /* end of microMIPS32 DSP */
14117 /* bits 15..12 for 0x2c */
14118 BITSWAP = 0x0,
14119 SEB = 0x2,
14120 SEH = 0x3,
14121 CLO = 0x4,
14122 CLZ = 0x5,
14123 RDHWR = 0x6,
14124 WSBH = 0x7,
14125 MULT = 0x8,
14126 MULTU = 0x9,
14127 DIV = 0xa,
14128 DIVU = 0xb,
14129 MADD = 0xc,
14130 MADDU = 0xd,
14131 MSUB = 0xe,
14132 MSUBU = 0xf,
14134 /* bits 15..12 for 0x34 */
14135 MFC2 = 0x4,
14136 MTC2 = 0x5,
14137 MFHC2 = 0x8,
14138 MTHC2 = 0x9,
14139 CFC2 = 0xc,
14140 CTC2 = 0xd,
14142 /* bits 15..12 for 0x3c */
14143 JALR = 0x0,
14144 JR = 0x0, /* alias */
14145 JALRC = 0x0,
14146 JRC = 0x0,
14147 JALR_HB = 0x1,
14148 JALRC_HB = 0x1,
14149 JALRS = 0x4,
14150 JALRS_HB = 0x5,
14152 /* bits 15..12 for 0x05 */
14153 RDPGPR = 0xe,
14154 WRPGPR = 0xf,
14156 /* bits 15..12 for 0x0d */
14157 TLBP = 0x0,
14158 TLBR = 0x1,
14159 TLBWI = 0x2,
14160 TLBWR = 0x3,
14161 TLBINV = 0x4,
14162 TLBINVF = 0x5,
14163 WAIT = 0x9,
14164 IRET = 0xd,
14165 DERET = 0xe,
14166 ERET = 0xf,
14168 /* bits 15..12 for 0x15 */
14169 DMT = 0x0,
14170 DVPE = 0x1,
14171 EMT = 0x2,
14172 EVPE = 0x3,
14174 /* bits 15..12 for 0x1d */
14175 DI = 0x4,
14176 EI = 0x5,
14178 /* bits 15..12 for 0x2d */
14179 SYNC = 0x6,
14180 SYSCALL = 0x8,
14181 SDBBP = 0xd,
14183 /* bits 15..12 for 0x35 */
14184 MFHI32 = 0x0,
14185 MFLO32 = 0x1,
14186 MTHI32 = 0x2,
14187 MTLO32 = 0x3,
14190 /* POOL32B encoding of minor opcode field (bits 15..12) */
14192 enum {
14193 LWC2 = 0x0,
14194 LWP = 0x1,
14195 LDP = 0x4,
14196 LWM32 = 0x5,
14197 CACHE = 0x6,
14198 LDM = 0x7,
14199 SWC2 = 0x8,
14200 SWP = 0x9,
14201 SDP = 0xc,
14202 SWM32 = 0xd,
14203 SDM = 0xf
14206 /* POOL32C encoding of minor opcode field (bits 15..12) */
14208 enum {
14209 LWL = 0x0,
14210 SWL = 0x8,
14211 LWR = 0x1,
14212 SWR = 0x9,
14213 PREF = 0x2,
14214 ST_EVA = 0xa,
14215 LL = 0x3,
14216 SC = 0xb,
14217 LDL = 0x4,
14218 SDL = 0xc,
14219 LDR = 0x5,
14220 SDR = 0xd,
14221 LD_EVA = 0x6,
14222 LWU = 0xe,
14223 LLD = 0x7,
14224 SCD = 0xf
14227 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14229 enum {
14230 LBUE = 0x0,
14231 LHUE = 0x1,
14232 LWLE = 0x2,
14233 LWRE = 0x3,
14234 LBE = 0x4,
14235 LHE = 0x5,
14236 LLE = 0x6,
14237 LWE = 0x7,
14240 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14242 enum {
14243 SWLE = 0x0,
14244 SWRE = 0x1,
14245 PREFE = 0x2,
14246 CACHEE = 0x3,
14247 SBE = 0x4,
14248 SHE = 0x5,
14249 SCE = 0x6,
14250 SWE = 0x7,
14253 /* POOL32F encoding of minor opcode field (bits 5..0) */
14255 enum {
14256 /* These are the bit 7..6 values */
14257 ADD_FMT = 0x0,
14259 SUB_FMT = 0x1,
14261 MUL_FMT = 0x2,
14263 DIV_FMT = 0x3,
14265 /* These are the bit 8..6 values */
14266 MOVN_FMT = 0x0,
14267 RSQRT2_FMT = 0x0,
14268 MOVF_FMT = 0x0,
14269 RINT_FMT = 0x0,
14270 SELNEZ_FMT = 0x0,
14272 MOVZ_FMT = 0x1,
14273 LWXC1 = 0x1,
14274 MOVT_FMT = 0x1,
14275 CLASS_FMT = 0x1,
14276 SELEQZ_FMT = 0x1,
14278 PLL_PS = 0x2,
14279 SWXC1 = 0x2,
14280 SEL_FMT = 0x2,
14282 PLU_PS = 0x3,
14283 LDXC1 = 0x3,
14285 MOVN_FMT_04 = 0x4,
14286 PUL_PS = 0x4,
14287 SDXC1 = 0x4,
14288 RECIP2_FMT = 0x4,
14290 MOVZ_FMT_05 = 0x05,
14291 PUU_PS = 0x5,
14292 LUXC1 = 0x5,
14294 CVT_PS_S = 0x6,
14295 SUXC1 = 0x6,
14296 ADDR_PS = 0x6,
14297 PREFX = 0x6,
14298 MADDF_FMT = 0x6,
14300 MULR_PS = 0x7,
14301 MSUBF_FMT = 0x7,
14303 MADD_S = 0x01,
14304 MADD_D = 0x09,
14305 MADD_PS = 0x11,
14306 ALNV_PS = 0x19,
14307 MSUB_S = 0x21,
14308 MSUB_D = 0x29,
14309 MSUB_PS = 0x31,
14311 NMADD_S = 0x02,
14312 NMADD_D = 0x0a,
14313 NMADD_PS = 0x12,
14314 NMSUB_S = 0x22,
14315 NMSUB_D = 0x2a,
14316 NMSUB_PS = 0x32,
14318 MIN_FMT = 0x3,
14319 MAX_FMT = 0xb,
14320 MINA_FMT = 0x23,
14321 MAXA_FMT = 0x2b,
14322 POOL32FXF = 0x3b,
14324 CABS_COND_FMT = 0x1c, /* MIPS3D */
14325 C_COND_FMT = 0x3c,
14327 CMP_CONDN_S = 0x5,
14328 CMP_CONDN_D = 0x15
14331 /* POOL32Fxf encoding of minor opcode extension field */
14333 enum {
14334 CVT_L = 0x04,
14335 RSQRT_FMT = 0x08,
14336 FLOOR_L = 0x0c,
14337 CVT_PW_PS = 0x1c,
14338 CVT_W = 0x24,
14339 SQRT_FMT = 0x28,
14340 FLOOR_W = 0x2c,
14341 CVT_PS_PW = 0x3c,
14342 CFC1 = 0x40,
14343 RECIP_FMT = 0x48,
14344 CEIL_L = 0x4c,
14345 CTC1 = 0x60,
14346 CEIL_W = 0x6c,
14347 MFC1 = 0x80,
14348 CVT_S_PL = 0x84,
14349 TRUNC_L = 0x8c,
14350 MTC1 = 0xa0,
14351 CVT_S_PU = 0xa4,
14352 TRUNC_W = 0xac,
14353 MFHC1 = 0xc0,
14354 ROUND_L = 0xcc,
14355 MTHC1 = 0xe0,
14356 ROUND_W = 0xec,
14358 MOV_FMT = 0x01,
14359 MOVF = 0x05,
14360 ABS_FMT = 0x0d,
14361 RSQRT1_FMT = 0x1d,
14362 MOVT = 0x25,
14363 NEG_FMT = 0x2d,
14364 CVT_D = 0x4d,
14365 RECIP1_FMT = 0x5d,
14366 CVT_S = 0x6d
14369 /* POOL32I encoding of minor opcode field (bits 25..21) */
14371 enum {
14372 BLTZ = 0x00,
14373 BLTZAL = 0x01,
14374 BGEZ = 0x02,
14375 BGEZAL = 0x03,
14376 BLEZ = 0x04,
14377 BNEZC = 0x05,
14378 BGTZ = 0x06,
14379 BEQZC = 0x07,
14380 TLTI = 0x08,
14381 BC1EQZC = 0x08,
14382 TGEI = 0x09,
14383 BC1NEZC = 0x09,
14384 TLTIU = 0x0a,
14385 BC2EQZC = 0x0a,
14386 TGEIU = 0x0b,
14387 BC2NEZC = 0x0a,
14388 TNEI = 0x0c,
14389 R6_SYNCI = 0x0c,
14390 LUI = 0x0d,
14391 TEQI = 0x0e,
14392 SYNCI = 0x10,
14393 BLTZALS = 0x11,
14394 BGEZALS = 0x13,
14395 BC2F = 0x14,
14396 BC2T = 0x15,
14397 BPOSGE64 = 0x1a,
14398 BPOSGE32 = 0x1b,
14399 /* These overlap and are distinguished by bit16 of the instruction */
14400 BC1F = 0x1c,
14401 BC1T = 0x1d,
14402 BC1ANY2F = 0x1c,
14403 BC1ANY2T = 0x1d,
14404 BC1ANY4F = 0x1e,
14405 BC1ANY4T = 0x1f
14408 /* POOL16A encoding of minor opcode field */
14410 enum {
14411 ADDU16 = 0x0,
14412 SUBU16 = 0x1
14415 /* POOL16B encoding of minor opcode field */
14417 enum {
14418 SLL16 = 0x0,
14419 SRL16 = 0x1
14422 /* POOL16C encoding of minor opcode field */
14424 enum {
14425 NOT16 = 0x00,
14426 XOR16 = 0x04,
14427 AND16 = 0x08,
14428 OR16 = 0x0c,
14429 LWM16 = 0x10,
14430 SWM16 = 0x14,
14431 JR16 = 0x18,
14432 JRC16 = 0x1a,
14433 JALR16 = 0x1c,
14434 JALR16S = 0x1e,
14435 MFHI16 = 0x20,
14436 MFLO16 = 0x24,
14437 BREAK16 = 0x28,
14438 SDBBP16 = 0x2c,
14439 JRADDIUSP = 0x30
14442 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14444 enum {
14445 R6_NOT16 = 0x00,
14446 R6_AND16 = 0x01,
14447 R6_LWM16 = 0x02,
14448 R6_JRC16 = 0x03,
14449 MOVEP = 0x04,
14450 MOVEP_05 = 0x05,
14451 MOVEP_06 = 0x06,
14452 MOVEP_07 = 0x07,
14453 R6_XOR16 = 0x08,
14454 R6_OR16 = 0x09,
14455 R6_SWM16 = 0x0a,
14456 JALRC16 = 0x0b,
14457 MOVEP_0C = 0x0c,
14458 MOVEP_0D = 0x0d,
14459 MOVEP_0E = 0x0e,
14460 MOVEP_0F = 0x0f,
14461 JRCADDIUSP = 0x13,
14462 R6_BREAK16 = 0x1b,
14463 R6_SDBBP16 = 0x3b
14466 /* POOL16D encoding of minor opcode field */
14468 enum {
14469 ADDIUS5 = 0x0,
14470 ADDIUSP = 0x1
14473 /* POOL16E encoding of minor opcode field */
14475 enum {
14476 ADDIUR2 = 0x0,
14477 ADDIUR1SP = 0x1
14480 static int mmreg (int r)
14482 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14484 return map[r];
14487 /* Used for 16-bit store instructions. */
14488 static int mmreg2 (int r)
14490 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14492 return map[r];
14495 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14496 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14497 #define uMIPS_RS2(op) uMIPS_RS(op)
14498 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14499 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14500 #define uMIPS_RS5(op) (op & 0x1f)
14502 /* Signed immediate */
14503 #define SIMM(op, start, width) \
14504 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14505 << (32-width)) \
14506 >> (32-width))
14507 /* Zero-extended immediate */
14508 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14510 static void gen_addiur1sp(DisasContext *ctx)
14512 int rd = mmreg(uMIPS_RD(ctx->opcode));
14514 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14517 static void gen_addiur2(DisasContext *ctx)
14519 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14520 int rd = mmreg(uMIPS_RD(ctx->opcode));
14521 int rs = mmreg(uMIPS_RS(ctx->opcode));
14523 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14526 static void gen_addiusp(DisasContext *ctx)
14528 int encoded = ZIMM(ctx->opcode, 1, 9);
14529 int decoded;
14531 if (encoded <= 1) {
14532 decoded = 256 + encoded;
14533 } else if (encoded <= 255) {
14534 decoded = encoded;
14535 } else if (encoded <= 509) {
14536 decoded = encoded - 512;
14537 } else {
14538 decoded = encoded - 768;
14541 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14544 static void gen_addius5(DisasContext *ctx)
14546 int imm = SIMM(ctx->opcode, 1, 4);
14547 int rd = (ctx->opcode >> 5) & 0x1f;
14549 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14552 static void gen_andi16(DisasContext *ctx)
14554 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14555 31, 32, 63, 64, 255, 32768, 65535 };
14556 int rd = mmreg(uMIPS_RD(ctx->opcode));
14557 int rs = mmreg(uMIPS_RS(ctx->opcode));
14558 int encoded = ZIMM(ctx->opcode, 0, 4);
14560 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14563 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14564 int base, int16_t offset)
14566 TCGv t0, t1;
14567 TCGv_i32 t2;
14569 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14570 generate_exception_end(ctx, EXCP_RI);
14571 return;
14574 t0 = tcg_temp_new();
14576 gen_base_offset_addr(ctx, t0, base, offset);
14578 t1 = tcg_const_tl(reglist);
14579 t2 = tcg_const_i32(ctx->mem_idx);
14581 save_cpu_state(ctx, 1);
14582 switch (opc) {
14583 case LWM32:
14584 gen_helper_lwm(cpu_env, t0, t1, t2);
14585 break;
14586 case SWM32:
14587 gen_helper_swm(cpu_env, t0, t1, t2);
14588 break;
14589 #ifdef TARGET_MIPS64
14590 case LDM:
14591 gen_helper_ldm(cpu_env, t0, t1, t2);
14592 break;
14593 case SDM:
14594 gen_helper_sdm(cpu_env, t0, t1, t2);
14595 break;
14596 #endif
14598 tcg_temp_free(t0);
14599 tcg_temp_free(t1);
14600 tcg_temp_free_i32(t2);
14604 static void gen_pool16c_insn(DisasContext *ctx)
14606 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14607 int rs = mmreg(ctx->opcode & 0x7);
14609 switch (((ctx->opcode) >> 4) & 0x3f) {
14610 case NOT16 + 0:
14611 case NOT16 + 1:
14612 case NOT16 + 2:
14613 case NOT16 + 3:
14614 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14615 break;
14616 case XOR16 + 0:
14617 case XOR16 + 1:
14618 case XOR16 + 2:
14619 case XOR16 + 3:
14620 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14621 break;
14622 case AND16 + 0:
14623 case AND16 + 1:
14624 case AND16 + 2:
14625 case AND16 + 3:
14626 gen_logic(ctx, OPC_AND, rd, rd, rs);
14627 break;
14628 case OR16 + 0:
14629 case OR16 + 1:
14630 case OR16 + 2:
14631 case OR16 + 3:
14632 gen_logic(ctx, OPC_OR, rd, rd, rs);
14633 break;
14634 case LWM16 + 0:
14635 case LWM16 + 1:
14636 case LWM16 + 2:
14637 case LWM16 + 3:
14639 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14640 int offset = ZIMM(ctx->opcode, 0, 4);
14642 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14643 29, offset << 2);
14645 break;
14646 case SWM16 + 0:
14647 case SWM16 + 1:
14648 case SWM16 + 2:
14649 case SWM16 + 3:
14651 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14652 int offset = ZIMM(ctx->opcode, 0, 4);
14654 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14655 29, offset << 2);
14657 break;
14658 case JR16 + 0:
14659 case JR16 + 1:
14661 int reg = ctx->opcode & 0x1f;
14663 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14665 break;
14666 case JRC16 + 0:
14667 case JRC16 + 1:
14669 int reg = ctx->opcode & 0x1f;
14670 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14671 /* Let normal delay slot handling in our caller take us
14672 to the branch target. */
14674 break;
14675 case JALR16 + 0:
14676 case JALR16 + 1:
14677 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14678 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14679 break;
14680 case JALR16S + 0:
14681 case JALR16S + 1:
14682 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14683 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14684 break;
14685 case MFHI16 + 0:
14686 case MFHI16 + 1:
14687 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14688 break;
14689 case MFLO16 + 0:
14690 case MFLO16 + 1:
14691 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14692 break;
14693 case BREAK16:
14694 generate_exception_end(ctx, EXCP_BREAK);
14695 break;
14696 case SDBBP16:
14697 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14698 gen_helper_do_semihosting(cpu_env);
14699 } else {
14700 /* XXX: not clear which exception should be raised
14701 * when in debug mode...
14703 check_insn(ctx, ISA_MIPS32);
14704 generate_exception_end(ctx, EXCP_DBp);
14706 break;
14707 case JRADDIUSP + 0:
14708 case JRADDIUSP + 1:
14710 int imm = ZIMM(ctx->opcode, 0, 5);
14711 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14712 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14713 /* Let normal delay slot handling in our caller take us
14714 to the branch target. */
14716 break;
14717 default:
14718 generate_exception_end(ctx, EXCP_RI);
14719 break;
14723 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14724 int enc_rs)
14726 int rd, rs, re, rt;
14727 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14728 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14729 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14730 rd = rd_enc[enc_dest];
14731 re = re_enc[enc_dest];
14732 rs = rs_rt_enc[enc_rs];
14733 rt = rs_rt_enc[enc_rt];
14734 if (rs) {
14735 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14736 } else {
14737 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14739 if (rt) {
14740 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14741 } else {
14742 tcg_gen_movi_tl(cpu_gpr[re], 0);
14746 static void gen_pool16c_r6_insn(DisasContext *ctx)
14748 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14749 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14751 switch (ctx->opcode & 0xf) {
14752 case R6_NOT16:
14753 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14754 break;
14755 case R6_AND16:
14756 gen_logic(ctx, OPC_AND, rt, rt, rs);
14757 break;
14758 case R6_LWM16:
14760 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14761 int offset = extract32(ctx->opcode, 4, 4);
14762 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14764 break;
14765 case R6_JRC16: /* JRCADDIUSP */
14766 if ((ctx->opcode >> 4) & 1) {
14767 /* JRCADDIUSP */
14768 int imm = extract32(ctx->opcode, 5, 5);
14769 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14770 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14771 } else {
14772 /* JRC16 */
14773 rs = extract32(ctx->opcode, 5, 5);
14774 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14776 break;
14777 case MOVEP:
14778 case MOVEP_05:
14779 case MOVEP_06:
14780 case MOVEP_07:
14781 case MOVEP_0C:
14782 case MOVEP_0D:
14783 case MOVEP_0E:
14784 case MOVEP_0F:
14786 int enc_dest = uMIPS_RD(ctx->opcode);
14787 int enc_rt = uMIPS_RS2(ctx->opcode);
14788 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14789 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14791 break;
14792 case R6_XOR16:
14793 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14794 break;
14795 case R6_OR16:
14796 gen_logic(ctx, OPC_OR, rt, rt, rs);
14797 break;
14798 case R6_SWM16:
14800 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14801 int offset = extract32(ctx->opcode, 4, 4);
14802 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14804 break;
14805 case JALRC16: /* BREAK16, SDBBP16 */
14806 switch (ctx->opcode & 0x3f) {
14807 case JALRC16:
14808 case JALRC16 + 0x20:
14809 /* JALRC16 */
14810 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14811 31, 0, 0);
14812 break;
14813 case R6_BREAK16:
14814 /* BREAK16 */
14815 generate_exception(ctx, EXCP_BREAK);
14816 break;
14817 case R6_SDBBP16:
14818 /* SDBBP16 */
14819 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14820 gen_helper_do_semihosting(cpu_env);
14821 } else {
14822 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14823 generate_exception(ctx, EXCP_RI);
14824 } else {
14825 generate_exception(ctx, EXCP_DBp);
14828 break;
14830 break;
14831 default:
14832 generate_exception(ctx, EXCP_RI);
14833 break;
14837 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14839 TCGv t0 = tcg_temp_new();
14840 TCGv t1 = tcg_temp_new();
14842 gen_load_gpr(t0, base);
14844 if (index != 0) {
14845 gen_load_gpr(t1, index);
14846 tcg_gen_shli_tl(t1, t1, 2);
14847 gen_op_addr_add(ctx, t0, t1, t0);
14850 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14851 gen_store_gpr(t1, rd);
14853 tcg_temp_free(t0);
14854 tcg_temp_free(t1);
14857 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14858 int base, int16_t offset)
14860 TCGv t0, t1;
14862 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14863 generate_exception_end(ctx, EXCP_RI);
14864 return;
14867 t0 = tcg_temp_new();
14868 t1 = tcg_temp_new();
14870 gen_base_offset_addr(ctx, t0, base, offset);
14872 switch (opc) {
14873 case LWP:
14874 if (rd == base) {
14875 generate_exception_end(ctx, EXCP_RI);
14876 return;
14878 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14879 gen_store_gpr(t1, rd);
14880 tcg_gen_movi_tl(t1, 4);
14881 gen_op_addr_add(ctx, t0, t0, t1);
14882 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14883 gen_store_gpr(t1, rd+1);
14884 break;
14885 case SWP:
14886 gen_load_gpr(t1, rd);
14887 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14888 tcg_gen_movi_tl(t1, 4);
14889 gen_op_addr_add(ctx, t0, t0, t1);
14890 gen_load_gpr(t1, rd+1);
14891 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14892 break;
14893 #ifdef TARGET_MIPS64
14894 case LDP:
14895 if (rd == base) {
14896 generate_exception_end(ctx, EXCP_RI);
14897 return;
14899 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14900 gen_store_gpr(t1, rd);
14901 tcg_gen_movi_tl(t1, 8);
14902 gen_op_addr_add(ctx, t0, t0, t1);
14903 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14904 gen_store_gpr(t1, rd+1);
14905 break;
14906 case SDP:
14907 gen_load_gpr(t1, rd);
14908 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14909 tcg_gen_movi_tl(t1, 8);
14910 gen_op_addr_add(ctx, t0, t0, t1);
14911 gen_load_gpr(t1, rd+1);
14912 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14913 break;
14914 #endif
14916 tcg_temp_free(t0);
14917 tcg_temp_free(t1);
14920 static void gen_sync(int stype)
14922 TCGBar tcg_mo = TCG_BAR_SC;
14924 switch (stype) {
14925 case 0x4: /* SYNC_WMB */
14926 tcg_mo |= TCG_MO_ST_ST;
14927 break;
14928 case 0x10: /* SYNC_MB */
14929 tcg_mo |= TCG_MO_ALL;
14930 break;
14931 case 0x11: /* SYNC_ACQUIRE */
14932 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14933 break;
14934 case 0x12: /* SYNC_RELEASE */
14935 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14936 break;
14937 case 0x13: /* SYNC_RMB */
14938 tcg_mo |= TCG_MO_LD_LD;
14939 break;
14940 default:
14941 tcg_mo |= TCG_MO_ALL;
14942 break;
14945 tcg_gen_mb(tcg_mo);
14948 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14950 int extension = (ctx->opcode >> 6) & 0x3f;
14951 int minor = (ctx->opcode >> 12) & 0xf;
14952 uint32_t mips32_op;
14954 switch (extension) {
14955 case TEQ:
14956 mips32_op = OPC_TEQ;
14957 goto do_trap;
14958 case TGE:
14959 mips32_op = OPC_TGE;
14960 goto do_trap;
14961 case TGEU:
14962 mips32_op = OPC_TGEU;
14963 goto do_trap;
14964 case TLT:
14965 mips32_op = OPC_TLT;
14966 goto do_trap;
14967 case TLTU:
14968 mips32_op = OPC_TLTU;
14969 goto do_trap;
14970 case TNE:
14971 mips32_op = OPC_TNE;
14972 do_trap:
14973 gen_trap(ctx, mips32_op, rs, rt, -1);
14974 break;
14975 #ifndef CONFIG_USER_ONLY
14976 case MFC0:
14977 case MFC0 + 32:
14978 check_cp0_enabled(ctx);
14979 if (rt == 0) {
14980 /* Treat as NOP. */
14981 break;
14983 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14984 break;
14985 case MTC0:
14986 case MTC0 + 32:
14987 check_cp0_enabled(ctx);
14989 TCGv t0 = tcg_temp_new();
14991 gen_load_gpr(t0, rt);
14992 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14993 tcg_temp_free(t0);
14995 break;
14996 #endif
14997 case 0x2a:
14998 switch (minor & 3) {
14999 case MADD_ACC:
15000 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
15001 break;
15002 case MADDU_ACC:
15003 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
15004 break;
15005 case MSUB_ACC:
15006 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
15007 break;
15008 case MSUBU_ACC:
15009 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
15010 break;
15011 default:
15012 goto pool32axf_invalid;
15014 break;
15015 case 0x32:
15016 switch (minor & 3) {
15017 case MULT_ACC:
15018 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
15019 break;
15020 case MULTU_ACC:
15021 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
15022 break;
15023 default:
15024 goto pool32axf_invalid;
15026 break;
15027 case 0x2c:
15028 switch (minor) {
15029 case BITSWAP:
15030 check_insn(ctx, ISA_MIPS32R6);
15031 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15032 break;
15033 case SEB:
15034 gen_bshfl(ctx, OPC_SEB, rs, rt);
15035 break;
15036 case SEH:
15037 gen_bshfl(ctx, OPC_SEH, rs, rt);
15038 break;
15039 case CLO:
15040 mips32_op = OPC_CLO;
15041 goto do_cl;
15042 case CLZ:
15043 mips32_op = OPC_CLZ;
15044 do_cl:
15045 check_insn(ctx, ISA_MIPS32);
15046 gen_cl(ctx, mips32_op, rt, rs);
15047 break;
15048 case RDHWR:
15049 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15050 gen_rdhwr(ctx, rt, rs, 0);
15051 break;
15052 case WSBH:
15053 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15054 break;
15055 case MULT:
15056 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15057 mips32_op = OPC_MULT;
15058 goto do_mul;
15059 case MULTU:
15060 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15061 mips32_op = OPC_MULTU;
15062 goto do_mul;
15063 case DIV:
15064 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15065 mips32_op = OPC_DIV;
15066 goto do_div;
15067 case DIVU:
15068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15069 mips32_op = OPC_DIVU;
15070 goto do_div;
15071 do_div:
15072 check_insn(ctx, ISA_MIPS32);
15073 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15074 break;
15075 case MADD:
15076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15077 mips32_op = OPC_MADD;
15078 goto do_mul;
15079 case MADDU:
15080 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15081 mips32_op = OPC_MADDU;
15082 goto do_mul;
15083 case MSUB:
15084 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15085 mips32_op = OPC_MSUB;
15086 goto do_mul;
15087 case MSUBU:
15088 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15089 mips32_op = OPC_MSUBU;
15090 do_mul:
15091 check_insn(ctx, ISA_MIPS32);
15092 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15093 break;
15094 default:
15095 goto pool32axf_invalid;
15097 break;
15098 case 0x34:
15099 switch (minor) {
15100 case MFC2:
15101 case MTC2:
15102 case MFHC2:
15103 case MTHC2:
15104 case CFC2:
15105 case CTC2:
15106 generate_exception_err(ctx, EXCP_CpU, 2);
15107 break;
15108 default:
15109 goto pool32axf_invalid;
15111 break;
15112 case 0x3c:
15113 switch (minor) {
15114 case JALR: /* JALRC */
15115 case JALR_HB: /* JALRC_HB */
15116 if (ctx->insn_flags & ISA_MIPS32R6) {
15117 /* JALRC, JALRC_HB */
15118 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15119 } else {
15120 /* JALR, JALR_HB */
15121 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15122 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15124 break;
15125 case JALRS:
15126 case JALRS_HB:
15127 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15128 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15129 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15130 break;
15131 default:
15132 goto pool32axf_invalid;
15134 break;
15135 case 0x05:
15136 switch (minor) {
15137 case RDPGPR:
15138 check_cp0_enabled(ctx);
15139 check_insn(ctx, ISA_MIPS32R2);
15140 gen_load_srsgpr(rs, rt);
15141 break;
15142 case WRPGPR:
15143 check_cp0_enabled(ctx);
15144 check_insn(ctx, ISA_MIPS32R2);
15145 gen_store_srsgpr(rs, rt);
15146 break;
15147 default:
15148 goto pool32axf_invalid;
15150 break;
15151 #ifndef CONFIG_USER_ONLY
15152 case 0x0d:
15153 switch (minor) {
15154 case TLBP:
15155 mips32_op = OPC_TLBP;
15156 goto do_cp0;
15157 case TLBR:
15158 mips32_op = OPC_TLBR;
15159 goto do_cp0;
15160 case TLBWI:
15161 mips32_op = OPC_TLBWI;
15162 goto do_cp0;
15163 case TLBWR:
15164 mips32_op = OPC_TLBWR;
15165 goto do_cp0;
15166 case TLBINV:
15167 mips32_op = OPC_TLBINV;
15168 goto do_cp0;
15169 case TLBINVF:
15170 mips32_op = OPC_TLBINVF;
15171 goto do_cp0;
15172 case WAIT:
15173 mips32_op = OPC_WAIT;
15174 goto do_cp0;
15175 case DERET:
15176 mips32_op = OPC_DERET;
15177 goto do_cp0;
15178 case ERET:
15179 mips32_op = OPC_ERET;
15180 do_cp0:
15181 gen_cp0(env, ctx, mips32_op, rt, rs);
15182 break;
15183 default:
15184 goto pool32axf_invalid;
15186 break;
15187 case 0x1d:
15188 switch (minor) {
15189 case DI:
15190 check_cp0_enabled(ctx);
15192 TCGv t0 = tcg_temp_new();
15194 save_cpu_state(ctx, 1);
15195 gen_helper_di(t0, cpu_env);
15196 gen_store_gpr(t0, rs);
15197 /* Stop translation as we may have switched the execution mode */
15198 ctx->base.is_jmp = DISAS_STOP;
15199 tcg_temp_free(t0);
15201 break;
15202 case EI:
15203 check_cp0_enabled(ctx);
15205 TCGv t0 = tcg_temp_new();
15207 save_cpu_state(ctx, 1);
15208 gen_helper_ei(t0, cpu_env);
15209 gen_store_gpr(t0, rs);
15210 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15211 of translated code to check for pending interrupts. */
15212 gen_save_pc(ctx->base.pc_next + 4);
15213 ctx->base.is_jmp = DISAS_EXIT;
15214 tcg_temp_free(t0);
15216 break;
15217 default:
15218 goto pool32axf_invalid;
15220 break;
15221 #endif
15222 case 0x2d:
15223 switch (minor) {
15224 case SYNC:
15225 gen_sync(extract32(ctx->opcode, 16, 5));
15226 break;
15227 case SYSCALL:
15228 generate_exception_end(ctx, EXCP_SYSCALL);
15229 break;
15230 case SDBBP:
15231 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15232 gen_helper_do_semihosting(cpu_env);
15233 } else {
15234 check_insn(ctx, ISA_MIPS32);
15235 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15236 generate_exception_end(ctx, EXCP_RI);
15237 } else {
15238 generate_exception_end(ctx, EXCP_DBp);
15241 break;
15242 default:
15243 goto pool32axf_invalid;
15245 break;
15246 case 0x01:
15247 switch (minor & 3) {
15248 case MFHI_ACC:
15249 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15250 break;
15251 case MFLO_ACC:
15252 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15253 break;
15254 case MTHI_ACC:
15255 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15256 break;
15257 case MTLO_ACC:
15258 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15259 break;
15260 default:
15261 goto pool32axf_invalid;
15263 break;
15264 case 0x35:
15265 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15266 switch (minor) {
15267 case MFHI32:
15268 gen_HILO(ctx, OPC_MFHI, 0, rs);
15269 break;
15270 case MFLO32:
15271 gen_HILO(ctx, OPC_MFLO, 0, rs);
15272 break;
15273 case MTHI32:
15274 gen_HILO(ctx, OPC_MTHI, 0, rs);
15275 break;
15276 case MTLO32:
15277 gen_HILO(ctx, OPC_MTLO, 0, rs);
15278 break;
15279 default:
15280 goto pool32axf_invalid;
15282 break;
15283 default:
15284 pool32axf_invalid:
15285 MIPS_INVAL("pool32axf");
15286 generate_exception_end(ctx, EXCP_RI);
15287 break;
15291 /* Values for microMIPS fmt field. Variable-width, depending on which
15292 formats the instruction supports. */
15294 enum {
15295 FMT_SD_S = 0,
15296 FMT_SD_D = 1,
15298 FMT_SDPS_S = 0,
15299 FMT_SDPS_D = 1,
15300 FMT_SDPS_PS = 2,
15302 FMT_SWL_S = 0,
15303 FMT_SWL_W = 1,
15304 FMT_SWL_L = 2,
15306 FMT_DWL_D = 0,
15307 FMT_DWL_W = 1,
15308 FMT_DWL_L = 2
15311 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15313 int extension = (ctx->opcode >> 6) & 0x3ff;
15314 uint32_t mips32_op;
15316 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15317 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15318 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15320 switch (extension) {
15321 case FLOAT_1BIT_FMT(CFC1, 0):
15322 mips32_op = OPC_CFC1;
15323 goto do_cp1;
15324 case FLOAT_1BIT_FMT(CTC1, 0):
15325 mips32_op = OPC_CTC1;
15326 goto do_cp1;
15327 case FLOAT_1BIT_FMT(MFC1, 0):
15328 mips32_op = OPC_MFC1;
15329 goto do_cp1;
15330 case FLOAT_1BIT_FMT(MTC1, 0):
15331 mips32_op = OPC_MTC1;
15332 goto do_cp1;
15333 case FLOAT_1BIT_FMT(MFHC1, 0):
15334 mips32_op = OPC_MFHC1;
15335 goto do_cp1;
15336 case FLOAT_1BIT_FMT(MTHC1, 0):
15337 mips32_op = OPC_MTHC1;
15338 do_cp1:
15339 gen_cp1(ctx, mips32_op, rt, rs);
15340 break;
15342 /* Reciprocal square root */
15343 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15344 mips32_op = OPC_RSQRT_S;
15345 goto do_unaryfp;
15346 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15347 mips32_op = OPC_RSQRT_D;
15348 goto do_unaryfp;
15350 /* Square root */
15351 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15352 mips32_op = OPC_SQRT_S;
15353 goto do_unaryfp;
15354 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15355 mips32_op = OPC_SQRT_D;
15356 goto do_unaryfp;
15358 /* Reciprocal */
15359 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15360 mips32_op = OPC_RECIP_S;
15361 goto do_unaryfp;
15362 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15363 mips32_op = OPC_RECIP_D;
15364 goto do_unaryfp;
15366 /* Floor */
15367 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15368 mips32_op = OPC_FLOOR_L_S;
15369 goto do_unaryfp;
15370 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15371 mips32_op = OPC_FLOOR_L_D;
15372 goto do_unaryfp;
15373 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15374 mips32_op = OPC_FLOOR_W_S;
15375 goto do_unaryfp;
15376 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15377 mips32_op = OPC_FLOOR_W_D;
15378 goto do_unaryfp;
15380 /* Ceiling */
15381 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15382 mips32_op = OPC_CEIL_L_S;
15383 goto do_unaryfp;
15384 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15385 mips32_op = OPC_CEIL_L_D;
15386 goto do_unaryfp;
15387 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15388 mips32_op = OPC_CEIL_W_S;
15389 goto do_unaryfp;
15390 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15391 mips32_op = OPC_CEIL_W_D;
15392 goto do_unaryfp;
15394 /* Truncation */
15395 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15396 mips32_op = OPC_TRUNC_L_S;
15397 goto do_unaryfp;
15398 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15399 mips32_op = OPC_TRUNC_L_D;
15400 goto do_unaryfp;
15401 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15402 mips32_op = OPC_TRUNC_W_S;
15403 goto do_unaryfp;
15404 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15405 mips32_op = OPC_TRUNC_W_D;
15406 goto do_unaryfp;
15408 /* Round */
15409 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15410 mips32_op = OPC_ROUND_L_S;
15411 goto do_unaryfp;
15412 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15413 mips32_op = OPC_ROUND_L_D;
15414 goto do_unaryfp;
15415 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15416 mips32_op = OPC_ROUND_W_S;
15417 goto do_unaryfp;
15418 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15419 mips32_op = OPC_ROUND_W_D;
15420 goto do_unaryfp;
15422 /* Integer to floating-point conversion */
15423 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15424 mips32_op = OPC_CVT_L_S;
15425 goto do_unaryfp;
15426 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15427 mips32_op = OPC_CVT_L_D;
15428 goto do_unaryfp;
15429 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15430 mips32_op = OPC_CVT_W_S;
15431 goto do_unaryfp;
15432 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15433 mips32_op = OPC_CVT_W_D;
15434 goto do_unaryfp;
15436 /* Paired-foo conversions */
15437 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15438 mips32_op = OPC_CVT_S_PL;
15439 goto do_unaryfp;
15440 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15441 mips32_op = OPC_CVT_S_PU;
15442 goto do_unaryfp;
15443 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15444 mips32_op = OPC_CVT_PW_PS;
15445 goto do_unaryfp;
15446 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15447 mips32_op = OPC_CVT_PS_PW;
15448 goto do_unaryfp;
15450 /* Floating-point moves */
15451 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15452 mips32_op = OPC_MOV_S;
15453 goto do_unaryfp;
15454 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15455 mips32_op = OPC_MOV_D;
15456 goto do_unaryfp;
15457 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15458 mips32_op = OPC_MOV_PS;
15459 goto do_unaryfp;
15461 /* Absolute value */
15462 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15463 mips32_op = OPC_ABS_S;
15464 goto do_unaryfp;
15465 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15466 mips32_op = OPC_ABS_D;
15467 goto do_unaryfp;
15468 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15469 mips32_op = OPC_ABS_PS;
15470 goto do_unaryfp;
15472 /* Negation */
15473 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15474 mips32_op = OPC_NEG_S;
15475 goto do_unaryfp;
15476 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15477 mips32_op = OPC_NEG_D;
15478 goto do_unaryfp;
15479 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15480 mips32_op = OPC_NEG_PS;
15481 goto do_unaryfp;
15483 /* Reciprocal square root step */
15484 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15485 mips32_op = OPC_RSQRT1_S;
15486 goto do_unaryfp;
15487 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15488 mips32_op = OPC_RSQRT1_D;
15489 goto do_unaryfp;
15490 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15491 mips32_op = OPC_RSQRT1_PS;
15492 goto do_unaryfp;
15494 /* Reciprocal step */
15495 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15496 mips32_op = OPC_RECIP1_S;
15497 goto do_unaryfp;
15498 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15499 mips32_op = OPC_RECIP1_S;
15500 goto do_unaryfp;
15501 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15502 mips32_op = OPC_RECIP1_PS;
15503 goto do_unaryfp;
15505 /* Conversions from double */
15506 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15507 mips32_op = OPC_CVT_D_S;
15508 goto do_unaryfp;
15509 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15510 mips32_op = OPC_CVT_D_W;
15511 goto do_unaryfp;
15512 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15513 mips32_op = OPC_CVT_D_L;
15514 goto do_unaryfp;
15516 /* Conversions from single */
15517 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15518 mips32_op = OPC_CVT_S_D;
15519 goto do_unaryfp;
15520 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15521 mips32_op = OPC_CVT_S_W;
15522 goto do_unaryfp;
15523 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15524 mips32_op = OPC_CVT_S_L;
15525 do_unaryfp:
15526 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15527 break;
15529 /* Conditional moves on floating-point codes */
15530 case COND_FLOAT_MOV(MOVT, 0):
15531 case COND_FLOAT_MOV(MOVT, 1):
15532 case COND_FLOAT_MOV(MOVT, 2):
15533 case COND_FLOAT_MOV(MOVT, 3):
15534 case COND_FLOAT_MOV(MOVT, 4):
15535 case COND_FLOAT_MOV(MOVT, 5):
15536 case COND_FLOAT_MOV(MOVT, 6):
15537 case COND_FLOAT_MOV(MOVT, 7):
15538 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15539 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15540 break;
15541 case COND_FLOAT_MOV(MOVF, 0):
15542 case COND_FLOAT_MOV(MOVF, 1):
15543 case COND_FLOAT_MOV(MOVF, 2):
15544 case COND_FLOAT_MOV(MOVF, 3):
15545 case COND_FLOAT_MOV(MOVF, 4):
15546 case COND_FLOAT_MOV(MOVF, 5):
15547 case COND_FLOAT_MOV(MOVF, 6):
15548 case COND_FLOAT_MOV(MOVF, 7):
15549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15550 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15551 break;
15552 default:
15553 MIPS_INVAL("pool32fxf");
15554 generate_exception_end(ctx, EXCP_RI);
15555 break;
15559 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15561 int32_t offset;
15562 uint16_t insn;
15563 int rt, rs, rd, rr;
15564 int16_t imm;
15565 uint32_t op, minor, minor2, mips32_op;
15566 uint32_t cond, fmt, cc;
15568 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15569 ctx->opcode = (ctx->opcode << 16) | insn;
15571 rt = (ctx->opcode >> 21) & 0x1f;
15572 rs = (ctx->opcode >> 16) & 0x1f;
15573 rd = (ctx->opcode >> 11) & 0x1f;
15574 rr = (ctx->opcode >> 6) & 0x1f;
15575 imm = (int16_t) ctx->opcode;
15577 op = (ctx->opcode >> 26) & 0x3f;
15578 switch (op) {
15579 case POOL32A:
15580 minor = ctx->opcode & 0x3f;
15581 switch (minor) {
15582 case 0x00:
15583 minor = (ctx->opcode >> 6) & 0xf;
15584 switch (minor) {
15585 case SLL32:
15586 mips32_op = OPC_SLL;
15587 goto do_shifti;
15588 case SRA:
15589 mips32_op = OPC_SRA;
15590 goto do_shifti;
15591 case SRL32:
15592 mips32_op = OPC_SRL;
15593 goto do_shifti;
15594 case ROTR:
15595 mips32_op = OPC_ROTR;
15596 do_shifti:
15597 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15598 break;
15599 case SELEQZ:
15600 check_insn(ctx, ISA_MIPS32R6);
15601 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15602 break;
15603 case SELNEZ:
15604 check_insn(ctx, ISA_MIPS32R6);
15605 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15606 break;
15607 case R6_RDHWR:
15608 check_insn(ctx, ISA_MIPS32R6);
15609 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15610 break;
15611 default:
15612 goto pool32a_invalid;
15614 break;
15615 case 0x10:
15616 minor = (ctx->opcode >> 6) & 0xf;
15617 switch (minor) {
15618 /* Arithmetic */
15619 case ADD:
15620 mips32_op = OPC_ADD;
15621 goto do_arith;
15622 case ADDU32:
15623 mips32_op = OPC_ADDU;
15624 goto do_arith;
15625 case SUB:
15626 mips32_op = OPC_SUB;
15627 goto do_arith;
15628 case SUBU32:
15629 mips32_op = OPC_SUBU;
15630 goto do_arith;
15631 case MUL:
15632 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15633 mips32_op = OPC_MUL;
15634 do_arith:
15635 gen_arith(ctx, mips32_op, rd, rs, rt);
15636 break;
15637 /* Shifts */
15638 case SLLV:
15639 mips32_op = OPC_SLLV;
15640 goto do_shift;
15641 case SRLV:
15642 mips32_op = OPC_SRLV;
15643 goto do_shift;
15644 case SRAV:
15645 mips32_op = OPC_SRAV;
15646 goto do_shift;
15647 case ROTRV:
15648 mips32_op = OPC_ROTRV;
15649 do_shift:
15650 gen_shift(ctx, mips32_op, rd, rs, rt);
15651 break;
15652 /* Logical operations */
15653 case AND:
15654 mips32_op = OPC_AND;
15655 goto do_logic;
15656 case OR32:
15657 mips32_op = OPC_OR;
15658 goto do_logic;
15659 case NOR:
15660 mips32_op = OPC_NOR;
15661 goto do_logic;
15662 case XOR32:
15663 mips32_op = OPC_XOR;
15664 do_logic:
15665 gen_logic(ctx, mips32_op, rd, rs, rt);
15666 break;
15667 /* Set less than */
15668 case SLT:
15669 mips32_op = OPC_SLT;
15670 goto do_slt;
15671 case SLTU:
15672 mips32_op = OPC_SLTU;
15673 do_slt:
15674 gen_slt(ctx, mips32_op, rd, rs, rt);
15675 break;
15676 default:
15677 goto pool32a_invalid;
15679 break;
15680 case 0x18:
15681 minor = (ctx->opcode >> 6) & 0xf;
15682 switch (minor) {
15683 /* Conditional moves */
15684 case MOVN: /* MUL */
15685 if (ctx->insn_flags & ISA_MIPS32R6) {
15686 /* MUL */
15687 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15688 } else {
15689 /* MOVN */
15690 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15692 break;
15693 case MOVZ: /* MUH */
15694 if (ctx->insn_flags & ISA_MIPS32R6) {
15695 /* MUH */
15696 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15697 } else {
15698 /* MOVZ */
15699 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15701 break;
15702 case MULU:
15703 check_insn(ctx, ISA_MIPS32R6);
15704 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15705 break;
15706 case MUHU:
15707 check_insn(ctx, ISA_MIPS32R6);
15708 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15709 break;
15710 case LWXS: /* DIV */
15711 if (ctx->insn_flags & ISA_MIPS32R6) {
15712 /* DIV */
15713 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15714 } else {
15715 /* LWXS */
15716 gen_ldxs(ctx, rs, rt, rd);
15718 break;
15719 case MOD:
15720 check_insn(ctx, ISA_MIPS32R6);
15721 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15722 break;
15723 case R6_DIVU:
15724 check_insn(ctx, ISA_MIPS32R6);
15725 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15726 break;
15727 case MODU:
15728 check_insn(ctx, ISA_MIPS32R6);
15729 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15730 break;
15731 default:
15732 goto pool32a_invalid;
15734 break;
15735 case INS:
15736 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15737 return;
15738 case LSA:
15739 check_insn(ctx, ISA_MIPS32R6);
15740 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15741 extract32(ctx->opcode, 9, 2));
15742 break;
15743 case ALIGN:
15744 check_insn(ctx, ISA_MIPS32R6);
15745 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15746 break;
15747 case EXT:
15748 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15749 return;
15750 case POOL32AXF:
15751 gen_pool32axf(env, ctx, rt, rs);
15752 break;
15753 case BREAK32:
15754 generate_exception_end(ctx, EXCP_BREAK);
15755 break;
15756 case SIGRIE:
15757 check_insn(ctx, ISA_MIPS32R6);
15758 generate_exception_end(ctx, EXCP_RI);
15759 break;
15760 default:
15761 pool32a_invalid:
15762 MIPS_INVAL("pool32a");
15763 generate_exception_end(ctx, EXCP_RI);
15764 break;
15766 break;
15767 case POOL32B:
15768 minor = (ctx->opcode >> 12) & 0xf;
15769 switch (minor) {
15770 case CACHE:
15771 check_cp0_enabled(ctx);
15772 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15773 gen_cache_operation(ctx, rt, rs, imm);
15775 break;
15776 case LWC2:
15777 case SWC2:
15778 /* COP2: Not implemented. */
15779 generate_exception_err(ctx, EXCP_CpU, 2);
15780 break;
15781 #ifdef TARGET_MIPS64
15782 case LDP:
15783 case SDP:
15784 check_insn(ctx, ISA_MIPS3);
15785 check_mips_64(ctx);
15786 #endif
15787 /* fall through */
15788 case LWP:
15789 case SWP:
15790 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15791 break;
15792 #ifdef TARGET_MIPS64
15793 case LDM:
15794 case SDM:
15795 check_insn(ctx, ISA_MIPS3);
15796 check_mips_64(ctx);
15797 #endif
15798 /* fall through */
15799 case LWM32:
15800 case SWM32:
15801 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15802 break;
15803 default:
15804 MIPS_INVAL("pool32b");
15805 generate_exception_end(ctx, EXCP_RI);
15806 break;
15808 break;
15809 case POOL32F:
15810 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15811 minor = ctx->opcode & 0x3f;
15812 check_cp1_enabled(ctx);
15813 switch (minor) {
15814 case ALNV_PS:
15815 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15816 mips32_op = OPC_ALNV_PS;
15817 goto do_madd;
15818 case MADD_S:
15819 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15820 mips32_op = OPC_MADD_S;
15821 goto do_madd;
15822 case MADD_D:
15823 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15824 mips32_op = OPC_MADD_D;
15825 goto do_madd;
15826 case MADD_PS:
15827 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15828 mips32_op = OPC_MADD_PS;
15829 goto do_madd;
15830 case MSUB_S:
15831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15832 mips32_op = OPC_MSUB_S;
15833 goto do_madd;
15834 case MSUB_D:
15835 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15836 mips32_op = OPC_MSUB_D;
15837 goto do_madd;
15838 case MSUB_PS:
15839 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15840 mips32_op = OPC_MSUB_PS;
15841 goto do_madd;
15842 case NMADD_S:
15843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15844 mips32_op = OPC_NMADD_S;
15845 goto do_madd;
15846 case NMADD_D:
15847 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15848 mips32_op = OPC_NMADD_D;
15849 goto do_madd;
15850 case NMADD_PS:
15851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15852 mips32_op = OPC_NMADD_PS;
15853 goto do_madd;
15854 case NMSUB_S:
15855 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15856 mips32_op = OPC_NMSUB_S;
15857 goto do_madd;
15858 case NMSUB_D:
15859 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15860 mips32_op = OPC_NMSUB_D;
15861 goto do_madd;
15862 case NMSUB_PS:
15863 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15864 mips32_op = OPC_NMSUB_PS;
15865 do_madd:
15866 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15867 break;
15868 case CABS_COND_FMT:
15869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15870 cond = (ctx->opcode >> 6) & 0xf;
15871 cc = (ctx->opcode >> 13) & 0x7;
15872 fmt = (ctx->opcode >> 10) & 0x3;
15873 switch (fmt) {
15874 case 0x0:
15875 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15876 break;
15877 case 0x1:
15878 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15879 break;
15880 case 0x2:
15881 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15882 break;
15883 default:
15884 goto pool32f_invalid;
15886 break;
15887 case C_COND_FMT:
15888 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15889 cond = (ctx->opcode >> 6) & 0xf;
15890 cc = (ctx->opcode >> 13) & 0x7;
15891 fmt = (ctx->opcode >> 10) & 0x3;
15892 switch (fmt) {
15893 case 0x0:
15894 gen_cmp_s(ctx, cond, rt, rs, cc);
15895 break;
15896 case 0x1:
15897 gen_cmp_d(ctx, cond, rt, rs, cc);
15898 break;
15899 case 0x2:
15900 gen_cmp_ps(ctx, cond, rt, rs, cc);
15901 break;
15902 default:
15903 goto pool32f_invalid;
15905 break;
15906 case CMP_CONDN_S:
15907 check_insn(ctx, ISA_MIPS32R6);
15908 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15909 break;
15910 case CMP_CONDN_D:
15911 check_insn(ctx, ISA_MIPS32R6);
15912 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15913 break;
15914 case POOL32FXF:
15915 gen_pool32fxf(ctx, rt, rs);
15916 break;
15917 case 0x00:
15918 /* PLL foo */
15919 switch ((ctx->opcode >> 6) & 0x7) {
15920 case PLL_PS:
15921 mips32_op = OPC_PLL_PS;
15922 goto do_ps;
15923 case PLU_PS:
15924 mips32_op = OPC_PLU_PS;
15925 goto do_ps;
15926 case PUL_PS:
15927 mips32_op = OPC_PUL_PS;
15928 goto do_ps;
15929 case PUU_PS:
15930 mips32_op = OPC_PUU_PS;
15931 goto do_ps;
15932 case CVT_PS_S:
15933 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15934 mips32_op = OPC_CVT_PS_S;
15935 do_ps:
15936 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15937 break;
15938 default:
15939 goto pool32f_invalid;
15941 break;
15942 case MIN_FMT:
15943 check_insn(ctx, ISA_MIPS32R6);
15944 switch ((ctx->opcode >> 9) & 0x3) {
15945 case FMT_SDPS_S:
15946 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15947 break;
15948 case FMT_SDPS_D:
15949 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15950 break;
15951 default:
15952 goto pool32f_invalid;
15954 break;
15955 case 0x08:
15956 /* [LS][WDU]XC1 */
15957 switch ((ctx->opcode >> 6) & 0x7) {
15958 case LWXC1:
15959 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15960 mips32_op = OPC_LWXC1;
15961 goto do_ldst_cp1;
15962 case SWXC1:
15963 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15964 mips32_op = OPC_SWXC1;
15965 goto do_ldst_cp1;
15966 case LDXC1:
15967 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15968 mips32_op = OPC_LDXC1;
15969 goto do_ldst_cp1;
15970 case SDXC1:
15971 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15972 mips32_op = OPC_SDXC1;
15973 goto do_ldst_cp1;
15974 case LUXC1:
15975 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15976 mips32_op = OPC_LUXC1;
15977 goto do_ldst_cp1;
15978 case SUXC1:
15979 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15980 mips32_op = OPC_SUXC1;
15981 do_ldst_cp1:
15982 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15983 break;
15984 default:
15985 goto pool32f_invalid;
15987 break;
15988 case MAX_FMT:
15989 check_insn(ctx, ISA_MIPS32R6);
15990 switch ((ctx->opcode >> 9) & 0x3) {
15991 case FMT_SDPS_S:
15992 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15993 break;
15994 case FMT_SDPS_D:
15995 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15996 break;
15997 default:
15998 goto pool32f_invalid;
16000 break;
16001 case 0x18:
16002 /* 3D insns */
16003 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16004 fmt = (ctx->opcode >> 9) & 0x3;
16005 switch ((ctx->opcode >> 6) & 0x7) {
16006 case RSQRT2_FMT:
16007 switch (fmt) {
16008 case FMT_SDPS_S:
16009 mips32_op = OPC_RSQRT2_S;
16010 goto do_3d;
16011 case FMT_SDPS_D:
16012 mips32_op = OPC_RSQRT2_D;
16013 goto do_3d;
16014 case FMT_SDPS_PS:
16015 mips32_op = OPC_RSQRT2_PS;
16016 goto do_3d;
16017 default:
16018 goto pool32f_invalid;
16020 break;
16021 case RECIP2_FMT:
16022 switch (fmt) {
16023 case FMT_SDPS_S:
16024 mips32_op = OPC_RECIP2_S;
16025 goto do_3d;
16026 case FMT_SDPS_D:
16027 mips32_op = OPC_RECIP2_D;
16028 goto do_3d;
16029 case FMT_SDPS_PS:
16030 mips32_op = OPC_RECIP2_PS;
16031 goto do_3d;
16032 default:
16033 goto pool32f_invalid;
16035 break;
16036 case ADDR_PS:
16037 mips32_op = OPC_ADDR_PS;
16038 goto do_3d;
16039 case MULR_PS:
16040 mips32_op = OPC_MULR_PS;
16041 do_3d:
16042 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16043 break;
16044 default:
16045 goto pool32f_invalid;
16047 break;
16048 case 0x20:
16049 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16050 cc = (ctx->opcode >> 13) & 0x7;
16051 fmt = (ctx->opcode >> 9) & 0x3;
16052 switch ((ctx->opcode >> 6) & 0x7) {
16053 case MOVF_FMT: /* RINT_FMT */
16054 if (ctx->insn_flags & ISA_MIPS32R6) {
16055 /* RINT_FMT */
16056 switch (fmt) {
16057 case FMT_SDPS_S:
16058 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16059 break;
16060 case FMT_SDPS_D:
16061 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16062 break;
16063 default:
16064 goto pool32f_invalid;
16066 } else {
16067 /* MOVF_FMT */
16068 switch (fmt) {
16069 case FMT_SDPS_S:
16070 gen_movcf_s(ctx, rs, rt, cc, 0);
16071 break;
16072 case FMT_SDPS_D:
16073 gen_movcf_d(ctx, rs, rt, cc, 0);
16074 break;
16075 case FMT_SDPS_PS:
16076 check_ps(ctx);
16077 gen_movcf_ps(ctx, rs, rt, cc, 0);
16078 break;
16079 default:
16080 goto pool32f_invalid;
16083 break;
16084 case MOVT_FMT: /* CLASS_FMT */
16085 if (ctx->insn_flags & ISA_MIPS32R6) {
16086 /* CLASS_FMT */
16087 switch (fmt) {
16088 case FMT_SDPS_S:
16089 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16090 break;
16091 case FMT_SDPS_D:
16092 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16093 break;
16094 default:
16095 goto pool32f_invalid;
16097 } else {
16098 /* MOVT_FMT */
16099 switch (fmt) {
16100 case FMT_SDPS_S:
16101 gen_movcf_s(ctx, rs, rt, cc, 1);
16102 break;
16103 case FMT_SDPS_D:
16104 gen_movcf_d(ctx, rs, rt, cc, 1);
16105 break;
16106 case FMT_SDPS_PS:
16107 check_ps(ctx);
16108 gen_movcf_ps(ctx, rs, rt, cc, 1);
16109 break;
16110 default:
16111 goto pool32f_invalid;
16114 break;
16115 case PREFX:
16116 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16117 break;
16118 default:
16119 goto pool32f_invalid;
16121 break;
16122 #define FINSN_3ARG_SDPS(prfx) \
16123 switch ((ctx->opcode >> 8) & 0x3) { \
16124 case FMT_SDPS_S: \
16125 mips32_op = OPC_##prfx##_S; \
16126 goto do_fpop; \
16127 case FMT_SDPS_D: \
16128 mips32_op = OPC_##prfx##_D; \
16129 goto do_fpop; \
16130 case FMT_SDPS_PS: \
16131 check_ps(ctx); \
16132 mips32_op = OPC_##prfx##_PS; \
16133 goto do_fpop; \
16134 default: \
16135 goto pool32f_invalid; \
16137 case MINA_FMT:
16138 check_insn(ctx, ISA_MIPS32R6);
16139 switch ((ctx->opcode >> 9) & 0x3) {
16140 case FMT_SDPS_S:
16141 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16142 break;
16143 case FMT_SDPS_D:
16144 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16145 break;
16146 default:
16147 goto pool32f_invalid;
16149 break;
16150 case MAXA_FMT:
16151 check_insn(ctx, ISA_MIPS32R6);
16152 switch ((ctx->opcode >> 9) & 0x3) {
16153 case FMT_SDPS_S:
16154 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16155 break;
16156 case FMT_SDPS_D:
16157 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16158 break;
16159 default:
16160 goto pool32f_invalid;
16162 break;
16163 case 0x30:
16164 /* regular FP ops */
16165 switch ((ctx->opcode >> 6) & 0x3) {
16166 case ADD_FMT:
16167 FINSN_3ARG_SDPS(ADD);
16168 break;
16169 case SUB_FMT:
16170 FINSN_3ARG_SDPS(SUB);
16171 break;
16172 case MUL_FMT:
16173 FINSN_3ARG_SDPS(MUL);
16174 break;
16175 case DIV_FMT:
16176 fmt = (ctx->opcode >> 8) & 0x3;
16177 if (fmt == 1) {
16178 mips32_op = OPC_DIV_D;
16179 } else if (fmt == 0) {
16180 mips32_op = OPC_DIV_S;
16181 } else {
16182 goto pool32f_invalid;
16184 goto do_fpop;
16185 default:
16186 goto pool32f_invalid;
16188 break;
16189 case 0x38:
16190 /* cmovs */
16191 switch ((ctx->opcode >> 6) & 0x7) {
16192 case MOVN_FMT: /* SELEQZ_FMT */
16193 if (ctx->insn_flags & ISA_MIPS32R6) {
16194 /* SELEQZ_FMT */
16195 switch ((ctx->opcode >> 9) & 0x3) {
16196 case FMT_SDPS_S:
16197 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16198 break;
16199 case FMT_SDPS_D:
16200 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16201 break;
16202 default:
16203 goto pool32f_invalid;
16205 } else {
16206 /* MOVN_FMT */
16207 FINSN_3ARG_SDPS(MOVN);
16209 break;
16210 case MOVN_FMT_04:
16211 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16212 FINSN_3ARG_SDPS(MOVN);
16213 break;
16214 case MOVZ_FMT: /* SELNEZ_FMT */
16215 if (ctx->insn_flags & ISA_MIPS32R6) {
16216 /* SELNEZ_FMT */
16217 switch ((ctx->opcode >> 9) & 0x3) {
16218 case FMT_SDPS_S:
16219 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16220 break;
16221 case FMT_SDPS_D:
16222 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16223 break;
16224 default:
16225 goto pool32f_invalid;
16227 } else {
16228 /* MOVZ_FMT */
16229 FINSN_3ARG_SDPS(MOVZ);
16231 break;
16232 case MOVZ_FMT_05:
16233 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16234 FINSN_3ARG_SDPS(MOVZ);
16235 break;
16236 case SEL_FMT:
16237 check_insn(ctx, ISA_MIPS32R6);
16238 switch ((ctx->opcode >> 9) & 0x3) {
16239 case FMT_SDPS_S:
16240 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16241 break;
16242 case FMT_SDPS_D:
16243 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16244 break;
16245 default:
16246 goto pool32f_invalid;
16248 break;
16249 case MADDF_FMT:
16250 check_insn(ctx, ISA_MIPS32R6);
16251 switch ((ctx->opcode >> 9) & 0x3) {
16252 case FMT_SDPS_S:
16253 mips32_op = OPC_MADDF_S;
16254 goto do_fpop;
16255 case FMT_SDPS_D:
16256 mips32_op = OPC_MADDF_D;
16257 goto do_fpop;
16258 default:
16259 goto pool32f_invalid;
16261 break;
16262 case MSUBF_FMT:
16263 check_insn(ctx, ISA_MIPS32R6);
16264 switch ((ctx->opcode >> 9) & 0x3) {
16265 case FMT_SDPS_S:
16266 mips32_op = OPC_MSUBF_S;
16267 goto do_fpop;
16268 case FMT_SDPS_D:
16269 mips32_op = OPC_MSUBF_D;
16270 goto do_fpop;
16271 default:
16272 goto pool32f_invalid;
16274 break;
16275 default:
16276 goto pool32f_invalid;
16278 break;
16279 do_fpop:
16280 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16281 break;
16282 default:
16283 pool32f_invalid:
16284 MIPS_INVAL("pool32f");
16285 generate_exception_end(ctx, EXCP_RI);
16286 break;
16288 } else {
16289 generate_exception_err(ctx, EXCP_CpU, 1);
16291 break;
16292 case POOL32I:
16293 minor = (ctx->opcode >> 21) & 0x1f;
16294 switch (minor) {
16295 case BLTZ:
16296 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16297 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16298 break;
16299 case BLTZAL:
16300 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16301 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16302 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16303 break;
16304 case BLTZALS:
16305 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16306 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16307 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16308 break;
16309 case BGEZ:
16310 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16311 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16312 break;
16313 case BGEZAL:
16314 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16315 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16316 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16317 break;
16318 case BGEZALS:
16319 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16320 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16321 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16322 break;
16323 case BLEZ:
16324 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16325 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16326 break;
16327 case BGTZ:
16328 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16329 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16330 break;
16332 /* Traps */
16333 case TLTI: /* BC1EQZC */
16334 if (ctx->insn_flags & ISA_MIPS32R6) {
16335 /* BC1EQZC */
16336 check_cp1_enabled(ctx);
16337 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16338 } else {
16339 /* TLTI */
16340 mips32_op = OPC_TLTI;
16341 goto do_trapi;
16343 break;
16344 case TGEI: /* BC1NEZC */
16345 if (ctx->insn_flags & ISA_MIPS32R6) {
16346 /* BC1NEZC */
16347 check_cp1_enabled(ctx);
16348 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16349 } else {
16350 /* TGEI */
16351 mips32_op = OPC_TGEI;
16352 goto do_trapi;
16354 break;
16355 case TLTIU:
16356 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16357 mips32_op = OPC_TLTIU;
16358 goto do_trapi;
16359 case TGEIU:
16360 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16361 mips32_op = OPC_TGEIU;
16362 goto do_trapi;
16363 case TNEI: /* SYNCI */
16364 if (ctx->insn_flags & ISA_MIPS32R6) {
16365 /* SYNCI */
16366 /* Break the TB to be able to sync copied instructions
16367 immediately */
16368 ctx->base.is_jmp = DISAS_STOP;
16369 } else {
16370 /* TNEI */
16371 mips32_op = OPC_TNEI;
16372 goto do_trapi;
16374 break;
16375 case TEQI:
16376 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16377 mips32_op = OPC_TEQI;
16378 do_trapi:
16379 gen_trap(ctx, mips32_op, rs, -1, imm);
16380 break;
16382 case BNEZC:
16383 case BEQZC:
16384 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16385 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16386 4, rs, 0, imm << 1, 0);
16387 /* Compact branches don't have a delay slot, so just let
16388 the normal delay slot handling take us to the branch
16389 target. */
16390 break;
16391 case LUI:
16392 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16393 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16394 break;
16395 case SYNCI:
16396 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16397 /* Break the TB to be able to sync copied instructions
16398 immediately */
16399 ctx->base.is_jmp = DISAS_STOP;
16400 break;
16401 case BC2F:
16402 case BC2T:
16403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16404 /* COP2: Not implemented. */
16405 generate_exception_err(ctx, EXCP_CpU, 2);
16406 break;
16407 case BC1F:
16408 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16409 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16410 goto do_cp1branch;
16411 case BC1T:
16412 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16413 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16414 goto do_cp1branch;
16415 case BC1ANY4F:
16416 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16417 mips32_op = OPC_BC1FANY4;
16418 goto do_cp1mips3d;
16419 case BC1ANY4T:
16420 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16421 mips32_op = OPC_BC1TANY4;
16422 do_cp1mips3d:
16423 check_cop1x(ctx);
16424 check_insn(ctx, ASE_MIPS3D);
16425 /* Fall through */
16426 do_cp1branch:
16427 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16428 check_cp1_enabled(ctx);
16429 gen_compute_branch1(ctx, mips32_op,
16430 (ctx->opcode >> 18) & 0x7, imm << 1);
16431 } else {
16432 generate_exception_err(ctx, EXCP_CpU, 1);
16434 break;
16435 case BPOSGE64:
16436 case BPOSGE32:
16437 /* MIPS DSP: not implemented */
16438 /* Fall through */
16439 default:
16440 MIPS_INVAL("pool32i");
16441 generate_exception_end(ctx, EXCP_RI);
16442 break;
16444 break;
16445 case POOL32C:
16446 minor = (ctx->opcode >> 12) & 0xf;
16447 offset = sextract32(ctx->opcode, 0,
16448 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16449 switch (minor) {
16450 case LWL:
16451 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16452 mips32_op = OPC_LWL;
16453 goto do_ld_lr;
16454 case SWL:
16455 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16456 mips32_op = OPC_SWL;
16457 goto do_st_lr;
16458 case LWR:
16459 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16460 mips32_op = OPC_LWR;
16461 goto do_ld_lr;
16462 case SWR:
16463 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16464 mips32_op = OPC_SWR;
16465 goto do_st_lr;
16466 #if defined(TARGET_MIPS64)
16467 case LDL:
16468 check_insn(ctx, ISA_MIPS3);
16469 check_mips_64(ctx);
16470 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16471 mips32_op = OPC_LDL;
16472 goto do_ld_lr;
16473 case SDL:
16474 check_insn(ctx, ISA_MIPS3);
16475 check_mips_64(ctx);
16476 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16477 mips32_op = OPC_SDL;
16478 goto do_st_lr;
16479 case LDR:
16480 check_insn(ctx, ISA_MIPS3);
16481 check_mips_64(ctx);
16482 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16483 mips32_op = OPC_LDR;
16484 goto do_ld_lr;
16485 case SDR:
16486 check_insn(ctx, ISA_MIPS3);
16487 check_mips_64(ctx);
16488 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16489 mips32_op = OPC_SDR;
16490 goto do_st_lr;
16491 case LWU:
16492 check_insn(ctx, ISA_MIPS3);
16493 check_mips_64(ctx);
16494 mips32_op = OPC_LWU;
16495 goto do_ld_lr;
16496 case LLD:
16497 check_insn(ctx, ISA_MIPS3);
16498 check_mips_64(ctx);
16499 mips32_op = OPC_LLD;
16500 goto do_ld_lr;
16501 #endif
16502 case LL:
16503 mips32_op = OPC_LL;
16504 goto do_ld_lr;
16505 do_ld_lr:
16506 gen_ld(ctx, mips32_op, rt, rs, offset);
16507 break;
16508 do_st_lr:
16509 gen_st(ctx, mips32_op, rt, rs, offset);
16510 break;
16511 case SC:
16512 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16513 break;
16514 #if defined(TARGET_MIPS64)
16515 case SCD:
16516 check_insn(ctx, ISA_MIPS3);
16517 check_mips_64(ctx);
16518 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16519 break;
16520 #endif
16521 case LD_EVA:
16522 if (!ctx->eva) {
16523 MIPS_INVAL("pool32c ld-eva");
16524 generate_exception_end(ctx, EXCP_RI);
16525 break;
16527 check_cp0_enabled(ctx);
16529 minor2 = (ctx->opcode >> 9) & 0x7;
16530 offset = sextract32(ctx->opcode, 0, 9);
16531 switch (minor2) {
16532 case LBUE:
16533 mips32_op = OPC_LBUE;
16534 goto do_ld_lr;
16535 case LHUE:
16536 mips32_op = OPC_LHUE;
16537 goto do_ld_lr;
16538 case LWLE:
16539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16540 mips32_op = OPC_LWLE;
16541 goto do_ld_lr;
16542 case LWRE:
16543 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16544 mips32_op = OPC_LWRE;
16545 goto do_ld_lr;
16546 case LBE:
16547 mips32_op = OPC_LBE;
16548 goto do_ld_lr;
16549 case LHE:
16550 mips32_op = OPC_LHE;
16551 goto do_ld_lr;
16552 case LLE:
16553 mips32_op = OPC_LLE;
16554 goto do_ld_lr;
16555 case LWE:
16556 mips32_op = OPC_LWE;
16557 goto do_ld_lr;
16559 break;
16560 case ST_EVA:
16561 if (!ctx->eva) {
16562 MIPS_INVAL("pool32c st-eva");
16563 generate_exception_end(ctx, EXCP_RI);
16564 break;
16566 check_cp0_enabled(ctx);
16568 minor2 = (ctx->opcode >> 9) & 0x7;
16569 offset = sextract32(ctx->opcode, 0, 9);
16570 switch (minor2) {
16571 case SWLE:
16572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16573 mips32_op = OPC_SWLE;
16574 goto do_st_lr;
16575 case SWRE:
16576 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16577 mips32_op = OPC_SWRE;
16578 goto do_st_lr;
16579 case PREFE:
16580 /* Treat as no-op */
16581 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16582 /* hint codes 24-31 are reserved and signal RI */
16583 generate_exception(ctx, EXCP_RI);
16585 break;
16586 case CACHEE:
16587 /* Treat as no-op */
16588 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16589 gen_cache_operation(ctx, rt, rs, offset);
16591 break;
16592 case SBE:
16593 mips32_op = OPC_SBE;
16594 goto do_st_lr;
16595 case SHE:
16596 mips32_op = OPC_SHE;
16597 goto do_st_lr;
16598 case SCE:
16599 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16600 break;
16601 case SWE:
16602 mips32_op = OPC_SWE;
16603 goto do_st_lr;
16605 break;
16606 case PREF:
16607 /* Treat as no-op */
16608 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16609 /* hint codes 24-31 are reserved and signal RI */
16610 generate_exception(ctx, EXCP_RI);
16612 break;
16613 default:
16614 MIPS_INVAL("pool32c");
16615 generate_exception_end(ctx, EXCP_RI);
16616 break;
16618 break;
16619 case ADDI32: /* AUI, LUI */
16620 if (ctx->insn_flags & ISA_MIPS32R6) {
16621 /* AUI, LUI */
16622 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16623 } else {
16624 /* ADDI32 */
16625 mips32_op = OPC_ADDI;
16626 goto do_addi;
16628 break;
16629 case ADDIU32:
16630 mips32_op = OPC_ADDIU;
16631 do_addi:
16632 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16633 break;
16635 /* Logical operations */
16636 case ORI32:
16637 mips32_op = OPC_ORI;
16638 goto do_logici;
16639 case XORI32:
16640 mips32_op = OPC_XORI;
16641 goto do_logici;
16642 case ANDI32:
16643 mips32_op = OPC_ANDI;
16644 do_logici:
16645 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16646 break;
16648 /* Set less than immediate */
16649 case SLTI32:
16650 mips32_op = OPC_SLTI;
16651 goto do_slti;
16652 case SLTIU32:
16653 mips32_op = OPC_SLTIU;
16654 do_slti:
16655 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16656 break;
16657 case JALX32:
16658 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16659 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16660 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16661 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16662 break;
16663 case JALS32: /* BOVC, BEQC, BEQZALC */
16664 if (ctx->insn_flags & ISA_MIPS32R6) {
16665 if (rs >= rt) {
16666 /* BOVC */
16667 mips32_op = OPC_BOVC;
16668 } else if (rs < rt && rs == 0) {
16669 /* BEQZALC */
16670 mips32_op = OPC_BEQZALC;
16671 } else {
16672 /* BEQC */
16673 mips32_op = OPC_BEQC;
16675 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16676 } else {
16677 /* JALS32 */
16678 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16679 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16680 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16682 break;
16683 case BEQ32: /* BC */
16684 if (ctx->insn_flags & ISA_MIPS32R6) {
16685 /* BC */
16686 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16687 sextract32(ctx->opcode << 1, 0, 27));
16688 } else {
16689 /* BEQ32 */
16690 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16692 break;
16693 case BNE32: /* BALC */
16694 if (ctx->insn_flags & ISA_MIPS32R6) {
16695 /* BALC */
16696 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16697 sextract32(ctx->opcode << 1, 0, 27));
16698 } else {
16699 /* BNE32 */
16700 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16702 break;
16703 case J32: /* BGTZC, BLTZC, BLTC */
16704 if (ctx->insn_flags & ISA_MIPS32R6) {
16705 if (rs == 0 && rt != 0) {
16706 /* BGTZC */
16707 mips32_op = OPC_BGTZC;
16708 } else if (rs != 0 && rt != 0 && rs == rt) {
16709 /* BLTZC */
16710 mips32_op = OPC_BLTZC;
16711 } else {
16712 /* BLTC */
16713 mips32_op = OPC_BLTC;
16715 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16716 } else {
16717 /* J32 */
16718 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16719 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16721 break;
16722 case JAL32: /* BLEZC, BGEZC, BGEC */
16723 if (ctx->insn_flags & ISA_MIPS32R6) {
16724 if (rs == 0 && rt != 0) {
16725 /* BLEZC */
16726 mips32_op = OPC_BLEZC;
16727 } else if (rs != 0 && rt != 0 && rs == rt) {
16728 /* BGEZC */
16729 mips32_op = OPC_BGEZC;
16730 } else {
16731 /* BGEC */
16732 mips32_op = OPC_BGEC;
16734 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16735 } else {
16736 /* JAL32 */
16737 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16738 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16739 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16741 break;
16742 /* Floating point (COP1) */
16743 case LWC132:
16744 mips32_op = OPC_LWC1;
16745 goto do_cop1;
16746 case LDC132:
16747 mips32_op = OPC_LDC1;
16748 goto do_cop1;
16749 case SWC132:
16750 mips32_op = OPC_SWC1;
16751 goto do_cop1;
16752 case SDC132:
16753 mips32_op = OPC_SDC1;
16754 do_cop1:
16755 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16756 break;
16757 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16758 if (ctx->insn_flags & ISA_MIPS32R6) {
16759 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16760 switch ((ctx->opcode >> 16) & 0x1f) {
16761 case ADDIUPC_00:
16762 case ADDIUPC_01:
16763 case ADDIUPC_02:
16764 case ADDIUPC_03:
16765 case ADDIUPC_04:
16766 case ADDIUPC_05:
16767 case ADDIUPC_06:
16768 case ADDIUPC_07:
16769 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16770 break;
16771 case AUIPC:
16772 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16773 break;
16774 case ALUIPC:
16775 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16776 break;
16777 case LWPC_08:
16778 case LWPC_09:
16779 case LWPC_0A:
16780 case LWPC_0B:
16781 case LWPC_0C:
16782 case LWPC_0D:
16783 case LWPC_0E:
16784 case LWPC_0F:
16785 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16786 break;
16787 default:
16788 generate_exception(ctx, EXCP_RI);
16789 break;
16791 } else {
16792 /* ADDIUPC */
16793 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16794 offset = SIMM(ctx->opcode, 0, 23) << 2;
16796 gen_addiupc(ctx, reg, offset, 0, 0);
16798 break;
16799 case BNVC: /* BNEC, BNEZALC */
16800 check_insn(ctx, ISA_MIPS32R6);
16801 if (rs >= rt) {
16802 /* BNVC */
16803 mips32_op = OPC_BNVC;
16804 } else if (rs < rt && rs == 0) {
16805 /* BNEZALC */
16806 mips32_op = OPC_BNEZALC;
16807 } else {
16808 /* BNEC */
16809 mips32_op = OPC_BNEC;
16811 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16812 break;
16813 case R6_BNEZC: /* JIALC */
16814 check_insn(ctx, ISA_MIPS32R6);
16815 if (rt != 0) {
16816 /* BNEZC */
16817 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16818 sextract32(ctx->opcode << 1, 0, 22));
16819 } else {
16820 /* JIALC */
16821 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16823 break;
16824 case R6_BEQZC: /* JIC */
16825 check_insn(ctx, ISA_MIPS32R6);
16826 if (rt != 0) {
16827 /* BEQZC */
16828 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16829 sextract32(ctx->opcode << 1, 0, 22));
16830 } else {
16831 /* JIC */
16832 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16834 break;
16835 case BLEZALC: /* BGEZALC, BGEUC */
16836 check_insn(ctx, ISA_MIPS32R6);
16837 if (rs == 0 && rt != 0) {
16838 /* BLEZALC */
16839 mips32_op = OPC_BLEZALC;
16840 } else if (rs != 0 && rt != 0 && rs == rt) {
16841 /* BGEZALC */
16842 mips32_op = OPC_BGEZALC;
16843 } else {
16844 /* BGEUC */
16845 mips32_op = OPC_BGEUC;
16847 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16848 break;
16849 case BGTZALC: /* BLTZALC, BLTUC */
16850 check_insn(ctx, ISA_MIPS32R6);
16851 if (rs == 0 && rt != 0) {
16852 /* BGTZALC */
16853 mips32_op = OPC_BGTZALC;
16854 } else if (rs != 0 && rt != 0 && rs == rt) {
16855 /* BLTZALC */
16856 mips32_op = OPC_BLTZALC;
16857 } else {
16858 /* BLTUC */
16859 mips32_op = OPC_BLTUC;
16861 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16862 break;
16863 /* Loads and stores */
16864 case LB32:
16865 mips32_op = OPC_LB;
16866 goto do_ld;
16867 case LBU32:
16868 mips32_op = OPC_LBU;
16869 goto do_ld;
16870 case LH32:
16871 mips32_op = OPC_LH;
16872 goto do_ld;
16873 case LHU32:
16874 mips32_op = OPC_LHU;
16875 goto do_ld;
16876 case LW32:
16877 mips32_op = OPC_LW;
16878 goto do_ld;
16879 #ifdef TARGET_MIPS64
16880 case LD32:
16881 check_insn(ctx, ISA_MIPS3);
16882 check_mips_64(ctx);
16883 mips32_op = OPC_LD;
16884 goto do_ld;
16885 case SD32:
16886 check_insn(ctx, ISA_MIPS3);
16887 check_mips_64(ctx);
16888 mips32_op = OPC_SD;
16889 goto do_st;
16890 #endif
16891 case SB32:
16892 mips32_op = OPC_SB;
16893 goto do_st;
16894 case SH32:
16895 mips32_op = OPC_SH;
16896 goto do_st;
16897 case SW32:
16898 mips32_op = OPC_SW;
16899 goto do_st;
16900 do_ld:
16901 gen_ld(ctx, mips32_op, rt, rs, imm);
16902 break;
16903 do_st:
16904 gen_st(ctx, mips32_op, rt, rs, imm);
16905 break;
16906 default:
16907 generate_exception_end(ctx, EXCP_RI);
16908 break;
16912 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16914 uint32_t op;
16916 /* make sure instructions are on a halfword boundary */
16917 if (ctx->base.pc_next & 0x1) {
16918 env->CP0_BadVAddr = ctx->base.pc_next;
16919 generate_exception_end(ctx, EXCP_AdEL);
16920 return 2;
16923 op = (ctx->opcode >> 10) & 0x3f;
16924 /* Enforce properly-sized instructions in a delay slot */
16925 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16926 switch (op & 0x7) { /* MSB-3..MSB-5 */
16927 case 0:
16928 /* POOL32A, POOL32B, POOL32I, POOL32C */
16929 case 4:
16930 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16931 case 5:
16932 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16933 case 6:
16934 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16935 case 7:
16936 /* LB32, LH32, LWC132, LDC132, LW32 */
16937 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16938 generate_exception_end(ctx, EXCP_RI);
16939 return 2;
16941 break;
16942 case 1:
16943 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16944 case 2:
16945 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16946 case 3:
16947 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16948 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16949 generate_exception_end(ctx, EXCP_RI);
16950 return 2;
16952 break;
16956 switch (op) {
16957 case POOL16A:
16959 int rd = mmreg(uMIPS_RD(ctx->opcode));
16960 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16961 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16962 uint32_t opc = 0;
16964 switch (ctx->opcode & 0x1) {
16965 case ADDU16:
16966 opc = OPC_ADDU;
16967 break;
16968 case SUBU16:
16969 opc = OPC_SUBU;
16970 break;
16972 if (ctx->insn_flags & ISA_MIPS32R6) {
16973 /* In the Release 6 the register number location in
16974 * the instruction encoding has changed.
16976 gen_arith(ctx, opc, rs1, rd, rs2);
16977 } else {
16978 gen_arith(ctx, opc, rd, rs1, rs2);
16981 break;
16982 case POOL16B:
16984 int rd = mmreg(uMIPS_RD(ctx->opcode));
16985 int rs = mmreg(uMIPS_RS(ctx->opcode));
16986 int amount = (ctx->opcode >> 1) & 0x7;
16987 uint32_t opc = 0;
16988 amount = amount == 0 ? 8 : amount;
16990 switch (ctx->opcode & 0x1) {
16991 case SLL16:
16992 opc = OPC_SLL;
16993 break;
16994 case SRL16:
16995 opc = OPC_SRL;
16996 break;
16999 gen_shift_imm(ctx, opc, rd, rs, amount);
17001 break;
17002 case POOL16C:
17003 if (ctx->insn_flags & ISA_MIPS32R6) {
17004 gen_pool16c_r6_insn(ctx);
17005 } else {
17006 gen_pool16c_insn(ctx);
17008 break;
17009 case LWGP16:
17011 int rd = mmreg(uMIPS_RD(ctx->opcode));
17012 int rb = 28; /* GP */
17013 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
17015 gen_ld(ctx, OPC_LW, rd, rb, offset);
17017 break;
17018 case POOL16F:
17019 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17020 if (ctx->opcode & 1) {
17021 generate_exception_end(ctx, EXCP_RI);
17022 } else {
17023 /* MOVEP */
17024 int enc_dest = uMIPS_RD(ctx->opcode);
17025 int enc_rt = uMIPS_RS2(ctx->opcode);
17026 int enc_rs = uMIPS_RS1(ctx->opcode);
17027 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17029 break;
17030 case LBU16:
17032 int rd = mmreg(uMIPS_RD(ctx->opcode));
17033 int rb = mmreg(uMIPS_RS(ctx->opcode));
17034 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17035 offset = (offset == 0xf ? -1 : offset);
17037 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17039 break;
17040 case LHU16:
17042 int rd = mmreg(uMIPS_RD(ctx->opcode));
17043 int rb = mmreg(uMIPS_RS(ctx->opcode));
17044 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17046 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17048 break;
17049 case LWSP16:
17051 int rd = (ctx->opcode >> 5) & 0x1f;
17052 int rb = 29; /* SP */
17053 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17055 gen_ld(ctx, OPC_LW, rd, rb, offset);
17057 break;
17058 case LW16:
17060 int rd = mmreg(uMIPS_RD(ctx->opcode));
17061 int rb = mmreg(uMIPS_RS(ctx->opcode));
17062 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17064 gen_ld(ctx, OPC_LW, rd, rb, offset);
17066 break;
17067 case SB16:
17069 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17070 int rb = mmreg(uMIPS_RS(ctx->opcode));
17071 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17073 gen_st(ctx, OPC_SB, rd, rb, offset);
17075 break;
17076 case SH16:
17078 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17079 int rb = mmreg(uMIPS_RS(ctx->opcode));
17080 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17082 gen_st(ctx, OPC_SH, rd, rb, offset);
17084 break;
17085 case SWSP16:
17087 int rd = (ctx->opcode >> 5) & 0x1f;
17088 int rb = 29; /* SP */
17089 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17091 gen_st(ctx, OPC_SW, rd, rb, offset);
17093 break;
17094 case SW16:
17096 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17097 int rb = mmreg(uMIPS_RS(ctx->opcode));
17098 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17100 gen_st(ctx, OPC_SW, rd, rb, offset);
17102 break;
17103 case MOVE16:
17105 int rd = uMIPS_RD5(ctx->opcode);
17106 int rs = uMIPS_RS5(ctx->opcode);
17108 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17110 break;
17111 case ANDI16:
17112 gen_andi16(ctx);
17113 break;
17114 case POOL16D:
17115 switch (ctx->opcode & 0x1) {
17116 case ADDIUS5:
17117 gen_addius5(ctx);
17118 break;
17119 case ADDIUSP:
17120 gen_addiusp(ctx);
17121 break;
17123 break;
17124 case POOL16E:
17125 switch (ctx->opcode & 0x1) {
17126 case ADDIUR2:
17127 gen_addiur2(ctx);
17128 break;
17129 case ADDIUR1SP:
17130 gen_addiur1sp(ctx);
17131 break;
17133 break;
17134 case B16: /* BC16 */
17135 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17136 sextract32(ctx->opcode, 0, 10) << 1,
17137 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17138 break;
17139 case BNEZ16: /* BNEZC16 */
17140 case BEQZ16: /* BEQZC16 */
17141 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17142 mmreg(uMIPS_RD(ctx->opcode)),
17143 0, sextract32(ctx->opcode, 0, 7) << 1,
17144 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17146 break;
17147 case LI16:
17149 int reg = mmreg(uMIPS_RD(ctx->opcode));
17150 int imm = ZIMM(ctx->opcode, 0, 7);
17152 imm = (imm == 0x7f ? -1 : imm);
17153 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17155 break;
17156 case RES_29:
17157 case RES_31:
17158 case RES_39:
17159 generate_exception_end(ctx, EXCP_RI);
17160 break;
17161 default:
17162 decode_micromips32_opc(env, ctx);
17163 return 4;
17166 return 2;
17171 * nanoMIPS opcodes
17175 /* MAJOR, P16, and P32 pools opcodes */
17176 enum {
17177 NM_P_ADDIU = 0x00,
17178 NM_ADDIUPC = 0x01,
17179 NM_MOVE_BALC = 0x02,
17180 NM_P16_MV = 0x04,
17181 NM_LW16 = 0x05,
17182 NM_BC16 = 0x06,
17183 NM_P16_SR = 0x07,
17185 NM_POOL32A = 0x08,
17186 NM_P_BAL = 0x0a,
17187 NM_P16_SHIFT = 0x0c,
17188 NM_LWSP16 = 0x0d,
17189 NM_BALC16 = 0x0e,
17190 NM_P16_4X4 = 0x0f,
17192 NM_P_GP_W = 0x10,
17193 NM_P_GP_BH = 0x11,
17194 NM_P_J = 0x12,
17195 NM_P16C = 0x14,
17196 NM_LWGP16 = 0x15,
17197 NM_P16_LB = 0x17,
17199 NM_P48I = 0x18,
17200 NM_P16_A1 = 0x1c,
17201 NM_LW4X4 = 0x1d,
17202 NM_P16_LH = 0x1f,
17204 NM_P_U12 = 0x20,
17205 NM_P_LS_U12 = 0x21,
17206 NM_P_BR1 = 0x22,
17207 NM_P16_A2 = 0x24,
17208 NM_SW16 = 0x25,
17209 NM_BEQZC16 = 0x26,
17211 NM_POOL32F = 0x28,
17212 NM_P_LS_S9 = 0x29,
17213 NM_P_BR2 = 0x2a,
17215 NM_P16_ADDU = 0x2c,
17216 NM_SWSP16 = 0x2d,
17217 NM_BNEZC16 = 0x2e,
17218 NM_MOVEP = 0x2f,
17220 NM_POOL32S = 0x30,
17221 NM_P_BRI = 0x32,
17222 NM_LI16 = 0x34,
17223 NM_SWGP16 = 0x35,
17224 NM_P16_BR = 0x36,
17226 NM_P_LUI = 0x38,
17227 NM_ANDI16 = 0x3c,
17228 NM_SW4X4 = 0x3d,
17229 NM_MOVEPREV = 0x3f,
17232 /* POOL32A instruction pool */
17233 enum {
17234 NM_POOL32A0 = 0x00,
17235 NM_SPECIAL2 = 0x01,
17236 NM_COP2_1 = 0x02,
17237 NM_UDI = 0x03,
17238 NM_POOL32A5 = 0x05,
17239 NM_POOL32A7 = 0x07,
17242 /* P.GP.W instruction pool */
17243 enum {
17244 NM_ADDIUGP_W = 0x00,
17245 NM_LWGP = 0x02,
17246 NM_SWGP = 0x03,
17249 /* P48I instruction pool */
17250 enum {
17251 NM_LI48 = 0x00,
17252 NM_ADDIU48 = 0x01,
17253 NM_ADDIUGP48 = 0x02,
17254 NM_ADDIUPC48 = 0x03,
17255 NM_LWPC48 = 0x0b,
17256 NM_SWPC48 = 0x0f,
17259 /* P.U12 instruction pool */
17260 enum {
17261 NM_ORI = 0x00,
17262 NM_XORI = 0x01,
17263 NM_ANDI = 0x02,
17264 NM_P_SR = 0x03,
17265 NM_SLTI = 0x04,
17266 NM_SLTIU = 0x05,
17267 NM_SEQI = 0x06,
17268 NM_ADDIUNEG = 0x08,
17269 NM_P_SHIFT = 0x0c,
17270 NM_P_ROTX = 0x0d,
17271 NM_P_INS = 0x0e,
17272 NM_P_EXT = 0x0f,
17275 /* POOL32F instruction pool */
17276 enum {
17277 NM_POOL32F_0 = 0x00,
17278 NM_POOL32F_3 = 0x03,
17279 NM_POOL32F_5 = 0x05,
17282 /* POOL32S instruction pool */
17283 enum {
17284 NM_POOL32S_0 = 0x00,
17285 NM_POOL32S_4 = 0x04,
17288 /* P.LUI instruction pool */
17289 enum {
17290 NM_LUI = 0x00,
17291 NM_ALUIPC = 0x01,
17294 /* P.GP.BH instruction pool */
17295 enum {
17296 NM_LBGP = 0x00,
17297 NM_SBGP = 0x01,
17298 NM_LBUGP = 0x02,
17299 NM_ADDIUGP_B = 0x03,
17300 NM_P_GP_LH = 0x04,
17301 NM_P_GP_SH = 0x05,
17302 NM_P_GP_CP1 = 0x06,
17305 /* P.LS.U12 instruction pool */
17306 enum {
17307 NM_LB = 0x00,
17308 NM_SB = 0x01,
17309 NM_LBU = 0x02,
17310 NM_P_PREFU12 = 0x03,
17311 NM_LH = 0x04,
17312 NM_SH = 0x05,
17313 NM_LHU = 0x06,
17314 NM_LWU = 0x07,
17315 NM_LW = 0x08,
17316 NM_SW = 0x09,
17317 NM_LWC1 = 0x0a,
17318 NM_SWC1 = 0x0b,
17319 NM_LDC1 = 0x0e,
17320 NM_SDC1 = 0x0f,
17323 /* P.LS.S9 instruction pool */
17324 enum {
17325 NM_P_LS_S0 = 0x00,
17326 NM_P_LS_S1 = 0x01,
17327 NM_P_LS_E0 = 0x02,
17328 NM_P_LS_WM = 0x04,
17329 NM_P_LS_UAWM = 0x05,
17332 /* P.BAL instruction pool */
17333 enum {
17334 NM_BC = 0x00,
17335 NM_BALC = 0x01,
17338 /* P.J instruction pool */
17339 enum {
17340 NM_JALRC = 0x00,
17341 NM_JALRC_HB = 0x01,
17342 NM_P_BALRSC = 0x08,
17345 /* P.BR1 instruction pool */
17346 enum {
17347 NM_BEQC = 0x00,
17348 NM_P_BR3A = 0x01,
17349 NM_BGEC = 0x02,
17350 NM_BGEUC = 0x03,
17353 /* P.BR2 instruction pool */
17354 enum {
17355 NM_BNEC = 0x00,
17356 NM_BLTC = 0x02,
17357 NM_BLTUC = 0x03,
17360 /* P.BRI instruction pool */
17361 enum {
17362 NM_BEQIC = 0x00,
17363 NM_BBEQZC = 0x01,
17364 NM_BGEIC = 0x02,
17365 NM_BGEIUC = 0x03,
17366 NM_BNEIC = 0x04,
17367 NM_BBNEZC = 0x05,
17368 NM_BLTIC = 0x06,
17369 NM_BLTIUC = 0x07,
17372 /* P16.SHIFT instruction pool */
17373 enum {
17374 NM_SLL16 = 0x00,
17375 NM_SRL16 = 0x01,
17378 /* POOL16C instruction pool */
17379 enum {
17380 NM_POOL16C_0 = 0x00,
17381 NM_LWXS16 = 0x01,
17384 /* P16.A1 instruction pool */
17385 enum {
17386 NM_ADDIUR1SP = 0x01,
17389 /* P16.A2 instruction pool */
17390 enum {
17391 NM_ADDIUR2 = 0x00,
17392 NM_P_ADDIURS5 = 0x01,
17395 /* P16.ADDU instruction pool */
17396 enum {
17397 NM_ADDU16 = 0x00,
17398 NM_SUBU16 = 0x01,
17401 /* P16.SR instruction pool */
17402 enum {
17403 NM_SAVE16 = 0x00,
17404 NM_RESTORE_JRC16 = 0x01,
17407 /* P16.4X4 instruction pool */
17408 enum {
17409 NM_ADDU4X4 = 0x00,
17410 NM_MUL4X4 = 0x01,
17413 /* P16.LB instruction pool */
17414 enum {
17415 NM_LB16 = 0x00,
17416 NM_SB16 = 0x01,
17417 NM_LBU16 = 0x02,
17420 /* P16.LH instruction pool */
17421 enum {
17422 NM_LH16 = 0x00,
17423 NM_SH16 = 0x01,
17424 NM_LHU16 = 0x02,
17427 /* P.RI instruction pool */
17428 enum {
17429 NM_SIGRIE = 0x00,
17430 NM_P_SYSCALL = 0x01,
17431 NM_BREAK = 0x02,
17432 NM_SDBBP = 0x03,
17435 /* POOL32A0 instruction pool */
17436 enum {
17437 NM_P_TRAP = 0x00,
17438 NM_SEB = 0x01,
17439 NM_SLLV = 0x02,
17440 NM_MUL = 0x03,
17441 NM_MFC0 = 0x06,
17442 NM_MFHC0 = 0x07,
17443 NM_SEH = 0x09,
17444 NM_SRLV = 0x0a,
17445 NM_MUH = 0x0b,
17446 NM_MTC0 = 0x0e,
17447 NM_MTHC0 = 0x0f,
17448 NM_SRAV = 0x12,
17449 NM_MULU = 0x13,
17450 NM_ROTRV = 0x1a,
17451 NM_MUHU = 0x1b,
17452 NM_ADD = 0x22,
17453 NM_DIV = 0x23,
17454 NM_ADDU = 0x2a,
17455 NM_MOD = 0x2b,
17456 NM_SUB = 0x32,
17457 NM_DIVU = 0x33,
17458 NM_RDHWR = 0x38,
17459 NM_SUBU = 0x3a,
17460 NM_MODU = 0x3b,
17461 NM_P_CMOVE = 0x42,
17462 NM_FORK = 0x45,
17463 NM_MFTR = 0x46,
17464 NM_MFHTR = 0x47,
17465 NM_AND = 0x4a,
17466 NM_YIELD = 0x4d,
17467 NM_MTTR = 0x4e,
17468 NM_MTHTR = 0x4f,
17469 NM_OR = 0x52,
17470 NM_D_E_MT_VPE = 0x56,
17471 NM_NOR = 0x5a,
17472 NM_XOR = 0x62,
17473 NM_SLT = 0x6a,
17474 NM_P_SLTU = 0x72,
17475 NM_SOV = 0x7a,
17478 /* CRC32 instruction pool */
17479 enum {
17480 NM_CRC32B = 0x00,
17481 NM_CRC32H = 0x01,
17482 NM_CRC32W = 0x02,
17483 NM_CRC32CB = 0x04,
17484 NM_CRC32CH = 0x05,
17485 NM_CRC32CW = 0x06,
17488 /* POOL32A5 instruction pool */
17489 enum {
17490 NM_CMP_EQ_PH = 0x00,
17491 NM_CMP_LT_PH = 0x08,
17492 NM_CMP_LE_PH = 0x10,
17493 NM_CMPGU_EQ_QB = 0x18,
17494 NM_CMPGU_LT_QB = 0x20,
17495 NM_CMPGU_LE_QB = 0x28,
17496 NM_CMPGDU_EQ_QB = 0x30,
17497 NM_CMPGDU_LT_QB = 0x38,
17498 NM_CMPGDU_LE_QB = 0x40,
17499 NM_CMPU_EQ_QB = 0x48,
17500 NM_CMPU_LT_QB = 0x50,
17501 NM_CMPU_LE_QB = 0x58,
17502 NM_ADDQ_S_W = 0x60,
17503 NM_SUBQ_S_W = 0x68,
17504 NM_ADDSC = 0x70,
17505 NM_ADDWC = 0x78,
17507 NM_ADDQ_S_PH = 0x01,
17508 NM_ADDQH_R_PH = 0x09,
17509 NM_ADDQH_R_W = 0x11,
17510 NM_ADDU_S_QB = 0x19,
17511 NM_ADDU_S_PH = 0x21,
17512 NM_ADDUH_R_QB = 0x29,
17513 NM_SHRAV_R_PH = 0x31,
17514 NM_SHRAV_R_QB = 0x39,
17515 NM_SUBQ_S_PH = 0x41,
17516 NM_SUBQH_R_PH = 0x49,
17517 NM_SUBQH_R_W = 0x51,
17518 NM_SUBU_S_QB = 0x59,
17519 NM_SUBU_S_PH = 0x61,
17520 NM_SUBUH_R_QB = 0x69,
17521 NM_SHLLV_S_PH = 0x71,
17522 NM_PRECR_SRA_R_PH_W = 0x79,
17524 NM_MULEU_S_PH_QBL = 0x12,
17525 NM_MULEU_S_PH_QBR = 0x1a,
17526 NM_MULQ_RS_PH = 0x22,
17527 NM_MULQ_S_PH = 0x2a,
17528 NM_MULQ_RS_W = 0x32,
17529 NM_MULQ_S_W = 0x3a,
17530 NM_APPEND = 0x42,
17531 NM_MODSUB = 0x52,
17532 NM_SHRAV_R_W = 0x5a,
17533 NM_SHRLV_PH = 0x62,
17534 NM_SHRLV_QB = 0x6a,
17535 NM_SHLLV_QB = 0x72,
17536 NM_SHLLV_S_W = 0x7a,
17538 NM_SHILO = 0x03,
17540 NM_MULEQ_S_W_PHL = 0x04,
17541 NM_MULEQ_S_W_PHR = 0x0c,
17543 NM_MUL_S_PH = 0x05,
17544 NM_PRECR_QB_PH = 0x0d,
17545 NM_PRECRQ_QB_PH = 0x15,
17546 NM_PRECRQ_PH_W = 0x1d,
17547 NM_PRECRQ_RS_PH_W = 0x25,
17548 NM_PRECRQU_S_QB_PH = 0x2d,
17549 NM_PACKRL_PH = 0x35,
17550 NM_PICK_QB = 0x3d,
17551 NM_PICK_PH = 0x45,
17553 NM_SHRA_R_W = 0x5e,
17554 NM_SHRA_R_PH = 0x66,
17555 NM_SHLL_S_PH = 0x76,
17556 NM_SHLL_S_W = 0x7e,
17558 NM_REPL_PH = 0x07
17561 /* POOL32A7 instruction pool */
17562 enum {
17563 NM_P_LSX = 0x00,
17564 NM_LSA = 0x01,
17565 NM_EXTW = 0x03,
17566 NM_POOL32AXF = 0x07,
17569 /* P.SR instruction pool */
17570 enum {
17571 NM_PP_SR = 0x00,
17572 NM_P_SR_F = 0x01,
17575 /* P.SHIFT instruction pool */
17576 enum {
17577 NM_P_SLL = 0x00,
17578 NM_SRL = 0x02,
17579 NM_SRA = 0x04,
17580 NM_ROTR = 0x06,
17583 /* P.ROTX instruction pool */
17584 enum {
17585 NM_ROTX = 0x00,
17588 /* P.INS instruction pool */
17589 enum {
17590 NM_INS = 0x00,
17593 /* P.EXT instruction pool */
17594 enum {
17595 NM_EXT = 0x00,
17598 /* POOL32F_0 (fmt) instruction pool */
17599 enum {
17600 NM_RINT_S = 0x04,
17601 NM_RINT_D = 0x44,
17602 NM_ADD_S = 0x06,
17603 NM_SELEQZ_S = 0x07,
17604 NM_SELEQZ_D = 0x47,
17605 NM_CLASS_S = 0x0c,
17606 NM_CLASS_D = 0x4c,
17607 NM_SUB_S = 0x0e,
17608 NM_SELNEZ_S = 0x0f,
17609 NM_SELNEZ_D = 0x4f,
17610 NM_MUL_S = 0x16,
17611 NM_SEL_S = 0x17,
17612 NM_SEL_D = 0x57,
17613 NM_DIV_S = 0x1e,
17614 NM_ADD_D = 0x26,
17615 NM_SUB_D = 0x2e,
17616 NM_MUL_D = 0x36,
17617 NM_MADDF_S = 0x37,
17618 NM_MADDF_D = 0x77,
17619 NM_DIV_D = 0x3e,
17620 NM_MSUBF_S = 0x3f,
17621 NM_MSUBF_D = 0x7f,
17624 /* POOL32F_3 instruction pool */
17625 enum {
17626 NM_MIN_FMT = 0x00,
17627 NM_MAX_FMT = 0x01,
17628 NM_MINA_FMT = 0x04,
17629 NM_MAXA_FMT = 0x05,
17630 NM_POOL32FXF = 0x07,
17633 /* POOL32F_5 instruction pool */
17634 enum {
17635 NM_CMP_CONDN_S = 0x00,
17636 NM_CMP_CONDN_D = 0x02,
17639 /* P.GP.LH instruction pool */
17640 enum {
17641 NM_LHGP = 0x00,
17642 NM_LHUGP = 0x01,
17645 /* P.GP.SH instruction pool */
17646 enum {
17647 NM_SHGP = 0x00,
17650 /* P.GP.CP1 instruction pool */
17651 enum {
17652 NM_LWC1GP = 0x00,
17653 NM_SWC1GP = 0x01,
17654 NM_LDC1GP = 0x02,
17655 NM_SDC1GP = 0x03,
17658 /* P.LS.S0 instruction pool */
17659 enum {
17660 NM_LBS9 = 0x00,
17661 NM_LHS9 = 0x04,
17662 NM_LWS9 = 0x08,
17663 NM_LDS9 = 0x0c,
17665 NM_SBS9 = 0x01,
17666 NM_SHS9 = 0x05,
17667 NM_SWS9 = 0x09,
17668 NM_SDS9 = 0x0d,
17670 NM_LBUS9 = 0x02,
17671 NM_LHUS9 = 0x06,
17672 NM_LWC1S9 = 0x0a,
17673 NM_LDC1S9 = 0x0e,
17675 NM_P_PREFS9 = 0x03,
17676 NM_LWUS9 = 0x07,
17677 NM_SWC1S9 = 0x0b,
17678 NM_SDC1S9 = 0x0f,
17681 /* P.LS.S1 instruction pool */
17682 enum {
17683 NM_ASET_ACLR = 0x02,
17684 NM_UALH = 0x04,
17685 NM_UASH = 0x05,
17686 NM_CACHE = 0x07,
17687 NM_P_LL = 0x0a,
17688 NM_P_SC = 0x0b,
17691 /* P.LS.E0 instruction pool */
17692 enum {
17693 NM_LBE = 0x00,
17694 NM_SBE = 0x01,
17695 NM_LBUE = 0x02,
17696 NM_P_PREFE = 0x03,
17697 NM_LHE = 0x04,
17698 NM_SHE = 0x05,
17699 NM_LHUE = 0x06,
17700 NM_CACHEE = 0x07,
17701 NM_LWE = 0x08,
17702 NM_SWE = 0x09,
17703 NM_P_LLE = 0x0a,
17704 NM_P_SCE = 0x0b,
17707 /* P.PREFE instruction pool */
17708 enum {
17709 NM_SYNCIE = 0x00,
17710 NM_PREFE = 0x01,
17713 /* P.LLE instruction pool */
17714 enum {
17715 NM_LLE = 0x00,
17716 NM_LLWPE = 0x01,
17719 /* P.SCE instruction pool */
17720 enum {
17721 NM_SCE = 0x00,
17722 NM_SCWPE = 0x01,
17725 /* P.LS.WM instruction pool */
17726 enum {
17727 NM_LWM = 0x00,
17728 NM_SWM = 0x01,
17731 /* P.LS.UAWM instruction pool */
17732 enum {
17733 NM_UALWM = 0x00,
17734 NM_UASWM = 0x01,
17737 /* P.BR3A instruction pool */
17738 enum {
17739 NM_BC1EQZC = 0x00,
17740 NM_BC1NEZC = 0x01,
17741 NM_BC2EQZC = 0x02,
17742 NM_BC2NEZC = 0x03,
17743 NM_BPOSGE32C = 0x04,
17746 /* P16.RI instruction pool */
17747 enum {
17748 NM_P16_SYSCALL = 0x01,
17749 NM_BREAK16 = 0x02,
17750 NM_SDBBP16 = 0x03,
17753 /* POOL16C_0 instruction pool */
17754 enum {
17755 NM_POOL16C_00 = 0x00,
17758 /* P16.JRC instruction pool */
17759 enum {
17760 NM_JRC = 0x00,
17761 NM_JALRC16 = 0x01,
17764 /* P.SYSCALL instruction pool */
17765 enum {
17766 NM_SYSCALL = 0x00,
17767 NM_HYPCALL = 0x01,
17770 /* P.TRAP instruction pool */
17771 enum {
17772 NM_TEQ = 0x00,
17773 NM_TNE = 0x01,
17776 /* P.CMOVE instruction pool */
17777 enum {
17778 NM_MOVZ = 0x00,
17779 NM_MOVN = 0x01,
17782 /* POOL32Axf instruction pool */
17783 enum {
17784 NM_POOL32AXF_1 = 0x01,
17785 NM_POOL32AXF_2 = 0x02,
17786 NM_POOL32AXF_4 = 0x04,
17787 NM_POOL32AXF_5 = 0x05,
17788 NM_POOL32AXF_7 = 0x07,
17791 /* POOL32Axf_1 instruction pool */
17792 enum {
17793 NM_POOL32AXF_1_0 = 0x00,
17794 NM_POOL32AXF_1_1 = 0x01,
17795 NM_POOL32AXF_1_3 = 0x03,
17796 NM_POOL32AXF_1_4 = 0x04,
17797 NM_POOL32AXF_1_5 = 0x05,
17798 NM_POOL32AXF_1_7 = 0x07,
17801 /* POOL32Axf_2 instruction pool */
17802 enum {
17803 NM_POOL32AXF_2_0_7 = 0x00,
17804 NM_POOL32AXF_2_8_15 = 0x01,
17805 NM_POOL32AXF_2_16_23 = 0x02,
17806 NM_POOL32AXF_2_24_31 = 0x03,
17809 /* POOL32Axf_7 instruction pool */
17810 enum {
17811 NM_SHRA_R_QB = 0x0,
17812 NM_SHRL_PH = 0x1,
17813 NM_REPL_QB = 0x2,
17816 /* POOL32Axf_1_0 instruction pool */
17817 enum {
17818 NM_MFHI = 0x0,
17819 NM_MFLO = 0x1,
17820 NM_MTHI = 0x2,
17821 NM_MTLO = 0x3,
17824 /* POOL32Axf_1_1 instruction pool */
17825 enum {
17826 NM_MTHLIP = 0x0,
17827 NM_SHILOV = 0x1,
17830 /* POOL32Axf_1_3 instruction pool */
17831 enum {
17832 NM_RDDSP = 0x0,
17833 NM_WRDSP = 0x1,
17834 NM_EXTP = 0x2,
17835 NM_EXTPDP = 0x3,
17838 /* POOL32Axf_1_4 instruction pool */
17839 enum {
17840 NM_SHLL_QB = 0x0,
17841 NM_SHRL_QB = 0x1,
17844 /* POOL32Axf_1_5 instruction pool */
17845 enum {
17846 NM_MAQ_S_W_PHR = 0x0,
17847 NM_MAQ_S_W_PHL = 0x1,
17848 NM_MAQ_SA_W_PHR = 0x2,
17849 NM_MAQ_SA_W_PHL = 0x3,
17852 /* POOL32Axf_1_7 instruction pool */
17853 enum {
17854 NM_EXTR_W = 0x0,
17855 NM_EXTR_R_W = 0x1,
17856 NM_EXTR_RS_W = 0x2,
17857 NM_EXTR_S_H = 0x3,
17860 /* POOL32Axf_2_0_7 instruction pool */
17861 enum {
17862 NM_DPA_W_PH = 0x0,
17863 NM_DPAQ_S_W_PH = 0x1,
17864 NM_DPS_W_PH = 0x2,
17865 NM_DPSQ_S_W_PH = 0x3,
17866 NM_BALIGN = 0x4,
17867 NM_MADD = 0x5,
17868 NM_MULT = 0x6,
17869 NM_EXTRV_W = 0x7,
17872 /* POOL32Axf_2_8_15 instruction pool */
17873 enum {
17874 NM_DPAX_W_PH = 0x0,
17875 NM_DPAQ_SA_L_W = 0x1,
17876 NM_DPSX_W_PH = 0x2,
17877 NM_DPSQ_SA_L_W = 0x3,
17878 NM_MADDU = 0x5,
17879 NM_MULTU = 0x6,
17880 NM_EXTRV_R_W = 0x7,
17883 /* POOL32Axf_2_16_23 instruction pool */
17884 enum {
17885 NM_DPAU_H_QBL = 0x0,
17886 NM_DPAQX_S_W_PH = 0x1,
17887 NM_DPSU_H_QBL = 0x2,
17888 NM_DPSQX_S_W_PH = 0x3,
17889 NM_EXTPV = 0x4,
17890 NM_MSUB = 0x5,
17891 NM_MULSA_W_PH = 0x6,
17892 NM_EXTRV_RS_W = 0x7,
17895 /* POOL32Axf_2_24_31 instruction pool */
17896 enum {
17897 NM_DPAU_H_QBR = 0x0,
17898 NM_DPAQX_SA_W_PH = 0x1,
17899 NM_DPSU_H_QBR = 0x2,
17900 NM_DPSQX_SA_W_PH = 0x3,
17901 NM_EXTPDPV = 0x4,
17902 NM_MSUBU = 0x5,
17903 NM_MULSAQ_S_W_PH = 0x6,
17904 NM_EXTRV_S_H = 0x7,
17907 /* POOL32Axf_{4, 5} instruction pool */
17908 enum {
17909 NM_CLO = 0x25,
17910 NM_CLZ = 0x2d,
17912 NM_TLBP = 0x01,
17913 NM_TLBR = 0x09,
17914 NM_TLBWI = 0x11,
17915 NM_TLBWR = 0x19,
17916 NM_TLBINV = 0x03,
17917 NM_TLBINVF = 0x0b,
17918 NM_DI = 0x23,
17919 NM_EI = 0x2b,
17920 NM_RDPGPR = 0x70,
17921 NM_WRPGPR = 0x78,
17922 NM_WAIT = 0x61,
17923 NM_DERET = 0x71,
17924 NM_ERETX = 0x79,
17926 /* nanoMIPS DSP instructions */
17927 NM_ABSQ_S_QB = 0x00,
17928 NM_ABSQ_S_PH = 0x08,
17929 NM_ABSQ_S_W = 0x10,
17930 NM_PRECEQ_W_PHL = 0x28,
17931 NM_PRECEQ_W_PHR = 0x30,
17932 NM_PRECEQU_PH_QBL = 0x38,
17933 NM_PRECEQU_PH_QBR = 0x48,
17934 NM_PRECEU_PH_QBL = 0x58,
17935 NM_PRECEU_PH_QBR = 0x68,
17936 NM_PRECEQU_PH_QBLA = 0x39,
17937 NM_PRECEQU_PH_QBRA = 0x49,
17938 NM_PRECEU_PH_QBLA = 0x59,
17939 NM_PRECEU_PH_QBRA = 0x69,
17940 NM_REPLV_PH = 0x01,
17941 NM_REPLV_QB = 0x09,
17942 NM_BITREV = 0x18,
17943 NM_INSV = 0x20,
17944 NM_RADDU_W_QB = 0x78,
17946 NM_BITSWAP = 0x05,
17947 NM_WSBH = 0x3d,
17950 /* PP.SR instruction pool */
17951 enum {
17952 NM_SAVE = 0x00,
17953 NM_RESTORE = 0x02,
17954 NM_RESTORE_JRC = 0x03,
17957 /* P.SR.F instruction pool */
17958 enum {
17959 NM_SAVEF = 0x00,
17960 NM_RESTOREF = 0x01,
17963 /* P16.SYSCALL instruction pool */
17964 enum {
17965 NM_SYSCALL16 = 0x00,
17966 NM_HYPCALL16 = 0x01,
17969 /* POOL16C_00 instruction pool */
17970 enum {
17971 NM_NOT16 = 0x00,
17972 NM_XOR16 = 0x01,
17973 NM_AND16 = 0x02,
17974 NM_OR16 = 0x03,
17977 /* PP.LSX and PP.LSXS instruction pool */
17978 enum {
17979 NM_LBX = 0x00,
17980 NM_LHX = 0x04,
17981 NM_LWX = 0x08,
17982 NM_LDX = 0x0c,
17984 NM_SBX = 0x01,
17985 NM_SHX = 0x05,
17986 NM_SWX = 0x09,
17987 NM_SDX = 0x0d,
17989 NM_LBUX = 0x02,
17990 NM_LHUX = 0x06,
17991 NM_LWC1X = 0x0a,
17992 NM_LDC1X = 0x0e,
17994 NM_LWUX = 0x07,
17995 NM_SWC1X = 0x0b,
17996 NM_SDC1X = 0x0f,
17998 NM_LHXS = 0x04,
17999 NM_LWXS = 0x08,
18000 NM_LDXS = 0x0c,
18002 NM_SHXS = 0x05,
18003 NM_SWXS = 0x09,
18004 NM_SDXS = 0x0d,
18006 NM_LHUXS = 0x06,
18007 NM_LWC1XS = 0x0a,
18008 NM_LDC1XS = 0x0e,
18010 NM_LWUXS = 0x07,
18011 NM_SWC1XS = 0x0b,
18012 NM_SDC1XS = 0x0f,
18015 /* ERETx instruction pool */
18016 enum {
18017 NM_ERET = 0x00,
18018 NM_ERETNC = 0x01,
18021 /* POOL32FxF_{0, 1} insturction pool */
18022 enum {
18023 NM_CFC1 = 0x40,
18024 NM_CTC1 = 0x60,
18025 NM_MFC1 = 0x80,
18026 NM_MTC1 = 0xa0,
18027 NM_MFHC1 = 0xc0,
18028 NM_MTHC1 = 0xe0,
18030 NM_CVT_S_PL = 0x84,
18031 NM_CVT_S_PU = 0xa4,
18033 NM_CVT_L_S = 0x004,
18034 NM_CVT_L_D = 0x104,
18035 NM_CVT_W_S = 0x024,
18036 NM_CVT_W_D = 0x124,
18038 NM_RSQRT_S = 0x008,
18039 NM_RSQRT_D = 0x108,
18041 NM_SQRT_S = 0x028,
18042 NM_SQRT_D = 0x128,
18044 NM_RECIP_S = 0x048,
18045 NM_RECIP_D = 0x148,
18047 NM_FLOOR_L_S = 0x00c,
18048 NM_FLOOR_L_D = 0x10c,
18050 NM_FLOOR_W_S = 0x02c,
18051 NM_FLOOR_W_D = 0x12c,
18053 NM_CEIL_L_S = 0x04c,
18054 NM_CEIL_L_D = 0x14c,
18055 NM_CEIL_W_S = 0x06c,
18056 NM_CEIL_W_D = 0x16c,
18057 NM_TRUNC_L_S = 0x08c,
18058 NM_TRUNC_L_D = 0x18c,
18059 NM_TRUNC_W_S = 0x0ac,
18060 NM_TRUNC_W_D = 0x1ac,
18061 NM_ROUND_L_S = 0x0cc,
18062 NM_ROUND_L_D = 0x1cc,
18063 NM_ROUND_W_S = 0x0ec,
18064 NM_ROUND_W_D = 0x1ec,
18066 NM_MOV_S = 0x01,
18067 NM_MOV_D = 0x81,
18068 NM_ABS_S = 0x0d,
18069 NM_ABS_D = 0x8d,
18070 NM_NEG_S = 0x2d,
18071 NM_NEG_D = 0xad,
18072 NM_CVT_D_S = 0x04d,
18073 NM_CVT_D_W = 0x0cd,
18074 NM_CVT_D_L = 0x14d,
18075 NM_CVT_S_D = 0x06d,
18076 NM_CVT_S_W = 0x0ed,
18077 NM_CVT_S_L = 0x16d,
18080 /* P.LL instruction pool */
18081 enum {
18082 NM_LL = 0x00,
18083 NM_LLWP = 0x01,
18086 /* P.SC instruction pool */
18087 enum {
18088 NM_SC = 0x00,
18089 NM_SCWP = 0x01,
18092 /* P.DVP instruction pool */
18093 enum {
18094 NM_DVP = 0x00,
18095 NM_EVP = 0x01,
18101 * nanoMIPS decoding engine
18106 /* extraction utilities */
18108 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18109 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18110 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18111 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18112 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18113 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18115 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18116 static inline int decode_gpr_gpr3(int r)
18118 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18120 return map[r & 0x7];
18123 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18124 static inline int decode_gpr_gpr3_src_store(int r)
18126 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18128 return map[r & 0x7];
18131 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18132 static inline int decode_gpr_gpr4(int r)
18134 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18135 16, 17, 18, 19, 20, 21, 22, 23 };
18137 return map[r & 0xf];
18140 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18141 static inline int decode_gpr_gpr4_zero(int r)
18143 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18144 16, 17, 18, 19, 20, 21, 22, 23 };
18146 return map[r & 0xf];
18150 /* extraction utilities */
18152 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18153 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18154 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18155 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18156 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18157 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18160 static void gen_adjust_sp(DisasContext *ctx, int u)
18162 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18165 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18166 uint8_t gp, uint16_t u)
18168 int counter = 0;
18169 TCGv va = tcg_temp_new();
18170 TCGv t0 = tcg_temp_new();
18172 while (counter != count) {
18173 bool use_gp = gp && (counter == count - 1);
18174 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18175 int this_offset = -((counter + 1) << 2);
18176 gen_base_offset_addr(ctx, va, 29, this_offset);
18177 gen_load_gpr(t0, this_rt);
18178 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18179 (MO_TEUL | ctx->default_tcg_memop_mask));
18180 counter++;
18183 /* adjust stack pointer */
18184 gen_adjust_sp(ctx, -u);
18186 tcg_temp_free(t0);
18187 tcg_temp_free(va);
18190 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18191 uint8_t gp, uint16_t u)
18193 int counter = 0;
18194 TCGv va = tcg_temp_new();
18195 TCGv t0 = tcg_temp_new();
18197 while (counter != count) {
18198 bool use_gp = gp && (counter == count - 1);
18199 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18200 int this_offset = u - ((counter + 1) << 2);
18201 gen_base_offset_addr(ctx, va, 29, this_offset);
18202 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18203 ctx->default_tcg_memop_mask);
18204 tcg_gen_ext32s_tl(t0, t0);
18205 gen_store_gpr(t0, this_rt);
18206 counter++;
18209 /* adjust stack pointer */
18210 gen_adjust_sp(ctx, u);
18212 tcg_temp_free(t0);
18213 tcg_temp_free(va);
18216 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18218 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18219 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18221 switch (extract32(ctx->opcode, 2, 2)) {
18222 case NM_NOT16:
18223 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18224 break;
18225 case NM_AND16:
18226 gen_logic(ctx, OPC_AND, rt, rt, rs);
18227 break;
18228 case NM_XOR16:
18229 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18230 break;
18231 case NM_OR16:
18232 gen_logic(ctx, OPC_OR, rt, rt, rs);
18233 break;
18237 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18239 int rt = extract32(ctx->opcode, 21, 5);
18240 int rs = extract32(ctx->opcode, 16, 5);
18241 int rd = extract32(ctx->opcode, 11, 5);
18243 switch (extract32(ctx->opcode, 3, 7)) {
18244 case NM_P_TRAP:
18245 switch (extract32(ctx->opcode, 10, 1)) {
18246 case NM_TEQ:
18247 check_nms(ctx);
18248 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18249 break;
18250 case NM_TNE:
18251 check_nms(ctx);
18252 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18253 break;
18255 break;
18256 case NM_RDHWR:
18257 check_nms(ctx);
18258 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18259 break;
18260 case NM_SEB:
18261 check_nms(ctx);
18262 gen_bshfl(ctx, OPC_SEB, rs, rt);
18263 break;
18264 case NM_SEH:
18265 gen_bshfl(ctx, OPC_SEH, rs, rt);
18266 break;
18267 case NM_SLLV:
18268 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18269 break;
18270 case NM_SRLV:
18271 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18272 break;
18273 case NM_SRAV:
18274 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18275 break;
18276 case NM_ROTRV:
18277 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18278 break;
18279 case NM_ADD:
18280 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18281 break;
18282 case NM_ADDU:
18283 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18284 break;
18285 case NM_SUB:
18286 check_nms(ctx);
18287 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18288 break;
18289 case NM_SUBU:
18290 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18291 break;
18292 case NM_P_CMOVE:
18293 switch (extract32(ctx->opcode, 10, 1)) {
18294 case NM_MOVZ:
18295 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18296 break;
18297 case NM_MOVN:
18298 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18299 break;
18301 break;
18302 case NM_AND:
18303 gen_logic(ctx, OPC_AND, rd, rs, rt);
18304 break;
18305 case NM_OR:
18306 gen_logic(ctx, OPC_OR, rd, rs, rt);
18307 break;
18308 case NM_NOR:
18309 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18310 break;
18311 case NM_XOR:
18312 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18313 break;
18314 case NM_SLT:
18315 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18316 break;
18317 case NM_P_SLTU:
18318 if (rd == 0) {
18319 /* P_DVP */
18320 #ifndef CONFIG_USER_ONLY
18321 TCGv t0 = tcg_temp_new();
18322 switch (extract32(ctx->opcode, 10, 1)) {
18323 case NM_DVP:
18324 if (ctx->vp) {
18325 check_cp0_enabled(ctx);
18326 gen_helper_dvp(t0, cpu_env);
18327 gen_store_gpr(t0, rt);
18329 break;
18330 case NM_EVP:
18331 if (ctx->vp) {
18332 check_cp0_enabled(ctx);
18333 gen_helper_evp(t0, cpu_env);
18334 gen_store_gpr(t0, rt);
18336 break;
18338 tcg_temp_free(t0);
18339 #endif
18340 } else {
18341 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18343 break;
18344 case NM_SOV:
18346 TCGv t0 = tcg_temp_new();
18347 TCGv t1 = tcg_temp_new();
18348 TCGv t2 = tcg_temp_new();
18350 gen_load_gpr(t1, rs);
18351 gen_load_gpr(t2, rt);
18352 tcg_gen_add_tl(t0, t1, t2);
18353 tcg_gen_ext32s_tl(t0, t0);
18354 tcg_gen_xor_tl(t1, t1, t2);
18355 tcg_gen_xor_tl(t2, t0, t2);
18356 tcg_gen_andc_tl(t1, t2, t1);
18358 /* operands of same sign, result different sign */
18359 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18360 gen_store_gpr(t0, rd);
18362 tcg_temp_free(t0);
18363 tcg_temp_free(t1);
18364 tcg_temp_free(t2);
18366 break;
18367 case NM_MUL:
18368 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18369 break;
18370 case NM_MUH:
18371 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18372 break;
18373 case NM_MULU:
18374 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18375 break;
18376 case NM_MUHU:
18377 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18378 break;
18379 case NM_DIV:
18380 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18381 break;
18382 case NM_MOD:
18383 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18384 break;
18385 case NM_DIVU:
18386 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18387 break;
18388 case NM_MODU:
18389 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18390 break;
18391 #ifndef CONFIG_USER_ONLY
18392 case NM_MFC0:
18393 check_cp0_enabled(ctx);
18394 if (rt == 0) {
18395 /* Treat as NOP. */
18396 break;
18398 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18399 break;
18400 case NM_MTC0:
18401 check_cp0_enabled(ctx);
18403 TCGv t0 = tcg_temp_new();
18405 gen_load_gpr(t0, rt);
18406 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18407 tcg_temp_free(t0);
18409 break;
18410 case NM_D_E_MT_VPE:
18412 uint8_t sc = extract32(ctx->opcode, 10, 1);
18413 TCGv t0 = tcg_temp_new();
18415 switch (sc) {
18416 case 0:
18417 if (rs == 1) {
18418 /* DMT */
18419 check_cp0_mt(ctx);
18420 gen_helper_dmt(t0);
18421 gen_store_gpr(t0, rt);
18422 } else if (rs == 0) {
18423 /* DVPE */
18424 check_cp0_mt(ctx);
18425 gen_helper_dvpe(t0, cpu_env);
18426 gen_store_gpr(t0, rt);
18427 } else {
18428 generate_exception_end(ctx, EXCP_RI);
18430 break;
18431 case 1:
18432 if (rs == 1) {
18433 /* EMT */
18434 check_cp0_mt(ctx);
18435 gen_helper_emt(t0);
18436 gen_store_gpr(t0, rt);
18437 } else if (rs == 0) {
18438 /* EVPE */
18439 check_cp0_mt(ctx);
18440 gen_helper_evpe(t0, cpu_env);
18441 gen_store_gpr(t0, rt);
18442 } else {
18443 generate_exception_end(ctx, EXCP_RI);
18445 break;
18448 tcg_temp_free(t0);
18450 break;
18451 case NM_FORK:
18452 check_mt(ctx);
18454 TCGv t0 = tcg_temp_new();
18455 TCGv t1 = tcg_temp_new();
18457 gen_load_gpr(t0, rt);
18458 gen_load_gpr(t1, rs);
18459 gen_helper_fork(t0, t1);
18460 tcg_temp_free(t0);
18461 tcg_temp_free(t1);
18463 break;
18464 case NM_MFTR:
18465 case NM_MFHTR:
18466 check_cp0_enabled(ctx);
18467 if (rd == 0) {
18468 /* Treat as NOP. */
18469 return;
18471 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18472 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18473 break;
18474 case NM_MTTR:
18475 case NM_MTHTR:
18476 check_cp0_enabled(ctx);
18477 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18478 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18479 break;
18480 case NM_YIELD:
18481 check_mt(ctx);
18483 TCGv t0 = tcg_temp_new();
18485 gen_load_gpr(t0, rs);
18486 gen_helper_yield(t0, cpu_env, t0);
18487 gen_store_gpr(t0, rt);
18488 tcg_temp_free(t0);
18490 break;
18491 #endif
18492 default:
18493 generate_exception_end(ctx, EXCP_RI);
18494 break;
18498 /* dsp */
18499 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18500 int ret, int v1, int v2)
18502 TCGv_i32 t0;
18503 TCGv v0_t;
18504 TCGv v1_t;
18506 t0 = tcg_temp_new_i32();
18508 v0_t = tcg_temp_new();
18509 v1_t = tcg_temp_new();
18511 tcg_gen_movi_i32(t0, v2 >> 3);
18513 gen_load_gpr(v0_t, ret);
18514 gen_load_gpr(v1_t, v1);
18516 switch (opc) {
18517 case NM_MAQ_S_W_PHR:
18518 check_dsp(ctx);
18519 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18520 break;
18521 case NM_MAQ_S_W_PHL:
18522 check_dsp(ctx);
18523 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18524 break;
18525 case NM_MAQ_SA_W_PHR:
18526 check_dsp(ctx);
18527 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18528 break;
18529 case NM_MAQ_SA_W_PHL:
18530 check_dsp(ctx);
18531 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18532 break;
18533 default:
18534 generate_exception_end(ctx, EXCP_RI);
18535 break;
18538 tcg_temp_free_i32(t0);
18540 tcg_temp_free(v0_t);
18541 tcg_temp_free(v1_t);
18545 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18546 int ret, int v1, int v2)
18548 int16_t imm;
18549 TCGv t0 = tcg_temp_new();
18550 TCGv t1 = tcg_temp_new();
18551 TCGv v0_t = tcg_temp_new();
18553 gen_load_gpr(v0_t, v1);
18555 switch (opc) {
18556 case NM_POOL32AXF_1_0:
18557 check_dsp(ctx);
18558 switch (extract32(ctx->opcode, 12, 2)) {
18559 case NM_MFHI:
18560 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18561 break;
18562 case NM_MFLO:
18563 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18564 break;
18565 case NM_MTHI:
18566 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18567 break;
18568 case NM_MTLO:
18569 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18570 break;
18572 break;
18573 case NM_POOL32AXF_1_1:
18574 check_dsp(ctx);
18575 switch (extract32(ctx->opcode, 12, 2)) {
18576 case NM_MTHLIP:
18577 tcg_gen_movi_tl(t0, v2);
18578 gen_helper_mthlip(t0, v0_t, cpu_env);
18579 break;
18580 case NM_SHILOV:
18581 tcg_gen_movi_tl(t0, v2 >> 3);
18582 gen_helper_shilo(t0, v0_t, cpu_env);
18583 break;
18584 default:
18585 generate_exception_end(ctx, EXCP_RI);
18586 break;
18588 break;
18589 case NM_POOL32AXF_1_3:
18590 check_dsp(ctx);
18591 imm = extract32(ctx->opcode, 14, 7);
18592 switch (extract32(ctx->opcode, 12, 2)) {
18593 case NM_RDDSP:
18594 tcg_gen_movi_tl(t0, imm);
18595 gen_helper_rddsp(t0, t0, cpu_env);
18596 gen_store_gpr(t0, ret);
18597 break;
18598 case NM_WRDSP:
18599 gen_load_gpr(t0, ret);
18600 tcg_gen_movi_tl(t1, imm);
18601 gen_helper_wrdsp(t0, t1, cpu_env);
18602 break;
18603 case NM_EXTP:
18604 tcg_gen_movi_tl(t0, v2 >> 3);
18605 tcg_gen_movi_tl(t1, v1);
18606 gen_helper_extp(t0, t0, t1, cpu_env);
18607 gen_store_gpr(t0, ret);
18608 break;
18609 case NM_EXTPDP:
18610 tcg_gen_movi_tl(t0, v2 >> 3);
18611 tcg_gen_movi_tl(t1, v1);
18612 gen_helper_extpdp(t0, t0, t1, cpu_env);
18613 gen_store_gpr(t0, ret);
18614 break;
18616 break;
18617 case NM_POOL32AXF_1_4:
18618 check_dsp(ctx);
18619 tcg_gen_movi_tl(t0, v2 >> 2);
18620 switch (extract32(ctx->opcode, 12, 1)) {
18621 case NM_SHLL_QB:
18622 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18623 gen_store_gpr(t0, ret);
18624 break;
18625 case NM_SHRL_QB:
18626 gen_helper_shrl_qb(t0, t0, v0_t);
18627 gen_store_gpr(t0, ret);
18628 break;
18630 break;
18631 case NM_POOL32AXF_1_5:
18632 opc = extract32(ctx->opcode, 12, 2);
18633 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18634 break;
18635 case NM_POOL32AXF_1_7:
18636 check_dsp(ctx);
18637 tcg_gen_movi_tl(t0, v2 >> 3);
18638 tcg_gen_movi_tl(t1, v1);
18639 switch (extract32(ctx->opcode, 12, 2)) {
18640 case NM_EXTR_W:
18641 gen_helper_extr_w(t0, t0, t1, cpu_env);
18642 gen_store_gpr(t0, ret);
18643 break;
18644 case NM_EXTR_R_W:
18645 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18646 gen_store_gpr(t0, ret);
18647 break;
18648 case NM_EXTR_RS_W:
18649 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18650 gen_store_gpr(t0, ret);
18651 break;
18652 case NM_EXTR_S_H:
18653 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18654 gen_store_gpr(t0, ret);
18655 break;
18657 break;
18658 default:
18659 generate_exception_end(ctx, EXCP_RI);
18660 break;
18663 tcg_temp_free(t0);
18664 tcg_temp_free(t1);
18665 tcg_temp_free(v0_t);
18668 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18669 TCGv v0, TCGv v1, int rd)
18671 TCGv_i32 t0;
18673 t0 = tcg_temp_new_i32();
18675 tcg_gen_movi_i32(t0, rd >> 3);
18677 switch (opc) {
18678 case NM_POOL32AXF_2_0_7:
18679 switch (extract32(ctx->opcode, 9, 3)) {
18680 case NM_DPA_W_PH:
18681 check_dsp_r2(ctx);
18682 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18683 break;
18684 case NM_DPAQ_S_W_PH:
18685 check_dsp(ctx);
18686 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18687 break;
18688 case NM_DPS_W_PH:
18689 check_dsp_r2(ctx);
18690 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18691 break;
18692 case NM_DPSQ_S_W_PH:
18693 check_dsp(ctx);
18694 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18695 break;
18696 default:
18697 generate_exception_end(ctx, EXCP_RI);
18698 break;
18700 break;
18701 case NM_POOL32AXF_2_8_15:
18702 switch (extract32(ctx->opcode, 9, 3)) {
18703 case NM_DPAX_W_PH:
18704 check_dsp_r2(ctx);
18705 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18706 break;
18707 case NM_DPAQ_SA_L_W:
18708 check_dsp(ctx);
18709 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18710 break;
18711 case NM_DPSX_W_PH:
18712 check_dsp_r2(ctx);
18713 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18714 break;
18715 case NM_DPSQ_SA_L_W:
18716 check_dsp(ctx);
18717 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18718 break;
18719 default:
18720 generate_exception_end(ctx, EXCP_RI);
18721 break;
18723 break;
18724 case NM_POOL32AXF_2_16_23:
18725 switch (extract32(ctx->opcode, 9, 3)) {
18726 case NM_DPAU_H_QBL:
18727 check_dsp(ctx);
18728 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18729 break;
18730 case NM_DPAQX_S_W_PH:
18731 check_dsp_r2(ctx);
18732 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18733 break;
18734 case NM_DPSU_H_QBL:
18735 check_dsp(ctx);
18736 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18737 break;
18738 case NM_DPSQX_S_W_PH:
18739 check_dsp_r2(ctx);
18740 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18741 break;
18742 case NM_MULSA_W_PH:
18743 check_dsp_r2(ctx);
18744 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18745 break;
18746 default:
18747 generate_exception_end(ctx, EXCP_RI);
18748 break;
18750 break;
18751 case NM_POOL32AXF_2_24_31:
18752 switch (extract32(ctx->opcode, 9, 3)) {
18753 case NM_DPAU_H_QBR:
18754 check_dsp(ctx);
18755 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18756 break;
18757 case NM_DPAQX_SA_W_PH:
18758 check_dsp_r2(ctx);
18759 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18760 break;
18761 case NM_DPSU_H_QBR:
18762 check_dsp(ctx);
18763 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18764 break;
18765 case NM_DPSQX_SA_W_PH:
18766 check_dsp_r2(ctx);
18767 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18768 break;
18769 case NM_MULSAQ_S_W_PH:
18770 check_dsp(ctx);
18771 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18772 break;
18773 default:
18774 generate_exception_end(ctx, EXCP_RI);
18775 break;
18777 break;
18778 default:
18779 generate_exception_end(ctx, EXCP_RI);
18780 break;
18783 tcg_temp_free_i32(t0);
18786 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18787 int rt, int rs, int rd)
18789 int ret = rt;
18790 TCGv t0 = tcg_temp_new();
18791 TCGv t1 = tcg_temp_new();
18792 TCGv v0_t = tcg_temp_new();
18793 TCGv v1_t = tcg_temp_new();
18795 gen_load_gpr(v0_t, rt);
18796 gen_load_gpr(v1_t, rs);
18798 switch (opc) {
18799 case NM_POOL32AXF_2_0_7:
18800 switch (extract32(ctx->opcode, 9, 3)) {
18801 case NM_DPA_W_PH:
18802 case NM_DPAQ_S_W_PH:
18803 case NM_DPS_W_PH:
18804 case NM_DPSQ_S_W_PH:
18805 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18806 break;
18807 case NM_BALIGN:
18808 check_dsp_r2(ctx);
18809 if (rt != 0) {
18810 gen_load_gpr(t0, rs);
18811 rd &= 3;
18812 if (rd != 0 && rd != 2) {
18813 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18814 tcg_gen_ext32u_tl(t0, t0);
18815 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18816 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18818 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18820 break;
18821 case NM_MADD:
18822 check_dsp(ctx);
18824 int acc = extract32(ctx->opcode, 14, 2);
18825 TCGv_i64 t2 = tcg_temp_new_i64();
18826 TCGv_i64 t3 = tcg_temp_new_i64();
18828 gen_load_gpr(t0, rt);
18829 gen_load_gpr(t1, rs);
18830 tcg_gen_ext_tl_i64(t2, t0);
18831 tcg_gen_ext_tl_i64(t3, t1);
18832 tcg_gen_mul_i64(t2, t2, t3);
18833 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18834 tcg_gen_add_i64(t2, t2, t3);
18835 tcg_temp_free_i64(t3);
18836 gen_move_low32(cpu_LO[acc], t2);
18837 gen_move_high32(cpu_HI[acc], t2);
18838 tcg_temp_free_i64(t2);
18840 break;
18841 case NM_MULT:
18842 check_dsp(ctx);
18844 int acc = extract32(ctx->opcode, 14, 2);
18845 TCGv_i32 t2 = tcg_temp_new_i32();
18846 TCGv_i32 t3 = tcg_temp_new_i32();
18848 gen_load_gpr(t0, rs);
18849 gen_load_gpr(t1, rt);
18850 tcg_gen_trunc_tl_i32(t2, t0);
18851 tcg_gen_trunc_tl_i32(t3, t1);
18852 tcg_gen_muls2_i32(t2, t3, t2, t3);
18853 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18854 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18855 tcg_temp_free_i32(t2);
18856 tcg_temp_free_i32(t3);
18858 break;
18859 case NM_EXTRV_W:
18860 check_dsp(ctx);
18861 gen_load_gpr(v1_t, rs);
18862 tcg_gen_movi_tl(t0, rd >> 3);
18863 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18864 gen_store_gpr(t0, ret);
18865 break;
18867 break;
18868 case NM_POOL32AXF_2_8_15:
18869 switch (extract32(ctx->opcode, 9, 3)) {
18870 case NM_DPAX_W_PH:
18871 case NM_DPAQ_SA_L_W:
18872 case NM_DPSX_W_PH:
18873 case NM_DPSQ_SA_L_W:
18874 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18875 break;
18876 case NM_MADDU:
18877 check_dsp(ctx);
18879 int acc = extract32(ctx->opcode, 14, 2);
18880 TCGv_i64 t2 = tcg_temp_new_i64();
18881 TCGv_i64 t3 = tcg_temp_new_i64();
18883 gen_load_gpr(t0, rs);
18884 gen_load_gpr(t1, rt);
18885 tcg_gen_ext32u_tl(t0, t0);
18886 tcg_gen_ext32u_tl(t1, t1);
18887 tcg_gen_extu_tl_i64(t2, t0);
18888 tcg_gen_extu_tl_i64(t3, t1);
18889 tcg_gen_mul_i64(t2, t2, t3);
18890 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18891 tcg_gen_add_i64(t2, t2, t3);
18892 tcg_temp_free_i64(t3);
18893 gen_move_low32(cpu_LO[acc], t2);
18894 gen_move_high32(cpu_HI[acc], t2);
18895 tcg_temp_free_i64(t2);
18897 break;
18898 case NM_MULTU:
18899 check_dsp(ctx);
18901 int acc = extract32(ctx->opcode, 14, 2);
18902 TCGv_i32 t2 = tcg_temp_new_i32();
18903 TCGv_i32 t3 = tcg_temp_new_i32();
18905 gen_load_gpr(t0, rs);
18906 gen_load_gpr(t1, rt);
18907 tcg_gen_trunc_tl_i32(t2, t0);
18908 tcg_gen_trunc_tl_i32(t3, t1);
18909 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18910 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18911 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18912 tcg_temp_free_i32(t2);
18913 tcg_temp_free_i32(t3);
18915 break;
18916 case NM_EXTRV_R_W:
18917 check_dsp(ctx);
18918 tcg_gen_movi_tl(t0, rd >> 3);
18919 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18920 gen_store_gpr(t0, ret);
18921 break;
18922 default:
18923 generate_exception_end(ctx, EXCP_RI);
18924 break;
18926 break;
18927 case NM_POOL32AXF_2_16_23:
18928 switch (extract32(ctx->opcode, 9, 3)) {
18929 case NM_DPAU_H_QBL:
18930 case NM_DPAQX_S_W_PH:
18931 case NM_DPSU_H_QBL:
18932 case NM_DPSQX_S_W_PH:
18933 case NM_MULSA_W_PH:
18934 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18935 break;
18936 case NM_EXTPV:
18937 check_dsp(ctx);
18938 tcg_gen_movi_tl(t0, rd >> 3);
18939 gen_helper_extp(t0, t0, v1_t, cpu_env);
18940 gen_store_gpr(t0, ret);
18941 break;
18942 case NM_MSUB:
18943 check_dsp(ctx);
18945 int acc = extract32(ctx->opcode, 14, 2);
18946 TCGv_i64 t2 = tcg_temp_new_i64();
18947 TCGv_i64 t3 = tcg_temp_new_i64();
18949 gen_load_gpr(t0, rs);
18950 gen_load_gpr(t1, rt);
18951 tcg_gen_ext_tl_i64(t2, t0);
18952 tcg_gen_ext_tl_i64(t3, t1);
18953 tcg_gen_mul_i64(t2, t2, t3);
18954 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18955 tcg_gen_sub_i64(t2, t3, t2);
18956 tcg_temp_free_i64(t3);
18957 gen_move_low32(cpu_LO[acc], t2);
18958 gen_move_high32(cpu_HI[acc], t2);
18959 tcg_temp_free_i64(t2);
18961 break;
18962 case NM_EXTRV_RS_W:
18963 check_dsp(ctx);
18964 tcg_gen_movi_tl(t0, rd >> 3);
18965 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18966 gen_store_gpr(t0, ret);
18967 break;
18969 break;
18970 case NM_POOL32AXF_2_24_31:
18971 switch (extract32(ctx->opcode, 9, 3)) {
18972 case NM_DPAU_H_QBR:
18973 case NM_DPAQX_SA_W_PH:
18974 case NM_DPSU_H_QBR:
18975 case NM_DPSQX_SA_W_PH:
18976 case NM_MULSAQ_S_W_PH:
18977 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18978 break;
18979 case NM_EXTPDPV:
18980 check_dsp(ctx);
18981 tcg_gen_movi_tl(t0, rd >> 3);
18982 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18983 gen_store_gpr(t0, ret);
18984 break;
18985 case NM_MSUBU:
18986 check_dsp(ctx);
18988 int acc = extract32(ctx->opcode, 14, 2);
18989 TCGv_i64 t2 = tcg_temp_new_i64();
18990 TCGv_i64 t3 = tcg_temp_new_i64();
18992 gen_load_gpr(t0, rs);
18993 gen_load_gpr(t1, rt);
18994 tcg_gen_ext32u_tl(t0, t0);
18995 tcg_gen_ext32u_tl(t1, t1);
18996 tcg_gen_extu_tl_i64(t2, t0);
18997 tcg_gen_extu_tl_i64(t3, t1);
18998 tcg_gen_mul_i64(t2, t2, t3);
18999 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19000 tcg_gen_sub_i64(t2, t3, t2);
19001 tcg_temp_free_i64(t3);
19002 gen_move_low32(cpu_LO[acc], t2);
19003 gen_move_high32(cpu_HI[acc], t2);
19004 tcg_temp_free_i64(t2);
19006 break;
19007 case NM_EXTRV_S_H:
19008 check_dsp(ctx);
19009 tcg_gen_movi_tl(t0, rd >> 3);
19010 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
19011 gen_store_gpr(t0, ret);
19012 break;
19014 break;
19015 default:
19016 generate_exception_end(ctx, EXCP_RI);
19017 break;
19020 tcg_temp_free(t0);
19021 tcg_temp_free(t1);
19023 tcg_temp_free(v0_t);
19024 tcg_temp_free(v1_t);
19027 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
19028 int rt, int rs)
19030 int ret = rt;
19031 TCGv t0 = tcg_temp_new();
19032 TCGv v0_t = tcg_temp_new();
19034 gen_load_gpr(v0_t, rs);
19036 switch (opc) {
19037 case NM_ABSQ_S_QB:
19038 check_dsp_r2(ctx);
19039 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19040 gen_store_gpr(v0_t, ret);
19041 break;
19042 case NM_ABSQ_S_PH:
19043 check_dsp(ctx);
19044 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19045 gen_store_gpr(v0_t, ret);
19046 break;
19047 case NM_ABSQ_S_W:
19048 check_dsp(ctx);
19049 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19050 gen_store_gpr(v0_t, ret);
19051 break;
19052 case NM_PRECEQ_W_PHL:
19053 check_dsp(ctx);
19054 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19055 tcg_gen_ext32s_tl(v0_t, v0_t);
19056 gen_store_gpr(v0_t, ret);
19057 break;
19058 case NM_PRECEQ_W_PHR:
19059 check_dsp(ctx);
19060 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19061 tcg_gen_shli_tl(v0_t, v0_t, 16);
19062 tcg_gen_ext32s_tl(v0_t, v0_t);
19063 gen_store_gpr(v0_t, ret);
19064 break;
19065 case NM_PRECEQU_PH_QBL:
19066 check_dsp(ctx);
19067 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19068 gen_store_gpr(v0_t, ret);
19069 break;
19070 case NM_PRECEQU_PH_QBR:
19071 check_dsp(ctx);
19072 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19073 gen_store_gpr(v0_t, ret);
19074 break;
19075 case NM_PRECEQU_PH_QBLA:
19076 check_dsp(ctx);
19077 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19078 gen_store_gpr(v0_t, ret);
19079 break;
19080 case NM_PRECEQU_PH_QBRA:
19081 check_dsp(ctx);
19082 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19083 gen_store_gpr(v0_t, ret);
19084 break;
19085 case NM_PRECEU_PH_QBL:
19086 check_dsp(ctx);
19087 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19088 gen_store_gpr(v0_t, ret);
19089 break;
19090 case NM_PRECEU_PH_QBR:
19091 check_dsp(ctx);
19092 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19093 gen_store_gpr(v0_t, ret);
19094 break;
19095 case NM_PRECEU_PH_QBLA:
19096 check_dsp(ctx);
19097 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19098 gen_store_gpr(v0_t, ret);
19099 break;
19100 case NM_PRECEU_PH_QBRA:
19101 check_dsp(ctx);
19102 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19103 gen_store_gpr(v0_t, ret);
19104 break;
19105 case NM_REPLV_PH:
19106 check_dsp(ctx);
19107 tcg_gen_ext16u_tl(v0_t, v0_t);
19108 tcg_gen_shli_tl(t0, v0_t, 16);
19109 tcg_gen_or_tl(v0_t, v0_t, t0);
19110 tcg_gen_ext32s_tl(v0_t, v0_t);
19111 gen_store_gpr(v0_t, ret);
19112 break;
19113 case NM_REPLV_QB:
19114 check_dsp(ctx);
19115 tcg_gen_ext8u_tl(v0_t, v0_t);
19116 tcg_gen_shli_tl(t0, v0_t, 8);
19117 tcg_gen_or_tl(v0_t, v0_t, t0);
19118 tcg_gen_shli_tl(t0, v0_t, 16);
19119 tcg_gen_or_tl(v0_t, v0_t, t0);
19120 tcg_gen_ext32s_tl(v0_t, v0_t);
19121 gen_store_gpr(v0_t, ret);
19122 break;
19123 case NM_BITREV:
19124 check_dsp(ctx);
19125 gen_helper_bitrev(v0_t, v0_t);
19126 gen_store_gpr(v0_t, ret);
19127 break;
19128 case NM_INSV:
19129 check_dsp(ctx);
19131 TCGv tv0 = tcg_temp_new();
19133 gen_load_gpr(tv0, rt);
19134 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19135 gen_store_gpr(v0_t, ret);
19136 tcg_temp_free(tv0);
19138 break;
19139 case NM_RADDU_W_QB:
19140 check_dsp(ctx);
19141 gen_helper_raddu_w_qb(v0_t, v0_t);
19142 gen_store_gpr(v0_t, ret);
19143 break;
19144 case NM_BITSWAP:
19145 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19146 break;
19147 case NM_CLO:
19148 check_nms(ctx);
19149 gen_cl(ctx, OPC_CLO, ret, rs);
19150 break;
19151 case NM_CLZ:
19152 check_nms(ctx);
19153 gen_cl(ctx, OPC_CLZ, ret, rs);
19154 break;
19155 case NM_WSBH:
19156 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19157 break;
19158 default:
19159 generate_exception_end(ctx, EXCP_RI);
19160 break;
19163 tcg_temp_free(v0_t);
19164 tcg_temp_free(t0);
19167 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19168 int rt, int rs, int rd)
19170 TCGv t0 = tcg_temp_new();
19171 TCGv rs_t = tcg_temp_new();
19173 gen_load_gpr(rs_t, rs);
19175 switch (opc) {
19176 case NM_SHRA_R_QB:
19177 check_dsp_r2(ctx);
19178 tcg_gen_movi_tl(t0, rd >> 2);
19179 switch (extract32(ctx->opcode, 12, 1)) {
19180 case 0:
19181 /* NM_SHRA_QB */
19182 gen_helper_shra_qb(t0, t0, rs_t);
19183 gen_store_gpr(t0, rt);
19184 break;
19185 case 1:
19186 /* NM_SHRA_R_QB */
19187 gen_helper_shra_r_qb(t0, t0, rs_t);
19188 gen_store_gpr(t0, rt);
19189 break;
19191 break;
19192 case NM_SHRL_PH:
19193 check_dsp_r2(ctx);
19194 tcg_gen_movi_tl(t0, rd >> 1);
19195 gen_helper_shrl_ph(t0, t0, rs_t);
19196 gen_store_gpr(t0, rt);
19197 break;
19198 case NM_REPL_QB:
19199 check_dsp(ctx);
19201 int16_t imm;
19202 target_long result;
19203 imm = extract32(ctx->opcode, 13, 8);
19204 result = (uint32_t)imm << 24 |
19205 (uint32_t)imm << 16 |
19206 (uint32_t)imm << 8 |
19207 (uint32_t)imm;
19208 result = (int32_t)result;
19209 tcg_gen_movi_tl(t0, result);
19210 gen_store_gpr(t0, rt);
19212 break;
19213 default:
19214 generate_exception_end(ctx, EXCP_RI);
19215 break;
19217 tcg_temp_free(t0);
19218 tcg_temp_free(rs_t);
19222 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19224 int rt = extract32(ctx->opcode, 21, 5);
19225 int rs = extract32(ctx->opcode, 16, 5);
19226 int rd = extract32(ctx->opcode, 11, 5);
19228 switch (extract32(ctx->opcode, 6, 3)) {
19229 case NM_POOL32AXF_1:
19231 int32_t op1 = extract32(ctx->opcode, 9, 3);
19232 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19234 break;
19235 case NM_POOL32AXF_2:
19237 int32_t op1 = extract32(ctx->opcode, 12, 2);
19238 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19240 break;
19241 case NM_POOL32AXF_4:
19243 int32_t op1 = extract32(ctx->opcode, 9, 7);
19244 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19246 break;
19247 case NM_POOL32AXF_5:
19248 switch (extract32(ctx->opcode, 9, 7)) {
19249 #ifndef CONFIG_USER_ONLY
19250 case NM_TLBP:
19251 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19252 break;
19253 case NM_TLBR:
19254 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19255 break;
19256 case NM_TLBWI:
19257 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19258 break;
19259 case NM_TLBWR:
19260 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19261 break;
19262 case NM_TLBINV:
19263 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19264 break;
19265 case NM_TLBINVF:
19266 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19267 break;
19268 case NM_DI:
19269 check_cp0_enabled(ctx);
19271 TCGv t0 = tcg_temp_new();
19273 save_cpu_state(ctx, 1);
19274 gen_helper_di(t0, cpu_env);
19275 gen_store_gpr(t0, rt);
19276 /* Stop translation as we may have switched the execution mode */
19277 ctx->base.is_jmp = DISAS_STOP;
19278 tcg_temp_free(t0);
19280 break;
19281 case NM_EI:
19282 check_cp0_enabled(ctx);
19284 TCGv t0 = tcg_temp_new();
19286 save_cpu_state(ctx, 1);
19287 gen_helper_ei(t0, cpu_env);
19288 gen_store_gpr(t0, rt);
19289 /* Stop translation as we may have switched the execution mode */
19290 ctx->base.is_jmp = DISAS_STOP;
19291 tcg_temp_free(t0);
19293 break;
19294 case NM_RDPGPR:
19295 gen_load_srsgpr(rs, rt);
19296 break;
19297 case NM_WRPGPR:
19298 gen_store_srsgpr(rs, rt);
19299 break;
19300 case NM_WAIT:
19301 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19302 break;
19303 case NM_DERET:
19304 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19305 break;
19306 case NM_ERETX:
19307 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19308 break;
19309 #endif
19310 default:
19311 generate_exception_end(ctx, EXCP_RI);
19312 break;
19314 break;
19315 case NM_POOL32AXF_7:
19317 int32_t op1 = extract32(ctx->opcode, 9, 3);
19318 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19320 break;
19321 default:
19322 generate_exception_end(ctx, EXCP_RI);
19323 break;
19327 /* Immediate Value Compact Branches */
19328 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19329 int rt, int32_t imm, int32_t offset)
19331 TCGCond cond;
19332 int bcond_compute = 0;
19333 TCGv t0 = tcg_temp_new();
19334 TCGv t1 = tcg_temp_new();
19336 gen_load_gpr(t0, rt);
19337 tcg_gen_movi_tl(t1, imm);
19338 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19340 /* Load needed operands and calculate btarget */
19341 switch (opc) {
19342 case NM_BEQIC:
19343 if (rt == 0 && imm == 0) {
19344 /* Unconditional branch */
19345 } else if (rt == 0 && imm != 0) {
19346 /* Treat as NOP */
19347 goto out;
19348 } else {
19349 bcond_compute = 1;
19350 cond = TCG_COND_EQ;
19352 break;
19353 case NM_BBEQZC:
19354 case NM_BBNEZC:
19355 check_nms(ctx);
19356 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19357 generate_exception_end(ctx, EXCP_RI);
19358 goto out;
19359 } else if (rt == 0 && opc == NM_BBEQZC) {
19360 /* Unconditional branch */
19361 } else if (rt == 0 && opc == NM_BBNEZC) {
19362 /* Treat as NOP */
19363 goto out;
19364 } else {
19365 tcg_gen_shri_tl(t0, t0, imm);
19366 tcg_gen_andi_tl(t0, t0, 1);
19367 tcg_gen_movi_tl(t1, 0);
19368 bcond_compute = 1;
19369 if (opc == NM_BBEQZC) {
19370 cond = TCG_COND_EQ;
19371 } else {
19372 cond = TCG_COND_NE;
19375 break;
19376 case NM_BNEIC:
19377 if (rt == 0 && imm == 0) {
19378 /* Treat as NOP */
19379 goto out;
19380 } else if (rt == 0 && imm != 0) {
19381 /* Unconditional branch */
19382 } else {
19383 bcond_compute = 1;
19384 cond = TCG_COND_NE;
19386 break;
19387 case NM_BGEIC:
19388 if (rt == 0 && imm == 0) {
19389 /* Unconditional branch */
19390 } else {
19391 bcond_compute = 1;
19392 cond = TCG_COND_GE;
19394 break;
19395 case NM_BLTIC:
19396 bcond_compute = 1;
19397 cond = TCG_COND_LT;
19398 break;
19399 case NM_BGEIUC:
19400 if (rt == 0 && imm == 0) {
19401 /* Unconditional branch */
19402 } else {
19403 bcond_compute = 1;
19404 cond = TCG_COND_GEU;
19406 break;
19407 case NM_BLTIUC:
19408 bcond_compute = 1;
19409 cond = TCG_COND_LTU;
19410 break;
19411 default:
19412 MIPS_INVAL("Immediate Value Compact branch");
19413 generate_exception_end(ctx, EXCP_RI);
19414 goto out;
19417 if (bcond_compute == 0) {
19418 /* Uncoditional compact branch */
19419 gen_goto_tb(ctx, 0, ctx->btarget);
19420 } else {
19421 /* Conditional compact branch */
19422 TCGLabel *fs = gen_new_label();
19424 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19426 gen_goto_tb(ctx, 1, ctx->btarget);
19427 gen_set_label(fs);
19429 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19432 out:
19433 tcg_temp_free(t0);
19434 tcg_temp_free(t1);
19437 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19438 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19439 int rt)
19441 TCGv t0 = tcg_temp_new();
19442 TCGv t1 = tcg_temp_new();
19444 /* load rs */
19445 gen_load_gpr(t0, rs);
19447 /* link */
19448 if (rt != 0) {
19449 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19452 /* calculate btarget */
19453 tcg_gen_shli_tl(t0, t0, 1);
19454 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19455 gen_op_addr_add(ctx, btarget, t1, t0);
19457 /* unconditional branch to register */
19458 tcg_gen_mov_tl(cpu_PC, btarget);
19459 tcg_gen_lookup_and_goto_ptr();
19461 tcg_temp_free(t0);
19462 tcg_temp_free(t1);
19465 /* nanoMIPS Branches */
19466 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19467 int rs, int rt, int32_t offset)
19469 int bcond_compute = 0;
19470 TCGv t0 = tcg_temp_new();
19471 TCGv t1 = tcg_temp_new();
19473 /* Load needed operands and calculate btarget */
19474 switch (opc) {
19475 /* compact branch */
19476 case OPC_BGEC:
19477 case OPC_BLTC:
19478 gen_load_gpr(t0, rs);
19479 gen_load_gpr(t1, rt);
19480 bcond_compute = 1;
19481 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19482 break;
19483 case OPC_BGEUC:
19484 case OPC_BLTUC:
19485 if (rs == 0 || rs == rt) {
19486 /* OPC_BLEZALC, OPC_BGEZALC */
19487 /* OPC_BGTZALC, OPC_BLTZALC */
19488 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19490 gen_load_gpr(t0, rs);
19491 gen_load_gpr(t1, rt);
19492 bcond_compute = 1;
19493 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19494 break;
19495 case OPC_BC:
19496 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19497 break;
19498 case OPC_BEQZC:
19499 if (rs != 0) {
19500 /* OPC_BEQZC, OPC_BNEZC */
19501 gen_load_gpr(t0, rs);
19502 bcond_compute = 1;
19503 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19504 } else {
19505 /* OPC_JIC, OPC_JIALC */
19506 TCGv tbase = tcg_temp_new();
19507 TCGv toffset = tcg_temp_new();
19509 gen_load_gpr(tbase, rt);
19510 tcg_gen_movi_tl(toffset, offset);
19511 gen_op_addr_add(ctx, btarget, tbase, toffset);
19512 tcg_temp_free(tbase);
19513 tcg_temp_free(toffset);
19515 break;
19516 default:
19517 MIPS_INVAL("Compact branch/jump");
19518 generate_exception_end(ctx, EXCP_RI);
19519 goto out;
19522 if (bcond_compute == 0) {
19523 /* Uncoditional compact branch */
19524 switch (opc) {
19525 case OPC_BC:
19526 gen_goto_tb(ctx, 0, ctx->btarget);
19527 break;
19528 default:
19529 MIPS_INVAL("Compact branch/jump");
19530 generate_exception_end(ctx, EXCP_RI);
19531 goto out;
19533 } else {
19534 /* Conditional compact branch */
19535 TCGLabel *fs = gen_new_label();
19537 switch (opc) {
19538 case OPC_BGEUC:
19539 if (rs == 0 && rt != 0) {
19540 /* OPC_BLEZALC */
19541 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19542 } else if (rs != 0 && rt != 0 && rs == rt) {
19543 /* OPC_BGEZALC */
19544 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19545 } else {
19546 /* OPC_BGEUC */
19547 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19549 break;
19550 case OPC_BLTUC:
19551 if (rs == 0 && rt != 0) {
19552 /* OPC_BGTZALC */
19553 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19554 } else if (rs != 0 && rt != 0 && rs == rt) {
19555 /* OPC_BLTZALC */
19556 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19557 } else {
19558 /* OPC_BLTUC */
19559 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19561 break;
19562 case OPC_BGEC:
19563 if (rs == 0 && rt != 0) {
19564 /* OPC_BLEZC */
19565 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19566 } else if (rs != 0 && rt != 0 && rs == rt) {
19567 /* OPC_BGEZC */
19568 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19569 } else {
19570 /* OPC_BGEC */
19571 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19573 break;
19574 case OPC_BLTC:
19575 if (rs == 0 && rt != 0) {
19576 /* OPC_BGTZC */
19577 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19578 } else if (rs != 0 && rt != 0 && rs == rt) {
19579 /* OPC_BLTZC */
19580 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19581 } else {
19582 /* OPC_BLTC */
19583 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19585 break;
19586 case OPC_BEQZC:
19587 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19588 break;
19589 default:
19590 MIPS_INVAL("Compact conditional branch/jump");
19591 generate_exception_end(ctx, EXCP_RI);
19592 goto out;
19595 /* Generating branch here as compact branches don't have delay slot */
19596 gen_goto_tb(ctx, 1, ctx->btarget);
19597 gen_set_label(fs);
19599 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19602 out:
19603 tcg_temp_free(t0);
19604 tcg_temp_free(t1);
19608 /* nanoMIPS CP1 Branches */
19609 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19610 int32_t ft, int32_t offset)
19612 target_ulong btarget;
19613 TCGv_i64 t0 = tcg_temp_new_i64();
19615 gen_load_fpr64(ctx, t0, ft);
19616 tcg_gen_andi_i64(t0, t0, 1);
19618 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19620 switch (op) {
19621 case NM_BC1EQZC:
19622 tcg_gen_xori_i64(t0, t0, 1);
19623 ctx->hflags |= MIPS_HFLAG_BC;
19624 break;
19625 case NM_BC1NEZC:
19626 /* t0 already set */
19627 ctx->hflags |= MIPS_HFLAG_BC;
19628 break;
19629 default:
19630 MIPS_INVAL("cp1 cond branch");
19631 generate_exception_end(ctx, EXCP_RI);
19632 goto out;
19635 tcg_gen_trunc_i64_tl(bcond, t0);
19637 ctx->btarget = btarget;
19639 out:
19640 tcg_temp_free_i64(t0);
19644 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19646 TCGv t0, t1;
19647 t0 = tcg_temp_new();
19648 t1 = tcg_temp_new();
19650 gen_load_gpr(t0, rs);
19651 gen_load_gpr(t1, rt);
19653 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19654 /* PP.LSXS instructions require shifting */
19655 switch (extract32(ctx->opcode, 7, 4)) {
19656 case NM_SHXS:
19657 check_nms(ctx);
19658 case NM_LHXS:
19659 case NM_LHUXS:
19660 tcg_gen_shli_tl(t0, t0, 1);
19661 break;
19662 case NM_SWXS:
19663 check_nms(ctx);
19664 case NM_LWXS:
19665 case NM_LWC1XS:
19666 case NM_SWC1XS:
19667 tcg_gen_shli_tl(t0, t0, 2);
19668 break;
19669 case NM_LDC1XS:
19670 case NM_SDC1XS:
19671 tcg_gen_shli_tl(t0, t0, 3);
19672 break;
19675 gen_op_addr_add(ctx, t0, t0, t1);
19677 switch (extract32(ctx->opcode, 7, 4)) {
19678 case NM_LBX:
19679 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19680 MO_SB);
19681 gen_store_gpr(t0, rd);
19682 break;
19683 case NM_LHX:
19684 /*case NM_LHXS:*/
19685 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19686 MO_TESW);
19687 gen_store_gpr(t0, rd);
19688 break;
19689 case NM_LWX:
19690 /*case NM_LWXS:*/
19691 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19692 MO_TESL);
19693 gen_store_gpr(t0, rd);
19694 break;
19695 case NM_LBUX:
19696 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19697 MO_UB);
19698 gen_store_gpr(t0, rd);
19699 break;
19700 case NM_LHUX:
19701 /*case NM_LHUXS:*/
19702 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19703 MO_TEUW);
19704 gen_store_gpr(t0, rd);
19705 break;
19706 case NM_SBX:
19707 check_nms(ctx);
19708 gen_load_gpr(t1, rd);
19709 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19710 MO_8);
19711 break;
19712 case NM_SHX:
19713 /*case NM_SHXS:*/
19714 check_nms(ctx);
19715 gen_load_gpr(t1, rd);
19716 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19717 MO_TEUW);
19718 break;
19719 case NM_SWX:
19720 /*case NM_SWXS:*/
19721 check_nms(ctx);
19722 gen_load_gpr(t1, rd);
19723 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19724 MO_TEUL);
19725 break;
19726 case NM_LWC1X:
19727 /*case NM_LWC1XS:*/
19728 case NM_LDC1X:
19729 /*case NM_LDC1XS:*/
19730 case NM_SWC1X:
19731 /*case NM_SWC1XS:*/
19732 case NM_SDC1X:
19733 /*case NM_SDC1XS:*/
19734 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19735 check_cp1_enabled(ctx);
19736 switch (extract32(ctx->opcode, 7, 4)) {
19737 case NM_LWC1X:
19738 /*case NM_LWC1XS:*/
19739 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19740 break;
19741 case NM_LDC1X:
19742 /*case NM_LDC1XS:*/
19743 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19744 break;
19745 case NM_SWC1X:
19746 /*case NM_SWC1XS:*/
19747 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19748 break;
19749 case NM_SDC1X:
19750 /*case NM_SDC1XS:*/
19751 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19752 break;
19754 } else {
19755 generate_exception_err(ctx, EXCP_CpU, 1);
19757 break;
19758 default:
19759 generate_exception_end(ctx, EXCP_RI);
19760 break;
19763 tcg_temp_free(t0);
19764 tcg_temp_free(t1);
19767 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19769 int rt, rs, rd;
19771 rt = extract32(ctx->opcode, 21, 5);
19772 rs = extract32(ctx->opcode, 16, 5);
19773 rd = extract32(ctx->opcode, 11, 5);
19775 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19776 generate_exception_end(ctx, EXCP_RI);
19777 return;
19779 check_cp1_enabled(ctx);
19780 switch (extract32(ctx->opcode, 0, 3)) {
19781 case NM_POOL32F_0:
19782 switch (extract32(ctx->opcode, 3, 7)) {
19783 case NM_RINT_S:
19784 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19785 break;
19786 case NM_RINT_D:
19787 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19788 break;
19789 case NM_CLASS_S:
19790 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19791 break;
19792 case NM_CLASS_D:
19793 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19794 break;
19795 case NM_ADD_S:
19796 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19797 break;
19798 case NM_ADD_D:
19799 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19800 break;
19801 case NM_SUB_S:
19802 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19803 break;
19804 case NM_SUB_D:
19805 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19806 break;
19807 case NM_MUL_S:
19808 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19809 break;
19810 case NM_MUL_D:
19811 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19812 break;
19813 case NM_DIV_S:
19814 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19815 break;
19816 case NM_DIV_D:
19817 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19818 break;
19819 case NM_SELEQZ_S:
19820 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19821 break;
19822 case NM_SELEQZ_D:
19823 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19824 break;
19825 case NM_SELNEZ_S:
19826 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19827 break;
19828 case NM_SELNEZ_D:
19829 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19830 break;
19831 case NM_SEL_S:
19832 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19833 break;
19834 case NM_SEL_D:
19835 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19836 break;
19837 case NM_MADDF_S:
19838 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19839 break;
19840 case NM_MADDF_D:
19841 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19842 break;
19843 case NM_MSUBF_S:
19844 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19845 break;
19846 case NM_MSUBF_D:
19847 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19848 break;
19849 default:
19850 generate_exception_end(ctx, EXCP_RI);
19851 break;
19853 break;
19854 case NM_POOL32F_3:
19855 switch (extract32(ctx->opcode, 3, 3)) {
19856 case NM_MIN_FMT:
19857 switch (extract32(ctx->opcode, 9, 1)) {
19858 case FMT_SDPS_S:
19859 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19860 break;
19861 case FMT_SDPS_D:
19862 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19863 break;
19865 break;
19866 case NM_MAX_FMT:
19867 switch (extract32(ctx->opcode, 9, 1)) {
19868 case FMT_SDPS_S:
19869 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19870 break;
19871 case FMT_SDPS_D:
19872 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19873 break;
19875 break;
19876 case NM_MINA_FMT:
19877 switch (extract32(ctx->opcode, 9, 1)) {
19878 case FMT_SDPS_S:
19879 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19880 break;
19881 case FMT_SDPS_D:
19882 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19883 break;
19885 break;
19886 case NM_MAXA_FMT:
19887 switch (extract32(ctx->opcode, 9, 1)) {
19888 case FMT_SDPS_S:
19889 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19890 break;
19891 case FMT_SDPS_D:
19892 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19893 break;
19895 break;
19896 case NM_POOL32FXF:
19897 switch (extract32(ctx->opcode, 6, 8)) {
19898 case NM_CFC1:
19899 gen_cp1(ctx, OPC_CFC1, rt, rs);
19900 break;
19901 case NM_CTC1:
19902 gen_cp1(ctx, OPC_CTC1, rt, rs);
19903 break;
19904 case NM_MFC1:
19905 gen_cp1(ctx, OPC_MFC1, rt, rs);
19906 break;
19907 case NM_MTC1:
19908 gen_cp1(ctx, OPC_MTC1, rt, rs);
19909 break;
19910 case NM_MFHC1:
19911 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19912 break;
19913 case NM_MTHC1:
19914 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19915 break;
19916 case NM_CVT_S_PL:
19917 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19918 break;
19919 case NM_CVT_S_PU:
19920 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19921 break;
19922 default:
19923 switch (extract32(ctx->opcode, 6, 9)) {
19924 case NM_CVT_L_S:
19925 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19926 break;
19927 case NM_CVT_L_D:
19928 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19929 break;
19930 case NM_CVT_W_S:
19931 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19932 break;
19933 case NM_CVT_W_D:
19934 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19935 break;
19936 case NM_RSQRT_S:
19937 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19938 break;
19939 case NM_RSQRT_D:
19940 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19941 break;
19942 case NM_SQRT_S:
19943 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19944 break;
19945 case NM_SQRT_D:
19946 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19947 break;
19948 case NM_RECIP_S:
19949 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19950 break;
19951 case NM_RECIP_D:
19952 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19953 break;
19954 case NM_FLOOR_L_S:
19955 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19956 break;
19957 case NM_FLOOR_L_D:
19958 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19959 break;
19960 case NM_FLOOR_W_S:
19961 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19962 break;
19963 case NM_FLOOR_W_D:
19964 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19965 break;
19966 case NM_CEIL_L_S:
19967 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19968 break;
19969 case NM_CEIL_L_D:
19970 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19971 break;
19972 case NM_CEIL_W_S:
19973 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19974 break;
19975 case NM_CEIL_W_D:
19976 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19977 break;
19978 case NM_TRUNC_L_S:
19979 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19980 break;
19981 case NM_TRUNC_L_D:
19982 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19983 break;
19984 case NM_TRUNC_W_S:
19985 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19986 break;
19987 case NM_TRUNC_W_D:
19988 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19989 break;
19990 case NM_ROUND_L_S:
19991 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19992 break;
19993 case NM_ROUND_L_D:
19994 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19995 break;
19996 case NM_ROUND_W_S:
19997 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19998 break;
19999 case NM_ROUND_W_D:
20000 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
20001 break;
20002 case NM_MOV_S:
20003 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
20004 break;
20005 case NM_MOV_D:
20006 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
20007 break;
20008 case NM_ABS_S:
20009 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
20010 break;
20011 case NM_ABS_D:
20012 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
20013 break;
20014 case NM_NEG_S:
20015 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
20016 break;
20017 case NM_NEG_D:
20018 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
20019 break;
20020 case NM_CVT_D_S:
20021 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
20022 break;
20023 case NM_CVT_D_W:
20024 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
20025 break;
20026 case NM_CVT_D_L:
20027 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
20028 break;
20029 case NM_CVT_S_D:
20030 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
20031 break;
20032 case NM_CVT_S_W:
20033 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20034 break;
20035 case NM_CVT_S_L:
20036 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20037 break;
20038 default:
20039 generate_exception_end(ctx, EXCP_RI);
20040 break;
20042 break;
20044 break;
20046 break;
20047 case NM_POOL32F_5:
20048 switch (extract32(ctx->opcode, 3, 3)) {
20049 case NM_CMP_CONDN_S:
20050 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20051 break;
20052 case NM_CMP_CONDN_D:
20053 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20054 break;
20055 default:
20056 generate_exception_end(ctx, EXCP_RI);
20057 break;
20059 break;
20060 default:
20061 generate_exception_end(ctx, EXCP_RI);
20062 break;
20066 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20067 int rd, int rs, int rt)
20069 int ret = rd;
20070 TCGv t0 = tcg_temp_new();
20071 TCGv v1_t = tcg_temp_new();
20072 TCGv v2_t = tcg_temp_new();
20074 gen_load_gpr(v1_t, rs);
20075 gen_load_gpr(v2_t, rt);
20077 switch (opc) {
20078 case NM_CMP_EQ_PH:
20079 check_dsp(ctx);
20080 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20081 break;
20082 case NM_CMP_LT_PH:
20083 check_dsp(ctx);
20084 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20085 break;
20086 case NM_CMP_LE_PH:
20087 check_dsp(ctx);
20088 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20089 break;
20090 case NM_CMPU_EQ_QB:
20091 check_dsp(ctx);
20092 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20093 break;
20094 case NM_CMPU_LT_QB:
20095 check_dsp(ctx);
20096 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20097 break;
20098 case NM_CMPU_LE_QB:
20099 check_dsp(ctx);
20100 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20101 break;
20102 case NM_CMPGU_EQ_QB:
20103 check_dsp(ctx);
20104 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20105 gen_store_gpr(v1_t, ret);
20106 break;
20107 case NM_CMPGU_LT_QB:
20108 check_dsp(ctx);
20109 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20110 gen_store_gpr(v1_t, ret);
20111 break;
20112 case NM_CMPGU_LE_QB:
20113 check_dsp(ctx);
20114 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20115 gen_store_gpr(v1_t, ret);
20116 break;
20117 case NM_CMPGDU_EQ_QB:
20118 check_dsp_r2(ctx);
20119 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20120 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20121 gen_store_gpr(v1_t, ret);
20122 break;
20123 case NM_CMPGDU_LT_QB:
20124 check_dsp_r2(ctx);
20125 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20126 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20127 gen_store_gpr(v1_t, ret);
20128 break;
20129 case NM_CMPGDU_LE_QB:
20130 check_dsp_r2(ctx);
20131 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20132 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20133 gen_store_gpr(v1_t, ret);
20134 break;
20135 case NM_PACKRL_PH:
20136 check_dsp(ctx);
20137 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20138 gen_store_gpr(v1_t, ret);
20139 break;
20140 case NM_PICK_QB:
20141 check_dsp(ctx);
20142 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20143 gen_store_gpr(v1_t, ret);
20144 break;
20145 case NM_PICK_PH:
20146 check_dsp(ctx);
20147 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20148 gen_store_gpr(v1_t, ret);
20149 break;
20150 case NM_ADDQ_S_W:
20151 check_dsp(ctx);
20152 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20153 gen_store_gpr(v1_t, ret);
20154 break;
20155 case NM_SUBQ_S_W:
20156 check_dsp(ctx);
20157 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20158 gen_store_gpr(v1_t, ret);
20159 break;
20160 case NM_ADDSC:
20161 check_dsp(ctx);
20162 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20163 gen_store_gpr(v1_t, ret);
20164 break;
20165 case NM_ADDWC:
20166 check_dsp(ctx);
20167 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20168 gen_store_gpr(v1_t, ret);
20169 break;
20170 case NM_ADDQ_S_PH:
20171 check_dsp(ctx);
20172 switch (extract32(ctx->opcode, 10, 1)) {
20173 case 0:
20174 /* ADDQ_PH */
20175 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20176 gen_store_gpr(v1_t, ret);
20177 break;
20178 case 1:
20179 /* ADDQ_S_PH */
20180 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20181 gen_store_gpr(v1_t, ret);
20182 break;
20184 break;
20185 case NM_ADDQH_R_PH:
20186 check_dsp_r2(ctx);
20187 switch (extract32(ctx->opcode, 10, 1)) {
20188 case 0:
20189 /* ADDQH_PH */
20190 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20191 gen_store_gpr(v1_t, ret);
20192 break;
20193 case 1:
20194 /* ADDQH_R_PH */
20195 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20196 gen_store_gpr(v1_t, ret);
20197 break;
20199 break;
20200 case NM_ADDQH_R_W:
20201 check_dsp_r2(ctx);
20202 switch (extract32(ctx->opcode, 10, 1)) {
20203 case 0:
20204 /* ADDQH_W */
20205 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20206 gen_store_gpr(v1_t, ret);
20207 break;
20208 case 1:
20209 /* ADDQH_R_W */
20210 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20211 gen_store_gpr(v1_t, ret);
20212 break;
20214 break;
20215 case NM_ADDU_S_QB:
20216 check_dsp(ctx);
20217 switch (extract32(ctx->opcode, 10, 1)) {
20218 case 0:
20219 /* ADDU_QB */
20220 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20221 gen_store_gpr(v1_t, ret);
20222 break;
20223 case 1:
20224 /* ADDU_S_QB */
20225 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20226 gen_store_gpr(v1_t, ret);
20227 break;
20229 break;
20230 case NM_ADDU_S_PH:
20231 check_dsp_r2(ctx);
20232 switch (extract32(ctx->opcode, 10, 1)) {
20233 case 0:
20234 /* ADDU_PH */
20235 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20236 gen_store_gpr(v1_t, ret);
20237 break;
20238 case 1:
20239 /* ADDU_S_PH */
20240 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20241 gen_store_gpr(v1_t, ret);
20242 break;
20244 break;
20245 case NM_ADDUH_R_QB:
20246 check_dsp_r2(ctx);
20247 switch (extract32(ctx->opcode, 10, 1)) {
20248 case 0:
20249 /* ADDUH_QB */
20250 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20251 gen_store_gpr(v1_t, ret);
20252 break;
20253 case 1:
20254 /* ADDUH_R_QB */
20255 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20256 gen_store_gpr(v1_t, ret);
20257 break;
20259 break;
20260 case NM_SHRAV_R_PH:
20261 check_dsp(ctx);
20262 switch (extract32(ctx->opcode, 10, 1)) {
20263 case 0:
20264 /* SHRAV_PH */
20265 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20266 gen_store_gpr(v1_t, ret);
20267 break;
20268 case 1:
20269 /* SHRAV_R_PH */
20270 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20271 gen_store_gpr(v1_t, ret);
20272 break;
20274 break;
20275 case NM_SHRAV_R_QB:
20276 check_dsp_r2(ctx);
20277 switch (extract32(ctx->opcode, 10, 1)) {
20278 case 0:
20279 /* SHRAV_QB */
20280 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20281 gen_store_gpr(v1_t, ret);
20282 break;
20283 case 1:
20284 /* SHRAV_R_QB */
20285 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20286 gen_store_gpr(v1_t, ret);
20287 break;
20289 break;
20290 case NM_SUBQ_S_PH:
20291 check_dsp(ctx);
20292 switch (extract32(ctx->opcode, 10, 1)) {
20293 case 0:
20294 /* SUBQ_PH */
20295 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20296 gen_store_gpr(v1_t, ret);
20297 break;
20298 case 1:
20299 /* SUBQ_S_PH */
20300 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20301 gen_store_gpr(v1_t, ret);
20302 break;
20304 break;
20305 case NM_SUBQH_R_PH:
20306 check_dsp_r2(ctx);
20307 switch (extract32(ctx->opcode, 10, 1)) {
20308 case 0:
20309 /* SUBQH_PH */
20310 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20311 gen_store_gpr(v1_t, ret);
20312 break;
20313 case 1:
20314 /* SUBQH_R_PH */
20315 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20316 gen_store_gpr(v1_t, ret);
20317 break;
20319 break;
20320 case NM_SUBQH_R_W:
20321 check_dsp_r2(ctx);
20322 switch (extract32(ctx->opcode, 10, 1)) {
20323 case 0:
20324 /* SUBQH_W */
20325 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20326 gen_store_gpr(v1_t, ret);
20327 break;
20328 case 1:
20329 /* SUBQH_R_W */
20330 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20331 gen_store_gpr(v1_t, ret);
20332 break;
20334 break;
20335 case NM_SUBU_S_QB:
20336 check_dsp(ctx);
20337 switch (extract32(ctx->opcode, 10, 1)) {
20338 case 0:
20339 /* SUBU_QB */
20340 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20341 gen_store_gpr(v1_t, ret);
20342 break;
20343 case 1:
20344 /* SUBU_S_QB */
20345 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20346 gen_store_gpr(v1_t, ret);
20347 break;
20349 break;
20350 case NM_SUBU_S_PH:
20351 check_dsp_r2(ctx);
20352 switch (extract32(ctx->opcode, 10, 1)) {
20353 case 0:
20354 /* SUBU_PH */
20355 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20356 gen_store_gpr(v1_t, ret);
20357 break;
20358 case 1:
20359 /* SUBU_S_PH */
20360 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20361 gen_store_gpr(v1_t, ret);
20362 break;
20364 break;
20365 case NM_SUBUH_R_QB:
20366 check_dsp_r2(ctx);
20367 switch (extract32(ctx->opcode, 10, 1)) {
20368 case 0:
20369 /* SUBUH_QB */
20370 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20371 gen_store_gpr(v1_t, ret);
20372 break;
20373 case 1:
20374 /* SUBUH_R_QB */
20375 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20376 gen_store_gpr(v1_t, ret);
20377 break;
20379 break;
20380 case NM_SHLLV_S_PH:
20381 check_dsp(ctx);
20382 switch (extract32(ctx->opcode, 10, 1)) {
20383 case 0:
20384 /* SHLLV_PH */
20385 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20386 gen_store_gpr(v1_t, ret);
20387 break;
20388 case 1:
20389 /* SHLLV_S_PH */
20390 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20391 gen_store_gpr(v1_t, ret);
20392 break;
20394 break;
20395 case NM_PRECR_SRA_R_PH_W:
20396 check_dsp_r2(ctx);
20397 switch (extract32(ctx->opcode, 10, 1)) {
20398 case 0:
20399 /* PRECR_SRA_PH_W */
20401 TCGv_i32 sa_t = tcg_const_i32(rd);
20402 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20403 cpu_gpr[rt]);
20404 gen_store_gpr(v1_t, rt);
20405 tcg_temp_free_i32(sa_t);
20407 break;
20408 case 1:
20409 /* PRECR_SRA_R_PH_W */
20411 TCGv_i32 sa_t = tcg_const_i32(rd);
20412 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20413 cpu_gpr[rt]);
20414 gen_store_gpr(v1_t, rt);
20415 tcg_temp_free_i32(sa_t);
20417 break;
20419 break;
20420 case NM_MULEU_S_PH_QBL:
20421 check_dsp(ctx);
20422 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20423 gen_store_gpr(v1_t, ret);
20424 break;
20425 case NM_MULEU_S_PH_QBR:
20426 check_dsp(ctx);
20427 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20428 gen_store_gpr(v1_t, ret);
20429 break;
20430 case NM_MULQ_RS_PH:
20431 check_dsp(ctx);
20432 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20433 gen_store_gpr(v1_t, ret);
20434 break;
20435 case NM_MULQ_S_PH:
20436 check_dsp_r2(ctx);
20437 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20438 gen_store_gpr(v1_t, ret);
20439 break;
20440 case NM_MULQ_RS_W:
20441 check_dsp_r2(ctx);
20442 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20443 gen_store_gpr(v1_t, ret);
20444 break;
20445 case NM_MULQ_S_W:
20446 check_dsp_r2(ctx);
20447 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20448 gen_store_gpr(v1_t, ret);
20449 break;
20450 case NM_APPEND:
20451 check_dsp_r2(ctx);
20452 gen_load_gpr(t0, rs);
20453 if (rd != 0) {
20454 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20456 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20457 break;
20458 case NM_MODSUB:
20459 check_dsp(ctx);
20460 gen_helper_modsub(v1_t, v1_t, v2_t);
20461 gen_store_gpr(v1_t, ret);
20462 break;
20463 case NM_SHRAV_R_W:
20464 check_dsp(ctx);
20465 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20466 gen_store_gpr(v1_t, ret);
20467 break;
20468 case NM_SHRLV_PH:
20469 check_dsp_r2(ctx);
20470 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20471 gen_store_gpr(v1_t, ret);
20472 break;
20473 case NM_SHRLV_QB:
20474 check_dsp(ctx);
20475 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20476 gen_store_gpr(v1_t, ret);
20477 break;
20478 case NM_SHLLV_QB:
20479 check_dsp(ctx);
20480 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20481 gen_store_gpr(v1_t, ret);
20482 break;
20483 case NM_SHLLV_S_W:
20484 check_dsp(ctx);
20485 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20486 gen_store_gpr(v1_t, ret);
20487 break;
20488 case NM_SHILO:
20489 check_dsp(ctx);
20491 TCGv tv0 = tcg_temp_new();
20492 TCGv tv1 = tcg_temp_new();
20493 int16_t imm = extract32(ctx->opcode, 16, 7);
20495 tcg_gen_movi_tl(tv0, rd >> 3);
20496 tcg_gen_movi_tl(tv1, imm);
20497 gen_helper_shilo(tv0, tv1, cpu_env);
20499 break;
20500 case NM_MULEQ_S_W_PHL:
20501 check_dsp(ctx);
20502 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20503 gen_store_gpr(v1_t, ret);
20504 break;
20505 case NM_MULEQ_S_W_PHR:
20506 check_dsp(ctx);
20507 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20508 gen_store_gpr(v1_t, ret);
20509 break;
20510 case NM_MUL_S_PH:
20511 check_dsp_r2(ctx);
20512 switch (extract32(ctx->opcode, 10, 1)) {
20513 case 0:
20514 /* MUL_PH */
20515 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20516 gen_store_gpr(v1_t, ret);
20517 break;
20518 case 1:
20519 /* MUL_S_PH */
20520 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20521 gen_store_gpr(v1_t, ret);
20522 break;
20524 break;
20525 case NM_PRECR_QB_PH:
20526 check_dsp_r2(ctx);
20527 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20528 gen_store_gpr(v1_t, ret);
20529 break;
20530 case NM_PRECRQ_QB_PH:
20531 check_dsp(ctx);
20532 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20533 gen_store_gpr(v1_t, ret);
20534 break;
20535 case NM_PRECRQ_PH_W:
20536 check_dsp(ctx);
20537 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20538 gen_store_gpr(v1_t, ret);
20539 break;
20540 case NM_PRECRQ_RS_PH_W:
20541 check_dsp(ctx);
20542 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20543 gen_store_gpr(v1_t, ret);
20544 break;
20545 case NM_PRECRQU_S_QB_PH:
20546 check_dsp(ctx);
20547 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20548 gen_store_gpr(v1_t, ret);
20549 break;
20550 case NM_SHRA_R_W:
20551 check_dsp(ctx);
20552 tcg_gen_movi_tl(t0, rd);
20553 gen_helper_shra_r_w(v1_t, t0, v1_t);
20554 gen_store_gpr(v1_t, rt);
20555 break;
20556 case NM_SHRA_R_PH:
20557 check_dsp(ctx);
20558 tcg_gen_movi_tl(t0, rd >> 1);
20559 switch (extract32(ctx->opcode, 10, 1)) {
20560 case 0:
20561 /* SHRA_PH */
20562 gen_helper_shra_ph(v1_t, t0, v1_t);
20563 gen_store_gpr(v1_t, rt);
20564 break;
20565 case 1:
20566 /* SHRA_R_PH */
20567 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20568 gen_store_gpr(v1_t, rt);
20569 break;
20571 break;
20572 case NM_SHLL_S_PH:
20573 check_dsp(ctx);
20574 tcg_gen_movi_tl(t0, rd >> 1);
20575 switch (extract32(ctx->opcode, 10, 2)) {
20576 case 0:
20577 /* SHLL_PH */
20578 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20579 gen_store_gpr(v1_t, rt);
20580 break;
20581 case 2:
20582 /* SHLL_S_PH */
20583 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20584 gen_store_gpr(v1_t, rt);
20585 break;
20586 default:
20587 generate_exception_end(ctx, EXCP_RI);
20588 break;
20590 break;
20591 case NM_SHLL_S_W:
20592 check_dsp(ctx);
20593 tcg_gen_movi_tl(t0, rd);
20594 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20595 gen_store_gpr(v1_t, rt);
20596 break;
20597 case NM_REPL_PH:
20598 check_dsp(ctx);
20600 int16_t imm;
20601 imm = sextract32(ctx->opcode, 11, 11);
20602 imm = (int16_t)(imm << 6) >> 6;
20603 if (rt != 0) {
20604 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20607 break;
20608 default:
20609 generate_exception_end(ctx, EXCP_RI);
20610 break;
20614 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20616 uint16_t insn;
20617 uint32_t op;
20618 int rt, rs, rd;
20619 int offset;
20620 int imm;
20622 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20623 ctx->opcode = (ctx->opcode << 16) | insn;
20625 rt = extract32(ctx->opcode, 21, 5);
20626 rs = extract32(ctx->opcode, 16, 5);
20627 rd = extract32(ctx->opcode, 11, 5);
20629 op = extract32(ctx->opcode, 26, 6);
20630 switch (op) {
20631 case NM_P_ADDIU:
20632 if (rt == 0) {
20633 /* P.RI */
20634 switch (extract32(ctx->opcode, 19, 2)) {
20635 case NM_SIGRIE:
20636 default:
20637 generate_exception_end(ctx, EXCP_RI);
20638 break;
20639 case NM_P_SYSCALL:
20640 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20641 generate_exception_end(ctx, EXCP_SYSCALL);
20642 } else {
20643 generate_exception_end(ctx, EXCP_RI);
20645 break;
20646 case NM_BREAK:
20647 generate_exception_end(ctx, EXCP_BREAK);
20648 break;
20649 case NM_SDBBP:
20650 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20651 gen_helper_do_semihosting(cpu_env);
20652 } else {
20653 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20654 generate_exception_end(ctx, EXCP_RI);
20655 } else {
20656 generate_exception_end(ctx, EXCP_DBp);
20659 break;
20661 } else {
20662 /* NM_ADDIU */
20663 imm = extract32(ctx->opcode, 0, 16);
20664 if (rs != 0) {
20665 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20666 } else {
20667 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20669 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20671 break;
20672 case NM_ADDIUPC:
20673 if (rt != 0) {
20674 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20675 extract32(ctx->opcode, 1, 20) << 1;
20676 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20677 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20679 break;
20680 case NM_POOL32A:
20681 switch (ctx->opcode & 0x07) {
20682 case NM_POOL32A0:
20683 gen_pool32a0_nanomips_insn(env, ctx);
20684 break;
20685 case NM_POOL32A5:
20687 int32_t op1 = extract32(ctx->opcode, 3, 7);
20688 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20690 break;
20691 case NM_POOL32A7:
20692 switch (extract32(ctx->opcode, 3, 3)) {
20693 case NM_P_LSX:
20694 gen_p_lsx(ctx, rd, rs, rt);
20695 break;
20696 case NM_LSA:
20697 /* In nanoMIPS, the shift field directly encodes the shift
20698 * amount, meaning that the supported shift values are in
20699 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20700 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20701 extract32(ctx->opcode, 9, 2) - 1);
20702 break;
20703 case NM_EXTW:
20704 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20705 break;
20706 case NM_POOL32AXF:
20707 gen_pool32axf_nanomips_insn(env, ctx);
20708 break;
20709 default:
20710 generate_exception_end(ctx, EXCP_RI);
20711 break;
20713 break;
20714 default:
20715 generate_exception_end(ctx, EXCP_RI);
20716 break;
20718 break;
20719 case NM_P_GP_W:
20720 switch (ctx->opcode & 0x03) {
20721 case NM_ADDIUGP_W:
20722 if (rt != 0) {
20723 offset = extract32(ctx->opcode, 0, 21);
20724 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20726 break;
20727 case NM_LWGP:
20728 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20729 break;
20730 case NM_SWGP:
20731 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20732 break;
20733 default:
20734 generate_exception_end(ctx, EXCP_RI);
20735 break;
20737 break;
20738 case NM_P48I:
20740 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20741 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20742 switch (extract32(ctx->opcode, 16, 5)) {
20743 case NM_LI48:
20744 check_nms(ctx);
20745 if (rt != 0) {
20746 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20748 break;
20749 case NM_ADDIU48:
20750 check_nms(ctx);
20751 if (rt != 0) {
20752 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20753 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20755 break;
20756 case NM_ADDIUGP48:
20757 check_nms(ctx);
20758 if (rt != 0) {
20759 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20761 break;
20762 case NM_ADDIUPC48:
20763 check_nms(ctx);
20764 if (rt != 0) {
20765 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20766 addr_off);
20768 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20770 break;
20771 case NM_LWPC48:
20772 check_nms(ctx);
20773 if (rt != 0) {
20774 TCGv t0;
20775 t0 = tcg_temp_new();
20777 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20778 addr_off);
20780 tcg_gen_movi_tl(t0, addr);
20781 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20782 tcg_temp_free(t0);
20784 break;
20785 case NM_SWPC48:
20786 check_nms(ctx);
20788 TCGv t0, t1;
20789 t0 = tcg_temp_new();
20790 t1 = tcg_temp_new();
20792 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20793 addr_off);
20795 tcg_gen_movi_tl(t0, addr);
20796 gen_load_gpr(t1, rt);
20798 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20800 tcg_temp_free(t0);
20801 tcg_temp_free(t1);
20803 break;
20804 default:
20805 generate_exception_end(ctx, EXCP_RI);
20806 break;
20808 return 6;
20810 case NM_P_U12:
20811 switch (extract32(ctx->opcode, 12, 4)) {
20812 case NM_ORI:
20813 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20814 break;
20815 case NM_XORI:
20816 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20817 break;
20818 case NM_ANDI:
20819 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20820 break;
20821 case NM_P_SR:
20822 switch (extract32(ctx->opcode, 20, 1)) {
20823 case NM_PP_SR:
20824 switch (ctx->opcode & 3) {
20825 case NM_SAVE:
20826 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20827 extract32(ctx->opcode, 2, 1),
20828 extract32(ctx->opcode, 3, 9) << 3);
20829 break;
20830 case NM_RESTORE:
20831 case NM_RESTORE_JRC:
20832 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20833 extract32(ctx->opcode, 2, 1),
20834 extract32(ctx->opcode, 3, 9) << 3);
20835 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20836 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20838 break;
20839 default:
20840 generate_exception_end(ctx, EXCP_RI);
20841 break;
20843 break;
20844 case NM_P_SR_F:
20845 generate_exception_end(ctx, EXCP_RI);
20846 break;
20848 break;
20849 case NM_SLTI:
20850 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20851 break;
20852 case NM_SLTIU:
20853 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20854 break;
20855 case NM_SEQI:
20857 TCGv t0 = tcg_temp_new();
20859 imm = extract32(ctx->opcode, 0, 12);
20860 gen_load_gpr(t0, rs);
20861 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20862 gen_store_gpr(t0, rt);
20864 tcg_temp_free(t0);
20866 break;
20867 case NM_ADDIUNEG:
20868 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20869 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20870 break;
20871 case NM_P_SHIFT:
20873 int shift = extract32(ctx->opcode, 0, 5);
20874 switch (extract32(ctx->opcode, 5, 4)) {
20875 case NM_P_SLL:
20876 if (rt == 0 && shift == 0) {
20877 /* NOP */
20878 } else if (rt == 0 && shift == 3) {
20879 /* EHB - treat as NOP */
20880 } else if (rt == 0 && shift == 5) {
20881 /* PAUSE - treat as NOP */
20882 } else if (rt == 0 && shift == 6) {
20883 /* SYNC */
20884 gen_sync(extract32(ctx->opcode, 16, 5));
20885 } else {
20886 /* SLL */
20887 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20888 extract32(ctx->opcode, 0, 5));
20890 break;
20891 case NM_SRL:
20892 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20893 extract32(ctx->opcode, 0, 5));
20894 break;
20895 case NM_SRA:
20896 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20897 extract32(ctx->opcode, 0, 5));
20898 break;
20899 case NM_ROTR:
20900 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20901 extract32(ctx->opcode, 0, 5));
20902 break;
20905 break;
20906 case NM_P_ROTX:
20907 check_nms(ctx);
20908 if (rt != 0) {
20909 TCGv t0 = tcg_temp_new();
20910 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20911 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20912 << 1);
20913 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20915 gen_load_gpr(t0, rs);
20916 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20917 tcg_temp_free(t0);
20919 tcg_temp_free_i32(shift);
20920 tcg_temp_free_i32(shiftx);
20921 tcg_temp_free_i32(stripe);
20923 break;
20924 case NM_P_INS:
20925 switch (((ctx->opcode >> 10) & 2) |
20926 (extract32(ctx->opcode, 5, 1))) {
20927 case NM_INS:
20928 check_nms(ctx);
20929 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20930 extract32(ctx->opcode, 6, 5));
20931 break;
20932 default:
20933 generate_exception_end(ctx, EXCP_RI);
20934 break;
20936 break;
20937 case NM_P_EXT:
20938 switch (((ctx->opcode >> 10) & 2) |
20939 (extract32(ctx->opcode, 5, 1))) {
20940 case NM_EXT:
20941 check_nms(ctx);
20942 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20943 extract32(ctx->opcode, 6, 5));
20944 break;
20945 default:
20946 generate_exception_end(ctx, EXCP_RI);
20947 break;
20949 break;
20950 default:
20951 generate_exception_end(ctx, EXCP_RI);
20952 break;
20954 break;
20955 case NM_POOL32F:
20956 gen_pool32f_nanomips_insn(ctx);
20957 break;
20958 case NM_POOL32S:
20959 break;
20960 case NM_P_LUI:
20961 switch (extract32(ctx->opcode, 1, 1)) {
20962 case NM_LUI:
20963 if (rt != 0) {
20964 tcg_gen_movi_tl(cpu_gpr[rt],
20965 sextract32(ctx->opcode, 0, 1) << 31 |
20966 extract32(ctx->opcode, 2, 10) << 21 |
20967 extract32(ctx->opcode, 12, 9) << 12);
20969 break;
20970 case NM_ALUIPC:
20971 if (rt != 0) {
20972 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20973 extract32(ctx->opcode, 2, 10) << 21 |
20974 extract32(ctx->opcode, 12, 9) << 12;
20975 target_long addr;
20976 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20977 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20979 break;
20981 break;
20982 case NM_P_GP_BH:
20984 uint32_t u = extract32(ctx->opcode, 0, 18);
20986 switch (extract32(ctx->opcode, 18, 3)) {
20987 case NM_LBGP:
20988 gen_ld(ctx, OPC_LB, rt, 28, u);
20989 break;
20990 case NM_SBGP:
20991 gen_st(ctx, OPC_SB, rt, 28, u);
20992 break;
20993 case NM_LBUGP:
20994 gen_ld(ctx, OPC_LBU, rt, 28, u);
20995 break;
20996 case NM_ADDIUGP_B:
20997 if (rt != 0) {
20998 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
21000 break;
21001 case NM_P_GP_LH:
21002 u &= ~1;
21003 switch (ctx->opcode & 1) {
21004 case NM_LHGP:
21005 gen_ld(ctx, OPC_LH, rt, 28, u);
21006 break;
21007 case NM_LHUGP:
21008 gen_ld(ctx, OPC_LHU, rt, 28, u);
21009 break;
21011 break;
21012 case NM_P_GP_SH:
21013 u &= ~1;
21014 switch (ctx->opcode & 1) {
21015 case NM_SHGP:
21016 gen_st(ctx, OPC_SH, rt, 28, u);
21017 break;
21018 default:
21019 generate_exception_end(ctx, EXCP_RI);
21020 break;
21022 break;
21023 case NM_P_GP_CP1:
21024 u &= ~0x3;
21025 switch (ctx->opcode & 0x3) {
21026 case NM_LWC1GP:
21027 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
21028 break;
21029 case NM_LDC1GP:
21030 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
21031 break;
21032 case NM_SWC1GP:
21033 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21034 break;
21035 case NM_SDC1GP:
21036 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21037 break;
21039 break;
21040 default:
21041 generate_exception_end(ctx, EXCP_RI);
21042 break;
21045 break;
21046 case NM_P_LS_U12:
21048 uint32_t u = extract32(ctx->opcode, 0, 12);
21050 switch (extract32(ctx->opcode, 12, 4)) {
21051 case NM_P_PREFU12:
21052 if (rt == 31) {
21053 /* SYNCI */
21054 /* Break the TB to be able to sync copied instructions
21055 immediately */
21056 ctx->base.is_jmp = DISAS_STOP;
21057 } else {
21058 /* PREF */
21059 /* Treat as NOP. */
21061 break;
21062 case NM_LB:
21063 gen_ld(ctx, OPC_LB, rt, rs, u);
21064 break;
21065 case NM_LH:
21066 gen_ld(ctx, OPC_LH, rt, rs, u);
21067 break;
21068 case NM_LW:
21069 gen_ld(ctx, OPC_LW, rt, rs, u);
21070 break;
21071 case NM_LBU:
21072 gen_ld(ctx, OPC_LBU, rt, rs, u);
21073 break;
21074 case NM_LHU:
21075 gen_ld(ctx, OPC_LHU, rt, rs, u);
21076 break;
21077 case NM_SB:
21078 gen_st(ctx, OPC_SB, rt, rs, u);
21079 break;
21080 case NM_SH:
21081 gen_st(ctx, OPC_SH, rt, rs, u);
21082 break;
21083 case NM_SW:
21084 gen_st(ctx, OPC_SW, rt, rs, u);
21085 break;
21086 case NM_LWC1:
21087 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21088 break;
21089 case NM_LDC1:
21090 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21091 break;
21092 case NM_SWC1:
21093 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21094 break;
21095 case NM_SDC1:
21096 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21097 break;
21098 default:
21099 generate_exception_end(ctx, EXCP_RI);
21100 break;
21103 break;
21104 case NM_P_LS_S9:
21106 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21107 extract32(ctx->opcode, 0, 8);
21109 switch (extract32(ctx->opcode, 8, 3)) {
21110 case NM_P_LS_S0:
21111 switch (extract32(ctx->opcode, 11, 4)) {
21112 case NM_LBS9:
21113 gen_ld(ctx, OPC_LB, rt, rs, s);
21114 break;
21115 case NM_LHS9:
21116 gen_ld(ctx, OPC_LH, rt, rs, s);
21117 break;
21118 case NM_LWS9:
21119 gen_ld(ctx, OPC_LW, rt, rs, s);
21120 break;
21121 case NM_LBUS9:
21122 gen_ld(ctx, OPC_LBU, rt, rs, s);
21123 break;
21124 case NM_LHUS9:
21125 gen_ld(ctx, OPC_LHU, rt, rs, s);
21126 break;
21127 case NM_SBS9:
21128 gen_st(ctx, OPC_SB, rt, rs, s);
21129 break;
21130 case NM_SHS9:
21131 gen_st(ctx, OPC_SH, rt, rs, s);
21132 break;
21133 case NM_SWS9:
21134 gen_st(ctx, OPC_SW, rt, rs, s);
21135 break;
21136 case NM_LWC1S9:
21137 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21138 break;
21139 case NM_LDC1S9:
21140 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21141 break;
21142 case NM_SWC1S9:
21143 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21144 break;
21145 case NM_SDC1S9:
21146 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21147 break;
21148 case NM_P_PREFS9:
21149 if (rt == 31) {
21150 /* SYNCI */
21151 /* Break the TB to be able to sync copied instructions
21152 immediately */
21153 ctx->base.is_jmp = DISAS_STOP;
21154 } else {
21155 /* PREF */
21156 /* Treat as NOP. */
21158 break;
21159 default:
21160 generate_exception_end(ctx, EXCP_RI);
21161 break;
21163 break;
21164 case NM_P_LS_S1:
21165 switch (extract32(ctx->opcode, 11, 4)) {
21166 case NM_UALH:
21167 case NM_UASH:
21168 check_nms(ctx);
21170 TCGv t0 = tcg_temp_new();
21171 TCGv t1 = tcg_temp_new();
21173 gen_base_offset_addr(ctx, t0, rs, s);
21175 switch (extract32(ctx->opcode, 11, 4)) {
21176 case NM_UALH:
21177 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21178 MO_UNALN);
21179 gen_store_gpr(t0, rt);
21180 break;
21181 case NM_UASH:
21182 gen_load_gpr(t1, rt);
21183 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21184 MO_UNALN);
21185 break;
21187 tcg_temp_free(t0);
21188 tcg_temp_free(t1);
21190 break;
21191 case NM_P_LL:
21192 switch (ctx->opcode & 0x03) {
21193 case NM_LL:
21194 gen_ld(ctx, OPC_LL, rt, rs, s);
21195 break;
21196 case NM_LLWP:
21197 check_xnp(ctx);
21198 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21199 break;
21201 break;
21202 case NM_P_SC:
21203 switch (ctx->opcode & 0x03) {
21204 case NM_SC:
21205 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21206 break;
21207 case NM_SCWP:
21208 check_xnp(ctx);
21209 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21210 break;
21212 break;
21213 case NM_CACHE:
21214 check_cp0_enabled(ctx);
21215 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21216 gen_cache_operation(ctx, rt, rs, s);
21218 break;
21220 break;
21221 case NM_P_LS_WM:
21222 case NM_P_LS_UAWM:
21223 check_nms(ctx);
21225 int count = extract32(ctx->opcode, 12, 3);
21226 int counter = 0;
21228 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21229 extract32(ctx->opcode, 0, 8);
21230 TCGv va = tcg_temp_new();
21231 TCGv t1 = tcg_temp_new();
21232 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21233 NM_P_LS_UAWM ? MO_UNALN : 0;
21235 count = (count == 0) ? 8 : count;
21236 while (counter != count) {
21237 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21238 int this_offset = offset + (counter << 2);
21240 gen_base_offset_addr(ctx, va, rs, this_offset);
21242 switch (extract32(ctx->opcode, 11, 1)) {
21243 case NM_LWM:
21244 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21245 memop | MO_TESL);
21246 gen_store_gpr(t1, this_rt);
21247 if ((this_rt == rs) &&
21248 (counter != (count - 1))) {
21249 /* UNPREDICTABLE */
21251 break;
21252 case NM_SWM:
21253 this_rt = (rt == 0) ? 0 : this_rt;
21254 gen_load_gpr(t1, this_rt);
21255 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21256 memop | MO_TEUL);
21257 break;
21259 counter++;
21261 tcg_temp_free(va);
21262 tcg_temp_free(t1);
21264 break;
21265 default:
21266 generate_exception_end(ctx, EXCP_RI);
21267 break;
21270 break;
21271 case NM_MOVE_BALC:
21272 check_nms(ctx);
21274 TCGv t0 = tcg_temp_new();
21275 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21276 extract32(ctx->opcode, 1, 20) << 1;
21277 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21278 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21279 extract32(ctx->opcode, 21, 3));
21280 gen_load_gpr(t0, rt);
21281 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21282 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21283 tcg_temp_free(t0);
21285 break;
21286 case NM_P_BAL:
21288 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21289 extract32(ctx->opcode, 1, 24) << 1;
21291 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21292 /* BC */
21293 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21294 } else {
21295 /* BALC */
21296 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21299 break;
21300 case NM_P_J:
21301 switch (extract32(ctx->opcode, 12, 4)) {
21302 case NM_JALRC:
21303 case NM_JALRC_HB:
21304 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21305 break;
21306 case NM_P_BALRSC:
21307 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21308 break;
21309 default:
21310 generate_exception_end(ctx, EXCP_RI);
21311 break;
21313 break;
21314 case NM_P_BR1:
21316 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21317 extract32(ctx->opcode, 1, 13) << 1;
21318 switch (extract32(ctx->opcode, 14, 2)) {
21319 case NM_BEQC:
21320 check_nms(ctx);
21321 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21322 break;
21323 case NM_P_BR3A:
21324 s = sextract32(ctx->opcode, 0, 1) << 14 |
21325 extract32(ctx->opcode, 1, 13) << 1;
21326 check_cp1_enabled(ctx);
21327 switch (extract32(ctx->opcode, 16, 5)) {
21328 case NM_BC1EQZC:
21329 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21330 break;
21331 case NM_BC1NEZC:
21332 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21333 break;
21334 case NM_BPOSGE32C:
21335 check_dsp_r3(ctx);
21337 int32_t imm = extract32(ctx->opcode, 1, 13) |
21338 extract32(ctx->opcode, 0, 1) << 13;
21340 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21341 imm);
21343 break;
21344 default:
21345 generate_exception_end(ctx, EXCP_RI);
21346 break;
21348 break;
21349 case NM_BGEC:
21350 if (rs == rt) {
21351 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21352 } else {
21353 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21355 break;
21356 case NM_BGEUC:
21357 if (rs == rt || rt == 0) {
21358 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21359 } else if (rs == 0) {
21360 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21361 } else {
21362 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21364 break;
21367 break;
21368 case NM_P_BR2:
21370 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21371 extract32(ctx->opcode, 1, 13) << 1;
21372 switch (extract32(ctx->opcode, 14, 2)) {
21373 case NM_BNEC:
21374 check_nms(ctx);
21375 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21376 break;
21377 case NM_BLTC:
21378 if (rs != 0 && rt != 0 && rs == rt) {
21379 /* NOP */
21380 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21381 } else {
21382 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21384 break;
21385 case NM_BLTUC:
21386 if (rs == 0 || rs == rt) {
21387 /* NOP */
21388 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21389 } else {
21390 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21392 break;
21393 default:
21394 generate_exception_end(ctx, EXCP_RI);
21395 break;
21398 break;
21399 case NM_P_BRI:
21401 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21402 extract32(ctx->opcode, 1, 10) << 1;
21403 uint32_t u = extract32(ctx->opcode, 11, 7);
21405 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21406 rt, u, s);
21408 break;
21409 default:
21410 generate_exception_end(ctx, EXCP_RI);
21411 break;
21413 return 4;
21416 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21418 uint32_t op;
21419 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21420 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21421 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21422 int offset;
21423 int imm;
21425 /* make sure instructions are on a halfword boundary */
21426 if (ctx->base.pc_next & 0x1) {
21427 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21428 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21429 tcg_temp_free(tmp);
21430 generate_exception_end(ctx, EXCP_AdEL);
21431 return 2;
21434 op = extract32(ctx->opcode, 10, 6);
21435 switch (op) {
21436 case NM_P16_MV:
21437 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21438 if (rt != 0) {
21439 /* MOVE */
21440 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21441 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21442 } else {
21443 /* P16.RI */
21444 switch (extract32(ctx->opcode, 3, 2)) {
21445 case NM_P16_SYSCALL:
21446 if (extract32(ctx->opcode, 2, 1) == 0) {
21447 generate_exception_end(ctx, EXCP_SYSCALL);
21448 } else {
21449 generate_exception_end(ctx, EXCP_RI);
21451 break;
21452 case NM_BREAK16:
21453 generate_exception_end(ctx, EXCP_BREAK);
21454 break;
21455 case NM_SDBBP16:
21456 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21457 gen_helper_do_semihosting(cpu_env);
21458 } else {
21459 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21460 generate_exception_end(ctx, EXCP_RI);
21461 } else {
21462 generate_exception_end(ctx, EXCP_DBp);
21465 break;
21466 default:
21467 generate_exception_end(ctx, EXCP_RI);
21468 break;
21471 break;
21472 case NM_P16_SHIFT:
21474 int shift = extract32(ctx->opcode, 0, 3);
21475 uint32_t opc = 0;
21476 shift = (shift == 0) ? 8 : shift;
21478 switch (extract32(ctx->opcode, 3, 1)) {
21479 case NM_SLL16:
21480 opc = OPC_SLL;
21481 break;
21482 case NM_SRL16:
21483 opc = OPC_SRL;
21484 break;
21486 gen_shift_imm(ctx, opc, rt, rs, shift);
21488 break;
21489 case NM_P16C:
21490 switch (ctx->opcode & 1) {
21491 case NM_POOL16C_0:
21492 gen_pool16c_nanomips_insn(ctx);
21493 break;
21494 case NM_LWXS16:
21495 gen_ldxs(ctx, rt, rs, rd);
21496 break;
21498 break;
21499 case NM_P16_A1:
21500 switch (extract32(ctx->opcode, 6, 1)) {
21501 case NM_ADDIUR1SP:
21502 imm = extract32(ctx->opcode, 0, 6) << 2;
21503 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21504 break;
21505 default:
21506 generate_exception_end(ctx, EXCP_RI);
21507 break;
21509 break;
21510 case NM_P16_A2:
21511 switch (extract32(ctx->opcode, 3, 1)) {
21512 case NM_ADDIUR2:
21513 imm = extract32(ctx->opcode, 0, 3) << 2;
21514 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21515 break;
21516 case NM_P_ADDIURS5:
21517 rt = extract32(ctx->opcode, 5, 5);
21518 if (rt != 0) {
21519 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21520 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21521 (extract32(ctx->opcode, 0, 3));
21522 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21524 break;
21526 break;
21527 case NM_P16_ADDU:
21528 switch (ctx->opcode & 0x1) {
21529 case NM_ADDU16:
21530 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21531 break;
21532 case NM_SUBU16:
21533 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21534 break;
21536 break;
21537 case NM_P16_4X4:
21538 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21539 extract32(ctx->opcode, 5, 3);
21540 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21541 extract32(ctx->opcode, 0, 3);
21542 rt = decode_gpr_gpr4(rt);
21543 rs = decode_gpr_gpr4(rs);
21544 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21545 (extract32(ctx->opcode, 3, 1))) {
21546 case NM_ADDU4X4:
21547 check_nms(ctx);
21548 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21549 break;
21550 case NM_MUL4X4:
21551 check_nms(ctx);
21552 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21553 break;
21554 default:
21555 generate_exception_end(ctx, EXCP_RI);
21556 break;
21558 break;
21559 case NM_LI16:
21561 int imm = extract32(ctx->opcode, 0, 7);
21562 imm = (imm == 0x7f ? -1 : imm);
21563 if (rt != 0) {
21564 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21567 break;
21568 case NM_ANDI16:
21570 uint32_t u = extract32(ctx->opcode, 0, 4);
21571 u = (u == 12) ? 0xff :
21572 (u == 13) ? 0xffff : u;
21573 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21575 break;
21576 case NM_P16_LB:
21577 offset = extract32(ctx->opcode, 0, 2);
21578 switch (extract32(ctx->opcode, 2, 2)) {
21579 case NM_LB16:
21580 gen_ld(ctx, OPC_LB, rt, rs, offset);
21581 break;
21582 case NM_SB16:
21583 rt = decode_gpr_gpr3_src_store(
21584 NANOMIPS_EXTRACT_RD(ctx->opcode));
21585 gen_st(ctx, OPC_SB, rt, rs, offset);
21586 break;
21587 case NM_LBU16:
21588 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21589 break;
21590 default:
21591 generate_exception_end(ctx, EXCP_RI);
21592 break;
21594 break;
21595 case NM_P16_LH:
21596 offset = extract32(ctx->opcode, 1, 2) << 1;
21597 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21598 case NM_LH16:
21599 gen_ld(ctx, OPC_LH, rt, rs, offset);
21600 break;
21601 case NM_SH16:
21602 rt = decode_gpr_gpr3_src_store(
21603 NANOMIPS_EXTRACT_RD(ctx->opcode));
21604 gen_st(ctx, OPC_SH, rt, rs, offset);
21605 break;
21606 case NM_LHU16:
21607 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21608 break;
21609 default:
21610 generate_exception_end(ctx, EXCP_RI);
21611 break;
21613 break;
21614 case NM_LW16:
21615 offset = extract32(ctx->opcode, 0, 4) << 2;
21616 gen_ld(ctx, OPC_LW, rt, rs, offset);
21617 break;
21618 case NM_LWSP16:
21619 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21620 offset = extract32(ctx->opcode, 0, 5) << 2;
21621 gen_ld(ctx, OPC_LW, rt, 29, offset);
21622 break;
21623 case NM_LW4X4:
21624 check_nms(ctx);
21625 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21626 extract32(ctx->opcode, 5, 3);
21627 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21628 extract32(ctx->opcode, 0, 3);
21629 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21630 (extract32(ctx->opcode, 8, 1) << 2);
21631 rt = decode_gpr_gpr4(rt);
21632 rs = decode_gpr_gpr4(rs);
21633 gen_ld(ctx, OPC_LW, rt, rs, offset);
21634 break;
21635 case NM_SW4X4:
21636 check_nms(ctx);
21637 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21638 extract32(ctx->opcode, 5, 3);
21639 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21640 extract32(ctx->opcode, 0, 3);
21641 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21642 (extract32(ctx->opcode, 8, 1) << 2);
21643 rt = decode_gpr_gpr4_zero(rt);
21644 rs = decode_gpr_gpr4(rs);
21645 gen_st(ctx, OPC_SW, rt, rs, offset);
21646 break;
21647 case NM_LWGP16:
21648 offset = extract32(ctx->opcode, 0, 7) << 2;
21649 gen_ld(ctx, OPC_LW, rt, 28, offset);
21650 break;
21651 case NM_SWSP16:
21652 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21653 offset = extract32(ctx->opcode, 0, 5) << 2;
21654 gen_st(ctx, OPC_SW, rt, 29, offset);
21655 break;
21656 case NM_SW16:
21657 rt = decode_gpr_gpr3_src_store(
21658 NANOMIPS_EXTRACT_RD(ctx->opcode));
21659 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21660 offset = extract32(ctx->opcode, 0, 4) << 2;
21661 gen_st(ctx, OPC_SW, rt, rs, offset);
21662 break;
21663 case NM_SWGP16:
21664 rt = decode_gpr_gpr3_src_store(
21665 NANOMIPS_EXTRACT_RD(ctx->opcode));
21666 offset = extract32(ctx->opcode, 0, 7) << 2;
21667 gen_st(ctx, OPC_SW, rt, 28, offset);
21668 break;
21669 case NM_BC16:
21670 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21671 (sextract32(ctx->opcode, 0, 1) << 10) |
21672 (extract32(ctx->opcode, 1, 9) << 1));
21673 break;
21674 case NM_BALC16:
21675 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21676 (sextract32(ctx->opcode, 0, 1) << 10) |
21677 (extract32(ctx->opcode, 1, 9) << 1));
21678 break;
21679 case NM_BEQZC16:
21680 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21681 (sextract32(ctx->opcode, 0, 1) << 7) |
21682 (extract32(ctx->opcode, 1, 6) << 1));
21683 break;
21684 case NM_BNEZC16:
21685 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21686 (sextract32(ctx->opcode, 0, 1) << 7) |
21687 (extract32(ctx->opcode, 1, 6) << 1));
21688 break;
21689 case NM_P16_BR:
21690 switch (ctx->opcode & 0xf) {
21691 case 0:
21692 /* P16.JRC */
21693 switch (extract32(ctx->opcode, 4, 1)) {
21694 case NM_JRC:
21695 gen_compute_branch_nm(ctx, OPC_JR, 2,
21696 extract32(ctx->opcode, 5, 5), 0, 0);
21697 break;
21698 case NM_JALRC16:
21699 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21700 extract32(ctx->opcode, 5, 5), 31, 0);
21701 break;
21703 break;
21704 default:
21706 /* P16.BRI */
21707 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21708 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21709 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21710 extract32(ctx->opcode, 0, 4) << 1);
21712 break;
21714 break;
21715 case NM_P16_SR:
21717 int count = extract32(ctx->opcode, 0, 4);
21718 int u = extract32(ctx->opcode, 4, 4) << 4;
21720 rt = 30 + extract32(ctx->opcode, 9, 1);
21721 switch (extract32(ctx->opcode, 8, 1)) {
21722 case NM_SAVE16:
21723 gen_save(ctx, rt, count, 0, u);
21724 break;
21725 case NM_RESTORE_JRC16:
21726 gen_restore(ctx, rt, count, 0, u);
21727 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21728 break;
21731 break;
21732 case NM_MOVEP:
21733 case NM_MOVEPREV:
21734 check_nms(ctx);
21736 static const int gpr2reg1[] = {4, 5, 6, 7};
21737 static const int gpr2reg2[] = {5, 6, 7, 8};
21738 int re;
21739 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21740 extract32(ctx->opcode, 8, 1);
21741 int r1 = gpr2reg1[rd2];
21742 int r2 = gpr2reg2[rd2];
21743 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21744 extract32(ctx->opcode, 0, 3);
21745 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21746 extract32(ctx->opcode, 5, 3);
21747 TCGv t0 = tcg_temp_new();
21748 TCGv t1 = tcg_temp_new();
21749 if (op == NM_MOVEP) {
21750 rd = r1;
21751 re = r2;
21752 rs = decode_gpr_gpr4_zero(r3);
21753 rt = decode_gpr_gpr4_zero(r4);
21754 } else {
21755 rd = decode_gpr_gpr4(r3);
21756 re = decode_gpr_gpr4(r4);
21757 rs = r1;
21758 rt = r2;
21760 gen_load_gpr(t0, rs);
21761 gen_load_gpr(t1, rt);
21762 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21763 tcg_gen_mov_tl(cpu_gpr[re], t1);
21764 tcg_temp_free(t0);
21765 tcg_temp_free(t1);
21767 break;
21768 default:
21769 return decode_nanomips_32_48_opc(env, ctx);
21772 return 2;
21776 /* SmartMIPS extension to MIPS32 */
21778 #if defined(TARGET_MIPS64)
21780 /* MDMX extension to MIPS64 */
21782 #endif
21784 /* MIPSDSP functions. */
21785 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21786 int rd, int base, int offset)
21788 TCGv t0;
21790 check_dsp(ctx);
21791 t0 = tcg_temp_new();
21793 if (base == 0) {
21794 gen_load_gpr(t0, offset);
21795 } else if (offset == 0) {
21796 gen_load_gpr(t0, base);
21797 } else {
21798 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21801 switch (opc) {
21802 case OPC_LBUX:
21803 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21804 gen_store_gpr(t0, rd);
21805 break;
21806 case OPC_LHX:
21807 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21808 gen_store_gpr(t0, rd);
21809 break;
21810 case OPC_LWX:
21811 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21812 gen_store_gpr(t0, rd);
21813 break;
21814 #if defined(TARGET_MIPS64)
21815 case OPC_LDX:
21816 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21817 gen_store_gpr(t0, rd);
21818 break;
21819 #endif
21821 tcg_temp_free(t0);
21824 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21825 int ret, int v1, int v2)
21827 TCGv v1_t;
21828 TCGv v2_t;
21830 if (ret == 0) {
21831 /* Treat as NOP. */
21832 return;
21835 v1_t = tcg_temp_new();
21836 v2_t = tcg_temp_new();
21838 gen_load_gpr(v1_t, v1);
21839 gen_load_gpr(v2_t, v2);
21841 switch (op1) {
21842 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21843 case OPC_MULT_G_2E:
21844 check_dsp_r2(ctx);
21845 switch (op2) {
21846 case OPC_ADDUH_QB:
21847 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21848 break;
21849 case OPC_ADDUH_R_QB:
21850 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21851 break;
21852 case OPC_ADDQH_PH:
21853 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21854 break;
21855 case OPC_ADDQH_R_PH:
21856 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21857 break;
21858 case OPC_ADDQH_W:
21859 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21860 break;
21861 case OPC_ADDQH_R_W:
21862 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21863 break;
21864 case OPC_SUBUH_QB:
21865 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21866 break;
21867 case OPC_SUBUH_R_QB:
21868 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21869 break;
21870 case OPC_SUBQH_PH:
21871 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21872 break;
21873 case OPC_SUBQH_R_PH:
21874 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21875 break;
21876 case OPC_SUBQH_W:
21877 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21878 break;
21879 case OPC_SUBQH_R_W:
21880 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21881 break;
21883 break;
21884 case OPC_ABSQ_S_PH_DSP:
21885 switch (op2) {
21886 case OPC_ABSQ_S_QB:
21887 check_dsp_r2(ctx);
21888 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21889 break;
21890 case OPC_ABSQ_S_PH:
21891 check_dsp(ctx);
21892 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21893 break;
21894 case OPC_ABSQ_S_W:
21895 check_dsp(ctx);
21896 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21897 break;
21898 case OPC_PRECEQ_W_PHL:
21899 check_dsp(ctx);
21900 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21901 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21902 break;
21903 case OPC_PRECEQ_W_PHR:
21904 check_dsp(ctx);
21905 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21906 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21907 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21908 break;
21909 case OPC_PRECEQU_PH_QBL:
21910 check_dsp(ctx);
21911 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21912 break;
21913 case OPC_PRECEQU_PH_QBR:
21914 check_dsp(ctx);
21915 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21916 break;
21917 case OPC_PRECEQU_PH_QBLA:
21918 check_dsp(ctx);
21919 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21920 break;
21921 case OPC_PRECEQU_PH_QBRA:
21922 check_dsp(ctx);
21923 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21924 break;
21925 case OPC_PRECEU_PH_QBL:
21926 check_dsp(ctx);
21927 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21928 break;
21929 case OPC_PRECEU_PH_QBR:
21930 check_dsp(ctx);
21931 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21932 break;
21933 case OPC_PRECEU_PH_QBLA:
21934 check_dsp(ctx);
21935 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21936 break;
21937 case OPC_PRECEU_PH_QBRA:
21938 check_dsp(ctx);
21939 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21940 break;
21942 break;
21943 case OPC_ADDU_QB_DSP:
21944 switch (op2) {
21945 case OPC_ADDQ_PH:
21946 check_dsp(ctx);
21947 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21948 break;
21949 case OPC_ADDQ_S_PH:
21950 check_dsp(ctx);
21951 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21952 break;
21953 case OPC_ADDQ_S_W:
21954 check_dsp(ctx);
21955 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21956 break;
21957 case OPC_ADDU_QB:
21958 check_dsp(ctx);
21959 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21960 break;
21961 case OPC_ADDU_S_QB:
21962 check_dsp(ctx);
21963 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21964 break;
21965 case OPC_ADDU_PH:
21966 check_dsp_r2(ctx);
21967 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21968 break;
21969 case OPC_ADDU_S_PH:
21970 check_dsp_r2(ctx);
21971 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21972 break;
21973 case OPC_SUBQ_PH:
21974 check_dsp(ctx);
21975 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21976 break;
21977 case OPC_SUBQ_S_PH:
21978 check_dsp(ctx);
21979 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21980 break;
21981 case OPC_SUBQ_S_W:
21982 check_dsp(ctx);
21983 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21984 break;
21985 case OPC_SUBU_QB:
21986 check_dsp(ctx);
21987 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21988 break;
21989 case OPC_SUBU_S_QB:
21990 check_dsp(ctx);
21991 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21992 break;
21993 case OPC_SUBU_PH:
21994 check_dsp_r2(ctx);
21995 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21996 break;
21997 case OPC_SUBU_S_PH:
21998 check_dsp_r2(ctx);
21999 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22000 break;
22001 case OPC_ADDSC:
22002 check_dsp(ctx);
22003 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22004 break;
22005 case OPC_ADDWC:
22006 check_dsp(ctx);
22007 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22008 break;
22009 case OPC_MODSUB:
22010 check_dsp(ctx);
22011 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
22012 break;
22013 case OPC_RADDU_W_QB:
22014 check_dsp(ctx);
22015 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
22016 break;
22018 break;
22019 case OPC_CMPU_EQ_QB_DSP:
22020 switch (op2) {
22021 case OPC_PRECR_QB_PH:
22022 check_dsp_r2(ctx);
22023 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22024 break;
22025 case OPC_PRECRQ_QB_PH:
22026 check_dsp(ctx);
22027 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
22028 break;
22029 case OPC_PRECR_SRA_PH_W:
22030 check_dsp_r2(ctx);
22032 TCGv_i32 sa_t = tcg_const_i32(v2);
22033 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22034 cpu_gpr[ret]);
22035 tcg_temp_free_i32(sa_t);
22036 break;
22038 case OPC_PRECR_SRA_R_PH_W:
22039 check_dsp_r2(ctx);
22041 TCGv_i32 sa_t = tcg_const_i32(v2);
22042 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22043 cpu_gpr[ret]);
22044 tcg_temp_free_i32(sa_t);
22045 break;
22047 case OPC_PRECRQ_PH_W:
22048 check_dsp(ctx);
22049 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22050 break;
22051 case OPC_PRECRQ_RS_PH_W:
22052 check_dsp(ctx);
22053 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22054 break;
22055 case OPC_PRECRQU_S_QB_PH:
22056 check_dsp(ctx);
22057 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22058 break;
22060 break;
22061 #ifdef TARGET_MIPS64
22062 case OPC_ABSQ_S_QH_DSP:
22063 switch (op2) {
22064 case OPC_PRECEQ_L_PWL:
22065 check_dsp(ctx);
22066 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22067 break;
22068 case OPC_PRECEQ_L_PWR:
22069 check_dsp(ctx);
22070 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22071 break;
22072 case OPC_PRECEQ_PW_QHL:
22073 check_dsp(ctx);
22074 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22075 break;
22076 case OPC_PRECEQ_PW_QHR:
22077 check_dsp(ctx);
22078 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22079 break;
22080 case OPC_PRECEQ_PW_QHLA:
22081 check_dsp(ctx);
22082 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22083 break;
22084 case OPC_PRECEQ_PW_QHRA:
22085 check_dsp(ctx);
22086 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22087 break;
22088 case OPC_PRECEQU_QH_OBL:
22089 check_dsp(ctx);
22090 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22091 break;
22092 case OPC_PRECEQU_QH_OBR:
22093 check_dsp(ctx);
22094 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22095 break;
22096 case OPC_PRECEQU_QH_OBLA:
22097 check_dsp(ctx);
22098 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22099 break;
22100 case OPC_PRECEQU_QH_OBRA:
22101 check_dsp(ctx);
22102 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22103 break;
22104 case OPC_PRECEU_QH_OBL:
22105 check_dsp(ctx);
22106 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22107 break;
22108 case OPC_PRECEU_QH_OBR:
22109 check_dsp(ctx);
22110 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22111 break;
22112 case OPC_PRECEU_QH_OBLA:
22113 check_dsp(ctx);
22114 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22115 break;
22116 case OPC_PRECEU_QH_OBRA:
22117 check_dsp(ctx);
22118 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22119 break;
22120 case OPC_ABSQ_S_OB:
22121 check_dsp_r2(ctx);
22122 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22123 break;
22124 case OPC_ABSQ_S_PW:
22125 check_dsp(ctx);
22126 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22127 break;
22128 case OPC_ABSQ_S_QH:
22129 check_dsp(ctx);
22130 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22131 break;
22133 break;
22134 case OPC_ADDU_OB_DSP:
22135 switch (op2) {
22136 case OPC_RADDU_L_OB:
22137 check_dsp(ctx);
22138 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22139 break;
22140 case OPC_SUBQ_PW:
22141 check_dsp(ctx);
22142 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22143 break;
22144 case OPC_SUBQ_S_PW:
22145 check_dsp(ctx);
22146 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22147 break;
22148 case OPC_SUBQ_QH:
22149 check_dsp(ctx);
22150 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22151 break;
22152 case OPC_SUBQ_S_QH:
22153 check_dsp(ctx);
22154 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22155 break;
22156 case OPC_SUBU_OB:
22157 check_dsp(ctx);
22158 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22159 break;
22160 case OPC_SUBU_S_OB:
22161 check_dsp(ctx);
22162 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22163 break;
22164 case OPC_SUBU_QH:
22165 check_dsp_r2(ctx);
22166 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22167 break;
22168 case OPC_SUBU_S_QH:
22169 check_dsp_r2(ctx);
22170 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22171 break;
22172 case OPC_SUBUH_OB:
22173 check_dsp_r2(ctx);
22174 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22175 break;
22176 case OPC_SUBUH_R_OB:
22177 check_dsp_r2(ctx);
22178 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22179 break;
22180 case OPC_ADDQ_PW:
22181 check_dsp(ctx);
22182 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22183 break;
22184 case OPC_ADDQ_S_PW:
22185 check_dsp(ctx);
22186 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22187 break;
22188 case OPC_ADDQ_QH:
22189 check_dsp(ctx);
22190 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22191 break;
22192 case OPC_ADDQ_S_QH:
22193 check_dsp(ctx);
22194 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22195 break;
22196 case OPC_ADDU_OB:
22197 check_dsp(ctx);
22198 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22199 break;
22200 case OPC_ADDU_S_OB:
22201 check_dsp(ctx);
22202 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22203 break;
22204 case OPC_ADDU_QH:
22205 check_dsp_r2(ctx);
22206 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22207 break;
22208 case OPC_ADDU_S_QH:
22209 check_dsp_r2(ctx);
22210 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22211 break;
22212 case OPC_ADDUH_OB:
22213 check_dsp_r2(ctx);
22214 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22215 break;
22216 case OPC_ADDUH_R_OB:
22217 check_dsp_r2(ctx);
22218 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22219 break;
22221 break;
22222 case OPC_CMPU_EQ_OB_DSP:
22223 switch (op2) {
22224 case OPC_PRECR_OB_QH:
22225 check_dsp_r2(ctx);
22226 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22227 break;
22228 case OPC_PRECR_SRA_QH_PW:
22229 check_dsp_r2(ctx);
22231 TCGv_i32 ret_t = tcg_const_i32(ret);
22232 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22233 tcg_temp_free_i32(ret_t);
22234 break;
22236 case OPC_PRECR_SRA_R_QH_PW:
22237 check_dsp_r2(ctx);
22239 TCGv_i32 sa_v = tcg_const_i32(ret);
22240 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22241 tcg_temp_free_i32(sa_v);
22242 break;
22244 case OPC_PRECRQ_OB_QH:
22245 check_dsp(ctx);
22246 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22247 break;
22248 case OPC_PRECRQ_PW_L:
22249 check_dsp(ctx);
22250 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22251 break;
22252 case OPC_PRECRQ_QH_PW:
22253 check_dsp(ctx);
22254 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22255 break;
22256 case OPC_PRECRQ_RS_QH_PW:
22257 check_dsp(ctx);
22258 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22259 break;
22260 case OPC_PRECRQU_S_OB_QH:
22261 check_dsp(ctx);
22262 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22263 break;
22265 break;
22266 #endif
22269 tcg_temp_free(v1_t);
22270 tcg_temp_free(v2_t);
22273 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22274 int ret, int v1, int v2)
22276 uint32_t op2;
22277 TCGv t0;
22278 TCGv v1_t;
22279 TCGv v2_t;
22281 if (ret == 0) {
22282 /* Treat as NOP. */
22283 return;
22286 t0 = tcg_temp_new();
22287 v1_t = tcg_temp_new();
22288 v2_t = tcg_temp_new();
22290 tcg_gen_movi_tl(t0, v1);
22291 gen_load_gpr(v1_t, v1);
22292 gen_load_gpr(v2_t, v2);
22294 switch (opc) {
22295 case OPC_SHLL_QB_DSP:
22297 op2 = MASK_SHLL_QB(ctx->opcode);
22298 switch (op2) {
22299 case OPC_SHLL_QB:
22300 check_dsp(ctx);
22301 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22302 break;
22303 case OPC_SHLLV_QB:
22304 check_dsp(ctx);
22305 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22306 break;
22307 case OPC_SHLL_PH:
22308 check_dsp(ctx);
22309 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22310 break;
22311 case OPC_SHLLV_PH:
22312 check_dsp(ctx);
22313 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22314 break;
22315 case OPC_SHLL_S_PH:
22316 check_dsp(ctx);
22317 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22318 break;
22319 case OPC_SHLLV_S_PH:
22320 check_dsp(ctx);
22321 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22322 break;
22323 case OPC_SHLL_S_W:
22324 check_dsp(ctx);
22325 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22326 break;
22327 case OPC_SHLLV_S_W:
22328 check_dsp(ctx);
22329 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22330 break;
22331 case OPC_SHRL_QB:
22332 check_dsp(ctx);
22333 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22334 break;
22335 case OPC_SHRLV_QB:
22336 check_dsp(ctx);
22337 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22338 break;
22339 case OPC_SHRL_PH:
22340 check_dsp_r2(ctx);
22341 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22342 break;
22343 case OPC_SHRLV_PH:
22344 check_dsp_r2(ctx);
22345 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22346 break;
22347 case OPC_SHRA_QB:
22348 check_dsp_r2(ctx);
22349 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22350 break;
22351 case OPC_SHRA_R_QB:
22352 check_dsp_r2(ctx);
22353 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22354 break;
22355 case OPC_SHRAV_QB:
22356 check_dsp_r2(ctx);
22357 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22358 break;
22359 case OPC_SHRAV_R_QB:
22360 check_dsp_r2(ctx);
22361 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22362 break;
22363 case OPC_SHRA_PH:
22364 check_dsp(ctx);
22365 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22366 break;
22367 case OPC_SHRA_R_PH:
22368 check_dsp(ctx);
22369 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22370 break;
22371 case OPC_SHRAV_PH:
22372 check_dsp(ctx);
22373 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22374 break;
22375 case OPC_SHRAV_R_PH:
22376 check_dsp(ctx);
22377 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22378 break;
22379 case OPC_SHRA_R_W:
22380 check_dsp(ctx);
22381 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22382 break;
22383 case OPC_SHRAV_R_W:
22384 check_dsp(ctx);
22385 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22386 break;
22387 default: /* Invalid */
22388 MIPS_INVAL("MASK SHLL.QB");
22389 generate_exception_end(ctx, EXCP_RI);
22390 break;
22392 break;
22394 #ifdef TARGET_MIPS64
22395 case OPC_SHLL_OB_DSP:
22396 op2 = MASK_SHLL_OB(ctx->opcode);
22397 switch (op2) {
22398 case OPC_SHLL_PW:
22399 check_dsp(ctx);
22400 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22401 break;
22402 case OPC_SHLLV_PW:
22403 check_dsp(ctx);
22404 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22405 break;
22406 case OPC_SHLL_S_PW:
22407 check_dsp(ctx);
22408 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22409 break;
22410 case OPC_SHLLV_S_PW:
22411 check_dsp(ctx);
22412 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22413 break;
22414 case OPC_SHLL_OB:
22415 check_dsp(ctx);
22416 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22417 break;
22418 case OPC_SHLLV_OB:
22419 check_dsp(ctx);
22420 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22421 break;
22422 case OPC_SHLL_QH:
22423 check_dsp(ctx);
22424 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22425 break;
22426 case OPC_SHLLV_QH:
22427 check_dsp(ctx);
22428 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22429 break;
22430 case OPC_SHLL_S_QH:
22431 check_dsp(ctx);
22432 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22433 break;
22434 case OPC_SHLLV_S_QH:
22435 check_dsp(ctx);
22436 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22437 break;
22438 case OPC_SHRA_OB:
22439 check_dsp_r2(ctx);
22440 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22441 break;
22442 case OPC_SHRAV_OB:
22443 check_dsp_r2(ctx);
22444 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22445 break;
22446 case OPC_SHRA_R_OB:
22447 check_dsp_r2(ctx);
22448 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22449 break;
22450 case OPC_SHRAV_R_OB:
22451 check_dsp_r2(ctx);
22452 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22453 break;
22454 case OPC_SHRA_PW:
22455 check_dsp(ctx);
22456 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22457 break;
22458 case OPC_SHRAV_PW:
22459 check_dsp(ctx);
22460 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22461 break;
22462 case OPC_SHRA_R_PW:
22463 check_dsp(ctx);
22464 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22465 break;
22466 case OPC_SHRAV_R_PW:
22467 check_dsp(ctx);
22468 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22469 break;
22470 case OPC_SHRA_QH:
22471 check_dsp(ctx);
22472 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22473 break;
22474 case OPC_SHRAV_QH:
22475 check_dsp(ctx);
22476 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22477 break;
22478 case OPC_SHRA_R_QH:
22479 check_dsp(ctx);
22480 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22481 break;
22482 case OPC_SHRAV_R_QH:
22483 check_dsp(ctx);
22484 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22485 break;
22486 case OPC_SHRL_OB:
22487 check_dsp(ctx);
22488 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22489 break;
22490 case OPC_SHRLV_OB:
22491 check_dsp(ctx);
22492 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22493 break;
22494 case OPC_SHRL_QH:
22495 check_dsp_r2(ctx);
22496 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22497 break;
22498 case OPC_SHRLV_QH:
22499 check_dsp_r2(ctx);
22500 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22501 break;
22502 default: /* Invalid */
22503 MIPS_INVAL("MASK SHLL.OB");
22504 generate_exception_end(ctx, EXCP_RI);
22505 break;
22507 break;
22508 #endif
22511 tcg_temp_free(t0);
22512 tcg_temp_free(v1_t);
22513 tcg_temp_free(v2_t);
22516 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22517 int ret, int v1, int v2, int check_ret)
22519 TCGv_i32 t0;
22520 TCGv v1_t;
22521 TCGv v2_t;
22523 if ((ret == 0) && (check_ret == 1)) {
22524 /* Treat as NOP. */
22525 return;
22528 t0 = tcg_temp_new_i32();
22529 v1_t = tcg_temp_new();
22530 v2_t = tcg_temp_new();
22532 tcg_gen_movi_i32(t0, ret);
22533 gen_load_gpr(v1_t, v1);
22534 gen_load_gpr(v2_t, v2);
22536 switch (op1) {
22537 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22538 * the same mask and op1. */
22539 case OPC_MULT_G_2E:
22540 check_dsp_r2(ctx);
22541 switch (op2) {
22542 case OPC_MUL_PH:
22543 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22544 break;
22545 case OPC_MUL_S_PH:
22546 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22547 break;
22548 case OPC_MULQ_S_W:
22549 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22550 break;
22551 case OPC_MULQ_RS_W:
22552 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22553 break;
22555 break;
22556 case OPC_DPA_W_PH_DSP:
22557 switch (op2) {
22558 case OPC_DPAU_H_QBL:
22559 check_dsp(ctx);
22560 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22561 break;
22562 case OPC_DPAU_H_QBR:
22563 check_dsp(ctx);
22564 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22565 break;
22566 case OPC_DPSU_H_QBL:
22567 check_dsp(ctx);
22568 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22569 break;
22570 case OPC_DPSU_H_QBR:
22571 check_dsp(ctx);
22572 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22573 break;
22574 case OPC_DPA_W_PH:
22575 check_dsp_r2(ctx);
22576 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22577 break;
22578 case OPC_DPAX_W_PH:
22579 check_dsp_r2(ctx);
22580 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22581 break;
22582 case OPC_DPAQ_S_W_PH:
22583 check_dsp(ctx);
22584 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22585 break;
22586 case OPC_DPAQX_S_W_PH:
22587 check_dsp_r2(ctx);
22588 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22589 break;
22590 case OPC_DPAQX_SA_W_PH:
22591 check_dsp_r2(ctx);
22592 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22593 break;
22594 case OPC_DPS_W_PH:
22595 check_dsp_r2(ctx);
22596 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22597 break;
22598 case OPC_DPSX_W_PH:
22599 check_dsp_r2(ctx);
22600 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22601 break;
22602 case OPC_DPSQ_S_W_PH:
22603 check_dsp(ctx);
22604 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22605 break;
22606 case OPC_DPSQX_S_W_PH:
22607 check_dsp_r2(ctx);
22608 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22609 break;
22610 case OPC_DPSQX_SA_W_PH:
22611 check_dsp_r2(ctx);
22612 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22613 break;
22614 case OPC_MULSAQ_S_W_PH:
22615 check_dsp(ctx);
22616 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22617 break;
22618 case OPC_DPAQ_SA_L_W:
22619 check_dsp(ctx);
22620 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22621 break;
22622 case OPC_DPSQ_SA_L_W:
22623 check_dsp(ctx);
22624 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22625 break;
22626 case OPC_MAQ_S_W_PHL:
22627 check_dsp(ctx);
22628 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22629 break;
22630 case OPC_MAQ_S_W_PHR:
22631 check_dsp(ctx);
22632 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22633 break;
22634 case OPC_MAQ_SA_W_PHL:
22635 check_dsp(ctx);
22636 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22637 break;
22638 case OPC_MAQ_SA_W_PHR:
22639 check_dsp(ctx);
22640 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22641 break;
22642 case OPC_MULSA_W_PH:
22643 check_dsp_r2(ctx);
22644 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22645 break;
22647 break;
22648 #ifdef TARGET_MIPS64
22649 case OPC_DPAQ_W_QH_DSP:
22651 int ac = ret & 0x03;
22652 tcg_gen_movi_i32(t0, ac);
22654 switch (op2) {
22655 case OPC_DMADD:
22656 check_dsp(ctx);
22657 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22658 break;
22659 case OPC_DMADDU:
22660 check_dsp(ctx);
22661 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22662 break;
22663 case OPC_DMSUB:
22664 check_dsp(ctx);
22665 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22666 break;
22667 case OPC_DMSUBU:
22668 check_dsp(ctx);
22669 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22670 break;
22671 case OPC_DPA_W_QH:
22672 check_dsp_r2(ctx);
22673 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22674 break;
22675 case OPC_DPAQ_S_W_QH:
22676 check_dsp(ctx);
22677 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22678 break;
22679 case OPC_DPAQ_SA_L_PW:
22680 check_dsp(ctx);
22681 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22682 break;
22683 case OPC_DPAU_H_OBL:
22684 check_dsp(ctx);
22685 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22686 break;
22687 case OPC_DPAU_H_OBR:
22688 check_dsp(ctx);
22689 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22690 break;
22691 case OPC_DPS_W_QH:
22692 check_dsp_r2(ctx);
22693 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22694 break;
22695 case OPC_DPSQ_S_W_QH:
22696 check_dsp(ctx);
22697 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22698 break;
22699 case OPC_DPSQ_SA_L_PW:
22700 check_dsp(ctx);
22701 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22702 break;
22703 case OPC_DPSU_H_OBL:
22704 check_dsp(ctx);
22705 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22706 break;
22707 case OPC_DPSU_H_OBR:
22708 check_dsp(ctx);
22709 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22710 break;
22711 case OPC_MAQ_S_L_PWL:
22712 check_dsp(ctx);
22713 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22714 break;
22715 case OPC_MAQ_S_L_PWR:
22716 check_dsp(ctx);
22717 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22718 break;
22719 case OPC_MAQ_S_W_QHLL:
22720 check_dsp(ctx);
22721 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22722 break;
22723 case OPC_MAQ_SA_W_QHLL:
22724 check_dsp(ctx);
22725 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22726 break;
22727 case OPC_MAQ_S_W_QHLR:
22728 check_dsp(ctx);
22729 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22730 break;
22731 case OPC_MAQ_SA_W_QHLR:
22732 check_dsp(ctx);
22733 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22734 break;
22735 case OPC_MAQ_S_W_QHRL:
22736 check_dsp(ctx);
22737 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22738 break;
22739 case OPC_MAQ_SA_W_QHRL:
22740 check_dsp(ctx);
22741 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22742 break;
22743 case OPC_MAQ_S_W_QHRR:
22744 check_dsp(ctx);
22745 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22746 break;
22747 case OPC_MAQ_SA_W_QHRR:
22748 check_dsp(ctx);
22749 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22750 break;
22751 case OPC_MULSAQ_S_L_PW:
22752 check_dsp(ctx);
22753 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22754 break;
22755 case OPC_MULSAQ_S_W_QH:
22756 check_dsp(ctx);
22757 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22758 break;
22761 break;
22762 #endif
22763 case OPC_ADDU_QB_DSP:
22764 switch (op2) {
22765 case OPC_MULEU_S_PH_QBL:
22766 check_dsp(ctx);
22767 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22768 break;
22769 case OPC_MULEU_S_PH_QBR:
22770 check_dsp(ctx);
22771 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22772 break;
22773 case OPC_MULQ_RS_PH:
22774 check_dsp(ctx);
22775 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22776 break;
22777 case OPC_MULEQ_S_W_PHL:
22778 check_dsp(ctx);
22779 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22780 break;
22781 case OPC_MULEQ_S_W_PHR:
22782 check_dsp(ctx);
22783 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22784 break;
22785 case OPC_MULQ_S_PH:
22786 check_dsp_r2(ctx);
22787 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22788 break;
22790 break;
22791 #ifdef TARGET_MIPS64
22792 case OPC_ADDU_OB_DSP:
22793 switch (op2) {
22794 case OPC_MULEQ_S_PW_QHL:
22795 check_dsp(ctx);
22796 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22797 break;
22798 case OPC_MULEQ_S_PW_QHR:
22799 check_dsp(ctx);
22800 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22801 break;
22802 case OPC_MULEU_S_QH_OBL:
22803 check_dsp(ctx);
22804 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22805 break;
22806 case OPC_MULEU_S_QH_OBR:
22807 check_dsp(ctx);
22808 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22809 break;
22810 case OPC_MULQ_RS_QH:
22811 check_dsp(ctx);
22812 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22813 break;
22815 break;
22816 #endif
22819 tcg_temp_free_i32(t0);
22820 tcg_temp_free(v1_t);
22821 tcg_temp_free(v2_t);
22824 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22825 int ret, int val)
22827 int16_t imm;
22828 TCGv t0;
22829 TCGv val_t;
22831 if (ret == 0) {
22832 /* Treat as NOP. */
22833 return;
22836 t0 = tcg_temp_new();
22837 val_t = tcg_temp_new();
22838 gen_load_gpr(val_t, val);
22840 switch (op1) {
22841 case OPC_ABSQ_S_PH_DSP:
22842 switch (op2) {
22843 case OPC_BITREV:
22844 check_dsp(ctx);
22845 gen_helper_bitrev(cpu_gpr[ret], val_t);
22846 break;
22847 case OPC_REPL_QB:
22848 check_dsp(ctx);
22850 target_long result;
22851 imm = (ctx->opcode >> 16) & 0xFF;
22852 result = (uint32_t)imm << 24 |
22853 (uint32_t)imm << 16 |
22854 (uint32_t)imm << 8 |
22855 (uint32_t)imm;
22856 result = (int32_t)result;
22857 tcg_gen_movi_tl(cpu_gpr[ret], result);
22859 break;
22860 case OPC_REPLV_QB:
22861 check_dsp(ctx);
22862 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22863 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22864 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22865 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22866 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22867 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22868 break;
22869 case OPC_REPL_PH:
22870 check_dsp(ctx);
22872 imm = (ctx->opcode >> 16) & 0x03FF;
22873 imm = (int16_t)(imm << 6) >> 6;
22874 tcg_gen_movi_tl(cpu_gpr[ret], \
22875 (target_long)((int32_t)imm << 16 | \
22876 (uint16_t)imm));
22878 break;
22879 case OPC_REPLV_PH:
22880 check_dsp(ctx);
22881 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22882 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22883 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22884 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22885 break;
22887 break;
22888 #ifdef TARGET_MIPS64
22889 case OPC_ABSQ_S_QH_DSP:
22890 switch (op2) {
22891 case OPC_REPL_OB:
22892 check_dsp(ctx);
22894 target_long temp;
22896 imm = (ctx->opcode >> 16) & 0xFF;
22897 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22898 temp = (temp << 16) | temp;
22899 temp = (temp << 32) | temp;
22900 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22901 break;
22903 case OPC_REPL_PW:
22904 check_dsp(ctx);
22906 target_long temp;
22908 imm = (ctx->opcode >> 16) & 0x03FF;
22909 imm = (int16_t)(imm << 6) >> 6;
22910 temp = ((target_long)imm << 32) \
22911 | ((target_long)imm & 0xFFFFFFFF);
22912 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22913 break;
22915 case OPC_REPL_QH:
22916 check_dsp(ctx);
22918 target_long temp;
22920 imm = (ctx->opcode >> 16) & 0x03FF;
22921 imm = (int16_t)(imm << 6) >> 6;
22923 temp = ((uint64_t)(uint16_t)imm << 48) |
22924 ((uint64_t)(uint16_t)imm << 32) |
22925 ((uint64_t)(uint16_t)imm << 16) |
22926 (uint64_t)(uint16_t)imm;
22927 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22928 break;
22930 case OPC_REPLV_OB:
22931 check_dsp(ctx);
22932 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22933 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22934 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22935 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22936 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22937 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22938 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22939 break;
22940 case OPC_REPLV_PW:
22941 check_dsp(ctx);
22942 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22943 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22944 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22945 break;
22946 case OPC_REPLV_QH:
22947 check_dsp(ctx);
22948 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22949 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22950 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22951 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22952 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22953 break;
22955 break;
22956 #endif
22958 tcg_temp_free(t0);
22959 tcg_temp_free(val_t);
22962 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22963 uint32_t op1, uint32_t op2,
22964 int ret, int v1, int v2, int check_ret)
22966 TCGv t1;
22967 TCGv v1_t;
22968 TCGv v2_t;
22970 if ((ret == 0) && (check_ret == 1)) {
22971 /* Treat as NOP. */
22972 return;
22975 t1 = tcg_temp_new();
22976 v1_t = tcg_temp_new();
22977 v2_t = tcg_temp_new();
22979 gen_load_gpr(v1_t, v1);
22980 gen_load_gpr(v2_t, v2);
22982 switch (op1) {
22983 case OPC_CMPU_EQ_QB_DSP:
22984 switch (op2) {
22985 case OPC_CMPU_EQ_QB:
22986 check_dsp(ctx);
22987 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22988 break;
22989 case OPC_CMPU_LT_QB:
22990 check_dsp(ctx);
22991 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22992 break;
22993 case OPC_CMPU_LE_QB:
22994 check_dsp(ctx);
22995 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22996 break;
22997 case OPC_CMPGU_EQ_QB:
22998 check_dsp(ctx);
22999 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
23000 break;
23001 case OPC_CMPGU_LT_QB:
23002 check_dsp(ctx);
23003 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
23004 break;
23005 case OPC_CMPGU_LE_QB:
23006 check_dsp(ctx);
23007 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
23008 break;
23009 case OPC_CMPGDU_EQ_QB:
23010 check_dsp_r2(ctx);
23011 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
23012 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23013 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23014 tcg_gen_shli_tl(t1, t1, 24);
23015 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23016 break;
23017 case OPC_CMPGDU_LT_QB:
23018 check_dsp_r2(ctx);
23019 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
23020 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23021 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23022 tcg_gen_shli_tl(t1, t1, 24);
23023 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23024 break;
23025 case OPC_CMPGDU_LE_QB:
23026 check_dsp_r2(ctx);
23027 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
23028 tcg_gen_mov_tl(cpu_gpr[ret], t1);
23029 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
23030 tcg_gen_shli_tl(t1, t1, 24);
23031 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
23032 break;
23033 case OPC_CMP_EQ_PH:
23034 check_dsp(ctx);
23035 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23036 break;
23037 case OPC_CMP_LT_PH:
23038 check_dsp(ctx);
23039 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23040 break;
23041 case OPC_CMP_LE_PH:
23042 check_dsp(ctx);
23043 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23044 break;
23045 case OPC_PICK_QB:
23046 check_dsp(ctx);
23047 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23048 break;
23049 case OPC_PICK_PH:
23050 check_dsp(ctx);
23051 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23052 break;
23053 case OPC_PACKRL_PH:
23054 check_dsp(ctx);
23055 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23056 break;
23058 break;
23059 #ifdef TARGET_MIPS64
23060 case OPC_CMPU_EQ_OB_DSP:
23061 switch (op2) {
23062 case OPC_CMP_EQ_PW:
23063 check_dsp(ctx);
23064 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23065 break;
23066 case OPC_CMP_LT_PW:
23067 check_dsp(ctx);
23068 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23069 break;
23070 case OPC_CMP_LE_PW:
23071 check_dsp(ctx);
23072 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23073 break;
23074 case OPC_CMP_EQ_QH:
23075 check_dsp(ctx);
23076 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23077 break;
23078 case OPC_CMP_LT_QH:
23079 check_dsp(ctx);
23080 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23081 break;
23082 case OPC_CMP_LE_QH:
23083 check_dsp(ctx);
23084 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23085 break;
23086 case OPC_CMPGDU_EQ_OB:
23087 check_dsp_r2(ctx);
23088 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23089 break;
23090 case OPC_CMPGDU_LT_OB:
23091 check_dsp_r2(ctx);
23092 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23093 break;
23094 case OPC_CMPGDU_LE_OB:
23095 check_dsp_r2(ctx);
23096 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23097 break;
23098 case OPC_CMPGU_EQ_OB:
23099 check_dsp(ctx);
23100 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23101 break;
23102 case OPC_CMPGU_LT_OB:
23103 check_dsp(ctx);
23104 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23105 break;
23106 case OPC_CMPGU_LE_OB:
23107 check_dsp(ctx);
23108 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23109 break;
23110 case OPC_CMPU_EQ_OB:
23111 check_dsp(ctx);
23112 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23113 break;
23114 case OPC_CMPU_LT_OB:
23115 check_dsp(ctx);
23116 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23117 break;
23118 case OPC_CMPU_LE_OB:
23119 check_dsp(ctx);
23120 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23121 break;
23122 case OPC_PACKRL_PW:
23123 check_dsp(ctx);
23124 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23125 break;
23126 case OPC_PICK_OB:
23127 check_dsp(ctx);
23128 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23129 break;
23130 case OPC_PICK_PW:
23131 check_dsp(ctx);
23132 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23133 break;
23134 case OPC_PICK_QH:
23135 check_dsp(ctx);
23136 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23137 break;
23139 break;
23140 #endif
23143 tcg_temp_free(t1);
23144 tcg_temp_free(v1_t);
23145 tcg_temp_free(v2_t);
23148 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23149 uint32_t op1, int rt, int rs, int sa)
23151 TCGv t0;
23153 check_dsp_r2(ctx);
23155 if (rt == 0) {
23156 /* Treat as NOP. */
23157 return;
23160 t0 = tcg_temp_new();
23161 gen_load_gpr(t0, rs);
23163 switch (op1) {
23164 case OPC_APPEND_DSP:
23165 switch (MASK_APPEND(ctx->opcode)) {
23166 case OPC_APPEND:
23167 if (sa != 0) {
23168 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23170 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23171 break;
23172 case OPC_PREPEND:
23173 if (sa != 0) {
23174 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23175 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23176 tcg_gen_shli_tl(t0, t0, 32 - sa);
23177 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23179 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23180 break;
23181 case OPC_BALIGN:
23182 sa &= 3;
23183 if (sa != 0 && sa != 2) {
23184 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23185 tcg_gen_ext32u_tl(t0, t0);
23186 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23187 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23189 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23190 break;
23191 default: /* Invalid */
23192 MIPS_INVAL("MASK APPEND");
23193 generate_exception_end(ctx, EXCP_RI);
23194 break;
23196 break;
23197 #ifdef TARGET_MIPS64
23198 case OPC_DAPPEND_DSP:
23199 switch (MASK_DAPPEND(ctx->opcode)) {
23200 case OPC_DAPPEND:
23201 if (sa != 0) {
23202 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23204 break;
23205 case OPC_PREPENDD:
23206 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23207 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23208 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23209 break;
23210 case OPC_PREPENDW:
23211 if (sa != 0) {
23212 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23213 tcg_gen_shli_tl(t0, t0, 64 - sa);
23214 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23216 break;
23217 case OPC_DBALIGN:
23218 sa &= 7;
23219 if (sa != 0 && sa != 2 && sa != 4) {
23220 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23221 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23222 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23224 break;
23225 default: /* Invalid */
23226 MIPS_INVAL("MASK DAPPEND");
23227 generate_exception_end(ctx, EXCP_RI);
23228 break;
23230 break;
23231 #endif
23233 tcg_temp_free(t0);
23236 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23237 int ret, int v1, int v2, int check_ret)
23240 TCGv t0;
23241 TCGv t1;
23242 TCGv v1_t;
23243 TCGv v2_t;
23244 int16_t imm;
23246 if ((ret == 0) && (check_ret == 1)) {
23247 /* Treat as NOP. */
23248 return;
23251 t0 = tcg_temp_new();
23252 t1 = tcg_temp_new();
23253 v1_t = tcg_temp_new();
23254 v2_t = tcg_temp_new();
23256 gen_load_gpr(v1_t, v1);
23257 gen_load_gpr(v2_t, v2);
23259 switch (op1) {
23260 case OPC_EXTR_W_DSP:
23261 check_dsp(ctx);
23262 switch (op2) {
23263 case OPC_EXTR_W:
23264 tcg_gen_movi_tl(t0, v2);
23265 tcg_gen_movi_tl(t1, v1);
23266 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23267 break;
23268 case OPC_EXTR_R_W:
23269 tcg_gen_movi_tl(t0, v2);
23270 tcg_gen_movi_tl(t1, v1);
23271 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23272 break;
23273 case OPC_EXTR_RS_W:
23274 tcg_gen_movi_tl(t0, v2);
23275 tcg_gen_movi_tl(t1, v1);
23276 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23277 break;
23278 case OPC_EXTR_S_H:
23279 tcg_gen_movi_tl(t0, v2);
23280 tcg_gen_movi_tl(t1, v1);
23281 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23282 break;
23283 case OPC_EXTRV_S_H:
23284 tcg_gen_movi_tl(t0, v2);
23285 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23286 break;
23287 case OPC_EXTRV_W:
23288 tcg_gen_movi_tl(t0, v2);
23289 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23290 break;
23291 case OPC_EXTRV_R_W:
23292 tcg_gen_movi_tl(t0, v2);
23293 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23294 break;
23295 case OPC_EXTRV_RS_W:
23296 tcg_gen_movi_tl(t0, v2);
23297 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23298 break;
23299 case OPC_EXTP:
23300 tcg_gen_movi_tl(t0, v2);
23301 tcg_gen_movi_tl(t1, v1);
23302 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23303 break;
23304 case OPC_EXTPV:
23305 tcg_gen_movi_tl(t0, v2);
23306 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23307 break;
23308 case OPC_EXTPDP:
23309 tcg_gen_movi_tl(t0, v2);
23310 tcg_gen_movi_tl(t1, v1);
23311 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23312 break;
23313 case OPC_EXTPDPV:
23314 tcg_gen_movi_tl(t0, v2);
23315 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23316 break;
23317 case OPC_SHILO:
23318 imm = (ctx->opcode >> 20) & 0x3F;
23319 tcg_gen_movi_tl(t0, ret);
23320 tcg_gen_movi_tl(t1, imm);
23321 gen_helper_shilo(t0, t1, cpu_env);
23322 break;
23323 case OPC_SHILOV:
23324 tcg_gen_movi_tl(t0, ret);
23325 gen_helper_shilo(t0, v1_t, cpu_env);
23326 break;
23327 case OPC_MTHLIP:
23328 tcg_gen_movi_tl(t0, ret);
23329 gen_helper_mthlip(t0, v1_t, cpu_env);
23330 break;
23331 case OPC_WRDSP:
23332 imm = (ctx->opcode >> 11) & 0x3FF;
23333 tcg_gen_movi_tl(t0, imm);
23334 gen_helper_wrdsp(v1_t, t0, cpu_env);
23335 break;
23336 case OPC_RDDSP:
23337 imm = (ctx->opcode >> 16) & 0x03FF;
23338 tcg_gen_movi_tl(t0, imm);
23339 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23340 break;
23342 break;
23343 #ifdef TARGET_MIPS64
23344 case OPC_DEXTR_W_DSP:
23345 check_dsp(ctx);
23346 switch (op2) {
23347 case OPC_DMTHLIP:
23348 tcg_gen_movi_tl(t0, ret);
23349 gen_helper_dmthlip(v1_t, t0, cpu_env);
23350 break;
23351 case OPC_DSHILO:
23353 int shift = (ctx->opcode >> 19) & 0x7F;
23354 int ac = (ctx->opcode >> 11) & 0x03;
23355 tcg_gen_movi_tl(t0, shift);
23356 tcg_gen_movi_tl(t1, ac);
23357 gen_helper_dshilo(t0, t1, cpu_env);
23358 break;
23360 case OPC_DSHILOV:
23362 int ac = (ctx->opcode >> 11) & 0x03;
23363 tcg_gen_movi_tl(t0, ac);
23364 gen_helper_dshilo(v1_t, t0, cpu_env);
23365 break;
23367 case OPC_DEXTP:
23368 tcg_gen_movi_tl(t0, v2);
23369 tcg_gen_movi_tl(t1, v1);
23371 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23372 break;
23373 case OPC_DEXTPV:
23374 tcg_gen_movi_tl(t0, v2);
23375 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23376 break;
23377 case OPC_DEXTPDP:
23378 tcg_gen_movi_tl(t0, v2);
23379 tcg_gen_movi_tl(t1, v1);
23380 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23381 break;
23382 case OPC_DEXTPDPV:
23383 tcg_gen_movi_tl(t0, v2);
23384 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23385 break;
23386 case OPC_DEXTR_L:
23387 tcg_gen_movi_tl(t0, v2);
23388 tcg_gen_movi_tl(t1, v1);
23389 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23390 break;
23391 case OPC_DEXTR_R_L:
23392 tcg_gen_movi_tl(t0, v2);
23393 tcg_gen_movi_tl(t1, v1);
23394 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23395 break;
23396 case OPC_DEXTR_RS_L:
23397 tcg_gen_movi_tl(t0, v2);
23398 tcg_gen_movi_tl(t1, v1);
23399 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23400 break;
23401 case OPC_DEXTR_W:
23402 tcg_gen_movi_tl(t0, v2);
23403 tcg_gen_movi_tl(t1, v1);
23404 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23405 break;
23406 case OPC_DEXTR_R_W:
23407 tcg_gen_movi_tl(t0, v2);
23408 tcg_gen_movi_tl(t1, v1);
23409 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23410 break;
23411 case OPC_DEXTR_RS_W:
23412 tcg_gen_movi_tl(t0, v2);
23413 tcg_gen_movi_tl(t1, v1);
23414 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23415 break;
23416 case OPC_DEXTR_S_H:
23417 tcg_gen_movi_tl(t0, v2);
23418 tcg_gen_movi_tl(t1, v1);
23419 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23420 break;
23421 case OPC_DEXTRV_S_H:
23422 tcg_gen_movi_tl(t0, v2);
23423 tcg_gen_movi_tl(t1, v1);
23424 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23425 break;
23426 case OPC_DEXTRV_L:
23427 tcg_gen_movi_tl(t0, v2);
23428 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23429 break;
23430 case OPC_DEXTRV_R_L:
23431 tcg_gen_movi_tl(t0, v2);
23432 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23433 break;
23434 case OPC_DEXTRV_RS_L:
23435 tcg_gen_movi_tl(t0, v2);
23436 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23437 break;
23438 case OPC_DEXTRV_W:
23439 tcg_gen_movi_tl(t0, v2);
23440 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23441 break;
23442 case OPC_DEXTRV_R_W:
23443 tcg_gen_movi_tl(t0, v2);
23444 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23445 break;
23446 case OPC_DEXTRV_RS_W:
23447 tcg_gen_movi_tl(t0, v2);
23448 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23449 break;
23451 break;
23452 #endif
23455 tcg_temp_free(t0);
23456 tcg_temp_free(t1);
23457 tcg_temp_free(v1_t);
23458 tcg_temp_free(v2_t);
23461 /* End MIPSDSP functions. */
23463 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23465 int rs, rt, rd, sa;
23466 uint32_t op1, op2;
23468 rs = (ctx->opcode >> 21) & 0x1f;
23469 rt = (ctx->opcode >> 16) & 0x1f;
23470 rd = (ctx->opcode >> 11) & 0x1f;
23471 sa = (ctx->opcode >> 6) & 0x1f;
23473 op1 = MASK_SPECIAL(ctx->opcode);
23474 switch (op1) {
23475 case OPC_LSA:
23476 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23477 break;
23478 case OPC_MULT:
23479 case OPC_MULTU:
23480 case OPC_DIV:
23481 case OPC_DIVU:
23482 op2 = MASK_R6_MULDIV(ctx->opcode);
23483 switch (op2) {
23484 case R6_OPC_MUL:
23485 case R6_OPC_MUH:
23486 case R6_OPC_MULU:
23487 case R6_OPC_MUHU:
23488 case R6_OPC_DIV:
23489 case R6_OPC_MOD:
23490 case R6_OPC_DIVU:
23491 case R6_OPC_MODU:
23492 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23493 break;
23494 default:
23495 MIPS_INVAL("special_r6 muldiv");
23496 generate_exception_end(ctx, EXCP_RI);
23497 break;
23499 break;
23500 case OPC_SELEQZ:
23501 case OPC_SELNEZ:
23502 gen_cond_move(ctx, op1, rd, rs, rt);
23503 break;
23504 case R6_OPC_CLO:
23505 case R6_OPC_CLZ:
23506 if (rt == 0 && sa == 1) {
23507 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23508 We need additionally to check other fields */
23509 gen_cl(ctx, op1, rd, rs);
23510 } else {
23511 generate_exception_end(ctx, EXCP_RI);
23513 break;
23514 case R6_OPC_SDBBP:
23515 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23516 gen_helper_do_semihosting(cpu_env);
23517 } else {
23518 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23519 generate_exception_end(ctx, EXCP_RI);
23520 } else {
23521 generate_exception_end(ctx, EXCP_DBp);
23524 break;
23525 #if defined(TARGET_MIPS64)
23526 case OPC_DLSA:
23527 check_mips_64(ctx);
23528 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23529 break;
23530 case R6_OPC_DCLO:
23531 case R6_OPC_DCLZ:
23532 if (rt == 0 && sa == 1) {
23533 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23534 We need additionally to check other fields */
23535 check_mips_64(ctx);
23536 gen_cl(ctx, op1, rd, rs);
23537 } else {
23538 generate_exception_end(ctx, EXCP_RI);
23540 break;
23541 case OPC_DMULT:
23542 case OPC_DMULTU:
23543 case OPC_DDIV:
23544 case OPC_DDIVU:
23546 op2 = MASK_R6_MULDIV(ctx->opcode);
23547 switch (op2) {
23548 case R6_OPC_DMUL:
23549 case R6_OPC_DMUH:
23550 case R6_OPC_DMULU:
23551 case R6_OPC_DMUHU:
23552 case R6_OPC_DDIV:
23553 case R6_OPC_DMOD:
23554 case R6_OPC_DDIVU:
23555 case R6_OPC_DMODU:
23556 check_mips_64(ctx);
23557 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23558 break;
23559 default:
23560 MIPS_INVAL("special_r6 muldiv");
23561 generate_exception_end(ctx, EXCP_RI);
23562 break;
23564 break;
23565 #endif
23566 default: /* Invalid */
23567 MIPS_INVAL("special_r6");
23568 generate_exception_end(ctx, EXCP_RI);
23569 break;
23573 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23575 int rs, rt, rd, sa;
23576 uint32_t op1;
23578 rs = (ctx->opcode >> 21) & 0x1f;
23579 rt = (ctx->opcode >> 16) & 0x1f;
23580 rd = (ctx->opcode >> 11) & 0x1f;
23581 sa = (ctx->opcode >> 6) & 0x1f;
23583 op1 = MASK_SPECIAL(ctx->opcode);
23584 switch (op1) {
23585 case OPC_MOVN: /* Conditional move */
23586 case OPC_MOVZ:
23587 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23588 INSN_LOONGSON2E | INSN_LOONGSON2F | INSN_R5900);
23589 gen_cond_move(ctx, op1, rd, rs, rt);
23590 break;
23591 case OPC_MFHI: /* Move from HI/LO */
23592 case OPC_MFLO:
23593 gen_HILO(ctx, op1, rs & 3, rd);
23594 break;
23595 case OPC_MTHI:
23596 case OPC_MTLO: /* Move to HI/LO */
23597 gen_HILO(ctx, op1, rd & 3, rs);
23598 break;
23599 case OPC_MOVCI:
23600 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23601 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23602 check_cp1_enabled(ctx);
23603 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23604 (ctx->opcode >> 16) & 1);
23605 } else {
23606 generate_exception_err(ctx, EXCP_CpU, 1);
23608 break;
23609 case OPC_MULT:
23610 case OPC_MULTU:
23611 if (sa) {
23612 check_insn(ctx, INSN_VR54XX);
23613 op1 = MASK_MUL_VR54XX(ctx->opcode);
23614 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23615 } else if (ctx->insn_flags & INSN_R5900) {
23616 gen_mul_txx9(ctx, op1, rd, rs, rt);
23617 } else {
23618 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23620 break;
23621 case OPC_DIV:
23622 case OPC_DIVU:
23623 gen_muldiv(ctx, op1, 0, rs, rt);
23624 break;
23625 #if defined(TARGET_MIPS64)
23626 case OPC_DMULT:
23627 case OPC_DMULTU:
23628 case OPC_DDIV:
23629 case OPC_DDIVU:
23630 check_insn(ctx, ISA_MIPS3);
23631 check_insn_opc_user_only(ctx, INSN_R5900);
23632 check_mips_64(ctx);
23633 gen_muldiv(ctx, op1, 0, rs, rt);
23634 break;
23635 #endif
23636 case OPC_JR:
23637 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23638 break;
23639 case OPC_SPIM:
23640 #ifdef MIPS_STRICT_STANDARD
23641 MIPS_INVAL("SPIM");
23642 generate_exception_end(ctx, EXCP_RI);
23643 #else
23644 /* Implemented as RI exception for now. */
23645 MIPS_INVAL("spim (unofficial)");
23646 generate_exception_end(ctx, EXCP_RI);
23647 #endif
23648 break;
23649 default: /* Invalid */
23650 MIPS_INVAL("special_legacy");
23651 generate_exception_end(ctx, EXCP_RI);
23652 break;
23656 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23658 int rs, rt, rd, sa;
23659 uint32_t op1;
23661 rs = (ctx->opcode >> 21) & 0x1f;
23662 rt = (ctx->opcode >> 16) & 0x1f;
23663 rd = (ctx->opcode >> 11) & 0x1f;
23664 sa = (ctx->opcode >> 6) & 0x1f;
23666 op1 = MASK_SPECIAL(ctx->opcode);
23667 switch (op1) {
23668 case OPC_SLL: /* Shift with immediate */
23669 if (sa == 5 && rd == 0 &&
23670 rs == 0 && rt == 0) { /* PAUSE */
23671 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23672 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23673 generate_exception_end(ctx, EXCP_RI);
23674 break;
23677 /* Fallthrough */
23678 case OPC_SRA:
23679 gen_shift_imm(ctx, op1, rd, rt, sa);
23680 break;
23681 case OPC_SRL:
23682 switch ((ctx->opcode >> 21) & 0x1f) {
23683 case 1:
23684 /* rotr is decoded as srl on non-R2 CPUs */
23685 if (ctx->insn_flags & ISA_MIPS32R2) {
23686 op1 = OPC_ROTR;
23688 /* Fallthrough */
23689 case 0:
23690 gen_shift_imm(ctx, op1, rd, rt, sa);
23691 break;
23692 default:
23693 generate_exception_end(ctx, EXCP_RI);
23694 break;
23696 break;
23697 case OPC_ADD:
23698 case OPC_ADDU:
23699 case OPC_SUB:
23700 case OPC_SUBU:
23701 gen_arith(ctx, op1, rd, rs, rt);
23702 break;
23703 case OPC_SLLV: /* Shifts */
23704 case OPC_SRAV:
23705 gen_shift(ctx, op1, rd, rs, rt);
23706 break;
23707 case OPC_SRLV:
23708 switch ((ctx->opcode >> 6) & 0x1f) {
23709 case 1:
23710 /* rotrv is decoded as srlv on non-R2 CPUs */
23711 if (ctx->insn_flags & ISA_MIPS32R2) {
23712 op1 = OPC_ROTRV;
23714 /* Fallthrough */
23715 case 0:
23716 gen_shift(ctx, op1, rd, rs, rt);
23717 break;
23718 default:
23719 generate_exception_end(ctx, EXCP_RI);
23720 break;
23722 break;
23723 case OPC_SLT: /* Set on less than */
23724 case OPC_SLTU:
23725 gen_slt(ctx, op1, rd, rs, rt);
23726 break;
23727 case OPC_AND: /* Logic*/
23728 case OPC_OR:
23729 case OPC_NOR:
23730 case OPC_XOR:
23731 gen_logic(ctx, op1, rd, rs, rt);
23732 break;
23733 case OPC_JALR:
23734 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23735 break;
23736 case OPC_TGE: /* Traps */
23737 case OPC_TGEU:
23738 case OPC_TLT:
23739 case OPC_TLTU:
23740 case OPC_TEQ:
23741 case OPC_TNE:
23742 check_insn(ctx, ISA_MIPS2);
23743 gen_trap(ctx, op1, rs, rt, -1);
23744 break;
23745 case OPC_LSA: /* OPC_PMON */
23746 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23747 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23748 decode_opc_special_r6(env, ctx);
23749 } else {
23750 /* Pmon entry point, also R4010 selsl */
23751 #ifdef MIPS_STRICT_STANDARD
23752 MIPS_INVAL("PMON / selsl");
23753 generate_exception_end(ctx, EXCP_RI);
23754 #else
23755 gen_helper_0e0i(pmon, sa);
23756 #endif
23758 break;
23759 case OPC_SYSCALL:
23760 generate_exception_end(ctx, EXCP_SYSCALL);
23761 break;
23762 case OPC_BREAK:
23763 generate_exception_end(ctx, EXCP_BREAK);
23764 break;
23765 case OPC_SYNC:
23766 check_insn(ctx, ISA_MIPS2);
23767 gen_sync(extract32(ctx->opcode, 6, 5));
23768 break;
23770 #if defined(TARGET_MIPS64)
23771 /* MIPS64 specific opcodes */
23772 case OPC_DSLL:
23773 case OPC_DSRA:
23774 case OPC_DSLL32:
23775 case OPC_DSRA32:
23776 check_insn(ctx, ISA_MIPS3);
23777 check_mips_64(ctx);
23778 gen_shift_imm(ctx, op1, rd, rt, sa);
23779 break;
23780 case OPC_DSRL:
23781 switch ((ctx->opcode >> 21) & 0x1f) {
23782 case 1:
23783 /* drotr is decoded as dsrl on non-R2 CPUs */
23784 if (ctx->insn_flags & ISA_MIPS32R2) {
23785 op1 = OPC_DROTR;
23787 /* Fallthrough */
23788 case 0:
23789 check_insn(ctx, ISA_MIPS3);
23790 check_mips_64(ctx);
23791 gen_shift_imm(ctx, op1, rd, rt, sa);
23792 break;
23793 default:
23794 generate_exception_end(ctx, EXCP_RI);
23795 break;
23797 break;
23798 case OPC_DSRL32:
23799 switch ((ctx->opcode >> 21) & 0x1f) {
23800 case 1:
23801 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23802 if (ctx->insn_flags & ISA_MIPS32R2) {
23803 op1 = OPC_DROTR32;
23805 /* Fallthrough */
23806 case 0:
23807 check_insn(ctx, ISA_MIPS3);
23808 check_mips_64(ctx);
23809 gen_shift_imm(ctx, op1, rd, rt, sa);
23810 break;
23811 default:
23812 generate_exception_end(ctx, EXCP_RI);
23813 break;
23815 break;
23816 case OPC_DADD:
23817 case OPC_DADDU:
23818 case OPC_DSUB:
23819 case OPC_DSUBU:
23820 check_insn(ctx, ISA_MIPS3);
23821 check_mips_64(ctx);
23822 gen_arith(ctx, op1, rd, rs, rt);
23823 break;
23824 case OPC_DSLLV:
23825 case OPC_DSRAV:
23826 check_insn(ctx, ISA_MIPS3);
23827 check_mips_64(ctx);
23828 gen_shift(ctx, op1, rd, rs, rt);
23829 break;
23830 case OPC_DSRLV:
23831 switch ((ctx->opcode >> 6) & 0x1f) {
23832 case 1:
23833 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23834 if (ctx->insn_flags & ISA_MIPS32R2) {
23835 op1 = OPC_DROTRV;
23837 /* Fallthrough */
23838 case 0:
23839 check_insn(ctx, ISA_MIPS3);
23840 check_mips_64(ctx);
23841 gen_shift(ctx, op1, rd, rs, rt);
23842 break;
23843 default:
23844 generate_exception_end(ctx, EXCP_RI);
23845 break;
23847 break;
23848 case OPC_DLSA:
23849 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23850 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23851 decode_opc_special_r6(env, ctx);
23853 break;
23854 #endif
23855 default:
23856 if (ctx->insn_flags & ISA_MIPS32R6) {
23857 decode_opc_special_r6(env, ctx);
23858 } else {
23859 decode_opc_special_legacy(env, ctx);
23864 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23866 int rs, rt, rd;
23867 uint32_t op1;
23869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23871 rs = (ctx->opcode >> 21) & 0x1f;
23872 rt = (ctx->opcode >> 16) & 0x1f;
23873 rd = (ctx->opcode >> 11) & 0x1f;
23875 op1 = MASK_SPECIAL2(ctx->opcode);
23876 switch (op1) {
23877 case OPC_MADD: /* Multiply and add/sub */
23878 case OPC_MADDU:
23879 case OPC_MSUB:
23880 case OPC_MSUBU:
23881 check_insn(ctx, ISA_MIPS32);
23882 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23883 break;
23884 case OPC_MUL:
23885 gen_arith(ctx, op1, rd, rs, rt);
23886 break;
23887 case OPC_DIV_G_2F:
23888 case OPC_DIVU_G_2F:
23889 case OPC_MULT_G_2F:
23890 case OPC_MULTU_G_2F:
23891 case OPC_MOD_G_2F:
23892 case OPC_MODU_G_2F:
23893 check_insn(ctx, INSN_LOONGSON2F);
23894 gen_loongson_integer(ctx, op1, rd, rs, rt);
23895 break;
23896 case OPC_CLO:
23897 case OPC_CLZ:
23898 check_insn(ctx, ISA_MIPS32);
23899 gen_cl(ctx, op1, rd, rs);
23900 break;
23901 case OPC_SDBBP:
23902 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23903 gen_helper_do_semihosting(cpu_env);
23904 } else {
23905 /* XXX: not clear which exception should be raised
23906 * when in debug mode...
23908 check_insn(ctx, ISA_MIPS32);
23909 generate_exception_end(ctx, EXCP_DBp);
23911 break;
23912 #if defined(TARGET_MIPS64)
23913 case OPC_DCLO:
23914 case OPC_DCLZ:
23915 check_insn(ctx, ISA_MIPS64);
23916 check_mips_64(ctx);
23917 gen_cl(ctx, op1, rd, rs);
23918 break;
23919 case OPC_DMULT_G_2F:
23920 case OPC_DMULTU_G_2F:
23921 case OPC_DDIV_G_2F:
23922 case OPC_DDIVU_G_2F:
23923 case OPC_DMOD_G_2F:
23924 case OPC_DMODU_G_2F:
23925 check_insn(ctx, INSN_LOONGSON2F);
23926 gen_loongson_integer(ctx, op1, rd, rs, rt);
23927 break;
23928 #endif
23929 default: /* Invalid */
23930 MIPS_INVAL("special2_legacy");
23931 generate_exception_end(ctx, EXCP_RI);
23932 break;
23936 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23938 int rs, rt, rd, sa;
23939 uint32_t op1, op2;
23940 int16_t imm;
23942 rs = (ctx->opcode >> 21) & 0x1f;
23943 rt = (ctx->opcode >> 16) & 0x1f;
23944 rd = (ctx->opcode >> 11) & 0x1f;
23945 sa = (ctx->opcode >> 6) & 0x1f;
23946 imm = (int16_t)ctx->opcode >> 7;
23948 op1 = MASK_SPECIAL3(ctx->opcode);
23949 switch (op1) {
23950 case R6_OPC_PREF:
23951 if (rt >= 24) {
23952 /* hint codes 24-31 are reserved and signal RI */
23953 generate_exception_end(ctx, EXCP_RI);
23955 /* Treat as NOP. */
23956 break;
23957 case R6_OPC_CACHE:
23958 check_cp0_enabled(ctx);
23959 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23960 gen_cache_operation(ctx, rt, rs, imm);
23962 break;
23963 case R6_OPC_SC:
23964 gen_st_cond(ctx, op1, rt, rs, imm);
23965 break;
23966 case R6_OPC_LL:
23967 gen_ld(ctx, op1, rt, rs, imm);
23968 break;
23969 case OPC_BSHFL:
23971 if (rd == 0) {
23972 /* Treat as NOP. */
23973 break;
23975 op2 = MASK_BSHFL(ctx->opcode);
23976 switch (op2) {
23977 case OPC_ALIGN:
23978 case OPC_ALIGN_1:
23979 case OPC_ALIGN_2:
23980 case OPC_ALIGN_3:
23981 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23982 break;
23983 case OPC_BITSWAP:
23984 gen_bitswap(ctx, op2, rd, rt);
23985 break;
23988 break;
23989 #if defined(TARGET_MIPS64)
23990 case R6_OPC_SCD:
23991 gen_st_cond(ctx, op1, rt, rs, imm);
23992 break;
23993 case R6_OPC_LLD:
23994 gen_ld(ctx, op1, rt, rs, imm);
23995 break;
23996 case OPC_DBSHFL:
23997 check_mips_64(ctx);
23999 if (rd == 0) {
24000 /* Treat as NOP. */
24001 break;
24003 op2 = MASK_DBSHFL(ctx->opcode);
24004 switch (op2) {
24005 case OPC_DALIGN:
24006 case OPC_DALIGN_1:
24007 case OPC_DALIGN_2:
24008 case OPC_DALIGN_3:
24009 case OPC_DALIGN_4:
24010 case OPC_DALIGN_5:
24011 case OPC_DALIGN_6:
24012 case OPC_DALIGN_7:
24013 gen_align(ctx, 64, rd, rs, rt, sa & 7);
24014 break;
24015 case OPC_DBITSWAP:
24016 gen_bitswap(ctx, op2, rd, rt);
24017 break;
24021 break;
24022 #endif
24023 default: /* Invalid */
24024 MIPS_INVAL("special3_r6");
24025 generate_exception_end(ctx, EXCP_RI);
24026 break;
24030 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
24032 int rs, rt, rd;
24033 uint32_t op1, op2;
24035 rs = (ctx->opcode >> 21) & 0x1f;
24036 rt = (ctx->opcode >> 16) & 0x1f;
24037 rd = (ctx->opcode >> 11) & 0x1f;
24039 op1 = MASK_SPECIAL3(ctx->opcode);
24040 switch (op1) {
24041 case OPC_DIV_G_2E:
24042 case OPC_DIVU_G_2E:
24043 case OPC_MOD_G_2E:
24044 case OPC_MODU_G_2E:
24045 case OPC_MULT_G_2E:
24046 case OPC_MULTU_G_2E:
24047 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
24048 * the same mask and op1. */
24049 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
24050 op2 = MASK_ADDUH_QB(ctx->opcode);
24051 switch (op2) {
24052 case OPC_ADDUH_QB:
24053 case OPC_ADDUH_R_QB:
24054 case OPC_ADDQH_PH:
24055 case OPC_ADDQH_R_PH:
24056 case OPC_ADDQH_W:
24057 case OPC_ADDQH_R_W:
24058 case OPC_SUBUH_QB:
24059 case OPC_SUBUH_R_QB:
24060 case OPC_SUBQH_PH:
24061 case OPC_SUBQH_R_PH:
24062 case OPC_SUBQH_W:
24063 case OPC_SUBQH_R_W:
24064 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24065 break;
24066 case OPC_MUL_PH:
24067 case OPC_MUL_S_PH:
24068 case OPC_MULQ_S_W:
24069 case OPC_MULQ_RS_W:
24070 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24071 break;
24072 default:
24073 MIPS_INVAL("MASK ADDUH.QB");
24074 generate_exception_end(ctx, EXCP_RI);
24075 break;
24077 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
24078 gen_loongson_integer(ctx, op1, rd, rs, rt);
24079 } else {
24080 generate_exception_end(ctx, EXCP_RI);
24082 break;
24083 case OPC_LX_DSP:
24084 op2 = MASK_LX(ctx->opcode);
24085 switch (op2) {
24086 #if defined(TARGET_MIPS64)
24087 case OPC_LDX:
24088 #endif
24089 case OPC_LBUX:
24090 case OPC_LHX:
24091 case OPC_LWX:
24092 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
24093 break;
24094 default: /* Invalid */
24095 MIPS_INVAL("MASK LX");
24096 generate_exception_end(ctx, EXCP_RI);
24097 break;
24099 break;
24100 case OPC_ABSQ_S_PH_DSP:
24101 op2 = MASK_ABSQ_S_PH(ctx->opcode);
24102 switch (op2) {
24103 case OPC_ABSQ_S_QB:
24104 case OPC_ABSQ_S_PH:
24105 case OPC_ABSQ_S_W:
24106 case OPC_PRECEQ_W_PHL:
24107 case OPC_PRECEQ_W_PHR:
24108 case OPC_PRECEQU_PH_QBL:
24109 case OPC_PRECEQU_PH_QBR:
24110 case OPC_PRECEQU_PH_QBLA:
24111 case OPC_PRECEQU_PH_QBRA:
24112 case OPC_PRECEU_PH_QBL:
24113 case OPC_PRECEU_PH_QBR:
24114 case OPC_PRECEU_PH_QBLA:
24115 case OPC_PRECEU_PH_QBRA:
24116 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24117 break;
24118 case OPC_BITREV:
24119 case OPC_REPL_QB:
24120 case OPC_REPLV_QB:
24121 case OPC_REPL_PH:
24122 case OPC_REPLV_PH:
24123 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24124 break;
24125 default:
24126 MIPS_INVAL("MASK ABSQ_S.PH");
24127 generate_exception_end(ctx, EXCP_RI);
24128 break;
24130 break;
24131 case OPC_ADDU_QB_DSP:
24132 op2 = MASK_ADDU_QB(ctx->opcode);
24133 switch (op2) {
24134 case OPC_ADDQ_PH:
24135 case OPC_ADDQ_S_PH:
24136 case OPC_ADDQ_S_W:
24137 case OPC_ADDU_QB:
24138 case OPC_ADDU_S_QB:
24139 case OPC_ADDU_PH:
24140 case OPC_ADDU_S_PH:
24141 case OPC_SUBQ_PH:
24142 case OPC_SUBQ_S_PH:
24143 case OPC_SUBQ_S_W:
24144 case OPC_SUBU_QB:
24145 case OPC_SUBU_S_QB:
24146 case OPC_SUBU_PH:
24147 case OPC_SUBU_S_PH:
24148 case OPC_ADDSC:
24149 case OPC_ADDWC:
24150 case OPC_MODSUB:
24151 case OPC_RADDU_W_QB:
24152 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24153 break;
24154 case OPC_MULEU_S_PH_QBL:
24155 case OPC_MULEU_S_PH_QBR:
24156 case OPC_MULQ_RS_PH:
24157 case OPC_MULEQ_S_W_PHL:
24158 case OPC_MULEQ_S_W_PHR:
24159 case OPC_MULQ_S_PH:
24160 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24161 break;
24162 default: /* Invalid */
24163 MIPS_INVAL("MASK ADDU.QB");
24164 generate_exception_end(ctx, EXCP_RI);
24165 break;
24168 break;
24169 case OPC_CMPU_EQ_QB_DSP:
24170 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24171 switch (op2) {
24172 case OPC_PRECR_SRA_PH_W:
24173 case OPC_PRECR_SRA_R_PH_W:
24174 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24175 break;
24176 case OPC_PRECR_QB_PH:
24177 case OPC_PRECRQ_QB_PH:
24178 case OPC_PRECRQ_PH_W:
24179 case OPC_PRECRQ_RS_PH_W:
24180 case OPC_PRECRQU_S_QB_PH:
24181 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24182 break;
24183 case OPC_CMPU_EQ_QB:
24184 case OPC_CMPU_LT_QB:
24185 case OPC_CMPU_LE_QB:
24186 case OPC_CMP_EQ_PH:
24187 case OPC_CMP_LT_PH:
24188 case OPC_CMP_LE_PH:
24189 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24190 break;
24191 case OPC_CMPGU_EQ_QB:
24192 case OPC_CMPGU_LT_QB:
24193 case OPC_CMPGU_LE_QB:
24194 case OPC_CMPGDU_EQ_QB:
24195 case OPC_CMPGDU_LT_QB:
24196 case OPC_CMPGDU_LE_QB:
24197 case OPC_PICK_QB:
24198 case OPC_PICK_PH:
24199 case OPC_PACKRL_PH:
24200 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24201 break;
24202 default: /* Invalid */
24203 MIPS_INVAL("MASK CMPU.EQ.QB");
24204 generate_exception_end(ctx, EXCP_RI);
24205 break;
24207 break;
24208 case OPC_SHLL_QB_DSP:
24209 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24210 break;
24211 case OPC_DPA_W_PH_DSP:
24212 op2 = MASK_DPA_W_PH(ctx->opcode);
24213 switch (op2) {
24214 case OPC_DPAU_H_QBL:
24215 case OPC_DPAU_H_QBR:
24216 case OPC_DPSU_H_QBL:
24217 case OPC_DPSU_H_QBR:
24218 case OPC_DPA_W_PH:
24219 case OPC_DPAX_W_PH:
24220 case OPC_DPAQ_S_W_PH:
24221 case OPC_DPAQX_S_W_PH:
24222 case OPC_DPAQX_SA_W_PH:
24223 case OPC_DPS_W_PH:
24224 case OPC_DPSX_W_PH:
24225 case OPC_DPSQ_S_W_PH:
24226 case OPC_DPSQX_S_W_PH:
24227 case OPC_DPSQX_SA_W_PH:
24228 case OPC_MULSAQ_S_W_PH:
24229 case OPC_DPAQ_SA_L_W:
24230 case OPC_DPSQ_SA_L_W:
24231 case OPC_MAQ_S_W_PHL:
24232 case OPC_MAQ_S_W_PHR:
24233 case OPC_MAQ_SA_W_PHL:
24234 case OPC_MAQ_SA_W_PHR:
24235 case OPC_MULSA_W_PH:
24236 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24237 break;
24238 default: /* Invalid */
24239 MIPS_INVAL("MASK DPAW.PH");
24240 generate_exception_end(ctx, EXCP_RI);
24241 break;
24243 break;
24244 case OPC_INSV_DSP:
24245 op2 = MASK_INSV(ctx->opcode);
24246 switch (op2) {
24247 case OPC_INSV:
24248 check_dsp(ctx);
24250 TCGv t0, t1;
24252 if (rt == 0) {
24253 break;
24256 t0 = tcg_temp_new();
24257 t1 = tcg_temp_new();
24259 gen_load_gpr(t0, rt);
24260 gen_load_gpr(t1, rs);
24262 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24264 tcg_temp_free(t0);
24265 tcg_temp_free(t1);
24266 break;
24268 default: /* Invalid */
24269 MIPS_INVAL("MASK INSV");
24270 generate_exception_end(ctx, EXCP_RI);
24271 break;
24273 break;
24274 case OPC_APPEND_DSP:
24275 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24276 break;
24277 case OPC_EXTR_W_DSP:
24278 op2 = MASK_EXTR_W(ctx->opcode);
24279 switch (op2) {
24280 case OPC_EXTR_W:
24281 case OPC_EXTR_R_W:
24282 case OPC_EXTR_RS_W:
24283 case OPC_EXTR_S_H:
24284 case OPC_EXTRV_S_H:
24285 case OPC_EXTRV_W:
24286 case OPC_EXTRV_R_W:
24287 case OPC_EXTRV_RS_W:
24288 case OPC_EXTP:
24289 case OPC_EXTPV:
24290 case OPC_EXTPDP:
24291 case OPC_EXTPDPV:
24292 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24293 break;
24294 case OPC_RDDSP:
24295 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24296 break;
24297 case OPC_SHILO:
24298 case OPC_SHILOV:
24299 case OPC_MTHLIP:
24300 case OPC_WRDSP:
24301 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24302 break;
24303 default: /* Invalid */
24304 MIPS_INVAL("MASK EXTR.W");
24305 generate_exception_end(ctx, EXCP_RI);
24306 break;
24308 break;
24309 #if defined(TARGET_MIPS64)
24310 case OPC_DDIV_G_2E:
24311 case OPC_DDIVU_G_2E:
24312 case OPC_DMULT_G_2E:
24313 case OPC_DMULTU_G_2E:
24314 case OPC_DMOD_G_2E:
24315 case OPC_DMODU_G_2E:
24316 check_insn(ctx, INSN_LOONGSON2E);
24317 gen_loongson_integer(ctx, op1, rd, rs, rt);
24318 break;
24319 case OPC_ABSQ_S_QH_DSP:
24320 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24321 switch (op2) {
24322 case OPC_PRECEQ_L_PWL:
24323 case OPC_PRECEQ_L_PWR:
24324 case OPC_PRECEQ_PW_QHL:
24325 case OPC_PRECEQ_PW_QHR:
24326 case OPC_PRECEQ_PW_QHLA:
24327 case OPC_PRECEQ_PW_QHRA:
24328 case OPC_PRECEQU_QH_OBL:
24329 case OPC_PRECEQU_QH_OBR:
24330 case OPC_PRECEQU_QH_OBLA:
24331 case OPC_PRECEQU_QH_OBRA:
24332 case OPC_PRECEU_QH_OBL:
24333 case OPC_PRECEU_QH_OBR:
24334 case OPC_PRECEU_QH_OBLA:
24335 case OPC_PRECEU_QH_OBRA:
24336 case OPC_ABSQ_S_OB:
24337 case OPC_ABSQ_S_PW:
24338 case OPC_ABSQ_S_QH:
24339 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24340 break;
24341 case OPC_REPL_OB:
24342 case OPC_REPL_PW:
24343 case OPC_REPL_QH:
24344 case OPC_REPLV_OB:
24345 case OPC_REPLV_PW:
24346 case OPC_REPLV_QH:
24347 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24348 break;
24349 default: /* Invalid */
24350 MIPS_INVAL("MASK ABSQ_S.QH");
24351 generate_exception_end(ctx, EXCP_RI);
24352 break;
24354 break;
24355 case OPC_ADDU_OB_DSP:
24356 op2 = MASK_ADDU_OB(ctx->opcode);
24357 switch (op2) {
24358 case OPC_RADDU_L_OB:
24359 case OPC_SUBQ_PW:
24360 case OPC_SUBQ_S_PW:
24361 case OPC_SUBQ_QH:
24362 case OPC_SUBQ_S_QH:
24363 case OPC_SUBU_OB:
24364 case OPC_SUBU_S_OB:
24365 case OPC_SUBU_QH:
24366 case OPC_SUBU_S_QH:
24367 case OPC_SUBUH_OB:
24368 case OPC_SUBUH_R_OB:
24369 case OPC_ADDQ_PW:
24370 case OPC_ADDQ_S_PW:
24371 case OPC_ADDQ_QH:
24372 case OPC_ADDQ_S_QH:
24373 case OPC_ADDU_OB:
24374 case OPC_ADDU_S_OB:
24375 case OPC_ADDU_QH:
24376 case OPC_ADDU_S_QH:
24377 case OPC_ADDUH_OB:
24378 case OPC_ADDUH_R_OB:
24379 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24380 break;
24381 case OPC_MULEQ_S_PW_QHL:
24382 case OPC_MULEQ_S_PW_QHR:
24383 case OPC_MULEU_S_QH_OBL:
24384 case OPC_MULEU_S_QH_OBR:
24385 case OPC_MULQ_RS_QH:
24386 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24387 break;
24388 default: /* Invalid */
24389 MIPS_INVAL("MASK ADDU.OB");
24390 generate_exception_end(ctx, EXCP_RI);
24391 break;
24393 break;
24394 case OPC_CMPU_EQ_OB_DSP:
24395 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24396 switch (op2) {
24397 case OPC_PRECR_SRA_QH_PW:
24398 case OPC_PRECR_SRA_R_QH_PW:
24399 /* Return value is rt. */
24400 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24401 break;
24402 case OPC_PRECR_OB_QH:
24403 case OPC_PRECRQ_OB_QH:
24404 case OPC_PRECRQ_PW_L:
24405 case OPC_PRECRQ_QH_PW:
24406 case OPC_PRECRQ_RS_QH_PW:
24407 case OPC_PRECRQU_S_OB_QH:
24408 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24409 break;
24410 case OPC_CMPU_EQ_OB:
24411 case OPC_CMPU_LT_OB:
24412 case OPC_CMPU_LE_OB:
24413 case OPC_CMP_EQ_QH:
24414 case OPC_CMP_LT_QH:
24415 case OPC_CMP_LE_QH:
24416 case OPC_CMP_EQ_PW:
24417 case OPC_CMP_LT_PW:
24418 case OPC_CMP_LE_PW:
24419 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24420 break;
24421 case OPC_CMPGDU_EQ_OB:
24422 case OPC_CMPGDU_LT_OB:
24423 case OPC_CMPGDU_LE_OB:
24424 case OPC_CMPGU_EQ_OB:
24425 case OPC_CMPGU_LT_OB:
24426 case OPC_CMPGU_LE_OB:
24427 case OPC_PACKRL_PW:
24428 case OPC_PICK_OB:
24429 case OPC_PICK_PW:
24430 case OPC_PICK_QH:
24431 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24432 break;
24433 default: /* Invalid */
24434 MIPS_INVAL("MASK CMPU_EQ.OB");
24435 generate_exception_end(ctx, EXCP_RI);
24436 break;
24438 break;
24439 case OPC_DAPPEND_DSP:
24440 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24441 break;
24442 case OPC_DEXTR_W_DSP:
24443 op2 = MASK_DEXTR_W(ctx->opcode);
24444 switch (op2) {
24445 case OPC_DEXTP:
24446 case OPC_DEXTPDP:
24447 case OPC_DEXTPDPV:
24448 case OPC_DEXTPV:
24449 case OPC_DEXTR_L:
24450 case OPC_DEXTR_R_L:
24451 case OPC_DEXTR_RS_L:
24452 case OPC_DEXTR_W:
24453 case OPC_DEXTR_R_W:
24454 case OPC_DEXTR_RS_W:
24455 case OPC_DEXTR_S_H:
24456 case OPC_DEXTRV_L:
24457 case OPC_DEXTRV_R_L:
24458 case OPC_DEXTRV_RS_L:
24459 case OPC_DEXTRV_S_H:
24460 case OPC_DEXTRV_W:
24461 case OPC_DEXTRV_R_W:
24462 case OPC_DEXTRV_RS_W:
24463 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24464 break;
24465 case OPC_DMTHLIP:
24466 case OPC_DSHILO:
24467 case OPC_DSHILOV:
24468 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24469 break;
24470 default: /* Invalid */
24471 MIPS_INVAL("MASK EXTR.W");
24472 generate_exception_end(ctx, EXCP_RI);
24473 break;
24475 break;
24476 case OPC_DPAQ_W_QH_DSP:
24477 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24478 switch (op2) {
24479 case OPC_DPAU_H_OBL:
24480 case OPC_DPAU_H_OBR:
24481 case OPC_DPSU_H_OBL:
24482 case OPC_DPSU_H_OBR:
24483 case OPC_DPA_W_QH:
24484 case OPC_DPAQ_S_W_QH:
24485 case OPC_DPS_W_QH:
24486 case OPC_DPSQ_S_W_QH:
24487 case OPC_MULSAQ_S_W_QH:
24488 case OPC_DPAQ_SA_L_PW:
24489 case OPC_DPSQ_SA_L_PW:
24490 case OPC_MULSAQ_S_L_PW:
24491 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24492 break;
24493 case OPC_MAQ_S_W_QHLL:
24494 case OPC_MAQ_S_W_QHLR:
24495 case OPC_MAQ_S_W_QHRL:
24496 case OPC_MAQ_S_W_QHRR:
24497 case OPC_MAQ_SA_W_QHLL:
24498 case OPC_MAQ_SA_W_QHLR:
24499 case OPC_MAQ_SA_W_QHRL:
24500 case OPC_MAQ_SA_W_QHRR:
24501 case OPC_MAQ_S_L_PWL:
24502 case OPC_MAQ_S_L_PWR:
24503 case OPC_DMADD:
24504 case OPC_DMADDU:
24505 case OPC_DMSUB:
24506 case OPC_DMSUBU:
24507 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24508 break;
24509 default: /* Invalid */
24510 MIPS_INVAL("MASK DPAQ.W.QH");
24511 generate_exception_end(ctx, EXCP_RI);
24512 break;
24514 break;
24515 case OPC_DINSV_DSP:
24516 op2 = MASK_INSV(ctx->opcode);
24517 switch (op2) {
24518 case OPC_DINSV:
24520 TCGv t0, t1;
24522 if (rt == 0) {
24523 break;
24525 check_dsp(ctx);
24527 t0 = tcg_temp_new();
24528 t1 = tcg_temp_new();
24530 gen_load_gpr(t0, rt);
24531 gen_load_gpr(t1, rs);
24533 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24535 tcg_temp_free(t0);
24536 tcg_temp_free(t1);
24537 break;
24539 default: /* Invalid */
24540 MIPS_INVAL("MASK DINSV");
24541 generate_exception_end(ctx, EXCP_RI);
24542 break;
24544 break;
24545 case OPC_SHLL_OB_DSP:
24546 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24547 break;
24548 #endif
24549 default: /* Invalid */
24550 MIPS_INVAL("special3_legacy");
24551 generate_exception_end(ctx, EXCP_RI);
24552 break;
24556 static void decode_tx79_mmi0(CPUMIPSState *env, DisasContext *ctx)
24558 uint32_t opc = MASK_TX79_MMI0(ctx->opcode);
24560 switch (opc) {
24561 case TX79_MMI0_PADDW: /* TODO: TX79_MMI0_PADDW */
24562 case TX79_MMI0_PSUBW: /* TODO: TX79_MMI0_PSUBW */
24563 case TX79_MMI0_PCGTW: /* TODO: TX79_MMI0_PCGTW */
24564 case TX79_MMI0_PMAXW: /* TODO: TX79_MMI0_PMAXW */
24565 case TX79_MMI0_PADDH: /* TODO: TX79_MMI0_PADDH */
24566 case TX79_MMI0_PSUBH: /* TODO: TX79_MMI0_PSUBH */
24567 case TX79_MMI0_PCGTH: /* TODO: TX79_MMI0_PCGTH */
24568 case TX79_MMI0_PMAXH: /* TODO: TX79_MMI0_PMAXH */
24569 case TX79_MMI0_PADDB: /* TODO: TX79_MMI0_PADDB */
24570 case TX79_MMI0_PSUBB: /* TODO: TX79_MMI0_PSUBB */
24571 case TX79_MMI0_PCGTB: /* TODO: TX79_MMI0_PCGTB */
24572 case TX79_MMI0_PADDSW: /* TODO: TX79_MMI0_PADDSW */
24573 case TX79_MMI0_PSUBSW: /* TODO: TX79_MMI0_PSUBSW */
24574 case TX79_MMI0_PEXTLW: /* TODO: TX79_MMI0_PEXTLW */
24575 case TX79_MMI0_PPACW: /* TODO: TX79_MMI0_PPACW */
24576 case TX79_MMI0_PADDSH: /* TODO: TX79_MMI0_PADDSH */
24577 case TX79_MMI0_PSUBSH: /* TODO: TX79_MMI0_PSUBSH */
24578 case TX79_MMI0_PEXTLH: /* TODO: TX79_MMI0_PEXTLH */
24579 case TX79_MMI0_PPACH: /* TODO: TX79_MMI0_PPACH */
24580 case TX79_MMI0_PADDSB: /* TODO: TX79_MMI0_PADDSB */
24581 case TX79_MMI0_PSUBSB: /* TODO: TX79_MMI0_PSUBSB */
24582 case TX79_MMI0_PEXTLB: /* TODO: TX79_MMI0_PEXTLB */
24583 case TX79_MMI0_PPACB: /* TODO: TX79_MMI0_PPACB */
24584 case TX79_MMI0_PEXT5: /* TODO: TX79_MMI0_PEXT5 */
24585 case TX79_MMI0_PPAC5: /* TODO: TX79_MMI0_PPAC5 */
24586 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI0 */
24587 break;
24588 default:
24589 MIPS_INVAL("TX79 MMI class MMI0");
24590 generate_exception_end(ctx, EXCP_RI);
24591 break;
24595 static void decode_tx79_mmi1(CPUMIPSState *env, DisasContext *ctx)
24597 uint32_t opc = MASK_TX79_MMI1(ctx->opcode);
24599 switch (opc) {
24600 case TX79_MMI1_PABSW: /* TODO: TX79_MMI1_PABSW */
24601 case TX79_MMI1_PCEQW: /* TODO: TX79_MMI1_PCEQW */
24602 case TX79_MMI1_PMINW: /* TODO: TX79_MMI1_PMINW */
24603 case TX79_MMI1_PADSBH: /* TODO: TX79_MMI1_PADSBH */
24604 case TX79_MMI1_PABSH: /* TODO: TX79_MMI1_PABSH */
24605 case TX79_MMI1_PCEQH: /* TODO: TX79_MMI1_PCEQH */
24606 case TX79_MMI1_PMINH: /* TODO: TX79_MMI1_PMINH */
24607 case TX79_MMI1_PCEQB: /* TODO: TX79_MMI1_PCEQB */
24608 case TX79_MMI1_PADDUW: /* TODO: TX79_MMI1_PADDUW */
24609 case TX79_MMI1_PSUBUW: /* TODO: TX79_MMI1_PSUBUW */
24610 case TX79_MMI1_PEXTUW: /* TODO: TX79_MMI1_PEXTUW */
24611 case TX79_MMI1_PADDUH: /* TODO: TX79_MMI1_PADDUH */
24612 case TX79_MMI1_PSUBUH: /* TODO: TX79_MMI1_PSUBUH */
24613 case TX79_MMI1_PEXTUH: /* TODO: TX79_MMI1_PEXTUH */
24614 case TX79_MMI1_PADDUB: /* TODO: TX79_MMI1_PADDUB */
24615 case TX79_MMI1_PSUBUB: /* TODO: TX79_MMI1_PSUBUB */
24616 case TX79_MMI1_PEXTUB: /* TODO: TX79_MMI1_PEXTUB */
24617 case TX79_MMI1_QFSRV: /* TODO: TX79_MMI1_QFSRV */
24618 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI1 */
24619 break;
24620 default:
24621 MIPS_INVAL("TX79 MMI class MMI1");
24622 generate_exception_end(ctx, EXCP_RI);
24623 break;
24627 static void decode_tx79_mmi2(CPUMIPSState *env, DisasContext *ctx)
24629 uint32_t opc = MASK_TX79_MMI2(ctx->opcode);
24631 switch (opc) {
24632 case TX79_MMI2_PMADDW: /* TODO: TX79_MMI2_PMADDW */
24633 case TX79_MMI2_PSLLVW: /* TODO: TX79_MMI2_PSLLVW */
24634 case TX79_MMI2_PSRLVW: /* TODO: TX79_MMI2_PSRLVW */
24635 case TX79_MMI2_PMSUBW: /* TODO: TX79_MMI2_PMSUBW */
24636 case TX79_MMI2_PMFHI: /* TODO: TX79_MMI2_PMFHI */
24637 case TX79_MMI2_PMFLO: /* TODO: TX79_MMI2_PMFLO */
24638 case TX79_MMI2_PINTH: /* TODO: TX79_MMI2_PINTH */
24639 case TX79_MMI2_PMULTW: /* TODO: TX79_MMI2_PMULTW */
24640 case TX79_MMI2_PDIVW: /* TODO: TX79_MMI2_PDIVW */
24641 case TX79_MMI2_PCPYLD: /* TODO: TX79_MMI2_PCPYLD */
24642 case TX79_MMI2_PMADDH: /* TODO: TX79_MMI2_PMADDH */
24643 case TX79_MMI2_PHMADH: /* TODO: TX79_MMI2_PHMADH */
24644 case TX79_MMI2_PAND: /* TODO: TX79_MMI2_PAND */
24645 case TX79_MMI2_PXOR: /* TODO: TX79_MMI2_PXOR */
24646 case TX79_MMI2_PMSUBH: /* TODO: TX79_MMI2_PMSUBH */
24647 case TX79_MMI2_PHMSBH: /* TODO: TX79_MMI2_PHMSBH */
24648 case TX79_MMI2_PEXEH: /* TODO: TX79_MMI2_PEXEH */
24649 case TX79_MMI2_PREVH: /* TODO: TX79_MMI2_PREVH */
24650 case TX79_MMI2_PMULTH: /* TODO: TX79_MMI2_PMULTH */
24651 case TX79_MMI2_PDIVBW: /* TODO: TX79_MMI2_PDIVBW */
24652 case TX79_MMI2_PEXEW: /* TODO: TX79_MMI2_PEXEW */
24653 case TX79_MMI2_PROT3W: /* TODO: TX79_MMI2_PROT3W */
24654 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI2 */
24655 break;
24656 default:
24657 MIPS_INVAL("TX79 MMI class MMI2");
24658 generate_exception_end(ctx, EXCP_RI);
24659 break;
24663 static void decode_tx79_mmi3(CPUMIPSState *env, DisasContext *ctx)
24665 uint32_t opc = MASK_TX79_MMI3(ctx->opcode);
24667 switch (opc) {
24668 case TX79_MMI3_PMADDUW: /* TODO: TX79_MMI3_PMADDUW */
24669 case TX79_MMI3_PSRAVW: /* TODO: TX79_MMI3_PSRAVW */
24670 case TX79_MMI3_PMTHI: /* TODO: TX79_MMI3_PMTHI */
24671 case TX79_MMI3_PMTLO: /* TODO: TX79_MMI3_PMTLO */
24672 case TX79_MMI3_PINTEH: /* TODO: TX79_MMI3_PINTEH */
24673 case TX79_MMI3_PMULTUW: /* TODO: TX79_MMI3_PMULTUW */
24674 case TX79_MMI3_PDIVUW: /* TODO: TX79_MMI3_PDIVUW */
24675 case TX79_MMI3_PCPYUD: /* TODO: TX79_MMI3_PCPYUD */
24676 case TX79_MMI3_POR: /* TODO: TX79_MMI3_POR */
24677 case TX79_MMI3_PNOR: /* TODO: TX79_MMI3_PNOR */
24678 case TX79_MMI3_PEXCH: /* TODO: TX79_MMI3_PEXCH */
24679 case TX79_MMI3_PCPYH: /* TODO: TX79_MMI3_PCPYH */
24680 case TX79_MMI3_PEXCW: /* TODO: TX79_MMI3_PEXCW */
24681 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI3 */
24682 break;
24683 default:
24684 MIPS_INVAL("TX79 MMI class MMI3");
24685 generate_exception_end(ctx, EXCP_RI);
24686 break;
24690 static void decode_tx79_mmi(CPUMIPSState *env, DisasContext *ctx)
24692 uint32_t opc = MASK_TX79_MMI(ctx->opcode);
24693 int rs = extract32(ctx->opcode, 21, 5);
24694 int rt = extract32(ctx->opcode, 16, 5);
24695 int rd = extract32(ctx->opcode, 11, 5);
24697 switch (opc) {
24698 case TX79_MMI_CLASS_MMI0:
24699 decode_tx79_mmi0(env, ctx);
24700 break;
24701 case TX79_MMI_CLASS_MMI1:
24702 decode_tx79_mmi1(env, ctx);
24703 break;
24704 case TX79_MMI_CLASS_MMI2:
24705 decode_tx79_mmi2(env, ctx);
24706 break;
24707 case TX79_MMI_CLASS_MMI3:
24708 decode_tx79_mmi3(env, ctx);
24709 break;
24710 case TX79_MMI_MULT1:
24711 case TX79_MMI_MULTU1:
24712 gen_mul_txx9(ctx, opc, rd, rs, rt);
24713 break;
24714 case TX79_MMI_DIV1:
24715 case TX79_MMI_DIVU1:
24716 gen_muldiv(ctx, opc, 1, rs, rt);
24717 break;
24718 case TX79_MMI_MTLO1:
24719 case TX79_MMI_MTHI1:
24720 gen_HILO(ctx, opc, 1, rs);
24721 break;
24722 case TX79_MMI_MFLO1:
24723 case TX79_MMI_MFHI1:
24724 gen_HILO(ctx, opc, 1, rd);
24725 break;
24726 case TX79_MMI_MADD: /* TODO: TX79_MMI_MADD */
24727 case TX79_MMI_MADDU: /* TODO: TX79_MMI_MADDU */
24728 case TX79_MMI_PLZCW: /* TODO: TX79_MMI_PLZCW */
24729 case TX79_MMI_MADD1: /* TODO: TX79_MMI_MADD1 */
24730 case TX79_MMI_MADDU1: /* TODO: TX79_MMI_MADDU1 */
24731 case TX79_MMI_PMFHL: /* TODO: TX79_MMI_PMFHL */
24732 case TX79_MMI_PMTHL: /* TODO: TX79_MMI_PMTHL */
24733 case TX79_MMI_PSLLH: /* TODO: TX79_MMI_PSLLH */
24734 case TX79_MMI_PSRLH: /* TODO: TX79_MMI_PSRLH */
24735 case TX79_MMI_PSRAH: /* TODO: TX79_MMI_PSRAH */
24736 case TX79_MMI_PSLLW: /* TODO: TX79_MMI_PSLLW */
24737 case TX79_MMI_PSRLW: /* TODO: TX79_MMI_PSRLW */
24738 case TX79_MMI_PSRAW: /* TODO: TX79_MMI_PSRAW */
24739 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_CLASS_MMI */
24740 break;
24741 default:
24742 MIPS_INVAL("TX79 MMI class");
24743 generate_exception_end(ctx, EXCP_RI);
24744 break;
24748 static void decode_tx79_lq(CPUMIPSState *env, DisasContext *ctx)
24750 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_LQ */
24753 static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
24755 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
24759 * The TX79-specific instruction Store Quadword
24761 * +--------+-------+-------+------------------------+
24762 * | 011111 | base | rt | offset | SQ
24763 * +--------+-------+-------+------------------------+
24764 * 6 5 5 16
24766 * has the same opcode as the Read Hardware Register instruction
24768 * +--------+-------+-------+-------+-------+--------+
24769 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24770 * +--------+-------+-------+-------+-------+--------+
24771 * 6 5 5 5 5 6
24773 * that is required, trapped and emulated by the Linux kernel. However, all
24774 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24775 * offset is odd. Therefore all valid SQ instructions can execute normally.
24776 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24777 * between SQ and RDHWR, as the Linux kernel does.
24779 static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
24781 int base = extract32(ctx->opcode, 21, 5);
24782 int rt = extract32(ctx->opcode, 16, 5);
24783 int offset = extract32(ctx->opcode, 0, 16);
24785 #ifdef CONFIG_USER_ONLY
24786 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24787 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24789 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24790 int rd = extract32(ctx->opcode, 11, 5);
24792 gen_rdhwr(ctx, rt, rd, 0);
24793 return;
24795 #endif
24797 gen_tx79_sq(ctx, base, rt, offset);
24800 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24802 int rs, rt, rd, sa;
24803 uint32_t op1, op2;
24804 int16_t imm;
24806 rs = (ctx->opcode >> 21) & 0x1f;
24807 rt = (ctx->opcode >> 16) & 0x1f;
24808 rd = (ctx->opcode >> 11) & 0x1f;
24809 sa = (ctx->opcode >> 6) & 0x1f;
24810 imm = sextract32(ctx->opcode, 7, 9);
24812 op1 = MASK_SPECIAL3(ctx->opcode);
24815 * EVA loads and stores overlap Loongson 2E instructions decoded by
24816 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24817 * EVA is absent.
24819 if (ctx->eva) {
24820 switch (op1) {
24821 case OPC_LWLE:
24822 case OPC_LWRE:
24823 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24824 /* fall through */
24825 case OPC_LBUE:
24826 case OPC_LHUE:
24827 case OPC_LBE:
24828 case OPC_LHE:
24829 case OPC_LLE:
24830 case OPC_LWE:
24831 check_cp0_enabled(ctx);
24832 gen_ld(ctx, op1, rt, rs, imm);
24833 return;
24834 case OPC_SWLE:
24835 case OPC_SWRE:
24836 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24837 /* fall through */
24838 case OPC_SBE:
24839 case OPC_SHE:
24840 case OPC_SWE:
24841 check_cp0_enabled(ctx);
24842 gen_st(ctx, op1, rt, rs, imm);
24843 return;
24844 case OPC_SCE:
24845 check_cp0_enabled(ctx);
24846 gen_st_cond(ctx, op1, rt, rs, imm);
24847 return;
24848 case OPC_CACHEE:
24849 check_cp0_enabled(ctx);
24850 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24851 gen_cache_operation(ctx, rt, rs, imm);
24853 /* Treat as NOP. */
24854 return;
24855 case OPC_PREFE:
24856 check_cp0_enabled(ctx);
24857 /* Treat as NOP. */
24858 return;
24862 switch (op1) {
24863 case OPC_EXT:
24864 case OPC_INS:
24865 check_insn(ctx, ISA_MIPS32R2);
24866 gen_bitops(ctx, op1, rt, rs, sa, rd);
24867 break;
24868 case OPC_BSHFL:
24869 op2 = MASK_BSHFL(ctx->opcode);
24870 switch (op2) {
24871 case OPC_ALIGN:
24872 case OPC_ALIGN_1:
24873 case OPC_ALIGN_2:
24874 case OPC_ALIGN_3:
24875 case OPC_BITSWAP:
24876 check_insn(ctx, ISA_MIPS32R6);
24877 decode_opc_special3_r6(env, ctx);
24878 break;
24879 default:
24880 check_insn(ctx, ISA_MIPS32R2);
24881 gen_bshfl(ctx, op2, rt, rd);
24882 break;
24884 break;
24885 #if defined(TARGET_MIPS64)
24886 case OPC_DEXTM:
24887 case OPC_DEXTU:
24888 case OPC_DEXT:
24889 case OPC_DINSM:
24890 case OPC_DINSU:
24891 case OPC_DINS:
24892 check_insn(ctx, ISA_MIPS64R2);
24893 check_mips_64(ctx);
24894 gen_bitops(ctx, op1, rt, rs, sa, rd);
24895 break;
24896 case OPC_DBSHFL:
24897 op2 = MASK_DBSHFL(ctx->opcode);
24898 switch (op2) {
24899 case OPC_DALIGN:
24900 case OPC_DALIGN_1:
24901 case OPC_DALIGN_2:
24902 case OPC_DALIGN_3:
24903 case OPC_DALIGN_4:
24904 case OPC_DALIGN_5:
24905 case OPC_DALIGN_6:
24906 case OPC_DALIGN_7:
24907 case OPC_DBITSWAP:
24908 check_insn(ctx, ISA_MIPS32R6);
24909 decode_opc_special3_r6(env, ctx);
24910 break;
24911 default:
24912 check_insn(ctx, ISA_MIPS64R2);
24913 check_mips_64(ctx);
24914 op2 = MASK_DBSHFL(ctx->opcode);
24915 gen_bshfl(ctx, op2, rt, rd);
24916 break;
24918 break;
24919 #endif
24920 case OPC_RDHWR:
24921 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24922 break;
24923 case OPC_FORK:
24924 check_mt(ctx);
24926 TCGv t0 = tcg_temp_new();
24927 TCGv t1 = tcg_temp_new();
24929 gen_load_gpr(t0, rt);
24930 gen_load_gpr(t1, rs);
24931 gen_helper_fork(t0, t1);
24932 tcg_temp_free(t0);
24933 tcg_temp_free(t1);
24935 break;
24936 case OPC_YIELD:
24937 check_mt(ctx);
24939 TCGv t0 = tcg_temp_new();
24941 gen_load_gpr(t0, rs);
24942 gen_helper_yield(t0, cpu_env, t0);
24943 gen_store_gpr(t0, rd);
24944 tcg_temp_free(t0);
24946 break;
24947 default:
24948 if (ctx->insn_flags & ISA_MIPS32R6) {
24949 decode_opc_special3_r6(env, ctx);
24950 } else {
24951 decode_opc_special3_legacy(env, ctx);
24956 /* MIPS SIMD Architecture (MSA) */
24957 static inline int check_msa_access(DisasContext *ctx)
24959 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
24960 !(ctx->hflags & MIPS_HFLAG_F64))) {
24961 generate_exception_end(ctx, EXCP_RI);
24962 return 0;
24965 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
24966 if (ctx->insn_flags & ASE_MSA) {
24967 generate_exception_end(ctx, EXCP_MSADIS);
24968 return 0;
24969 } else {
24970 generate_exception_end(ctx, EXCP_RI);
24971 return 0;
24974 return 1;
24977 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
24979 /* generates tcg ops to check if any element is 0 */
24980 /* Note this function only works with MSA_WRLEN = 128 */
24981 uint64_t eval_zero_or_big = 0;
24982 uint64_t eval_big = 0;
24983 TCGv_i64 t0 = tcg_temp_new_i64();
24984 TCGv_i64 t1 = tcg_temp_new_i64();
24985 switch (df) {
24986 case DF_BYTE:
24987 eval_zero_or_big = 0x0101010101010101ULL;
24988 eval_big = 0x8080808080808080ULL;
24989 break;
24990 case DF_HALF:
24991 eval_zero_or_big = 0x0001000100010001ULL;
24992 eval_big = 0x8000800080008000ULL;
24993 break;
24994 case DF_WORD:
24995 eval_zero_or_big = 0x0000000100000001ULL;
24996 eval_big = 0x8000000080000000ULL;
24997 break;
24998 case DF_DOUBLE:
24999 eval_zero_or_big = 0x0000000000000001ULL;
25000 eval_big = 0x8000000000000000ULL;
25001 break;
25003 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
25004 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
25005 tcg_gen_andi_i64(t0, t0, eval_big);
25006 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
25007 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
25008 tcg_gen_andi_i64(t1, t1, eval_big);
25009 tcg_gen_or_i64(t0, t0, t1);
25010 /* if all bits are zero then all elements are not zero */
25011 /* if some bit is non-zero then some element is zero */
25012 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
25013 tcg_gen_trunc_i64_tl(tresult, t0);
25014 tcg_temp_free_i64(t0);
25015 tcg_temp_free_i64(t1);
25018 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
25020 uint8_t df = (ctx->opcode >> 21) & 0x3;
25021 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25022 int64_t s16 = (int16_t)ctx->opcode;
25024 check_msa_access(ctx);
25026 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25027 generate_exception_end(ctx, EXCP_RI);
25028 return;
25030 switch (op1) {
25031 case OPC_BZ_V:
25032 case OPC_BNZ_V:
25034 TCGv_i64 t0 = tcg_temp_new_i64();
25035 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
25036 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
25037 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
25038 tcg_gen_trunc_i64_tl(bcond, t0);
25039 tcg_temp_free_i64(t0);
25041 break;
25042 case OPC_BZ_B:
25043 case OPC_BZ_H:
25044 case OPC_BZ_W:
25045 case OPC_BZ_D:
25046 gen_check_zero_element(bcond, df, wt);
25047 break;
25048 case OPC_BNZ_B:
25049 case OPC_BNZ_H:
25050 case OPC_BNZ_W:
25051 case OPC_BNZ_D:
25052 gen_check_zero_element(bcond, df, wt);
25053 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
25054 break;
25057 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
25059 ctx->hflags |= MIPS_HFLAG_BC;
25060 ctx->hflags |= MIPS_HFLAG_BDS32;
25063 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
25065 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
25066 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
25067 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25068 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25070 TCGv_i32 twd = tcg_const_i32(wd);
25071 TCGv_i32 tws = tcg_const_i32(ws);
25072 TCGv_i32 ti8 = tcg_const_i32(i8);
25074 switch (MASK_MSA_I8(ctx->opcode)) {
25075 case OPC_ANDI_B:
25076 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
25077 break;
25078 case OPC_ORI_B:
25079 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
25080 break;
25081 case OPC_NORI_B:
25082 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
25083 break;
25084 case OPC_XORI_B:
25085 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
25086 break;
25087 case OPC_BMNZI_B:
25088 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
25089 break;
25090 case OPC_BMZI_B:
25091 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
25092 break;
25093 case OPC_BSELI_B:
25094 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
25095 break;
25096 case OPC_SHF_B:
25097 case OPC_SHF_H:
25098 case OPC_SHF_W:
25100 uint8_t df = (ctx->opcode >> 24) & 0x3;
25101 if (df == DF_DOUBLE) {
25102 generate_exception_end(ctx, EXCP_RI);
25103 } else {
25104 TCGv_i32 tdf = tcg_const_i32(df);
25105 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
25106 tcg_temp_free_i32(tdf);
25109 break;
25110 default:
25111 MIPS_INVAL("MSA instruction");
25112 generate_exception_end(ctx, EXCP_RI);
25113 break;
25116 tcg_temp_free_i32(twd);
25117 tcg_temp_free_i32(tws);
25118 tcg_temp_free_i32(ti8);
25121 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
25123 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25124 uint8_t df = (ctx->opcode >> 21) & 0x3;
25125 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
25126 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
25127 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25128 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25130 TCGv_i32 tdf = tcg_const_i32(df);
25131 TCGv_i32 twd = tcg_const_i32(wd);
25132 TCGv_i32 tws = tcg_const_i32(ws);
25133 TCGv_i32 timm = tcg_temp_new_i32();
25134 tcg_gen_movi_i32(timm, u5);
25136 switch (MASK_MSA_I5(ctx->opcode)) {
25137 case OPC_ADDVI_df:
25138 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
25139 break;
25140 case OPC_SUBVI_df:
25141 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
25142 break;
25143 case OPC_MAXI_S_df:
25144 tcg_gen_movi_i32(timm, s5);
25145 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
25146 break;
25147 case OPC_MAXI_U_df:
25148 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
25149 break;
25150 case OPC_MINI_S_df:
25151 tcg_gen_movi_i32(timm, s5);
25152 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
25153 break;
25154 case OPC_MINI_U_df:
25155 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
25156 break;
25157 case OPC_CEQI_df:
25158 tcg_gen_movi_i32(timm, s5);
25159 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
25160 break;
25161 case OPC_CLTI_S_df:
25162 tcg_gen_movi_i32(timm, s5);
25163 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
25164 break;
25165 case OPC_CLTI_U_df:
25166 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
25167 break;
25168 case OPC_CLEI_S_df:
25169 tcg_gen_movi_i32(timm, s5);
25170 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
25171 break;
25172 case OPC_CLEI_U_df:
25173 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
25174 break;
25175 case OPC_LDI_df:
25177 int32_t s10 = sextract32(ctx->opcode, 11, 10);
25178 tcg_gen_movi_i32(timm, s10);
25179 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
25181 break;
25182 default:
25183 MIPS_INVAL("MSA instruction");
25184 generate_exception_end(ctx, EXCP_RI);
25185 break;
25188 tcg_temp_free_i32(tdf);
25189 tcg_temp_free_i32(twd);
25190 tcg_temp_free_i32(tws);
25191 tcg_temp_free_i32(timm);
25194 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
25196 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25197 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
25198 uint32_t df = 0, m = 0;
25199 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25200 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25202 TCGv_i32 tdf;
25203 TCGv_i32 tm;
25204 TCGv_i32 twd;
25205 TCGv_i32 tws;
25207 if ((dfm & 0x40) == 0x00) {
25208 m = dfm & 0x3f;
25209 df = DF_DOUBLE;
25210 } else if ((dfm & 0x60) == 0x40) {
25211 m = dfm & 0x1f;
25212 df = DF_WORD;
25213 } else if ((dfm & 0x70) == 0x60) {
25214 m = dfm & 0x0f;
25215 df = DF_HALF;
25216 } else if ((dfm & 0x78) == 0x70) {
25217 m = dfm & 0x7;
25218 df = DF_BYTE;
25219 } else {
25220 generate_exception_end(ctx, EXCP_RI);
25221 return;
25224 tdf = tcg_const_i32(df);
25225 tm = tcg_const_i32(m);
25226 twd = tcg_const_i32(wd);
25227 tws = tcg_const_i32(ws);
25229 switch (MASK_MSA_BIT(ctx->opcode)) {
25230 case OPC_SLLI_df:
25231 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
25232 break;
25233 case OPC_SRAI_df:
25234 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
25235 break;
25236 case OPC_SRLI_df:
25237 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
25238 break;
25239 case OPC_BCLRI_df:
25240 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
25241 break;
25242 case OPC_BSETI_df:
25243 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
25244 break;
25245 case OPC_BNEGI_df:
25246 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
25247 break;
25248 case OPC_BINSLI_df:
25249 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
25250 break;
25251 case OPC_BINSRI_df:
25252 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
25253 break;
25254 case OPC_SAT_S_df:
25255 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
25256 break;
25257 case OPC_SAT_U_df:
25258 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
25259 break;
25260 case OPC_SRARI_df:
25261 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
25262 break;
25263 case OPC_SRLRI_df:
25264 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
25265 break;
25266 default:
25267 MIPS_INVAL("MSA instruction");
25268 generate_exception_end(ctx, EXCP_RI);
25269 break;
25272 tcg_temp_free_i32(tdf);
25273 tcg_temp_free_i32(tm);
25274 tcg_temp_free_i32(twd);
25275 tcg_temp_free_i32(tws);
25278 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
25280 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25281 uint8_t df = (ctx->opcode >> 21) & 0x3;
25282 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25283 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25284 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25286 TCGv_i32 tdf = tcg_const_i32(df);
25287 TCGv_i32 twd = tcg_const_i32(wd);
25288 TCGv_i32 tws = tcg_const_i32(ws);
25289 TCGv_i32 twt = tcg_const_i32(wt);
25291 switch (MASK_MSA_3R(ctx->opcode)) {
25292 case OPC_SLL_df:
25293 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
25294 break;
25295 case OPC_ADDV_df:
25296 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
25297 break;
25298 case OPC_CEQ_df:
25299 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
25300 break;
25301 case OPC_ADD_A_df:
25302 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
25303 break;
25304 case OPC_SUBS_S_df:
25305 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
25306 break;
25307 case OPC_MULV_df:
25308 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
25309 break;
25310 case OPC_SLD_df:
25311 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
25312 break;
25313 case OPC_VSHF_df:
25314 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
25315 break;
25316 case OPC_SRA_df:
25317 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
25318 break;
25319 case OPC_SUBV_df:
25320 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
25321 break;
25322 case OPC_ADDS_A_df:
25323 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
25324 break;
25325 case OPC_SUBS_U_df:
25326 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
25327 break;
25328 case OPC_MADDV_df:
25329 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
25330 break;
25331 case OPC_SPLAT_df:
25332 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
25333 break;
25334 case OPC_SRAR_df:
25335 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
25336 break;
25337 case OPC_SRL_df:
25338 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
25339 break;
25340 case OPC_MAX_S_df:
25341 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
25342 break;
25343 case OPC_CLT_S_df:
25344 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
25345 break;
25346 case OPC_ADDS_S_df:
25347 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
25348 break;
25349 case OPC_SUBSUS_U_df:
25350 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
25351 break;
25352 case OPC_MSUBV_df:
25353 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
25354 break;
25355 case OPC_PCKEV_df:
25356 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
25357 break;
25358 case OPC_SRLR_df:
25359 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
25360 break;
25361 case OPC_BCLR_df:
25362 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
25363 break;
25364 case OPC_MAX_U_df:
25365 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
25366 break;
25367 case OPC_CLT_U_df:
25368 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
25369 break;
25370 case OPC_ADDS_U_df:
25371 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
25372 break;
25373 case OPC_SUBSUU_S_df:
25374 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
25375 break;
25376 case OPC_PCKOD_df:
25377 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
25378 break;
25379 case OPC_BSET_df:
25380 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
25381 break;
25382 case OPC_MIN_S_df:
25383 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
25384 break;
25385 case OPC_CLE_S_df:
25386 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
25387 break;
25388 case OPC_AVE_S_df:
25389 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
25390 break;
25391 case OPC_ASUB_S_df:
25392 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
25393 break;
25394 case OPC_DIV_S_df:
25395 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
25396 break;
25397 case OPC_ILVL_df:
25398 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
25399 break;
25400 case OPC_BNEG_df:
25401 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
25402 break;
25403 case OPC_MIN_U_df:
25404 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
25405 break;
25406 case OPC_CLE_U_df:
25407 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
25408 break;
25409 case OPC_AVE_U_df:
25410 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
25411 break;
25412 case OPC_ASUB_U_df:
25413 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
25414 break;
25415 case OPC_DIV_U_df:
25416 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
25417 break;
25418 case OPC_ILVR_df:
25419 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
25420 break;
25421 case OPC_BINSL_df:
25422 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
25423 break;
25424 case OPC_MAX_A_df:
25425 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
25426 break;
25427 case OPC_AVER_S_df:
25428 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
25429 break;
25430 case OPC_MOD_S_df:
25431 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
25432 break;
25433 case OPC_ILVEV_df:
25434 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
25435 break;
25436 case OPC_BINSR_df:
25437 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
25438 break;
25439 case OPC_MIN_A_df:
25440 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
25441 break;
25442 case OPC_AVER_U_df:
25443 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
25444 break;
25445 case OPC_MOD_U_df:
25446 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
25447 break;
25448 case OPC_ILVOD_df:
25449 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
25450 break;
25452 case OPC_DOTP_S_df:
25453 case OPC_DOTP_U_df:
25454 case OPC_DPADD_S_df:
25455 case OPC_DPADD_U_df:
25456 case OPC_DPSUB_S_df:
25457 case OPC_HADD_S_df:
25458 case OPC_DPSUB_U_df:
25459 case OPC_HADD_U_df:
25460 case OPC_HSUB_S_df:
25461 case OPC_HSUB_U_df:
25462 if (df == DF_BYTE) {
25463 generate_exception_end(ctx, EXCP_RI);
25464 break;
25466 switch (MASK_MSA_3R(ctx->opcode)) {
25467 case OPC_DOTP_S_df:
25468 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
25469 break;
25470 case OPC_DOTP_U_df:
25471 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
25472 break;
25473 case OPC_DPADD_S_df:
25474 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
25475 break;
25476 case OPC_DPADD_U_df:
25477 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
25478 break;
25479 case OPC_DPSUB_S_df:
25480 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
25481 break;
25482 case OPC_HADD_S_df:
25483 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
25484 break;
25485 case OPC_DPSUB_U_df:
25486 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
25487 break;
25488 case OPC_HADD_U_df:
25489 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
25490 break;
25491 case OPC_HSUB_S_df:
25492 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
25493 break;
25494 case OPC_HSUB_U_df:
25495 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
25496 break;
25498 break;
25499 default:
25500 MIPS_INVAL("MSA instruction");
25501 generate_exception_end(ctx, EXCP_RI);
25502 break;
25504 tcg_temp_free_i32(twd);
25505 tcg_temp_free_i32(tws);
25506 tcg_temp_free_i32(twt);
25507 tcg_temp_free_i32(tdf);
25510 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
25512 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
25513 uint8_t source = (ctx->opcode >> 11) & 0x1f;
25514 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
25515 TCGv telm = tcg_temp_new();
25516 TCGv_i32 tsr = tcg_const_i32(source);
25517 TCGv_i32 tdt = tcg_const_i32(dest);
25519 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
25520 case OPC_CTCMSA:
25521 gen_load_gpr(telm, source);
25522 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
25523 break;
25524 case OPC_CFCMSA:
25525 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
25526 gen_store_gpr(telm, dest);
25527 break;
25528 case OPC_MOVE_V:
25529 gen_helper_msa_move_v(cpu_env, tdt, tsr);
25530 break;
25531 default:
25532 MIPS_INVAL("MSA instruction");
25533 generate_exception_end(ctx, EXCP_RI);
25534 break;
25537 tcg_temp_free(telm);
25538 tcg_temp_free_i32(tdt);
25539 tcg_temp_free_i32(tsr);
25542 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
25543 uint32_t n)
25545 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25546 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25547 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25549 TCGv_i32 tws = tcg_const_i32(ws);
25550 TCGv_i32 twd = tcg_const_i32(wd);
25551 TCGv_i32 tn = tcg_const_i32(n);
25552 TCGv_i32 tdf = tcg_const_i32(df);
25554 switch (MASK_MSA_ELM(ctx->opcode)) {
25555 case OPC_SLDI_df:
25556 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
25557 break;
25558 case OPC_SPLATI_df:
25559 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
25560 break;
25561 case OPC_INSVE_df:
25562 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
25563 break;
25564 case OPC_COPY_S_df:
25565 case OPC_COPY_U_df:
25566 case OPC_INSERT_df:
25567 #if !defined(TARGET_MIPS64)
25568 /* Double format valid only for MIPS64 */
25569 if (df == DF_DOUBLE) {
25570 generate_exception_end(ctx, EXCP_RI);
25571 break;
25573 #endif
25574 switch (MASK_MSA_ELM(ctx->opcode)) {
25575 case OPC_COPY_S_df:
25576 if (likely(wd != 0)) {
25577 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
25579 break;
25580 case OPC_COPY_U_df:
25581 if (likely(wd != 0)) {
25582 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
25584 break;
25585 case OPC_INSERT_df:
25586 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
25587 break;
25589 break;
25590 default:
25591 MIPS_INVAL("MSA instruction");
25592 generate_exception_end(ctx, EXCP_RI);
25594 tcg_temp_free_i32(twd);
25595 tcg_temp_free_i32(tws);
25596 tcg_temp_free_i32(tn);
25597 tcg_temp_free_i32(tdf);
25600 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
25602 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
25603 uint32_t df = 0, n = 0;
25605 if ((dfn & 0x30) == 0x00) {
25606 n = dfn & 0x0f;
25607 df = DF_BYTE;
25608 } else if ((dfn & 0x38) == 0x20) {
25609 n = dfn & 0x07;
25610 df = DF_HALF;
25611 } else if ((dfn & 0x3c) == 0x30) {
25612 n = dfn & 0x03;
25613 df = DF_WORD;
25614 } else if ((dfn & 0x3e) == 0x38) {
25615 n = dfn & 0x01;
25616 df = DF_DOUBLE;
25617 } else if (dfn == 0x3E) {
25618 /* CTCMSA, CFCMSA, MOVE.V */
25619 gen_msa_elm_3e(env, ctx);
25620 return;
25621 } else {
25622 generate_exception_end(ctx, EXCP_RI);
25623 return;
25626 gen_msa_elm_df(env, ctx, df, n);
25629 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
25631 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25632 uint8_t df = (ctx->opcode >> 21) & 0x1;
25633 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25634 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25635 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25637 TCGv_i32 twd = tcg_const_i32(wd);
25638 TCGv_i32 tws = tcg_const_i32(ws);
25639 TCGv_i32 twt = tcg_const_i32(wt);
25640 TCGv_i32 tdf = tcg_temp_new_i32();
25642 /* adjust df value for floating-point instruction */
25643 tcg_gen_movi_i32(tdf, df + 2);
25645 switch (MASK_MSA_3RF(ctx->opcode)) {
25646 case OPC_FCAF_df:
25647 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
25648 break;
25649 case OPC_FADD_df:
25650 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
25651 break;
25652 case OPC_FCUN_df:
25653 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
25654 break;
25655 case OPC_FSUB_df:
25656 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
25657 break;
25658 case OPC_FCOR_df:
25659 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
25660 break;
25661 case OPC_FCEQ_df:
25662 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
25663 break;
25664 case OPC_FMUL_df:
25665 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
25666 break;
25667 case OPC_FCUNE_df:
25668 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
25669 break;
25670 case OPC_FCUEQ_df:
25671 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
25672 break;
25673 case OPC_FDIV_df:
25674 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
25675 break;
25676 case OPC_FCNE_df:
25677 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
25678 break;
25679 case OPC_FCLT_df:
25680 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
25681 break;
25682 case OPC_FMADD_df:
25683 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
25684 break;
25685 case OPC_MUL_Q_df:
25686 tcg_gen_movi_i32(tdf, df + 1);
25687 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
25688 break;
25689 case OPC_FCULT_df:
25690 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
25691 break;
25692 case OPC_FMSUB_df:
25693 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
25694 break;
25695 case OPC_MADD_Q_df:
25696 tcg_gen_movi_i32(tdf, df + 1);
25697 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
25698 break;
25699 case OPC_FCLE_df:
25700 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
25701 break;
25702 case OPC_MSUB_Q_df:
25703 tcg_gen_movi_i32(tdf, df + 1);
25704 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
25705 break;
25706 case OPC_FCULE_df:
25707 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
25708 break;
25709 case OPC_FEXP2_df:
25710 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
25711 break;
25712 case OPC_FSAF_df:
25713 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
25714 break;
25715 case OPC_FEXDO_df:
25716 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
25717 break;
25718 case OPC_FSUN_df:
25719 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
25720 break;
25721 case OPC_FSOR_df:
25722 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
25723 break;
25724 case OPC_FSEQ_df:
25725 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
25726 break;
25727 case OPC_FTQ_df:
25728 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
25729 break;
25730 case OPC_FSUNE_df:
25731 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
25732 break;
25733 case OPC_FSUEQ_df:
25734 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
25735 break;
25736 case OPC_FSNE_df:
25737 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
25738 break;
25739 case OPC_FSLT_df:
25740 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
25741 break;
25742 case OPC_FMIN_df:
25743 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
25744 break;
25745 case OPC_MULR_Q_df:
25746 tcg_gen_movi_i32(tdf, df + 1);
25747 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
25748 break;
25749 case OPC_FSULT_df:
25750 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
25751 break;
25752 case OPC_FMIN_A_df:
25753 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
25754 break;
25755 case OPC_MADDR_Q_df:
25756 tcg_gen_movi_i32(tdf, df + 1);
25757 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
25758 break;
25759 case OPC_FSLE_df:
25760 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
25761 break;
25762 case OPC_FMAX_df:
25763 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
25764 break;
25765 case OPC_MSUBR_Q_df:
25766 tcg_gen_movi_i32(tdf, df + 1);
25767 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
25768 break;
25769 case OPC_FSULE_df:
25770 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
25771 break;
25772 case OPC_FMAX_A_df:
25773 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
25774 break;
25775 default:
25776 MIPS_INVAL("MSA instruction");
25777 generate_exception_end(ctx, EXCP_RI);
25778 break;
25781 tcg_temp_free_i32(twd);
25782 tcg_temp_free_i32(tws);
25783 tcg_temp_free_i32(twt);
25784 tcg_temp_free_i32(tdf);
25787 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
25789 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25790 (op & (0x7 << 18)))
25791 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25792 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25793 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25794 uint8_t df = (ctx->opcode >> 16) & 0x3;
25795 TCGv_i32 twd = tcg_const_i32(wd);
25796 TCGv_i32 tws = tcg_const_i32(ws);
25797 TCGv_i32 twt = tcg_const_i32(wt);
25798 TCGv_i32 tdf = tcg_const_i32(df);
25800 switch (MASK_MSA_2R(ctx->opcode)) {
25801 case OPC_FILL_df:
25802 #if !defined(TARGET_MIPS64)
25803 /* Double format valid only for MIPS64 */
25804 if (df == DF_DOUBLE) {
25805 generate_exception_end(ctx, EXCP_RI);
25806 break;
25808 #endif
25809 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
25810 break;
25811 case OPC_PCNT_df:
25812 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
25813 break;
25814 case OPC_NLOC_df:
25815 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
25816 break;
25817 case OPC_NLZC_df:
25818 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25819 break;
25820 default:
25821 MIPS_INVAL("MSA instruction");
25822 generate_exception_end(ctx, EXCP_RI);
25823 break;
25826 tcg_temp_free_i32(twd);
25827 tcg_temp_free_i32(tws);
25828 tcg_temp_free_i32(twt);
25829 tcg_temp_free_i32(tdf);
25832 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25834 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25835 (op & (0xf << 17)))
25836 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25837 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25838 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25839 uint8_t df = (ctx->opcode >> 16) & 0x1;
25840 TCGv_i32 twd = tcg_const_i32(wd);
25841 TCGv_i32 tws = tcg_const_i32(ws);
25842 TCGv_i32 twt = tcg_const_i32(wt);
25843 /* adjust df value for floating-point instruction */
25844 TCGv_i32 tdf = tcg_const_i32(df + 2);
25846 switch (MASK_MSA_2RF(ctx->opcode)) {
25847 case OPC_FCLASS_df:
25848 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25849 break;
25850 case OPC_FTRUNC_S_df:
25851 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25852 break;
25853 case OPC_FTRUNC_U_df:
25854 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25855 break;
25856 case OPC_FSQRT_df:
25857 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25858 break;
25859 case OPC_FRSQRT_df:
25860 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25861 break;
25862 case OPC_FRCP_df:
25863 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25864 break;
25865 case OPC_FRINT_df:
25866 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25867 break;
25868 case OPC_FLOG2_df:
25869 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
25870 break;
25871 case OPC_FEXUPL_df:
25872 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
25873 break;
25874 case OPC_FEXUPR_df:
25875 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
25876 break;
25877 case OPC_FFQL_df:
25878 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
25879 break;
25880 case OPC_FFQR_df:
25881 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
25882 break;
25883 case OPC_FTINT_S_df:
25884 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
25885 break;
25886 case OPC_FTINT_U_df:
25887 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
25888 break;
25889 case OPC_FFINT_S_df:
25890 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
25891 break;
25892 case OPC_FFINT_U_df:
25893 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
25894 break;
25897 tcg_temp_free_i32(twd);
25898 tcg_temp_free_i32(tws);
25899 tcg_temp_free_i32(twt);
25900 tcg_temp_free_i32(tdf);
25903 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
25905 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
25906 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25907 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25908 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25909 TCGv_i32 twd = tcg_const_i32(wd);
25910 TCGv_i32 tws = tcg_const_i32(ws);
25911 TCGv_i32 twt = tcg_const_i32(wt);
25913 switch (MASK_MSA_VEC(ctx->opcode)) {
25914 case OPC_AND_V:
25915 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
25916 break;
25917 case OPC_OR_V:
25918 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
25919 break;
25920 case OPC_NOR_V:
25921 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
25922 break;
25923 case OPC_XOR_V:
25924 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
25925 break;
25926 case OPC_BMNZ_V:
25927 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
25928 break;
25929 case OPC_BMZ_V:
25930 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
25931 break;
25932 case OPC_BSEL_V:
25933 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
25934 break;
25935 default:
25936 MIPS_INVAL("MSA instruction");
25937 generate_exception_end(ctx, EXCP_RI);
25938 break;
25941 tcg_temp_free_i32(twd);
25942 tcg_temp_free_i32(tws);
25943 tcg_temp_free_i32(twt);
25946 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
25948 switch (MASK_MSA_VEC(ctx->opcode)) {
25949 case OPC_AND_V:
25950 case OPC_OR_V:
25951 case OPC_NOR_V:
25952 case OPC_XOR_V:
25953 case OPC_BMNZ_V:
25954 case OPC_BMZ_V:
25955 case OPC_BSEL_V:
25956 gen_msa_vec_v(env, ctx);
25957 break;
25958 case OPC_MSA_2R:
25959 gen_msa_2r(env, ctx);
25960 break;
25961 case OPC_MSA_2RF:
25962 gen_msa_2rf(env, ctx);
25963 break;
25964 default:
25965 MIPS_INVAL("MSA instruction");
25966 generate_exception_end(ctx, EXCP_RI);
25967 break;
25971 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
25973 uint32_t opcode = ctx->opcode;
25974 check_insn(ctx, ASE_MSA);
25975 check_msa_access(ctx);
25977 switch (MASK_MSA_MINOR(opcode)) {
25978 case OPC_MSA_I8_00:
25979 case OPC_MSA_I8_01:
25980 case OPC_MSA_I8_02:
25981 gen_msa_i8(env, ctx);
25982 break;
25983 case OPC_MSA_I5_06:
25984 case OPC_MSA_I5_07:
25985 gen_msa_i5(env, ctx);
25986 break;
25987 case OPC_MSA_BIT_09:
25988 case OPC_MSA_BIT_0A:
25989 gen_msa_bit(env, ctx);
25990 break;
25991 case OPC_MSA_3R_0D:
25992 case OPC_MSA_3R_0E:
25993 case OPC_MSA_3R_0F:
25994 case OPC_MSA_3R_10:
25995 case OPC_MSA_3R_11:
25996 case OPC_MSA_3R_12:
25997 case OPC_MSA_3R_13:
25998 case OPC_MSA_3R_14:
25999 case OPC_MSA_3R_15:
26000 gen_msa_3r(env, ctx);
26001 break;
26002 case OPC_MSA_ELM:
26003 gen_msa_elm(env, ctx);
26004 break;
26005 case OPC_MSA_3RF_1A:
26006 case OPC_MSA_3RF_1B:
26007 case OPC_MSA_3RF_1C:
26008 gen_msa_3rf(env, ctx);
26009 break;
26010 case OPC_MSA_VEC:
26011 gen_msa_vec(env, ctx);
26012 break;
26013 case OPC_LD_B:
26014 case OPC_LD_H:
26015 case OPC_LD_W:
26016 case OPC_LD_D:
26017 case OPC_ST_B:
26018 case OPC_ST_H:
26019 case OPC_ST_W:
26020 case OPC_ST_D:
26022 int32_t s10 = sextract32(ctx->opcode, 16, 10);
26023 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
26024 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
26025 uint8_t df = (ctx->opcode >> 0) & 0x3;
26027 TCGv_i32 twd = tcg_const_i32(wd);
26028 TCGv taddr = tcg_temp_new();
26029 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
26031 switch (MASK_MSA_MINOR(opcode)) {
26032 case OPC_LD_B:
26033 gen_helper_msa_ld_b(cpu_env, twd, taddr);
26034 break;
26035 case OPC_LD_H:
26036 gen_helper_msa_ld_h(cpu_env, twd, taddr);
26037 break;
26038 case OPC_LD_W:
26039 gen_helper_msa_ld_w(cpu_env, twd, taddr);
26040 break;
26041 case OPC_LD_D:
26042 gen_helper_msa_ld_d(cpu_env, twd, taddr);
26043 break;
26044 case OPC_ST_B:
26045 gen_helper_msa_st_b(cpu_env, twd, taddr);
26046 break;
26047 case OPC_ST_H:
26048 gen_helper_msa_st_h(cpu_env, twd, taddr);
26049 break;
26050 case OPC_ST_W:
26051 gen_helper_msa_st_w(cpu_env, twd, taddr);
26052 break;
26053 case OPC_ST_D:
26054 gen_helper_msa_st_d(cpu_env, twd, taddr);
26055 break;
26058 tcg_temp_free_i32(twd);
26059 tcg_temp_free(taddr);
26061 break;
26062 default:
26063 MIPS_INVAL("MSA instruction");
26064 generate_exception_end(ctx, EXCP_RI);
26065 break;
26070 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
26072 int32_t offset;
26073 int rs, rt, rd, sa;
26074 uint32_t op, op1;
26075 int16_t imm;
26077 /* make sure instructions are on a word boundary */
26078 if (ctx->base.pc_next & 0x3) {
26079 env->CP0_BadVAddr = ctx->base.pc_next;
26080 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
26081 return;
26084 /* Handle blikely not taken case */
26085 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
26086 TCGLabel *l1 = gen_new_label();
26088 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
26089 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
26090 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
26091 gen_set_label(l1);
26094 op = MASK_OP_MAJOR(ctx->opcode);
26095 rs = (ctx->opcode >> 21) & 0x1f;
26096 rt = (ctx->opcode >> 16) & 0x1f;
26097 rd = (ctx->opcode >> 11) & 0x1f;
26098 sa = (ctx->opcode >> 6) & 0x1f;
26099 imm = (int16_t)ctx->opcode;
26100 switch (op) {
26101 case OPC_SPECIAL:
26102 decode_opc_special(env, ctx);
26103 break;
26104 case OPC_SPECIAL2:
26105 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
26106 decode_tx79_mmi(env, ctx);
26107 } else {
26108 decode_opc_special2_legacy(env, ctx);
26110 break;
26111 case OPC_SPECIAL3:
26112 if (ctx->insn_flags & INSN_R5900) {
26113 decode_tx79_sq(env, ctx); /* TX79_SQ */
26114 } else {
26115 decode_opc_special3(env, ctx);
26117 break;
26118 case OPC_REGIMM:
26119 op1 = MASK_REGIMM(ctx->opcode);
26120 switch (op1) {
26121 case OPC_BLTZL: /* REGIMM branches */
26122 case OPC_BGEZL:
26123 case OPC_BLTZALL:
26124 case OPC_BGEZALL:
26125 check_insn(ctx, ISA_MIPS2);
26126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26127 /* Fallthrough */
26128 case OPC_BLTZ:
26129 case OPC_BGEZ:
26130 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26131 break;
26132 case OPC_BLTZAL:
26133 case OPC_BGEZAL:
26134 if (ctx->insn_flags & ISA_MIPS32R6) {
26135 if (rs == 0) {
26136 /* OPC_NAL, OPC_BAL */
26137 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
26138 } else {
26139 generate_exception_end(ctx, EXCP_RI);
26141 } else {
26142 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26144 break;
26145 case OPC_TGEI: /* REGIMM traps */
26146 case OPC_TGEIU:
26147 case OPC_TLTI:
26148 case OPC_TLTIU:
26149 case OPC_TEQI:
26151 case OPC_TNEI:
26152 check_insn(ctx, ISA_MIPS2);
26153 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26154 gen_trap(ctx, op1, rs, -1, imm);
26155 break;
26156 case OPC_SIGRIE:
26157 check_insn(ctx, ISA_MIPS32R6);
26158 generate_exception_end(ctx, EXCP_RI);
26159 break;
26160 case OPC_SYNCI:
26161 check_insn(ctx, ISA_MIPS32R2);
26162 /* Break the TB to be able to sync copied instructions
26163 immediately */
26164 ctx->base.is_jmp = DISAS_STOP;
26165 break;
26166 case OPC_BPOSGE32: /* MIPS DSP branch */
26167 #if defined(TARGET_MIPS64)
26168 case OPC_BPOSGE64:
26169 #endif
26170 check_dsp(ctx);
26171 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
26172 break;
26173 #if defined(TARGET_MIPS64)
26174 case OPC_DAHI:
26175 check_insn(ctx, ISA_MIPS32R6);
26176 check_mips_64(ctx);
26177 if (rs != 0) {
26178 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
26180 break;
26181 case OPC_DATI:
26182 check_insn(ctx, ISA_MIPS32R6);
26183 check_mips_64(ctx);
26184 if (rs != 0) {
26185 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
26187 break;
26188 #endif
26189 default: /* Invalid */
26190 MIPS_INVAL("regimm");
26191 generate_exception_end(ctx, EXCP_RI);
26192 break;
26194 break;
26195 case OPC_CP0:
26196 check_cp0_enabled(ctx);
26197 op1 = MASK_CP0(ctx->opcode);
26198 switch (op1) {
26199 case OPC_MFC0:
26200 case OPC_MTC0:
26201 case OPC_MFTR:
26202 case OPC_MTTR:
26203 case OPC_MFHC0:
26204 case OPC_MTHC0:
26205 #if defined(TARGET_MIPS64)
26206 case OPC_DMFC0:
26207 case OPC_DMTC0:
26208 #endif
26209 #ifndef CONFIG_USER_ONLY
26210 gen_cp0(env, ctx, op1, rt, rd);
26211 #endif /* !CONFIG_USER_ONLY */
26212 break;
26213 case OPC_C0:
26214 case OPC_C0_1:
26215 case OPC_C0_2:
26216 case OPC_C0_3:
26217 case OPC_C0_4:
26218 case OPC_C0_5:
26219 case OPC_C0_6:
26220 case OPC_C0_7:
26221 case OPC_C0_8:
26222 case OPC_C0_9:
26223 case OPC_C0_A:
26224 case OPC_C0_B:
26225 case OPC_C0_C:
26226 case OPC_C0_D:
26227 case OPC_C0_E:
26228 case OPC_C0_F:
26229 #ifndef CONFIG_USER_ONLY
26230 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
26231 #endif /* !CONFIG_USER_ONLY */
26232 break;
26233 case OPC_MFMC0:
26234 #ifndef CONFIG_USER_ONLY
26236 uint32_t op2;
26237 TCGv t0 = tcg_temp_new();
26239 op2 = MASK_MFMC0(ctx->opcode);
26240 switch (op2) {
26241 case OPC_DMT:
26242 check_cp0_mt(ctx);
26243 gen_helper_dmt(t0);
26244 gen_store_gpr(t0, rt);
26245 break;
26246 case OPC_EMT:
26247 check_cp0_mt(ctx);
26248 gen_helper_emt(t0);
26249 gen_store_gpr(t0, rt);
26250 break;
26251 case OPC_DVPE:
26252 check_cp0_mt(ctx);
26253 gen_helper_dvpe(t0, cpu_env);
26254 gen_store_gpr(t0, rt);
26255 break;
26256 case OPC_EVPE:
26257 check_cp0_mt(ctx);
26258 gen_helper_evpe(t0, cpu_env);
26259 gen_store_gpr(t0, rt);
26260 break;
26261 case OPC_DVP:
26262 check_insn(ctx, ISA_MIPS32R6);
26263 if (ctx->vp) {
26264 gen_helper_dvp(t0, cpu_env);
26265 gen_store_gpr(t0, rt);
26267 break;
26268 case OPC_EVP:
26269 check_insn(ctx, ISA_MIPS32R6);
26270 if (ctx->vp) {
26271 gen_helper_evp(t0, cpu_env);
26272 gen_store_gpr(t0, rt);
26274 break;
26275 case OPC_DI:
26276 check_insn(ctx, ISA_MIPS32R2);
26277 save_cpu_state(ctx, 1);
26278 gen_helper_di(t0, cpu_env);
26279 gen_store_gpr(t0, rt);
26280 /* Stop translation as we may have switched
26281 the execution mode. */
26282 ctx->base.is_jmp = DISAS_STOP;
26283 break;
26284 case OPC_EI:
26285 check_insn(ctx, ISA_MIPS32R2);
26286 save_cpu_state(ctx, 1);
26287 gen_helper_ei(t0, cpu_env);
26288 gen_store_gpr(t0, rt);
26289 /* DISAS_STOP isn't sufficient, we need to ensure we break
26290 out of translated code to check for pending interrupts */
26291 gen_save_pc(ctx->base.pc_next + 4);
26292 ctx->base.is_jmp = DISAS_EXIT;
26293 break;
26294 default: /* Invalid */
26295 MIPS_INVAL("mfmc0");
26296 generate_exception_end(ctx, EXCP_RI);
26297 break;
26299 tcg_temp_free(t0);
26301 #endif /* !CONFIG_USER_ONLY */
26302 break;
26303 case OPC_RDPGPR:
26304 check_insn(ctx, ISA_MIPS32R2);
26305 gen_load_srsgpr(rt, rd);
26306 break;
26307 case OPC_WRPGPR:
26308 check_insn(ctx, ISA_MIPS32R2);
26309 gen_store_srsgpr(rt, rd);
26310 break;
26311 default:
26312 MIPS_INVAL("cp0");
26313 generate_exception_end(ctx, EXCP_RI);
26314 break;
26316 break;
26317 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
26318 if (ctx->insn_flags & ISA_MIPS32R6) {
26319 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
26320 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26321 } else {
26322 /* OPC_ADDI */
26323 /* Arithmetic with immediate opcode */
26324 gen_arith_imm(ctx, op, rt, rs, imm);
26326 break;
26327 case OPC_ADDIU:
26328 gen_arith_imm(ctx, op, rt, rs, imm);
26329 break;
26330 case OPC_SLTI: /* Set on less than with immediate opcode */
26331 case OPC_SLTIU:
26332 gen_slt_imm(ctx, op, rt, rs, imm);
26333 break;
26334 case OPC_ANDI: /* Arithmetic with immediate opcode */
26335 case OPC_LUI: /* OPC_AUI */
26336 case OPC_ORI:
26337 case OPC_XORI:
26338 gen_logic_imm(ctx, op, rt, rs, imm);
26339 break;
26340 case OPC_J: /* Jump */
26341 case OPC_JAL:
26342 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26343 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26344 break;
26345 /* Branch */
26346 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
26347 if (ctx->insn_flags & ISA_MIPS32R6) {
26348 if (rt == 0) {
26349 generate_exception_end(ctx, EXCP_RI);
26350 break;
26352 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
26353 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26354 } else {
26355 /* OPC_BLEZL */
26356 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26358 break;
26359 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
26360 if (ctx->insn_flags & ISA_MIPS32R6) {
26361 if (rt == 0) {
26362 generate_exception_end(ctx, EXCP_RI);
26363 break;
26365 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
26366 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26367 } else {
26368 /* OPC_BGTZL */
26369 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26371 break;
26372 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
26373 if (rt == 0) {
26374 /* OPC_BLEZ */
26375 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26376 } else {
26377 check_insn(ctx, ISA_MIPS32R6);
26378 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
26379 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26381 break;
26382 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
26383 if (rt == 0) {
26384 /* OPC_BGTZ */
26385 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26386 } else {
26387 check_insn(ctx, ISA_MIPS32R6);
26388 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
26389 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26391 break;
26392 case OPC_BEQL:
26393 case OPC_BNEL:
26394 check_insn(ctx, ISA_MIPS2);
26395 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26396 /* Fallthrough */
26397 case OPC_BEQ:
26398 case OPC_BNE:
26399 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26400 break;
26401 case OPC_LL: /* Load and stores */
26402 check_insn(ctx, ISA_MIPS2);
26403 check_insn_opc_user_only(ctx, INSN_R5900);
26404 /* Fallthrough */
26405 case OPC_LWL:
26406 case OPC_LWR:
26407 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26408 /* Fallthrough */
26409 case OPC_LB:
26410 case OPC_LH:
26411 case OPC_LW:
26412 case OPC_LWPC:
26413 case OPC_LBU:
26414 case OPC_LHU:
26415 gen_ld(ctx, op, rt, rs, imm);
26416 break;
26417 case OPC_SWL:
26418 case OPC_SWR:
26419 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26420 /* fall through */
26421 case OPC_SB:
26422 case OPC_SH:
26423 case OPC_SW:
26424 gen_st(ctx, op, rt, rs, imm);
26425 break;
26426 case OPC_SC:
26427 check_insn(ctx, ISA_MIPS2);
26428 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26429 check_insn_opc_user_only(ctx, INSN_R5900);
26430 gen_st_cond(ctx, op, rt, rs, imm);
26431 break;
26432 case OPC_CACHE:
26433 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26434 check_cp0_enabled(ctx);
26435 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
26436 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26437 gen_cache_operation(ctx, rt, rs, imm);
26439 /* Treat as NOP. */
26440 break;
26441 case OPC_PREF:
26442 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26443 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
26444 INSN_R5900);
26445 /* Treat as NOP. */
26446 break;
26448 /* Floating point (COP1). */
26449 case OPC_LWC1:
26450 case OPC_LDC1:
26451 case OPC_SWC1:
26452 case OPC_SDC1:
26453 gen_cop1_ldst(ctx, op, rt, rs, imm);
26454 break;
26456 case OPC_CP1:
26457 op1 = MASK_CP1(ctx->opcode);
26459 switch (op1) {
26460 case OPC_MFHC1:
26461 case OPC_MTHC1:
26462 check_cp1_enabled(ctx);
26463 check_insn(ctx, ISA_MIPS32R2);
26464 /* fall through */
26465 case OPC_MFC1:
26466 case OPC_CFC1:
26467 case OPC_MTC1:
26468 case OPC_CTC1:
26469 check_cp1_enabled(ctx);
26470 gen_cp1(ctx, op1, rt, rd);
26471 break;
26472 #if defined(TARGET_MIPS64)
26473 case OPC_DMFC1:
26474 case OPC_DMTC1:
26475 check_cp1_enabled(ctx);
26476 check_insn(ctx, ISA_MIPS3);
26477 check_mips_64(ctx);
26478 gen_cp1(ctx, op1, rt, rd);
26479 break;
26480 #endif
26481 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
26482 check_cp1_enabled(ctx);
26483 if (ctx->insn_flags & ISA_MIPS32R6) {
26484 /* OPC_BC1EQZ */
26485 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26486 rt, imm << 2, 4);
26487 } else {
26488 /* OPC_BC1ANY2 */
26489 check_cop1x(ctx);
26490 check_insn(ctx, ASE_MIPS3D);
26491 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26492 (rt >> 2) & 0x7, imm << 2);
26494 break;
26495 case OPC_BC1NEZ:
26496 check_cp1_enabled(ctx);
26497 check_insn(ctx, ISA_MIPS32R6);
26498 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26499 rt, imm << 2, 4);
26500 break;
26501 case OPC_BC1ANY4:
26502 check_cp1_enabled(ctx);
26503 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26504 check_cop1x(ctx);
26505 check_insn(ctx, ASE_MIPS3D);
26506 /* fall through */
26507 case OPC_BC1:
26508 check_cp1_enabled(ctx);
26509 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26510 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26511 (rt >> 2) & 0x7, imm << 2);
26512 break;
26513 case OPC_PS_FMT:
26514 check_ps(ctx);
26515 /* fall through */
26516 case OPC_S_FMT:
26517 case OPC_D_FMT:
26518 check_cp1_enabled(ctx);
26519 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26520 (imm >> 8) & 0x7);
26521 break;
26522 case OPC_W_FMT:
26523 case OPC_L_FMT:
26525 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
26526 check_cp1_enabled(ctx);
26527 if (ctx->insn_flags & ISA_MIPS32R6) {
26528 switch (r6_op) {
26529 case R6_OPC_CMP_AF_S:
26530 case R6_OPC_CMP_UN_S:
26531 case R6_OPC_CMP_EQ_S:
26532 case R6_OPC_CMP_UEQ_S:
26533 case R6_OPC_CMP_LT_S:
26534 case R6_OPC_CMP_ULT_S:
26535 case R6_OPC_CMP_LE_S:
26536 case R6_OPC_CMP_ULE_S:
26537 case R6_OPC_CMP_SAF_S:
26538 case R6_OPC_CMP_SUN_S:
26539 case R6_OPC_CMP_SEQ_S:
26540 case R6_OPC_CMP_SEUQ_S:
26541 case R6_OPC_CMP_SLT_S:
26542 case R6_OPC_CMP_SULT_S:
26543 case R6_OPC_CMP_SLE_S:
26544 case R6_OPC_CMP_SULE_S:
26545 case R6_OPC_CMP_OR_S:
26546 case R6_OPC_CMP_UNE_S:
26547 case R6_OPC_CMP_NE_S:
26548 case R6_OPC_CMP_SOR_S:
26549 case R6_OPC_CMP_SUNE_S:
26550 case R6_OPC_CMP_SNE_S:
26551 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26552 break;
26553 case R6_OPC_CMP_AF_D:
26554 case R6_OPC_CMP_UN_D:
26555 case R6_OPC_CMP_EQ_D:
26556 case R6_OPC_CMP_UEQ_D:
26557 case R6_OPC_CMP_LT_D:
26558 case R6_OPC_CMP_ULT_D:
26559 case R6_OPC_CMP_LE_D:
26560 case R6_OPC_CMP_ULE_D:
26561 case R6_OPC_CMP_SAF_D:
26562 case R6_OPC_CMP_SUN_D:
26563 case R6_OPC_CMP_SEQ_D:
26564 case R6_OPC_CMP_SEUQ_D:
26565 case R6_OPC_CMP_SLT_D:
26566 case R6_OPC_CMP_SULT_D:
26567 case R6_OPC_CMP_SLE_D:
26568 case R6_OPC_CMP_SULE_D:
26569 case R6_OPC_CMP_OR_D:
26570 case R6_OPC_CMP_UNE_D:
26571 case R6_OPC_CMP_NE_D:
26572 case R6_OPC_CMP_SOR_D:
26573 case R6_OPC_CMP_SUNE_D:
26574 case R6_OPC_CMP_SNE_D:
26575 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26576 break;
26577 default:
26578 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
26579 rt, rd, sa, (imm >> 8) & 0x7);
26581 break;
26583 } else {
26584 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26585 (imm >> 8) & 0x7);
26587 break;
26589 case OPC_BZ_V:
26590 case OPC_BNZ_V:
26591 case OPC_BZ_B:
26592 case OPC_BZ_H:
26593 case OPC_BZ_W:
26594 case OPC_BZ_D:
26595 case OPC_BNZ_B:
26596 case OPC_BNZ_H:
26597 case OPC_BNZ_W:
26598 case OPC_BNZ_D:
26599 check_insn(ctx, ASE_MSA);
26600 gen_msa_branch(env, ctx, op1);
26601 break;
26602 default:
26603 MIPS_INVAL("cp1");
26604 generate_exception_end(ctx, EXCP_RI);
26605 break;
26607 break;
26609 /* Compact branches [R6] and COP2 [non-R6] */
26610 case OPC_BC: /* OPC_LWC2 */
26611 case OPC_BALC: /* OPC_SWC2 */
26612 if (ctx->insn_flags & ISA_MIPS32R6) {
26613 /* OPC_BC, OPC_BALC */
26614 gen_compute_compact_branch(ctx, op, 0, 0,
26615 sextract32(ctx->opcode << 2, 0, 28));
26616 } else {
26617 /* OPC_LWC2, OPC_SWC2 */
26618 /* COP2: Not implemented. */
26619 generate_exception_err(ctx, EXCP_CpU, 2);
26621 break;
26622 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
26623 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
26624 if (ctx->insn_flags & ISA_MIPS32R6) {
26625 if (rs != 0) {
26626 /* OPC_BEQZC, OPC_BNEZC */
26627 gen_compute_compact_branch(ctx, op, rs, 0,
26628 sextract32(ctx->opcode << 2, 0, 23));
26629 } else {
26630 /* OPC_JIC, OPC_JIALC */
26631 gen_compute_compact_branch(ctx, op, 0, rt, imm);
26633 } else {
26634 /* OPC_LWC2, OPC_SWC2 */
26635 /* COP2: Not implemented. */
26636 generate_exception_err(ctx, EXCP_CpU, 2);
26638 break;
26639 case OPC_CP2:
26640 check_insn(ctx, INSN_LOONGSON2F);
26641 /* Note that these instructions use different fields. */
26642 gen_loongson_multimedia(ctx, sa, rd, rt);
26643 break;
26645 case OPC_CP3:
26646 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26647 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26648 check_cp1_enabled(ctx);
26649 op1 = MASK_CP3(ctx->opcode);
26650 switch (op1) {
26651 case OPC_LUXC1:
26652 case OPC_SUXC1:
26653 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26654 /* Fallthrough */
26655 case OPC_LWXC1:
26656 case OPC_LDXC1:
26657 case OPC_SWXC1:
26658 case OPC_SDXC1:
26659 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26660 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
26661 break;
26662 case OPC_PREFX:
26663 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26664 /* Treat as NOP. */
26665 break;
26666 case OPC_ALNV_PS:
26667 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26668 /* Fallthrough */
26669 case OPC_MADD_S:
26670 case OPC_MADD_D:
26671 case OPC_MADD_PS:
26672 case OPC_MSUB_S:
26673 case OPC_MSUB_D:
26674 case OPC_MSUB_PS:
26675 case OPC_NMADD_S:
26676 case OPC_NMADD_D:
26677 case OPC_NMADD_PS:
26678 case OPC_NMSUB_S:
26679 case OPC_NMSUB_D:
26680 case OPC_NMSUB_PS:
26681 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26682 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
26683 break;
26684 default:
26685 MIPS_INVAL("cp3");
26686 generate_exception_end(ctx, EXCP_RI);
26687 break;
26689 } else {
26690 generate_exception_err(ctx, EXCP_CpU, 1);
26692 break;
26694 #if defined(TARGET_MIPS64)
26695 /* MIPS64 opcodes */
26696 case OPC_LLD:
26697 check_insn_opc_user_only(ctx, INSN_R5900);
26698 /* fall through */
26699 case OPC_LDL:
26700 case OPC_LDR:
26701 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26702 /* fall through */
26703 case OPC_LWU:
26704 case OPC_LD:
26705 check_insn(ctx, ISA_MIPS3);
26706 check_mips_64(ctx);
26707 gen_ld(ctx, op, rt, rs, imm);
26708 break;
26709 case OPC_SDL:
26710 case OPC_SDR:
26711 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26712 /* fall through */
26713 case OPC_SD:
26714 check_insn(ctx, ISA_MIPS3);
26715 check_mips_64(ctx);
26716 gen_st(ctx, op, rt, rs, imm);
26717 break;
26718 case OPC_SCD:
26719 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26720 check_insn(ctx, ISA_MIPS3);
26721 check_insn_opc_user_only(ctx, INSN_R5900);
26722 check_mips_64(ctx);
26723 gen_st_cond(ctx, op, rt, rs, imm);
26724 break;
26725 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
26726 if (ctx->insn_flags & ISA_MIPS32R6) {
26727 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
26728 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26729 } else {
26730 /* OPC_DADDI */
26731 check_insn(ctx, ISA_MIPS3);
26732 check_mips_64(ctx);
26733 gen_arith_imm(ctx, op, rt, rs, imm);
26735 break;
26736 case OPC_DADDIU:
26737 check_insn(ctx, ISA_MIPS3);
26738 check_mips_64(ctx);
26739 gen_arith_imm(ctx, op, rt, rs, imm);
26740 break;
26741 #else
26742 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
26743 if (ctx->insn_flags & ISA_MIPS32R6) {
26744 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26745 } else {
26746 MIPS_INVAL("major opcode");
26747 generate_exception_end(ctx, EXCP_RI);
26749 break;
26750 #endif
26751 case OPC_DAUI: /* OPC_JALX */
26752 if (ctx->insn_flags & ISA_MIPS32R6) {
26753 #if defined(TARGET_MIPS64)
26754 /* OPC_DAUI */
26755 check_mips_64(ctx);
26756 if (rs == 0) {
26757 generate_exception(ctx, EXCP_RI);
26758 } else if (rt != 0) {
26759 TCGv t0 = tcg_temp_new();
26760 gen_load_gpr(t0, rs);
26761 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
26762 tcg_temp_free(t0);
26764 #else
26765 generate_exception_end(ctx, EXCP_RI);
26766 MIPS_INVAL("major opcode");
26767 #endif
26768 } else {
26769 /* OPC_JALX */
26770 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26771 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26772 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26774 break;
26775 case OPC_MSA: /* OPC_MDMX */
26776 if (ctx->insn_flags & INSN_R5900) {
26777 decode_tx79_lq(env, ctx); /* TX79_LQ */
26778 } else {
26779 /* MDMX: Not implemented. */
26780 gen_msa(env, ctx);
26782 break;
26783 case OPC_PCREL:
26784 check_insn(ctx, ISA_MIPS32R6);
26785 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
26786 break;
26787 default: /* Invalid */
26788 MIPS_INVAL("major opcode");
26789 generate_exception_end(ctx, EXCP_RI);
26790 break;
26794 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
26796 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26797 CPUMIPSState *env = cs->env_ptr;
26799 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
26800 ctx->saved_pc = -1;
26801 ctx->insn_flags = env->insn_flags;
26802 ctx->CP0_Config1 = env->CP0_Config1;
26803 ctx->CP0_Config2 = env->CP0_Config2;
26804 ctx->CP0_Config3 = env->CP0_Config3;
26805 ctx->CP0_Config5 = env->CP0_Config5;
26806 ctx->btarget = 0;
26807 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26808 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26809 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26810 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26811 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26812 ctx->PAMask = env->PAMask;
26813 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26814 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26815 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26816 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26817 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
26818 /* Restore delay slot state from the tb context. */
26819 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26820 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26821 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
26822 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
26823 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26824 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26825 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26826 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26827 restore_cpu_state(env, ctx);
26828 #ifdef CONFIG_USER_ONLY
26829 ctx->mem_idx = MIPS_HFLAG_UM;
26830 #else
26831 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
26832 #endif
26833 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
26834 MO_UNALN : MO_ALIGN;
26836 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26837 ctx->hflags);
26840 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26844 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26846 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26848 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26849 ctx->btarget);
26852 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26853 const CPUBreakpoint *bp)
26855 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26857 save_cpu_state(ctx, 1);
26858 ctx->base.is_jmp = DISAS_NORETURN;
26859 gen_helper_raise_exception_debug(cpu_env);
26860 /* The address covered by the breakpoint must be included in
26861 [tb->pc, tb->pc + tb->size) in order to for it to be
26862 properly cleared -- thus we increment the PC here so that
26863 the logic setting tb->size below does the right thing. */
26864 ctx->base.pc_next += 4;
26865 return true;
26868 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26870 CPUMIPSState *env = cs->env_ptr;
26871 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26872 int insn_bytes;
26873 int is_slot;
26875 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26876 if (ctx->insn_flags & ISA_NANOMIPS32) {
26877 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26878 insn_bytes = decode_nanomips_opc(env, ctx);
26879 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26880 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
26881 insn_bytes = 4;
26882 decode_opc(env, ctx);
26883 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26884 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26885 insn_bytes = decode_micromips_opc(env, ctx);
26886 } else if (ctx->insn_flags & ASE_MIPS16) {
26887 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26888 insn_bytes = decode_mips16_opc(env, ctx);
26889 } else {
26890 generate_exception_end(ctx, EXCP_RI);
26891 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26892 return;
26895 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26896 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26897 MIPS_HFLAG_FBNSLOT))) {
26898 /* force to generate branch as there is neither delay nor
26899 forbidden slot */
26900 is_slot = 1;
26902 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26903 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26904 /* Force to generate branch as microMIPS R6 doesn't restrict
26905 branches in the forbidden slot. */
26906 is_slot = 1;
26909 if (is_slot) {
26910 gen_branch(ctx, insn_bytes);
26912 ctx->base.pc_next += insn_bytes;
26914 if (ctx->base.is_jmp != DISAS_NEXT) {
26915 return;
26917 /* Execute a branch and its delay slot as a single instruction.
26918 This is what GDB expects and is consistent with what the
26919 hardware does (e.g. if a delay slot instruction faults, the
26920 reported PC is the PC of the branch). */
26921 if (ctx->base.singlestep_enabled &&
26922 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26923 ctx->base.is_jmp = DISAS_TOO_MANY;
26925 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26926 ctx->base.is_jmp = DISAS_TOO_MANY;
26930 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26932 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26934 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26935 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26936 gen_helper_raise_exception_debug(cpu_env);
26937 } else {
26938 switch (ctx->base.is_jmp) {
26939 case DISAS_STOP:
26940 gen_save_pc(ctx->base.pc_next);
26941 tcg_gen_lookup_and_goto_ptr();
26942 break;
26943 case DISAS_NEXT:
26944 case DISAS_TOO_MANY:
26945 save_cpu_state(ctx, 0);
26946 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26947 break;
26948 case DISAS_EXIT:
26949 tcg_gen_exit_tb(NULL, 0);
26950 break;
26951 case DISAS_NORETURN:
26952 break;
26953 default:
26954 g_assert_not_reached();
26959 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26961 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26962 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26965 static const TranslatorOps mips_tr_ops = {
26966 .init_disas_context = mips_tr_init_disas_context,
26967 .tb_start = mips_tr_tb_start,
26968 .insn_start = mips_tr_insn_start,
26969 .breakpoint_check = mips_tr_breakpoint_check,
26970 .translate_insn = mips_tr_translate_insn,
26971 .tb_stop = mips_tr_tb_stop,
26972 .disas_log = mips_tr_disas_log,
26975 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
26977 DisasContext ctx;
26979 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
26982 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
26983 int flags)
26985 int i;
26986 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26988 #define printfpr(fp) \
26989 do { \
26990 if (is_fpu64) \
26991 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26992 " fd:%13g fs:%13g psu: %13g\n", \
26993 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26994 (double)(fp)->fd, \
26995 (double)(fp)->fs[FP_ENDIAN_IDX], \
26996 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26997 else { \
26998 fpr_t tmp; \
26999 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
27000 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
27001 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
27002 " fd:%13g fs:%13g psu:%13g\n", \
27003 tmp.w[FP_ENDIAN_IDX], tmp.d, \
27004 (double)tmp.fd, \
27005 (double)tmp.fs[FP_ENDIAN_IDX], \
27006 (double)tmp.fs[!FP_ENDIAN_IDX]); \
27008 } while(0)
27011 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
27012 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
27013 get_float_exception_flags(&env->active_fpu.fp_status));
27014 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
27015 fpu_fprintf(f, "%3s: ", fregnames[i]);
27016 printfpr(&env->active_fpu.fpr[i]);
27019 #undef printfpr
27022 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
27023 int flags)
27025 MIPSCPU *cpu = MIPS_CPU(cs);
27026 CPUMIPSState *env = &cpu->env;
27027 int i;
27029 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
27030 " LO=0x" TARGET_FMT_lx " ds %04x "
27031 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
27032 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
27033 env->hflags, env->btarget, env->bcond);
27034 for (i = 0; i < 32; i++) {
27035 if ((i & 3) == 0)
27036 cpu_fprintf(f, "GPR%02d:", i);
27037 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
27038 if ((i & 3) == 3)
27039 cpu_fprintf(f, "\n");
27042 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
27043 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
27044 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
27045 PRIx64 "\n",
27046 env->CP0_Config0, env->CP0_Config1, env->lladdr);
27047 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
27048 env->CP0_Config2, env->CP0_Config3);
27049 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
27050 env->CP0_Config4, env->CP0_Config5);
27051 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
27052 fpu_dump_state(env, f, cpu_fprintf, flags);
27056 void mips_tcg_init(void)
27058 int i;
27060 cpu_gpr[0] = NULL;
27061 for (i = 1; i < 32; i++)
27062 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
27063 offsetof(CPUMIPSState, active_tc.gpr[i]),
27064 regnames[i]);
27066 for (i = 0; i < 32; i++) {
27067 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
27068 msa_wr_d[i * 2] =
27069 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
27070 /* The scalar floating-point unit (FPU) registers are mapped on
27071 * the MSA vector registers. */
27072 fpu_f64[i] = msa_wr_d[i * 2];
27073 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
27074 msa_wr_d[i * 2 + 1] =
27075 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
27078 cpu_PC = tcg_global_mem_new(cpu_env,
27079 offsetof(CPUMIPSState, active_tc.PC), "PC");
27080 for (i = 0; i < MIPS_DSP_ACC; i++) {
27081 cpu_HI[i] = tcg_global_mem_new(cpu_env,
27082 offsetof(CPUMIPSState, active_tc.HI[i]),
27083 regnames_HI[i]);
27084 cpu_LO[i] = tcg_global_mem_new(cpu_env,
27085 offsetof(CPUMIPSState, active_tc.LO[i]),
27086 regnames_LO[i]);
27088 cpu_dspctrl = tcg_global_mem_new(cpu_env,
27089 offsetof(CPUMIPSState, active_tc.DSPControl),
27090 "DSPControl");
27091 bcond = tcg_global_mem_new(cpu_env,
27092 offsetof(CPUMIPSState, bcond), "bcond");
27093 btarget = tcg_global_mem_new(cpu_env,
27094 offsetof(CPUMIPSState, btarget), "btarget");
27095 hflags = tcg_global_mem_new_i32(cpu_env,
27096 offsetof(CPUMIPSState, hflags), "hflags");
27098 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
27099 offsetof(CPUMIPSState, active_fpu.fcr0),
27100 "fcr0");
27101 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
27102 offsetof(CPUMIPSState, active_fpu.fcr31),
27103 "fcr31");
27106 #include "translate_init.inc.c"
27108 void cpu_mips_realize_env(CPUMIPSState *env)
27110 env->exception_base = (int32_t)0xBFC00000;
27112 #ifndef CONFIG_USER_ONLY
27113 mmu_init(env, env->cpu_model);
27114 #endif
27115 fpu_init(env, env->cpu_model);
27116 mvp_init(env, env->cpu_model);
27119 bool cpu_supports_cps_smp(const char *cpu_type)
27121 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27122 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
27125 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
27127 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27128 return (mcc->cpu_def->insn_flags & isa) != 0;
27131 void cpu_set_exception_base(int vp_index, target_ulong address)
27133 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
27134 vp->env.exception_base = address;
27137 void cpu_state_reset(CPUMIPSState *env)
27139 MIPSCPU *cpu = mips_env_get_cpu(env);
27140 CPUState *cs = CPU(cpu);
27142 /* Reset registers to their default values */
27143 env->CP0_PRid = env->cpu_model->CP0_PRid;
27144 env->CP0_Config0 = env->cpu_model->CP0_Config0;
27145 #ifdef TARGET_WORDS_BIGENDIAN
27146 env->CP0_Config0 |= (1 << CP0C0_BE);
27147 #endif
27148 env->CP0_Config1 = env->cpu_model->CP0_Config1;
27149 env->CP0_Config2 = env->cpu_model->CP0_Config2;
27150 env->CP0_Config3 = env->cpu_model->CP0_Config3;
27151 env->CP0_Config4 = env->cpu_model->CP0_Config4;
27152 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
27153 env->CP0_Config5 = env->cpu_model->CP0_Config5;
27154 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
27155 env->CP0_Config6 = env->cpu_model->CP0_Config6;
27156 env->CP0_Config7 = env->cpu_model->CP0_Config7;
27157 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
27158 << env->cpu_model->CP0_LLAddr_shift;
27159 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
27160 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
27161 env->CCRes = env->cpu_model->CCRes;
27162 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
27163 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
27164 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
27165 env->current_tc = 0;
27166 env->SEGBITS = env->cpu_model->SEGBITS;
27167 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
27168 #if defined(TARGET_MIPS64)
27169 if (env->cpu_model->insn_flags & ISA_MIPS3) {
27170 env->SEGMask |= 3ULL << 62;
27172 #endif
27173 env->PABITS = env->cpu_model->PABITS;
27174 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
27175 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
27176 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
27177 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
27178 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
27179 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
27180 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
27181 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
27182 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
27183 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
27184 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
27185 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
27186 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
27187 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
27188 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
27189 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
27190 env->msair = env->cpu_model->MSAIR;
27191 env->insn_flags = env->cpu_model->insn_flags;
27193 #if defined(CONFIG_USER_ONLY)
27194 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
27195 # ifdef TARGET_MIPS64
27196 /* Enable 64-bit register mode. */
27197 env->CP0_Status |= (1 << CP0St_PX);
27198 # endif
27199 # ifdef TARGET_ABI_MIPSN64
27200 /* Enable 64-bit address mode. */
27201 env->CP0_Status |= (1 << CP0St_UX);
27202 # endif
27203 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
27204 hardware registers. */
27205 env->CP0_HWREna |= 0x0000000F;
27206 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
27207 env->CP0_Status |= (1 << CP0St_CU1);
27209 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
27210 env->CP0_Status |= (1 << CP0St_MX);
27212 # if defined(TARGET_MIPS64)
27213 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
27214 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
27215 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
27216 env->CP0_Status |= (1 << CP0St_FR);
27218 # endif
27219 #else
27220 if (env->hflags & MIPS_HFLAG_BMASK) {
27221 /* If the exception was raised from a delay slot,
27222 come back to the jump. */
27223 env->CP0_ErrorEPC = (env->active_tc.PC
27224 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
27225 } else {
27226 env->CP0_ErrorEPC = env->active_tc.PC;
27228 env->active_tc.PC = env->exception_base;
27229 env->CP0_Random = env->tlb->nb_tlb - 1;
27230 env->tlb->tlb_in_use = env->tlb->nb_tlb;
27231 env->CP0_Wired = 0;
27232 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
27233 env->CP0_EBase = (cs->cpu_index & 0x3FF);
27234 if (mips_um_ksegs_enabled()) {
27235 env->CP0_EBase |= 0x40000000;
27236 } else {
27237 env->CP0_EBase |= (int32_t)0x80000000;
27239 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
27240 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
27242 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
27243 0x3ff : 0xff;
27244 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
27245 /* vectored interrupts not implemented, timer on int 7,
27246 no performance counters. */
27247 env->CP0_IntCtl = 0xe0000000;
27249 int i;
27251 for (i = 0; i < 7; i++) {
27252 env->CP0_WatchLo[i] = 0;
27253 env->CP0_WatchHi[i] = 0x80000000;
27255 env->CP0_WatchLo[7] = 0;
27256 env->CP0_WatchHi[7] = 0;
27258 /* Count register increments in debug mode, EJTAG version 1 */
27259 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
27261 cpu_mips_store_count(env, 1);
27263 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
27264 int i;
27266 /* Only TC0 on VPE 0 starts as active. */
27267 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
27268 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
27269 env->tcs[i].CP0_TCHalt = 1;
27271 env->active_tc.CP0_TCHalt = 1;
27272 cs->halted = 1;
27274 if (cs->cpu_index == 0) {
27275 /* VPE0 starts up enabled. */
27276 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
27277 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
27279 /* TC0 starts up unhalted. */
27280 cs->halted = 0;
27281 env->active_tc.CP0_TCHalt = 0;
27282 env->tcs[0].CP0_TCHalt = 0;
27283 /* With thread 0 active. */
27284 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
27285 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
27290 * Configure default legacy segmentation control. We use this regardless of
27291 * whether segmentation control is presented to the guest.
27293 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
27294 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
27295 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
27296 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
27297 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
27298 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27299 (2 << CP0SC_C);
27300 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
27301 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27302 (3 << CP0SC_C)) << 16;
27303 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
27304 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27305 (1 << CP0SC_EU) | (2 << CP0SC_C);
27306 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
27307 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27308 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
27309 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
27310 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
27311 #endif
27312 if ((env->insn_flags & ISA_MIPS32R6) &&
27313 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
27314 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
27315 env->CP0_Status |= (1 << CP0St_FR);
27318 if (env->insn_flags & ISA_MIPS32R6) {
27319 /* PTW = 1 */
27320 env->CP0_PWSize = 0x40;
27321 /* GDI = 12 */
27322 /* UDI = 12 */
27323 /* MDI = 12 */
27324 /* PRI = 12 */
27325 /* PTEI = 2 */
27326 env->CP0_PWField = 0x0C30C302;
27327 } else {
27328 /* GDI = 0 */
27329 /* UDI = 0 */
27330 /* MDI = 0 */
27331 /* PRI = 0 */
27332 /* PTEI = 2 */
27333 env->CP0_PWField = 0x02;
27336 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
27337 /* microMIPS on reset when Config3.ISA is 3 */
27338 env->hflags |= MIPS_HFLAG_M16;
27341 /* MSA */
27342 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
27343 msa_reset(env);
27346 compute_hflags(env);
27347 restore_fp_status(env);
27348 restore_pamask(env);
27349 cs->exception_index = EXCP_NONE;
27351 if (semihosting_get_argc()) {
27352 /* UHI interface can be used to obtain argc and argv */
27353 env->active_tc.gpr[4] = -1;
27357 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
27358 target_ulong *data)
27360 env->active_tc.PC = data[0];
27361 env->hflags &= ~MIPS_HFLAG_BMASK;
27362 env->hflags |= data[1];
27363 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
27364 case MIPS_HFLAG_BR:
27365 break;
27366 case MIPS_HFLAG_BC:
27367 case MIPS_HFLAG_BL:
27368 case MIPS_HFLAG_B:
27369 env->btarget = data[2];
27370 break;