target/mips: Support R5900 DIV1 and DIVU1 instructions
[qemu/ar7.git] / target / mips / translate.c
blobf2aeaf4b6e9076ac34adf43169d94c93f786e4ee
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "qemu/osdep.h"
25 #include "cpu.h"
26 #include "internal.h"
27 #include "disas/disas.h"
28 #include "exec/exec-all.h"
29 #include "tcg-op.h"
30 #include "exec/cpu_ldst.h"
31 #include "hw/mips/cpudevs.h"
33 #include "exec/helper-proto.h"
34 #include "exec/helper-gen.h"
35 #include "exec/semihost.h"
37 #include "target/mips/trace.h"
38 #include "trace-tcg.h"
39 #include "exec/translator.h"
40 #include "exec/log.h"
42 #define MIPS_DEBUG_DISAS 0
44 /* MIPS major opcodes */
45 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
47 enum {
48 /* indirect opcode tables */
49 OPC_SPECIAL = (0x00 << 26),
50 OPC_REGIMM = (0x01 << 26),
51 OPC_CP0 = (0x10 << 26),
52 OPC_CP1 = (0x11 << 26),
53 OPC_CP2 = (0x12 << 26),
54 OPC_CP3 = (0x13 << 26),
55 OPC_SPECIAL2 = (0x1C << 26),
56 OPC_SPECIAL3 = (0x1F << 26),
57 /* arithmetic with immediate */
58 OPC_ADDI = (0x08 << 26),
59 OPC_ADDIU = (0x09 << 26),
60 OPC_SLTI = (0x0A << 26),
61 OPC_SLTIU = (0x0B << 26),
62 /* logic with immediate */
63 OPC_ANDI = (0x0C << 26),
64 OPC_ORI = (0x0D << 26),
65 OPC_XORI = (0x0E << 26),
66 OPC_LUI = (0x0F << 26),
67 /* arithmetic with immediate */
68 OPC_DADDI = (0x18 << 26),
69 OPC_DADDIU = (0x19 << 26),
70 /* Jump and branches */
71 OPC_J = (0x02 << 26),
72 OPC_JAL = (0x03 << 26),
73 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
74 OPC_BEQL = (0x14 << 26),
75 OPC_BNE = (0x05 << 26),
76 OPC_BNEL = (0x15 << 26),
77 OPC_BLEZ = (0x06 << 26),
78 OPC_BLEZL = (0x16 << 26),
79 OPC_BGTZ = (0x07 << 26),
80 OPC_BGTZL = (0x17 << 26),
81 OPC_JALX = (0x1D << 26),
82 OPC_DAUI = (0x1D << 26),
83 /* Load and stores */
84 OPC_LDL = (0x1A << 26),
85 OPC_LDR = (0x1B << 26),
86 OPC_LB = (0x20 << 26),
87 OPC_LH = (0x21 << 26),
88 OPC_LWL = (0x22 << 26),
89 OPC_LW = (0x23 << 26),
90 OPC_LWPC = OPC_LW | 0x5,
91 OPC_LBU = (0x24 << 26),
92 OPC_LHU = (0x25 << 26),
93 OPC_LWR = (0x26 << 26),
94 OPC_LWU = (0x27 << 26),
95 OPC_SB = (0x28 << 26),
96 OPC_SH = (0x29 << 26),
97 OPC_SWL = (0x2A << 26),
98 OPC_SW = (0x2B << 26),
99 OPC_SDL = (0x2C << 26),
100 OPC_SDR = (0x2D << 26),
101 OPC_SWR = (0x2E << 26),
102 OPC_LL = (0x30 << 26),
103 OPC_LLD = (0x34 << 26),
104 OPC_LD = (0x37 << 26),
105 OPC_LDPC = OPC_LD | 0x5,
106 OPC_SC = (0x38 << 26),
107 OPC_SCD = (0x3C << 26),
108 OPC_SD = (0x3F << 26),
109 /* Floating point load/store */
110 OPC_LWC1 = (0x31 << 26),
111 OPC_LWC2 = (0x32 << 26),
112 OPC_LDC1 = (0x35 << 26),
113 OPC_LDC2 = (0x36 << 26),
114 OPC_SWC1 = (0x39 << 26),
115 OPC_SWC2 = (0x3A << 26),
116 OPC_SDC1 = (0x3D << 26),
117 OPC_SDC2 = (0x3E << 26),
118 /* Compact Branches */
119 OPC_BLEZALC = (0x06 << 26),
120 OPC_BGEZALC = (0x06 << 26),
121 OPC_BGEUC = (0x06 << 26),
122 OPC_BGTZALC = (0x07 << 26),
123 OPC_BLTZALC = (0x07 << 26),
124 OPC_BLTUC = (0x07 << 26),
125 OPC_BOVC = (0x08 << 26),
126 OPC_BEQZALC = (0x08 << 26),
127 OPC_BEQC = (0x08 << 26),
128 OPC_BLEZC = (0x16 << 26),
129 OPC_BGEZC = (0x16 << 26),
130 OPC_BGEC = (0x16 << 26),
131 OPC_BGTZC = (0x17 << 26),
132 OPC_BLTZC = (0x17 << 26),
133 OPC_BLTC = (0x17 << 26),
134 OPC_BNVC = (0x18 << 26),
135 OPC_BNEZALC = (0x18 << 26),
136 OPC_BNEC = (0x18 << 26),
137 OPC_BC = (0x32 << 26),
138 OPC_BEQZC = (0x36 << 26),
139 OPC_JIC = (0x36 << 26),
140 OPC_BALC = (0x3A << 26),
141 OPC_BNEZC = (0x3E << 26),
142 OPC_JIALC = (0x3E << 26),
143 /* MDMX ASE specific */
144 OPC_MDMX = (0x1E << 26),
145 /* MSA ASE, same as MDMX */
146 OPC_MSA = OPC_MDMX,
147 /* Cache and prefetch */
148 OPC_CACHE = (0x2F << 26),
149 OPC_PREF = (0x33 << 26),
150 /* PC-relative address computation / loads */
151 OPC_PCREL = (0x3B << 26),
154 /* PC-relative address computation / loads */
155 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
156 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
157 enum {
158 /* Instructions determined by bits 19 and 20 */
159 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
160 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
161 OPC_LWUPC = OPC_PCREL | (2 << 19),
163 /* Instructions determined by bits 16 ... 20 */
164 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
165 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
167 /* Other */
168 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 /* MIPS special opcodes */
172 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
174 enum {
175 /* Shifts */
176 OPC_SLL = 0x00 | OPC_SPECIAL,
177 /* NOP is SLL r0, r0, 0 */
178 /* SSNOP is SLL r0, r0, 1 */
179 /* EHB is SLL r0, r0, 3 */
180 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
181 OPC_ROTR = OPC_SRL | (1 << 21),
182 OPC_SRA = 0x03 | OPC_SPECIAL,
183 OPC_SLLV = 0x04 | OPC_SPECIAL,
184 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
185 OPC_ROTRV = OPC_SRLV | (1 << 6),
186 OPC_SRAV = 0x07 | OPC_SPECIAL,
187 OPC_DSLLV = 0x14 | OPC_SPECIAL,
188 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
189 OPC_DROTRV = OPC_DSRLV | (1 << 6),
190 OPC_DSRAV = 0x17 | OPC_SPECIAL,
191 OPC_DSLL = 0x38 | OPC_SPECIAL,
192 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
193 OPC_DROTR = OPC_DSRL | (1 << 21),
194 OPC_DSRA = 0x3B | OPC_SPECIAL,
195 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
196 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
197 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
198 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
199 /* Multiplication / division */
200 OPC_MULT = 0x18 | OPC_SPECIAL,
201 OPC_MULTU = 0x19 | OPC_SPECIAL,
202 OPC_DIV = 0x1A | OPC_SPECIAL,
203 OPC_DIVU = 0x1B | OPC_SPECIAL,
204 OPC_DMULT = 0x1C | OPC_SPECIAL,
205 OPC_DMULTU = 0x1D | OPC_SPECIAL,
206 OPC_DDIV = 0x1E | OPC_SPECIAL,
207 OPC_DDIVU = 0x1F | OPC_SPECIAL,
209 /* 2 registers arithmetic / logic */
210 OPC_ADD = 0x20 | OPC_SPECIAL,
211 OPC_ADDU = 0x21 | OPC_SPECIAL,
212 OPC_SUB = 0x22 | OPC_SPECIAL,
213 OPC_SUBU = 0x23 | OPC_SPECIAL,
214 OPC_AND = 0x24 | OPC_SPECIAL,
215 OPC_OR = 0x25 | OPC_SPECIAL,
216 OPC_XOR = 0x26 | OPC_SPECIAL,
217 OPC_NOR = 0x27 | OPC_SPECIAL,
218 OPC_SLT = 0x2A | OPC_SPECIAL,
219 OPC_SLTU = 0x2B | OPC_SPECIAL,
220 OPC_DADD = 0x2C | OPC_SPECIAL,
221 OPC_DADDU = 0x2D | OPC_SPECIAL,
222 OPC_DSUB = 0x2E | OPC_SPECIAL,
223 OPC_DSUBU = 0x2F | OPC_SPECIAL,
224 /* Jumps */
225 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
226 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
227 /* Traps */
228 OPC_TGE = 0x30 | OPC_SPECIAL,
229 OPC_TGEU = 0x31 | OPC_SPECIAL,
230 OPC_TLT = 0x32 | OPC_SPECIAL,
231 OPC_TLTU = 0x33 | OPC_SPECIAL,
232 OPC_TEQ = 0x34 | OPC_SPECIAL,
233 OPC_TNE = 0x36 | OPC_SPECIAL,
234 /* HI / LO registers load & stores */
235 OPC_MFHI = 0x10 | OPC_SPECIAL,
236 OPC_MTHI = 0x11 | OPC_SPECIAL,
237 OPC_MFLO = 0x12 | OPC_SPECIAL,
238 OPC_MTLO = 0x13 | OPC_SPECIAL,
239 /* Conditional moves */
240 OPC_MOVZ = 0x0A | OPC_SPECIAL,
241 OPC_MOVN = 0x0B | OPC_SPECIAL,
243 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
244 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
246 OPC_MOVCI = 0x01 | OPC_SPECIAL,
248 /* Special */
249 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
250 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
251 OPC_BREAK = 0x0D | OPC_SPECIAL,
252 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
253 OPC_SYNC = 0x0F | OPC_SPECIAL,
255 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
256 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
257 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
258 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 /* R6 Multiply and Divide instructions have the same Opcode
262 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
263 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
265 enum {
266 R6_OPC_MUL = OPC_MULT | (2 << 6),
267 R6_OPC_MUH = OPC_MULT | (3 << 6),
268 R6_OPC_MULU = OPC_MULTU | (2 << 6),
269 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
270 R6_OPC_DIV = OPC_DIV | (2 << 6),
271 R6_OPC_MOD = OPC_DIV | (3 << 6),
272 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
273 R6_OPC_MODU = OPC_DIVU | (3 << 6),
275 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
276 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
277 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
278 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
279 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
280 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
281 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
282 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
284 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
285 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
286 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
287 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
288 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
290 OPC_LSA = 0x05 | OPC_SPECIAL,
291 OPC_DLSA = 0x15 | OPC_SPECIAL,
294 /* Multiplication variants of the vr54xx. */
295 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
297 enum {
298 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
299 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
300 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
301 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
302 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
303 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
304 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
305 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
306 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
307 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
308 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
309 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
310 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
311 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
314 /* REGIMM (rt field) opcodes */
315 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
317 enum {
318 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
319 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
320 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
321 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
322 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
323 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
324 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
325 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
326 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
327 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
328 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
329 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
330 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
331 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
332 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
333 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
335 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
336 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
339 /* Special2 opcodes */
340 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
342 enum {
343 /* Multiply & xxx operations */
344 OPC_MADD = 0x00 | OPC_SPECIAL2,
345 OPC_MADDU = 0x01 | OPC_SPECIAL2,
346 OPC_MUL = 0x02 | OPC_SPECIAL2,
347 OPC_MSUB = 0x04 | OPC_SPECIAL2,
348 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
349 /* Loongson 2F */
350 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
351 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
352 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
353 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
354 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
355 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
356 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
357 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
358 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
359 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
360 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
361 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
362 /* Misc */
363 OPC_CLZ = 0x20 | OPC_SPECIAL2,
364 OPC_CLO = 0x21 | OPC_SPECIAL2,
365 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
366 OPC_DCLO = 0x25 | OPC_SPECIAL2,
367 /* Special */
368 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
371 /* Special3 opcodes */
372 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
374 enum {
375 OPC_EXT = 0x00 | OPC_SPECIAL3,
376 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
377 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
378 OPC_DEXT = 0x03 | OPC_SPECIAL3,
379 OPC_INS = 0x04 | OPC_SPECIAL3,
380 OPC_DINSM = 0x05 | OPC_SPECIAL3,
381 OPC_DINSU = 0x06 | OPC_SPECIAL3,
382 OPC_DINS = 0x07 | OPC_SPECIAL3,
383 OPC_FORK = 0x08 | OPC_SPECIAL3,
384 OPC_YIELD = 0x09 | OPC_SPECIAL3,
385 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
386 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
387 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* BSHFL opcodes */
460 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
462 enum {
463 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
464 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
465 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
466 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
467 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
468 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
471 /* DBSHFL opcodes */
472 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
474 enum {
475 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
476 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
477 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
478 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
479 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
482 /* MIPS DSP REGIMM opcodes */
483 enum {
484 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
485 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
488 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
489 /* MIPS DSP Load */
490 enum {
491 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
492 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
493 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
494 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
497 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
498 enum {
499 /* MIPS DSP Arithmetic Sub-class */
500 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
515 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
516 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
517 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
518 /* MIPS DSP Multiply Sub-class insns */
519 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
527 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
528 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
529 enum {
530 /* MIPS DSP Arithmetic Sub-class */
531 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
543 /* MIPS DSP Multiply Sub-class insns */
544 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
550 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
551 enum {
552 /* MIPS DSP Arithmetic Sub-class */
553 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
566 /* DSP Bit/Manipulation Sub-class */
567 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
574 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
584 /* DSP Compare-Pick Sub-class */
585 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
602 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
603 enum {
604 /* MIPS DSP GPR-Based Shift Sub-class */
605 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
629 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630 enum {
631 /* MIPS DSP Multiply Sub-class insns */
632 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
646 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
656 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
657 enum {
658 /* DSP Bit/Manipulation Sub-class */
659 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
662 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
663 enum {
664 /* MIPS DSP Append Sub-class */
665 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
666 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
667 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
670 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
671 enum {
672 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
673 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
686 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
687 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
688 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
689 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
692 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
693 enum {
694 /* MIPS DSP Arithmetic Sub-class */
695 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
712 /* DSP Bit/Manipulation Sub-class */
713 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
721 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
722 enum {
723 /* MIPS DSP Multiply Sub-class insns */
724 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
729 /* MIPS DSP Arithmetic Sub-class */
730 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
753 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
754 enum {
755 /* DSP Compare-Pick Sub-class */
756 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
786 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
787 enum {
788 /* DSP Append Sub-class */
789 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
791 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
792 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
795 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
798 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
799 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
821 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
822 enum {
823 /* DSP Bit/Manipulation Sub-class */
824 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
827 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
828 enum {
829 /* MIPS DSP Multiply Sub-class insns */
830 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
858 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
859 enum {
860 /* MIPS DSP GPR-Based Shift Sub-class */
861 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
889 /* Coprocessor 0 (rs field) */
890 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
892 enum {
893 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
894 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
895 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
896 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
897 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
898 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
899 OPC_MFTR = (0x08 << 21) | OPC_CP0,
900 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
901 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
902 OPC_MTTR = (0x0C << 21) | OPC_CP0,
903 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
904 OPC_C0 = (0x10 << 21) | OPC_CP0,
905 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
906 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
907 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
908 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
909 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
910 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
911 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
912 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
913 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
914 OPC_C0_A = (0x1A << 21) | OPC_CP0,
915 OPC_C0_B = (0x1B << 21) | OPC_CP0,
916 OPC_C0_C = (0x1C << 21) | OPC_CP0,
917 OPC_C0_D = (0x1D << 21) | OPC_CP0,
918 OPC_C0_E = (0x1E << 21) | OPC_CP0,
919 OPC_C0_F = (0x1F << 21) | OPC_CP0,
922 /* MFMC0 opcodes */
923 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
925 enum {
926 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
927 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
928 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
929 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
930 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
931 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
932 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
933 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
936 /* Coprocessor 0 (with rs == C0) */
937 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
939 enum {
940 OPC_TLBR = 0x01 | OPC_C0,
941 OPC_TLBWI = 0x02 | OPC_C0,
942 OPC_TLBINV = 0x03 | OPC_C0,
943 OPC_TLBINVF = 0x04 | OPC_C0,
944 OPC_TLBWR = 0x06 | OPC_C0,
945 OPC_TLBP = 0x08 | OPC_C0,
946 OPC_RFE = 0x10 | OPC_C0,
947 OPC_ERET = 0x18 | OPC_C0,
948 OPC_DERET = 0x1F | OPC_C0,
949 OPC_WAIT = 0x20 | OPC_C0,
952 /* Coprocessor 1 (rs field) */
953 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
955 /* Values for the fmt field in FP instructions */
956 enum {
957 /* 0 - 15 are reserved */
958 FMT_S = 16, /* single fp */
959 FMT_D = 17, /* double fp */
960 FMT_E = 18, /* extended fp */
961 FMT_Q = 19, /* quad fp */
962 FMT_W = 20, /* 32-bit fixed */
963 FMT_L = 21, /* 64-bit fixed */
964 FMT_PS = 22, /* paired single fp */
965 /* 23 - 31 are reserved */
968 enum {
969 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
970 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
971 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
972 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
973 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
974 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
975 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
976 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
977 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
978 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
979 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
980 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
981 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
982 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
983 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
984 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
985 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
986 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
987 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
988 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
989 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
990 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
991 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
992 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
993 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
994 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
995 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
996 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
997 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
998 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1001 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
1002 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
1004 enum {
1005 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1006 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1007 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1008 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1011 enum {
1012 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1013 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1016 enum {
1017 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1018 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1021 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1023 enum {
1024 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1025 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1026 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1027 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1028 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1029 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1030 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1031 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1032 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1033 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1034 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1037 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1039 enum {
1040 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1041 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1042 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1043 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1044 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1045 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1046 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1047 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1049 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1050 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1051 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1052 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1053 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1054 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1055 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1056 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1058 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1059 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1060 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1061 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1062 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1063 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1064 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1065 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1067 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1068 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1069 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1070 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1071 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1072 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1073 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1074 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1076 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1077 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1078 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1079 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1080 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1081 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1083 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1084 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1085 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1086 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1087 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1088 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1090 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1091 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1092 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1093 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1094 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1095 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1097 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1098 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1099 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1100 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1101 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1102 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1104 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1105 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1106 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1107 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1108 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1109 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1111 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1112 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1113 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1114 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1115 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1116 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1118 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1119 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1120 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1121 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1122 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1123 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1125 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1126 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1127 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1128 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1129 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1130 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1134 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1136 enum {
1137 OPC_LWXC1 = 0x00 | OPC_CP3,
1138 OPC_LDXC1 = 0x01 | OPC_CP3,
1139 OPC_LUXC1 = 0x05 | OPC_CP3,
1140 OPC_SWXC1 = 0x08 | OPC_CP3,
1141 OPC_SDXC1 = 0x09 | OPC_CP3,
1142 OPC_SUXC1 = 0x0D | OPC_CP3,
1143 OPC_PREFX = 0x0F | OPC_CP3,
1144 OPC_ALNV_PS = 0x1E | OPC_CP3,
1145 OPC_MADD_S = 0x20 | OPC_CP3,
1146 OPC_MADD_D = 0x21 | OPC_CP3,
1147 OPC_MADD_PS = 0x26 | OPC_CP3,
1148 OPC_MSUB_S = 0x28 | OPC_CP3,
1149 OPC_MSUB_D = 0x29 | OPC_CP3,
1150 OPC_MSUB_PS = 0x2E | OPC_CP3,
1151 OPC_NMADD_S = 0x30 | OPC_CP3,
1152 OPC_NMADD_D = 0x31 | OPC_CP3,
1153 OPC_NMADD_PS= 0x36 | OPC_CP3,
1154 OPC_NMSUB_S = 0x38 | OPC_CP3,
1155 OPC_NMSUB_D = 0x39 | OPC_CP3,
1156 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1159 /* MSA Opcodes */
1160 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1161 enum {
1162 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1163 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1164 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1165 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1166 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1167 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1168 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1169 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1170 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1171 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1172 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1173 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1174 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1175 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1176 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1177 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1178 OPC_MSA_ELM = 0x19 | OPC_MSA,
1179 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1180 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1181 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1182 OPC_MSA_VEC = 0x1E | OPC_MSA,
1184 /* MI10 instruction */
1185 OPC_LD_B = (0x20) | OPC_MSA,
1186 OPC_LD_H = (0x21) | OPC_MSA,
1187 OPC_LD_W = (0x22) | OPC_MSA,
1188 OPC_LD_D = (0x23) | OPC_MSA,
1189 OPC_ST_B = (0x24) | OPC_MSA,
1190 OPC_ST_H = (0x25) | OPC_MSA,
1191 OPC_ST_W = (0x26) | OPC_MSA,
1192 OPC_ST_D = (0x27) | OPC_MSA,
1195 enum {
1196 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1197 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1198 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1199 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1200 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1201 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1202 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1203 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1204 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1205 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1206 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1207 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1208 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1210 /* I8 instruction */
1211 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1212 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1213 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1214 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1215 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1216 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1217 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1218 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1219 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1220 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1222 /* VEC/2R/2RF instruction */
1223 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1224 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1225 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1226 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1227 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1228 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1229 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1231 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1232 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1234 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1235 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1236 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1237 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1238 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1240 /* 2RF instruction df(bit 16) = _w, _d */
1241 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1242 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1243 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1244 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1245 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1246 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1247 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1248 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1249 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1250 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1251 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1252 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1253 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1254 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1255 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1256 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1258 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1259 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1260 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1261 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1262 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1263 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1264 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1265 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1266 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1267 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1268 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1269 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1270 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1271 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1272 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1273 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1274 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1275 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1276 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1277 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1278 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1279 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1280 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1281 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1282 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1283 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1284 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1285 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1286 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1287 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1288 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1289 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1290 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1291 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1292 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1293 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1294 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1295 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1296 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1297 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1298 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1299 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1300 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1301 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1302 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1303 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1304 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1305 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1306 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1307 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1308 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1309 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1310 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1311 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1312 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1313 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1314 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1315 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1316 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1317 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1318 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1319 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1320 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1321 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1323 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1324 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1325 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1326 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1327 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1328 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1329 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1330 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1331 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1332 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1334 /* 3RF instruction _df(bit 21) = _w, _d */
1335 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1337 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1338 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1339 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1343 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1344 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1345 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1347 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1348 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1349 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1350 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1351 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1352 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1353 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1354 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1355 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1356 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1357 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1358 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1359 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1361 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1362 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1363 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1364 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1365 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1366 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1367 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1368 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1369 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1370 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1371 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1372 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1373 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1374 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1375 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1377 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1378 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1379 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1380 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1381 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1382 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1383 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1384 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1385 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1386 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1387 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1388 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1389 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1394 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1395 * ============================================
1397 * MXU (full name: MIPS eXtension/enhanced Unit) is an SIMD extension of MIPS32
1398 * instructions set. It is designed to fit the needs of signal, graphical and
1399 * video processing applications. MXU instruction set is used in Xburst family
1400 * of microprocessors by Ingenic.
1402 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1403 * the control register.
1405 * The notation used in MXU assembler mnemonics:
1407 * XRa, XRb, XRc, XRd - MXU registers
1408 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1409 * s12 - a subfield of an instruction code
1410 * strd2 - a subfield of an instruction code
1411 * eptn2 - a subfield of an instruction code
1412 * eptn3 - a subfield of an instruction code
1413 * optn2 - a subfield of an instruction code
1414 * optn3 - a subfield of an instruction code
1415 * sft4 - a subfield of an instruction code
1417 * Load/Store instructions Multiplication instructions
1418 * ----------------------- ---------------------------
1420 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1421 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1422 * S32LDDV XRa, Rb, rc, strd2 S32SUB XRa, XRd, Rs, Rt
1423 * S32STDV XRa, Rb, rc, strd2 S32SUBU XRa, XRd, Rs, Rt
1424 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1425 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1426 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1427 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1428 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1429 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1430 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1431 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1432 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1433 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1434 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1435 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1436 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1437 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1438 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1439 * S16SDI XRa, Rb, s10, eptn2
1440 * S8LDD XRa, Rb, s8, eptn3
1441 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1442 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1443 * S8SDI XRa, Rb, s8, eptn3
1444 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1445 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1446 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1447 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1448 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1449 * S32CPS XRa, XRb, XRc
1450 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1451 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1452 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1453 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1454 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1455 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1456 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1457 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1458 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1459 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1460 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1461 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1462 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1463 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1464 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1465 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1466 * Q8SLT XRa, XRb, XRc
1467 * Q8SLTU XRa, XRb, XRc
1468 * Q8MOVZ XRa, XRb, XRc Shift instructions
1469 * Q8MOVN XRa, XRb, XRc ------------------
1471 * D32SLL XRa, XRb, XRc, XRd, sft4
1472 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1473 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1474 * D32SARL XRa, XRb, XRc, sft4
1475 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1476 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1477 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1478 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1479 * Q16SLL XRa, XRb, XRc, XRd, sft4
1480 * Q16SLR XRa, XRb, XRc, XRd, sft4
1481 * Miscelaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1482 * ------------------------- Q16SLLV XRa, XRb, Rb
1483 * Q16SLRV XRa, XRb, Rb
1484 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1485 * S32ALN XRa, XRb, XRc, Rb
1486 * S32ALNI XRa, XRb, XRc, s3
1487 * S32LUI XRa, s8, optn3 Move instructions
1488 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1489 * S32EXTRV XRa, XRb, Rs, Rt
1490 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1491 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1494 * bits
1495 * 05..00
1497 * ┌─ 000000 ─ OPC_MXU_S32MADD
1498 * ├─ 000001 ─ OPC_MXU_S32MADDU
1499 * ├─ 000010 ─ <not assigned>
1500 * │ 20..18
1501 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1502 * │ ├─ 001 ─ OPC_MXU_S32MIN
1503 * │ ├─ 010 ─ OPC_MXU_D16MAX
1504 * │ ├─ 011 ─ OPC_MXU_D16MIN
1505 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1506 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1507 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1508 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1509 * ├─ 000100 ─ OPC_MXU_S32MSUB
1510 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1511 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1512 * │ ├─ 001 ─ OPC_MXU_D16SLT
1513 * │ ├─ 010 ─ OPC_MXU_D16AVG
1514 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1515 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1516 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1517 * │ └─ 111 ─ OPC_MXU_Q8ADD
1518 * │
1519 * │ 20..18
1520 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1521 * │ ├─ 010 ─ OPC_MXU_D16CPS
1522 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1523 * │ └─ 110 ─ OPC_MXU_Q16SAT
1524 * ├─ 001000 ─ OPC_MXU_D16MUL
1525 * │ 25..24
1526 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1527 * │ └─ 01 ─ OPC_MXU_D16MULE
1528 * ├─ 001010 ─ OPC_MXU_D16MAC
1529 * ├─ 001011 ─ OPC_MXU_D16MACF
1530 * ├─ 001100 ─ OPC_MXU_D16MADL
1531 * │ 25..24
1532 * ├─ 001101 ─ OPC_MXU__POOL04 ─┬─ 00 ─ OPC_MXU_S16MAD
1533 * │ └─ 01 ─ OPC_MXU_S16MAD_1
1534 * ├─ 001110 ─ OPC_MXU_Q16ADD
1535 * ├─ 001111 ─ OPC_MXU_D16MACE
1536 * │ 23
1537 * ├─ 010000 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32LDD
1538 * │ └─ 1 ─ OPC_MXU_S32LDDR
1539 * │
1540 * │ 23
1541 * ├─ 010001 ─ OPC_MXU__POOL06 ─┬─ 0 ─ OPC_MXU_S32STD
1542 * │ └─ 1 ─ OPC_MXU_S32STDR
1543 * │
1544 * │ 13..10
1545 * ├─ 010010 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1546 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1547 * │
1548 * │ 13..10
1549 * ├─ 010011 ─ OPC_MXU__POOL08 ─┬─ 0000 ─ OPC_MXU_S32STDV
1550 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1551 * │
1552 * │ 23
1553 * ├─ 010100 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32LDI
1554 * │ └─ 1 ─ OPC_MXU_S32LDIR
1555 * │
1556 * │ 23
1557 * ├─ 010101 ─ OPC_MXU__POOL10 ─┬─ 0 ─ OPC_MXU_S32SDI
1558 * │ └─ 1 ─ OPC_MXU_S32SDIR
1559 * │
1560 * │ 13..10
1561 * ├─ 010110 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1562 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1563 * │
1564 * │ 13..10
1565 * ├─ 010111 ─ OPC_MXU__POOL12 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1566 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1567 * ├─ 011000 ─ OPC_MXU_D32ADD
1568 * │ 23..22
1569 * MXU ├─ 011001 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_D32ACC
1570 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1571 * │ └─ 10 ─ OPC_MXU_D32ASUM
1572 * ├─ 011010 ─ <not assigned>
1573 * │ 23..22
1574 * ├─ 011011 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q16ACC
1575 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1576 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1577 * │
1578 * │ 23..22
1579 * ├─ 011100 ─ OPC_MXU__POOL15 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1580 * │ ├─ 01 ─ OPC_MXU_D8SUM
1581 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1582 * ├─ 011110 ─ <not assigned>
1583 * ├─ 011111 ─ <not assigned>
1584 * ├─ 100000 ─ <not assigned>
1585 * ├─ 100001 ─ <not assigned>
1586 * ├─ 100010 ─ OPC_MXU_S8LDD
1587 * ├─ 100011 ─ OPC_MXU_S8STD
1588 * ├─ 100100 ─ OPC_MXU_S8LDI
1589 * ├─ 100101 ─ OPC_MXU_S8SDI
1590 * │ 15..14
1591 * ├─ 100110 ─ OPC_MXU__POOL16 ─┬─ 00 ─ OPC_MXU_S32MUL
1592 * │ ├─ 00 ─ OPC_MXU_S32MULU
1593 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1594 * │ └─ 00 ─ OPC_MXU_S32EXTRV
1595 * │
1596 * │ 20..18
1597 * ├─ 100111 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_D32SARW
1598 * │ ├─ 001 ─ OPC_MXU_S32ALN
1599 * ├─ 101000 ─ OPC_MXU_LXB ├─ 010 ─ OPC_MXU_S32ALNI
1600 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_S32NOR
1601 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_S32AND
1602 * ├─ 101011 ─ OPC_MXU_S16STD ├─ 101 ─ OPC_MXU_S32OR
1603 * ├─ 101100 ─ OPC_MXU_S16LDI ├─ 110 ─ OPC_MXU_S32XOR
1604 * ├─ 101101 ─ OPC_MXU_S16SDI └─ 111 ─ OPC_MXU_S32LUI
1605 * ├─ 101000 ─ <not assigned>
1606 * ├─ 101001 ─ <not assigned>
1607 * ├─ 101010 ─ <not assigned>
1608 * ├─ 101011 ─ <not assigned>
1609 * ├─ 101100 ─ <not assigned>
1610 * ├─ 101101 ─ <not assigned>
1611 * ├─ 101110 ─ OPC_MXU_S32M2I
1612 * ├─ 101111 ─ OPC_MXU_S32I2M
1613 * ├─ 110000 ─ OPC_MXU_D32SLL
1614 * ├─ 110001 ─ OPC_MXU_D32SLR
1615 * ├─ 110010 ─ OPC_MXU_D32SARL
1616 * ├─ 110011 ─ OPC_MXU_D32SAR
1617 * ├─ 110100 ─ OPC_MXU_Q16SLL
1618 * ├─ 110101 ─ OPC_MXU_Q16SLR 20..18
1619 * ├─ 110110 ─ OPC_MXU__POOL18 ─┬─ 000 ─ OPC_MXU_D32SLLV
1620 * │ ├─ 001 ─ OPC_MXU_D32SLRV
1621 * │ ├─ 010 ─ OPC_MXU_D32SARV
1622 * │ ├─ 011 ─ OPC_MXU_Q16SLLV
1623 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1624 * │ └─ 101 ─ OPC_MXU_Q16SARV
1625 * ├─ 110111 ─ OPC_MXU_Q16SAR
1626 * │ 23..22
1627 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1628 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1629 * │
1630 * │ 20..18
1631 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1632 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1633 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1634 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1635 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1636 * │ └─ 101 ─ OPC_MXU_S32MOV
1637 * │
1638 * │ 23..22
1639 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1640 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1641 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1642 * ├─ 111100 ─ OPC_MXU_Q8MADL
1643 * ├─ 111101 ─ OPC_MXU_S32SFL
1644 * ├─ 111110 ─ OPC_MXU_Q8SAD
1645 * └─ 111111 ─ <not assigned>
1648 * Compiled after:
1650 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1651 * Programming Manual", Ingenic Semiconductor Co, Ltd., 2017
1654 enum {
1655 OPC_MXU_S32MADD = 0x00,
1656 OPC_MXU_S32MADDU = 0x01,
1657 /* not assigned 0x02 */
1658 OPC_MXU__POOL00 = 0x03,
1659 OPC_MXU_S32MSUB = 0x04,
1660 OPC_MXU_S32MSUBU = 0x05,
1661 OPC_MXU__POOL01 = 0x06,
1662 OPC_MXU__POOL02 = 0x07,
1663 OPC_MXU_D16MUL = 0x08,
1664 OPC_MXU__POOL03 = 0x09,
1665 OPC_MXU_D16MAC = 0x0A,
1666 OPC_MXU_D16MACF = 0x0B,
1667 OPC_MXU_D16MADL = 0x0C,
1668 OPC_MXU__POOL04 = 0x0D,
1669 OPC_MXU_Q16ADD = 0x0E,
1670 OPC_MXU_D16MACE = 0x0F,
1671 OPC_MXU__POOL05 = 0x10,
1672 OPC_MXU__POOL06 = 0x11,
1673 OPC_MXU__POOL07 = 0x12,
1674 OPC_MXU__POOL08 = 0x13,
1675 OPC_MXU__POOL09 = 0x14,
1676 OPC_MXU__POOL10 = 0x15,
1677 OPC_MXU__POOL11 = 0x16,
1678 OPC_MXU__POOL12 = 0x17,
1679 OPC_MXU_D32ADD = 0x18,
1680 OPC_MXU__POOL13 = 0x19,
1681 /* not assigned 0x1A */
1682 OPC_MXU__POOL14 = 0x1B,
1683 OPC_MXU__POOL15 = 0x1C,
1684 OPC_MXU_Q8ACCE = 0x1D,
1685 /* not assigned 0x1E */
1686 /* not assigned 0x1F */
1687 /* not assigned 0x20 */
1688 /* not assigned 0x21 */
1689 OPC_MXU_S8LDD = 0x22,
1690 OPC_MXU_S8STD = 0x23,
1691 OPC_MXU_S8LDI = 0x24,
1692 OPC_MXU_S8SDI = 0x25,
1693 OPC_MXU__POOL16 = 0x26,
1694 OPC_MXU__POOL17 = 0x27,
1695 OPC_MXU_LXB = 0x28,
1696 /* not assigned 0x29 */
1697 OPC_MXU_S16LDD = 0x2A,
1698 OPC_MXU_S16STD = 0x2B,
1699 OPC_MXU_S16LDI = 0x2C,
1700 OPC_MXU_S16SDI = 0x2D,
1701 OPC_MXU_S32M2I = 0x2E,
1702 OPC_MXU_S32I2M = 0x2F,
1703 OPC_MXU_D32SLL = 0x30,
1704 OPC_MXU_D32SLR = 0x31,
1705 OPC_MXU_D32SARL = 0x32,
1706 OPC_MXU_D32SAR = 0x33,
1707 OPC_MXU_Q16SLL = 0x34,
1708 OPC_MXU_Q16SLR = 0x35,
1709 OPC_MXU__POOL18 = 0x36,
1710 OPC_MXU_Q16SAR = 0x37,
1711 OPC_MXU__POOL19 = 0x38,
1712 OPC_MXU__POOL20 = 0x39,
1713 OPC_MXU__POOL21 = 0x3A,
1714 OPC_MXU_Q16SCOP = 0x3B,
1715 OPC_MXU_Q8MADL = 0x3C,
1716 OPC_MXU_S32SFL = 0x3D,
1717 OPC_MXU_Q8SAD = 0x3E,
1718 /* not assigned 0x3F */
1723 * MXU pool 00
1725 enum {
1726 OPC_MXU_S32MAX = 0x00,
1727 OPC_MXU_S32MIN = 0x01,
1728 OPC_MXU_D16MAX = 0x02,
1729 OPC_MXU_D16MIN = 0x03,
1730 OPC_MXU_Q8MAX = 0x04,
1731 OPC_MXU_Q8MIN = 0x05,
1732 OPC_MXU_Q8SLT = 0x06,
1733 OPC_MXU_Q8SLTU = 0x07,
1737 * MXU pool 01
1739 enum {
1740 OPC_MXU_S32SLT = 0x00,
1741 OPC_MXU_D16SLT = 0x01,
1742 OPC_MXU_D16AVG = 0x02,
1743 OPC_MXU_D16AVGR = 0x03,
1744 OPC_MXU_Q8AVG = 0x04,
1745 OPC_MXU_Q8AVGR = 0x05,
1746 OPC_MXU_Q8ADD = 0x07,
1750 * MXU pool 02
1752 enum {
1753 OPC_MXU_S32CPS = 0x00,
1754 OPC_MXU_D16CPS = 0x02,
1755 OPC_MXU_Q8ABD = 0x04,
1756 OPC_MXU_Q16SAT = 0x06,
1760 * MXU pool 03
1762 enum {
1763 OPC_MXU_D16MULF = 0x00,
1764 OPC_MXU_D16MULE = 0x01,
1768 * MXU pool 04
1770 enum {
1771 OPC_MXU_S16MAD = 0x00,
1772 OPC_MXU_S16MAD_1 = 0x01,
1776 * MXU pool 05
1778 enum {
1779 OPC_MXU_S32LDD = 0x00,
1780 OPC_MXU_S32LDDR = 0x01,
1784 * MXU pool 06
1786 enum {
1787 OPC_MXU_S32STD = 0x00,
1788 OPC_MXU_S32STDR = 0x01,
1792 * MXU pool 07
1794 enum {
1795 OPC_MXU_S32LDDV = 0x00,
1796 OPC_MXU_S32LDDVR = 0x01,
1800 * MXU pool 08
1802 enum {
1803 OPC_MXU_S32STDV = 0x00,
1804 OPC_MXU_S32STDVR = 0x01,
1808 * MXU pool 09
1810 enum {
1811 OPC_MXU_S32LDI = 0x00,
1812 OPC_MXU_S32LDIR = 0x01,
1816 * MXU pool 10
1818 enum {
1819 OPC_MXU_S32SDI = 0x00,
1820 OPC_MXU_S32SDIR = 0x01,
1824 * MXU pool 11
1826 enum {
1827 OPC_MXU_S32LDIV = 0x00,
1828 OPC_MXU_S32LDIVR = 0x01,
1832 * MXU pool 12
1834 enum {
1835 OPC_MXU_S32SDIV = 0x00,
1836 OPC_MXU_S32SDIVR = 0x01,
1840 * MXU pool 13
1842 enum {
1843 OPC_MXU_D32ACC = 0x00,
1844 OPC_MXU_D32ACCM = 0x01,
1845 OPC_MXU_D32ASUM = 0x02,
1849 * MXU pool 14
1851 enum {
1852 OPC_MXU_Q16ACC = 0x00,
1853 OPC_MXU_Q16ACCM = 0x01,
1854 OPC_MXU_Q16ASUM = 0x02,
1858 * MXU pool 15
1860 enum {
1861 OPC_MXU_Q8ADDE = 0x00,
1862 OPC_MXU_D8SUM = 0x01,
1863 OPC_MXU_D8SUMC = 0x02,
1867 * MXU pool 16
1869 enum {
1870 OPC_MXU_S32MUL = 0x00,
1871 OPC_MXU_S32MULU = 0x01,
1872 OPC_MXU_S32EXTR = 0x02,
1873 OPC_MXU_S32EXTRV = 0x03,
1877 * MXU pool 17
1879 enum {
1880 OPC_MXU_D32SARW = 0x00,
1881 OPC_MXU_S32ALN = 0x01,
1882 OPC_MXU_S32ALNI = 0x02,
1883 OPC_MXU_S32NOR = 0x03,
1884 OPC_MXU_S32AND = 0x04,
1885 OPC_MXU_S32OR = 0x05,
1886 OPC_MXU_S32XOR = 0x06,
1887 OPC_MXU_S32LUI = 0x07,
1891 * MXU pool 18
1893 enum {
1894 OPC_MXU_D32SLLV = 0x00,
1895 OPC_MXU_D32SLRV = 0x01,
1896 OPC_MXU_D32SARV = 0x03,
1897 OPC_MXU_Q16SLLV = 0x04,
1898 OPC_MXU_Q16SLRV = 0x05,
1899 OPC_MXU_Q16SARV = 0x07,
1903 * MXU pool 19
1905 enum {
1906 OPC_MXU_Q8MUL = 0x00,
1907 OPC_MXU_Q8MULSU = 0x01,
1911 * MXU pool 20
1913 enum {
1914 OPC_MXU_Q8MOVZ = 0x00,
1915 OPC_MXU_Q8MOVN = 0x01,
1916 OPC_MXU_D16MOVZ = 0x02,
1917 OPC_MXU_D16MOVN = 0x03,
1918 OPC_MXU_S32MOVZ = 0x04,
1919 OPC_MXU_S32MOVN = 0x05,
1923 * MXU pool 21
1925 enum {
1926 OPC_MXU_Q8MAC = 0x00,
1927 OPC_MXU_Q8MACSU = 0x01,
1931 * Overview of the TX79-specific instruction set
1932 * =============================================
1934 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1935 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1936 * instructions and certain multimedia instructions (MMIs). These MMIs
1937 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1938 * or sixteen 8-bit paths.
1940 * Reference:
1942 * The Toshiba TX System RISC TX79 Core Architecture manual,
1943 * https://wiki.qemu.org/File:C790.pdf
1945 * Three-Operand Multiply and Multiply-Add (4 instructions)
1946 * --------------------------------------------------------
1947 * MADD [rd,] rs, rt Multiply/Add
1948 * MADDU [rd,] rs, rt Multiply/Add Unsigned
1949 * MULT [rd,] rs, rt Multiply (3-operand)
1950 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
1952 * Multiply Instructions for Pipeline 1 (10 instructions)
1953 * ------------------------------------------------------
1954 * MULT1 [rd,] rs, rt Multiply Pipeline 1
1955 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
1956 * DIV1 rs, rt Divide Pipeline 1
1957 * DIVU1 rs, rt Divide Unsigned Pipeline 1
1958 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
1959 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
1960 * MFHI1 rd Move From HI1 Register
1961 * MFLO1 rd Move From LO1 Register
1962 * MTHI1 rs Move To HI1 Register
1963 * MTLO1 rs Move To LO1 Register
1965 * Arithmetic (19 instructions)
1966 * ----------------------------
1967 * PADDB rd, rs, rt Parallel Add Byte
1968 * PSUBB rd, rs, rt Parallel Subtract Byte
1969 * PADDH rd, rs, rt Parallel Add Halfword
1970 * PSUBH rd, rs, rt Parallel Subtract Halfword
1971 * PADDW rd, rs, rt Parallel Add Word
1972 * PSUBW rd, rs, rt Parallel Subtract Word
1973 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
1974 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
1975 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
1976 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
1977 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
1978 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
1979 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
1980 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
1981 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
1982 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
1983 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
1984 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
1985 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
1987 * Min/Max (4 instructions)
1988 * ------------------------
1989 * PMAXH rd, rs, rt Parallel Maximum Halfword
1990 * PMINH rd, rs, rt Parallel Minimum Halfword
1991 * PMAXW rd, rs, rt Parallel Maximum Word
1992 * PMINW rd, rs, rt Parallel Minimum Word
1994 * Absolute (2 instructions)
1995 * -------------------------
1996 * PABSH rd, rt Parallel Absolute Halfword
1997 * PABSW rd, rt Parallel Absolute Word
1999 * Logical (4 instructions)
2000 * ------------------------
2001 * PAND rd, rs, rt Parallel AND
2002 * POR rd, rs, rt Parallel OR
2003 * PXOR rd, rs, rt Parallel XOR
2004 * PNOR rd, rs, rt Parallel NOR
2006 * Shift (9 instructions)
2007 * ----------------------
2008 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2009 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2010 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2011 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2012 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2013 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2014 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2015 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2016 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2018 * Compare (6 instructions)
2019 * ------------------------
2020 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2021 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2022 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2023 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2024 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2025 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2027 * LZC (1 instruction)
2028 * -------------------
2029 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2031 * Quadword Load and Store (2 instructions)
2032 * ----------------------------------------
2033 * LQ rt, offset(base) Load Quadword
2034 * SQ rt, offset(base) Store Quadword
2036 * Multiply and Divide (19 instructions)
2037 * -------------------------------------
2038 * PMULTW rd, rs, rt Parallel Multiply Word
2039 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2040 * PDIVW rs, rt Parallel Divide Word
2041 * PDIVUW rs, rt Parallel Divide Unsigned Word
2042 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2043 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2044 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2045 * PMULTH rd, rs, rt Parallel Multiply Halfword
2046 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2047 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2048 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2049 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2050 * PDIVBW rs, rt Parallel Divide Broadcast Word
2051 * PMFHI rd Parallel Move From HI Register
2052 * PMFLO rd Parallel Move From LO Register
2053 * PMTHI rs Parallel Move To HI Register
2054 * PMTLO rs Parallel Move To LO Register
2055 * PMFHL rd Parallel Move From HI/LO Register
2056 * PMTHL rs Parallel Move To HI/LO Register
2058 * Pack/Extend (11 instructions)
2059 * -----------------------------
2060 * PPAC5 rd, rt Parallel Pack to 5 bits
2061 * PPACB rd, rs, rt Parallel Pack to Byte
2062 * PPACH rd, rs, rt Parallel Pack to Halfword
2063 * PPACW rd, rs, rt Parallel Pack to Word
2064 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2065 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2066 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2067 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2068 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2069 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2070 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2072 * Others (16 instructions)
2073 * ------------------------
2074 * PCPYH rd, rt Parallel Copy Halfword
2075 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2076 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2077 * PREVH rd, rt Parallel Reverse Halfword
2078 * PINTH rd, rs, rt Parallel Interleave Halfword
2079 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2080 * PEXEH rd, rt Parallel Exchange Even Halfword
2081 * PEXCH rd, rt Parallel Exchange Center Halfword
2082 * PEXEW rd, rt Parallel Exchange Even Word
2083 * PEXCW rd, rt Parallel Exchange Center Word
2084 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2085 * MFSA rd Move from Shift Amount Register
2086 * MTSA rs Move to Shift Amount Register
2087 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2088 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2089 * PROT3W rd, rt Parallel Rotate 3 Words
2091 * The TX79-specific Multimedia Instruction encodings
2092 * ==================================================
2094 * TX79 Multimedia Instruction encoding table keys:
2096 * * This code is reserved for future use. An attempt to execute it
2097 * causes a Reserved Instruction exception.
2098 * % This code indicates an instruction class. The instruction word
2099 * must be further decoded by examining additional tables that show
2100 * the values for other instruction fields.
2101 * # This code is reserved for the unsupported instructions DMULT,
2102 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2103 * to execute it causes a Reserved Instruction exception.
2105 * TX79 Multimedia Instructions encoded by opcode field (MMI, LQ, SQ):
2107 * 31 26 0
2108 * +--------+----------------------------------------+
2109 * | opcode | |
2110 * +--------+----------------------------------------+
2112 * opcode bits 28..26
2113 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2114 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2115 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2116 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2117 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2118 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2119 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2120 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2121 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2122 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2123 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2126 enum {
2127 TX79_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2128 TX79_LQ = 0x1E << 26, /* Same as OPC_MSA */
2129 TX79_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2133 * TX79 Multimedia Instructions with opcode field = MMI:
2135 * 31 26 5 0
2136 * +--------+-------------------------------+--------+
2137 * | MMI | |function|
2138 * +--------+-------------------------------+--------+
2140 * function bits 2..0
2141 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2142 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2143 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2144 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2145 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2146 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2147 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2148 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2149 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2150 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2151 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2154 #define MASK_TX79_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2155 enum {
2156 TX79_MMI_MADD = 0x00 | TX79_CLASS_MMI, /* Same as OPC_MADD */
2157 TX79_MMI_MADDU = 0x01 | TX79_CLASS_MMI, /* Same as OPC_MADDU */
2158 TX79_MMI_PLZCW = 0x04 | TX79_CLASS_MMI,
2159 TX79_MMI_CLASS_MMI0 = 0x08 | TX79_CLASS_MMI,
2160 TX79_MMI_CLASS_MMI2 = 0x09 | TX79_CLASS_MMI,
2161 TX79_MMI_MFHI1 = 0x10 | TX79_CLASS_MMI, /* Same minor as OPC_MFHI */
2162 TX79_MMI_MTHI1 = 0x11 | TX79_CLASS_MMI, /* Same minor as OPC_MTHI */
2163 TX79_MMI_MFLO1 = 0x12 | TX79_CLASS_MMI, /* Same minor as OPC_MFLO */
2164 TX79_MMI_MTLO1 = 0x13 | TX79_CLASS_MMI, /* Same minor as OPC_MTLO */
2165 TX79_MMI_MULT1 = 0x18 | TX79_CLASS_MMI, /* Same minor as OPC_MULT */
2166 TX79_MMI_MULTU1 = 0x19 | TX79_CLASS_MMI, /* Same minor as OPC_MULTU */
2167 TX79_MMI_DIV1 = 0x1A | TX79_CLASS_MMI, /* Same minor as OPC_DIV */
2168 TX79_MMI_DIVU1 = 0x1B | TX79_CLASS_MMI, /* Same minor as OPC_DIVU */
2169 TX79_MMI_MADD1 = 0x20 | TX79_CLASS_MMI,
2170 TX79_MMI_MADDU1 = 0x21 | TX79_CLASS_MMI,
2171 TX79_MMI_CLASS_MMI1 = 0x28 | TX79_CLASS_MMI,
2172 TX79_MMI_CLASS_MMI3 = 0x29 | TX79_CLASS_MMI,
2173 TX79_MMI_PMFHL = 0x30 | TX79_CLASS_MMI,
2174 TX79_MMI_PMTHL = 0x31 | TX79_CLASS_MMI,
2175 TX79_MMI_PSLLH = 0x34 | TX79_CLASS_MMI,
2176 TX79_MMI_PSRLH = 0x36 | TX79_CLASS_MMI,
2177 TX79_MMI_PSRAH = 0x37 | TX79_CLASS_MMI,
2178 TX79_MMI_PSLLW = 0x3C | TX79_CLASS_MMI,
2179 TX79_MMI_PSRLW = 0x3E | TX79_CLASS_MMI,
2180 TX79_MMI_PSRAW = 0x3F | TX79_CLASS_MMI,
2184 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI0:
2186 * 31 26 10 6 5 0
2187 * +--------+----------------------+--------+--------+
2188 * | MMI | |function| MMI0 |
2189 * +--------+----------------------+--------+--------+
2191 * function bits 7..6
2192 * bits | 0 | 1 | 2 | 3
2193 * 10..8 | 00 | 01 | 10 | 11
2194 * -------+-------+-------+-------+-------
2195 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2196 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2197 * 2 010 | PADDB | PSUBB | PCGTB | *
2198 * 3 011 | * | * | * | *
2199 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2200 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2201 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2202 * 7 111 | * | * | PEXT5 | PPAC5
2205 #define MASK_TX79_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2206 enum {
2207 TX79_MMI0_PADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI0,
2208 TX79_MMI0_PSUBW = (0x01 << 6) | TX79_MMI_CLASS_MMI0,
2209 TX79_MMI0_PCGTW = (0x02 << 6) | TX79_MMI_CLASS_MMI0,
2210 TX79_MMI0_PMAXW = (0x03 << 6) | TX79_MMI_CLASS_MMI0,
2211 TX79_MMI0_PADDH = (0x04 << 6) | TX79_MMI_CLASS_MMI0,
2212 TX79_MMI0_PSUBH = (0x05 << 6) | TX79_MMI_CLASS_MMI0,
2213 TX79_MMI0_PCGTH = (0x06 << 6) | TX79_MMI_CLASS_MMI0,
2214 TX79_MMI0_PMAXH = (0x07 << 6) | TX79_MMI_CLASS_MMI0,
2215 TX79_MMI0_PADDB = (0x08 << 6) | TX79_MMI_CLASS_MMI0,
2216 TX79_MMI0_PSUBB = (0x09 << 6) | TX79_MMI_CLASS_MMI0,
2217 TX79_MMI0_PCGTB = (0x0A << 6) | TX79_MMI_CLASS_MMI0,
2218 TX79_MMI0_PADDSW = (0x10 << 6) | TX79_MMI_CLASS_MMI0,
2219 TX79_MMI0_PSUBSW = (0x11 << 6) | TX79_MMI_CLASS_MMI0,
2220 TX79_MMI0_PEXTLW = (0x12 << 6) | TX79_MMI_CLASS_MMI0,
2221 TX79_MMI0_PPACW = (0x13 << 6) | TX79_MMI_CLASS_MMI0,
2222 TX79_MMI0_PADDSH = (0x14 << 6) | TX79_MMI_CLASS_MMI0,
2223 TX79_MMI0_PSUBSH = (0x15 << 6) | TX79_MMI_CLASS_MMI0,
2224 TX79_MMI0_PEXTLH = (0x16 << 6) | TX79_MMI_CLASS_MMI0,
2225 TX79_MMI0_PPACH = (0x17 << 6) | TX79_MMI_CLASS_MMI0,
2226 TX79_MMI0_PADDSB = (0x18 << 6) | TX79_MMI_CLASS_MMI0,
2227 TX79_MMI0_PSUBSB = (0x19 << 6) | TX79_MMI_CLASS_MMI0,
2228 TX79_MMI0_PEXTLB = (0x1A << 6) | TX79_MMI_CLASS_MMI0,
2229 TX79_MMI0_PPACB = (0x1B << 6) | TX79_MMI_CLASS_MMI0,
2230 TX79_MMI0_PEXT5 = (0x1E << 6) | TX79_MMI_CLASS_MMI0,
2231 TX79_MMI0_PPAC5 = (0x1F << 6) | TX79_MMI_CLASS_MMI0,
2235 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI1:
2237 * 31 26 10 6 5 0
2238 * +--------+----------------------+--------+--------+
2239 * | MMI | |function| MMI1 |
2240 * +--------+----------------------+--------+--------+
2242 * function bits 7..6
2243 * bits | 0 | 1 | 2 | 3
2244 * 10..8 | 00 | 01 | 10 | 11
2245 * -------+-------+-------+-------+-------
2246 * 0 000 | * | PABSW | PCEQW | PMINW
2247 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2248 * 2 010 | * | * | PCEQB | *
2249 * 3 011 | * | * | * | *
2250 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2251 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2252 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2253 * 7 111 | * | * | * | *
2256 #define MASK_TX79_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2257 enum {
2258 TX79_MMI1_PABSW = (0x01 << 6) | TX79_MMI_CLASS_MMI1,
2259 TX79_MMI1_PCEQW = (0x02 << 6) | TX79_MMI_CLASS_MMI1,
2260 TX79_MMI1_PMINW = (0x03 << 6) | TX79_MMI_CLASS_MMI1,
2261 TX79_MMI1_PADSBH = (0x04 << 6) | TX79_MMI_CLASS_MMI1,
2262 TX79_MMI1_PABSH = (0x05 << 6) | TX79_MMI_CLASS_MMI1,
2263 TX79_MMI1_PCEQH = (0x06 << 6) | TX79_MMI_CLASS_MMI1,
2264 TX79_MMI1_PMINH = (0x07 << 6) | TX79_MMI_CLASS_MMI1,
2265 TX79_MMI1_PCEQB = (0x0A << 6) | TX79_MMI_CLASS_MMI1,
2266 TX79_MMI1_PADDUW = (0x10 << 6) | TX79_MMI_CLASS_MMI1,
2267 TX79_MMI1_PSUBUW = (0x11 << 6) | TX79_MMI_CLASS_MMI1,
2268 TX79_MMI1_PEXTUW = (0x12 << 6) | TX79_MMI_CLASS_MMI1,
2269 TX79_MMI1_PADDUH = (0x14 << 6) | TX79_MMI_CLASS_MMI1,
2270 TX79_MMI1_PSUBUH = (0x15 << 6) | TX79_MMI_CLASS_MMI1,
2271 TX79_MMI1_PEXTUH = (0x16 << 6) | TX79_MMI_CLASS_MMI1,
2272 TX79_MMI1_PADDUB = (0x18 << 6) | TX79_MMI_CLASS_MMI1,
2273 TX79_MMI1_PSUBUB = (0x19 << 6) | TX79_MMI_CLASS_MMI1,
2274 TX79_MMI1_PEXTUB = (0x1A << 6) | TX79_MMI_CLASS_MMI1,
2275 TX79_MMI1_QFSRV = (0x1B << 6) | TX79_MMI_CLASS_MMI1,
2279 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI2:
2281 * 31 26 10 6 5 0
2282 * +--------+----------------------+--------+--------+
2283 * | MMI | |function| MMI2 |
2284 * +--------+----------------------+--------+--------+
2286 * function bits 7..6
2287 * bits | 0 | 1 | 2 | 3
2288 * 10..8 | 00 | 01 | 10 | 11
2289 * -------+-------+-------+-------+-------
2290 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2291 * 1 001 | PMSUBW| * | * | *
2292 * 2 010 | PMFHI | PMFLO | PINTH | *
2293 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2294 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2295 * 5 101 | PMSUBH| PHMSBH| * | *
2296 * 6 110 | * | * | PEXEH | PREVH
2297 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2300 #define MASK_TX79_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2301 enum {
2302 TX79_MMI2_PMADDW = (0x00 << 6) | TX79_MMI_CLASS_MMI2,
2303 TX79_MMI2_PSLLVW = (0x02 << 6) | TX79_MMI_CLASS_MMI2,
2304 TX79_MMI2_PSRLVW = (0x03 << 6) | TX79_MMI_CLASS_MMI2,
2305 TX79_MMI2_PMSUBW = (0x04 << 6) | TX79_MMI_CLASS_MMI2,
2306 TX79_MMI2_PMFHI = (0x08 << 6) | TX79_MMI_CLASS_MMI2,
2307 TX79_MMI2_PMFLO = (0x09 << 6) | TX79_MMI_CLASS_MMI2,
2308 TX79_MMI2_PINTH = (0x0A << 6) | TX79_MMI_CLASS_MMI2,
2309 TX79_MMI2_PMULTW = (0x0C << 6) | TX79_MMI_CLASS_MMI2,
2310 TX79_MMI2_PDIVW = (0x0D << 6) | TX79_MMI_CLASS_MMI2,
2311 TX79_MMI2_PCPYLD = (0x0E << 6) | TX79_MMI_CLASS_MMI2,
2312 TX79_MMI2_PMADDH = (0x10 << 6) | TX79_MMI_CLASS_MMI2,
2313 TX79_MMI2_PHMADH = (0x11 << 6) | TX79_MMI_CLASS_MMI2,
2314 TX79_MMI2_PAND = (0x12 << 6) | TX79_MMI_CLASS_MMI2,
2315 TX79_MMI2_PXOR = (0x13 << 6) | TX79_MMI_CLASS_MMI2,
2316 TX79_MMI2_PMSUBH = (0x14 << 6) | TX79_MMI_CLASS_MMI2,
2317 TX79_MMI2_PHMSBH = (0x15 << 6) | TX79_MMI_CLASS_MMI2,
2318 TX79_MMI2_PEXEH = (0x1A << 6) | TX79_MMI_CLASS_MMI2,
2319 TX79_MMI2_PREVH = (0x1B << 6) | TX79_MMI_CLASS_MMI2,
2320 TX79_MMI2_PMULTH = (0x1C << 6) | TX79_MMI_CLASS_MMI2,
2321 TX79_MMI2_PDIVBW = (0x1D << 6) | TX79_MMI_CLASS_MMI2,
2322 TX79_MMI2_PEXEW = (0x1E << 6) | TX79_MMI_CLASS_MMI2,
2323 TX79_MMI2_PROT3W = (0x1F << 6) | TX79_MMI_CLASS_MMI2,
2327 * TX79 Multimedia Instructions with opcode field = MMI and bits 5..0 = MMI3:
2329 * 31 26 10 6 5 0
2330 * +--------+----------------------+--------+--------+
2331 * | MMI | |function| MMI3 |
2332 * +--------+----------------------+--------+--------+
2334 * function bits 7..6
2335 * bits | 0 | 1 | 2 | 3
2336 * 10..8 | 00 | 01 | 10 | 11
2337 * -------+-------+-------+-------+-------
2338 * 0 000 |PMADDUW| * | * | PSRAVW
2339 * 1 001 | * | * | * | *
2340 * 2 010 | PMTHI | PMTLO | PINTEH| *
2341 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2342 * 4 100 | * | * | POR | PNOR
2343 * 5 101 | * | * | * | *
2344 * 6 110 | * | * | PEXCH | PCPYH
2345 * 7 111 | * | * | PEXCW | *
2348 #define MASK_TX79_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2349 enum {
2350 TX79_MMI3_PMADDUW = (0x00 << 6) | TX79_MMI_CLASS_MMI3,
2351 TX79_MMI3_PSRAVW = (0x03 << 6) | TX79_MMI_CLASS_MMI3,
2352 TX79_MMI3_PMTHI = (0x08 << 6) | TX79_MMI_CLASS_MMI3,
2353 TX79_MMI3_PMTLO = (0x09 << 6) | TX79_MMI_CLASS_MMI3,
2354 TX79_MMI3_PINTEH = (0x0A << 6) | TX79_MMI_CLASS_MMI3,
2355 TX79_MMI3_PMULTUW = (0x0C << 6) | TX79_MMI_CLASS_MMI3,
2356 TX79_MMI3_PDIVUW = (0x0D << 6) | TX79_MMI_CLASS_MMI3,
2357 TX79_MMI3_PCPYUD = (0x0E << 6) | TX79_MMI_CLASS_MMI3,
2358 TX79_MMI3_POR = (0x12 << 6) | TX79_MMI_CLASS_MMI3,
2359 TX79_MMI3_PNOR = (0x13 << 6) | TX79_MMI_CLASS_MMI3,
2360 TX79_MMI3_PEXCH = (0x1A << 6) | TX79_MMI_CLASS_MMI3,
2361 TX79_MMI3_PCPYH = (0x1B << 6) | TX79_MMI_CLASS_MMI3,
2362 TX79_MMI3_PEXCW = (0x1E << 6) | TX79_MMI_CLASS_MMI3,
2365 /* global register indices */
2366 static TCGv cpu_gpr[32], cpu_PC;
2367 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2368 static TCGv cpu_dspctrl, btarget, bcond;
2369 static TCGv_i32 hflags;
2370 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2371 static TCGv_i64 fpu_f64[32];
2372 static TCGv_i64 msa_wr_d[64];
2374 #include "exec/gen-icount.h"
2376 #define gen_helper_0e0i(name, arg) do { \
2377 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2378 gen_helper_##name(cpu_env, helper_tmp); \
2379 tcg_temp_free_i32(helper_tmp); \
2380 } while(0)
2382 #define gen_helper_0e1i(name, arg1, arg2) do { \
2383 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2384 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2385 tcg_temp_free_i32(helper_tmp); \
2386 } while(0)
2388 #define gen_helper_1e0i(name, ret, arg1) do { \
2389 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2390 gen_helper_##name(ret, cpu_env, helper_tmp); \
2391 tcg_temp_free_i32(helper_tmp); \
2392 } while(0)
2394 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2395 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2396 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2397 tcg_temp_free_i32(helper_tmp); \
2398 } while(0)
2400 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2401 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2402 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2403 tcg_temp_free_i32(helper_tmp); \
2404 } while(0)
2406 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2407 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2408 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2409 tcg_temp_free_i32(helper_tmp); \
2410 } while(0)
2412 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2413 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2414 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2415 tcg_temp_free_i32(helper_tmp); \
2416 } while(0)
2418 typedef struct DisasContext {
2419 DisasContextBase base;
2420 target_ulong saved_pc;
2421 target_ulong page_start;
2422 uint32_t opcode;
2423 uint64_t insn_flags;
2424 int32_t CP0_Config1;
2425 int32_t CP0_Config2;
2426 int32_t CP0_Config3;
2427 int32_t CP0_Config5;
2428 /* Routine used to access memory */
2429 int mem_idx;
2430 TCGMemOp default_tcg_memop_mask;
2431 uint32_t hflags, saved_hflags;
2432 target_ulong btarget;
2433 bool ulri;
2434 int kscrexist;
2435 bool rxi;
2436 int ie;
2437 bool bi;
2438 bool bp;
2439 uint64_t PAMask;
2440 bool mvh;
2441 bool eva;
2442 bool sc;
2443 int CP0_LLAddr_shift;
2444 bool ps;
2445 bool vp;
2446 bool cmgcr;
2447 bool mrp;
2448 bool nan2008;
2449 bool abs2008;
2450 } DisasContext;
2452 #define DISAS_STOP DISAS_TARGET_0
2453 #define DISAS_EXIT DISAS_TARGET_1
2455 static const char * const regnames[] = {
2456 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2457 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2458 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2459 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2462 static const char * const regnames_HI[] = {
2463 "HI0", "HI1", "HI2", "HI3",
2466 static const char * const regnames_LO[] = {
2467 "LO0", "LO1", "LO2", "LO3",
2470 static const char * const fregnames[] = {
2471 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2472 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2473 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2474 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2477 static const char * const msaregnames[] = {
2478 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2479 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2480 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2481 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2482 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2483 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2484 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2485 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2486 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2487 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2488 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2489 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2490 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2491 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2492 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2493 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2496 #define LOG_DISAS(...) \
2497 do { \
2498 if (MIPS_DEBUG_DISAS) { \
2499 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2501 } while (0)
2503 #define MIPS_INVAL(op) \
2504 do { \
2505 if (MIPS_DEBUG_DISAS) { \
2506 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2507 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2508 ctx->base.pc_next, ctx->opcode, op, \
2509 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2510 ((ctx->opcode >> 16) & 0x1F)); \
2512 } while (0)
2514 /* General purpose registers moves. */
2515 static inline void gen_load_gpr (TCGv t, int reg)
2517 if (reg == 0)
2518 tcg_gen_movi_tl(t, 0);
2519 else
2520 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2523 static inline void gen_store_gpr (TCGv t, int reg)
2525 if (reg != 0)
2526 tcg_gen_mov_tl(cpu_gpr[reg], t);
2529 /* Moves to/from shadow registers. */
2530 static inline void gen_load_srsgpr (int from, int to)
2532 TCGv t0 = tcg_temp_new();
2534 if (from == 0)
2535 tcg_gen_movi_tl(t0, 0);
2536 else {
2537 TCGv_i32 t2 = tcg_temp_new_i32();
2538 TCGv_ptr addr = tcg_temp_new_ptr();
2540 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2541 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2542 tcg_gen_andi_i32(t2, t2, 0xf);
2543 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2544 tcg_gen_ext_i32_ptr(addr, t2);
2545 tcg_gen_add_ptr(addr, cpu_env, addr);
2547 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2548 tcg_temp_free_ptr(addr);
2549 tcg_temp_free_i32(t2);
2551 gen_store_gpr(t0, to);
2552 tcg_temp_free(t0);
2555 static inline void gen_store_srsgpr (int from, int to)
2557 if (to != 0) {
2558 TCGv t0 = tcg_temp_new();
2559 TCGv_i32 t2 = tcg_temp_new_i32();
2560 TCGv_ptr addr = tcg_temp_new_ptr();
2562 gen_load_gpr(t0, from);
2563 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2564 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2565 tcg_gen_andi_i32(t2, t2, 0xf);
2566 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2567 tcg_gen_ext_i32_ptr(addr, t2);
2568 tcg_gen_add_ptr(addr, cpu_env, addr);
2570 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2571 tcg_temp_free_ptr(addr);
2572 tcg_temp_free_i32(t2);
2573 tcg_temp_free(t0);
2577 /* Tests */
2578 static inline void gen_save_pc(target_ulong pc)
2580 tcg_gen_movi_tl(cpu_PC, pc);
2583 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2585 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2586 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2587 gen_save_pc(ctx->base.pc_next);
2588 ctx->saved_pc = ctx->base.pc_next;
2590 if (ctx->hflags != ctx->saved_hflags) {
2591 tcg_gen_movi_i32(hflags, ctx->hflags);
2592 ctx->saved_hflags = ctx->hflags;
2593 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2594 case MIPS_HFLAG_BR:
2595 break;
2596 case MIPS_HFLAG_BC:
2597 case MIPS_HFLAG_BL:
2598 case MIPS_HFLAG_B:
2599 tcg_gen_movi_tl(btarget, ctx->btarget);
2600 break;
2605 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2607 ctx->saved_hflags = ctx->hflags;
2608 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2609 case MIPS_HFLAG_BR:
2610 break;
2611 case MIPS_HFLAG_BC:
2612 case MIPS_HFLAG_BL:
2613 case MIPS_HFLAG_B:
2614 ctx->btarget = env->btarget;
2615 break;
2619 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2621 TCGv_i32 texcp = tcg_const_i32(excp);
2622 TCGv_i32 terr = tcg_const_i32(err);
2623 save_cpu_state(ctx, 1);
2624 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2625 tcg_temp_free_i32(terr);
2626 tcg_temp_free_i32(texcp);
2627 ctx->base.is_jmp = DISAS_NORETURN;
2630 static inline void generate_exception(DisasContext *ctx, int excp)
2632 gen_helper_0e0i(raise_exception, excp);
2635 static inline void generate_exception_end(DisasContext *ctx, int excp)
2637 generate_exception_err(ctx, excp, 0);
2640 /* Floating point register moves. */
2641 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2643 if (ctx->hflags & MIPS_HFLAG_FRE) {
2644 generate_exception(ctx, EXCP_RI);
2646 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2649 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2651 TCGv_i64 t64;
2652 if (ctx->hflags & MIPS_HFLAG_FRE) {
2653 generate_exception(ctx, EXCP_RI);
2655 t64 = tcg_temp_new_i64();
2656 tcg_gen_extu_i32_i64(t64, t);
2657 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2658 tcg_temp_free_i64(t64);
2661 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2663 if (ctx->hflags & MIPS_HFLAG_F64) {
2664 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2665 } else {
2666 gen_load_fpr32(ctx, t, reg | 1);
2670 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2672 if (ctx->hflags & MIPS_HFLAG_F64) {
2673 TCGv_i64 t64 = tcg_temp_new_i64();
2674 tcg_gen_extu_i32_i64(t64, t);
2675 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2676 tcg_temp_free_i64(t64);
2677 } else {
2678 gen_store_fpr32(ctx, t, reg | 1);
2682 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2684 if (ctx->hflags & MIPS_HFLAG_F64) {
2685 tcg_gen_mov_i64(t, fpu_f64[reg]);
2686 } else {
2687 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2691 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2693 if (ctx->hflags & MIPS_HFLAG_F64) {
2694 tcg_gen_mov_i64(fpu_f64[reg], t);
2695 } else {
2696 TCGv_i64 t0;
2697 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2698 t0 = tcg_temp_new_i64();
2699 tcg_gen_shri_i64(t0, t, 32);
2700 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2701 tcg_temp_free_i64(t0);
2705 static inline int get_fp_bit (int cc)
2707 if (cc)
2708 return 24 + cc;
2709 else
2710 return 23;
2713 /* Addresses computation */
2714 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2716 tcg_gen_add_tl(ret, arg0, arg1);
2718 #if defined(TARGET_MIPS64)
2719 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2720 tcg_gen_ext32s_i64(ret, ret);
2722 #endif
2725 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2726 target_long ofs)
2728 tcg_gen_addi_tl(ret, base, ofs);
2730 #if defined(TARGET_MIPS64)
2731 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2732 tcg_gen_ext32s_i64(ret, ret);
2734 #endif
2737 /* Addresses computation (translation time) */
2738 static target_long addr_add(DisasContext *ctx, target_long base,
2739 target_long offset)
2741 target_long sum = base + offset;
2743 #if defined(TARGET_MIPS64)
2744 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2745 sum = (int32_t)sum;
2747 #endif
2748 return sum;
2751 /* Sign-extract the low 32-bits to a target_long. */
2752 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2754 #if defined(TARGET_MIPS64)
2755 tcg_gen_ext32s_i64(ret, arg);
2756 #else
2757 tcg_gen_extrl_i64_i32(ret, arg);
2758 #endif
2761 /* Sign-extract the high 32-bits to a target_long. */
2762 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2764 #if defined(TARGET_MIPS64)
2765 tcg_gen_sari_i64(ret, arg, 32);
2766 #else
2767 tcg_gen_extrh_i64_i32(ret, arg);
2768 #endif
2771 static inline void check_cp0_enabled(DisasContext *ctx)
2773 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2774 generate_exception_err(ctx, EXCP_CpU, 0);
2777 static inline void check_cp1_enabled(DisasContext *ctx)
2779 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2780 generate_exception_err(ctx, EXCP_CpU, 1);
2783 /* Verify that the processor is running with COP1X instructions enabled.
2784 This is associated with the nabla symbol in the MIPS32 and MIPS64
2785 opcode tables. */
2787 static inline void check_cop1x(DisasContext *ctx)
2789 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2790 generate_exception_end(ctx, EXCP_RI);
2793 /* Verify that the processor is running with 64-bit floating-point
2794 operations enabled. */
2796 static inline void check_cp1_64bitmode(DisasContext *ctx)
2798 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2799 generate_exception_end(ctx, EXCP_RI);
2803 * Verify if floating point register is valid; an operation is not defined
2804 * if bit 0 of any register specification is set and the FR bit in the
2805 * Status register equals zero, since the register numbers specify an
2806 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2807 * in the Status register equals one, both even and odd register numbers
2808 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2810 * Multiple 64 bit wide registers can be checked by calling
2811 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2813 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2815 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2816 generate_exception_end(ctx, EXCP_RI);
2819 /* Verify that the processor is running with DSP instructions enabled.
2820 This is enabled by CP0 Status register MX(24) bit.
2823 static inline void check_dsp(DisasContext *ctx)
2825 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2826 if (ctx->insn_flags & ASE_DSP) {
2827 generate_exception_end(ctx, EXCP_DSPDIS);
2828 } else {
2829 generate_exception_end(ctx, EXCP_RI);
2834 static inline void check_dsp_r2(DisasContext *ctx)
2836 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2837 if (ctx->insn_flags & ASE_DSP) {
2838 generate_exception_end(ctx, EXCP_DSPDIS);
2839 } else {
2840 generate_exception_end(ctx, EXCP_RI);
2845 static inline void check_dsp_r3(DisasContext *ctx)
2847 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2848 if (ctx->insn_flags & ASE_DSP) {
2849 generate_exception_end(ctx, EXCP_DSPDIS);
2850 } else {
2851 generate_exception_end(ctx, EXCP_RI);
2856 /* This code generates a "reserved instruction" exception if the
2857 CPU does not support the instruction set corresponding to flags. */
2858 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2860 if (unlikely(!(ctx->insn_flags & flags))) {
2861 generate_exception_end(ctx, EXCP_RI);
2865 /* This code generates a "reserved instruction" exception if the
2866 CPU has corresponding flag set which indicates that the instruction
2867 has been removed. */
2868 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2870 if (unlikely(ctx->insn_flags & flags)) {
2871 generate_exception_end(ctx, EXCP_RI);
2875 /* This code generates a "reserved instruction" exception if the
2876 CPU does not support 64-bit paired-single (PS) floating point data type */
2877 static inline void check_ps(DisasContext *ctx)
2879 if (unlikely(!ctx->ps)) {
2880 generate_exception(ctx, EXCP_RI);
2882 check_cp1_64bitmode(ctx);
2885 #ifdef TARGET_MIPS64
2886 /* This code generates a "reserved instruction" exception if 64-bit
2887 instructions are not enabled. */
2888 static inline void check_mips_64(DisasContext *ctx)
2890 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2891 generate_exception_end(ctx, EXCP_RI);
2893 #endif
2895 #ifndef CONFIG_USER_ONLY
2896 static inline void check_mvh(DisasContext *ctx)
2898 if (unlikely(!ctx->mvh)) {
2899 generate_exception(ctx, EXCP_RI);
2902 #endif
2905 * This code generates a "reserved instruction" exception if the
2906 * Config5 XNP bit is set.
2908 static inline void check_xnp(DisasContext *ctx)
2910 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2911 generate_exception_end(ctx, EXCP_RI);
2915 #ifndef CONFIG_USER_ONLY
2917 * This code generates a "reserved instruction" exception if the
2918 * Config3 PW bit is NOT set.
2920 static inline void check_pw(DisasContext *ctx)
2922 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2923 generate_exception_end(ctx, EXCP_RI);
2926 #endif
2929 * This code generates a "reserved instruction" exception if the
2930 * Config3 MT bit is NOT set.
2932 static inline void check_mt(DisasContext *ctx)
2934 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2935 generate_exception_end(ctx, EXCP_RI);
2939 #ifndef CONFIG_USER_ONLY
2941 * This code generates a "coprocessor unusable" exception if CP0 is not
2942 * available, and, if that is not the case, generates a "reserved instruction"
2943 * exception if the Config5 MT bit is NOT set. This is needed for availability
2944 * control of some of MT ASE instructions.
2946 static inline void check_cp0_mt(DisasContext *ctx)
2948 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2949 generate_exception_err(ctx, EXCP_CpU, 0);
2950 } else {
2951 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2952 generate_exception_err(ctx, EXCP_RI, 0);
2956 #endif
2959 * This code generates a "reserved instruction" exception if the
2960 * Config5 NMS bit is set.
2962 static inline void check_nms(DisasContext *ctx)
2964 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2965 generate_exception_end(ctx, EXCP_RI);
2970 /* Define small wrappers for gen_load_fpr* so that we have a uniform
2971 calling interface for 32 and 64-bit FPRs. No sense in changing
2972 all callers for gen_load_fpr32 when we need the CTX parameter for
2973 this one use. */
2974 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2975 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2976 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2977 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2978 int ft, int fs, int cc) \
2980 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
2981 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
2982 switch (ifmt) { \
2983 case FMT_PS: \
2984 check_ps(ctx); \
2985 break; \
2986 case FMT_D: \
2987 if (abs) { \
2988 check_cop1x(ctx); \
2990 check_cp1_registers(ctx, fs | ft); \
2991 break; \
2992 case FMT_S: \
2993 if (abs) { \
2994 check_cop1x(ctx); \
2996 break; \
2998 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
2999 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
3000 switch (n) { \
3001 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
3002 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
3003 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
3004 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
3005 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
3006 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
3007 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
3008 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
3009 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
3010 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
3011 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
3012 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
3013 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
3014 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
3015 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
3016 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
3017 default: abort(); \
3019 tcg_temp_free_i##bits (fp0); \
3020 tcg_temp_free_i##bits (fp1); \
3023 FOP_CONDS(, 0, d, FMT_D, 64)
3024 FOP_CONDS(abs, 1, d, FMT_D, 64)
3025 FOP_CONDS(, 0, s, FMT_S, 32)
3026 FOP_CONDS(abs, 1, s, FMT_S, 32)
3027 FOP_CONDS(, 0, ps, FMT_PS, 64)
3028 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3029 #undef FOP_CONDS
3031 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3032 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
3033 int ft, int fs, int fd) \
3035 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3036 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3037 if (ifmt == FMT_D) { \
3038 check_cp1_registers(ctx, fs | ft | fd); \
3040 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3041 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3042 switch (n) { \
3043 case 0: \
3044 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3045 break; \
3046 case 1: \
3047 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3048 break; \
3049 case 2: \
3050 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3051 break; \
3052 case 3: \
3053 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3054 break; \
3055 case 4: \
3056 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3057 break; \
3058 case 5: \
3059 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3060 break; \
3061 case 6: \
3062 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3063 break; \
3064 case 7: \
3065 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3066 break; \
3067 case 8: \
3068 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3069 break; \
3070 case 9: \
3071 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3072 break; \
3073 case 10: \
3074 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3075 break; \
3076 case 11: \
3077 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3078 break; \
3079 case 12: \
3080 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3081 break; \
3082 case 13: \
3083 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3084 break; \
3085 case 14: \
3086 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3087 break; \
3088 case 15: \
3089 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3090 break; \
3091 case 17: \
3092 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3093 break; \
3094 case 18: \
3095 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3096 break; \
3097 case 19: \
3098 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3099 break; \
3100 case 25: \
3101 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3102 break; \
3103 case 26: \
3104 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3105 break; \
3106 case 27: \
3107 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3108 break; \
3109 default: \
3110 abort(); \
3112 STORE; \
3113 tcg_temp_free_i ## bits (fp0); \
3114 tcg_temp_free_i ## bits (fp1); \
3117 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3118 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3119 #undef FOP_CONDNS
3120 #undef gen_ldcmp_fpr32
3121 #undef gen_ldcmp_fpr64
3123 /* load/store instructions. */
3124 #ifdef CONFIG_USER_ONLY
3125 #define OP_LD_ATOMIC(insn,fname) \
3126 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3127 DisasContext *ctx) \
3129 TCGv t0 = tcg_temp_new(); \
3130 tcg_gen_mov_tl(t0, arg1); \
3131 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3132 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3133 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3134 tcg_temp_free(t0); \
3136 #else
3137 #define OP_LD_ATOMIC(insn,fname) \
3138 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3139 DisasContext *ctx) \
3141 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3143 #endif
3144 OP_LD_ATOMIC(ll,ld32s);
3145 #if defined(TARGET_MIPS64)
3146 OP_LD_ATOMIC(lld,ld64);
3147 #endif
3148 #undef OP_LD_ATOMIC
3150 #ifdef CONFIG_USER_ONLY
3151 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3152 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3153 DisasContext *ctx) \
3155 TCGv t0 = tcg_temp_new(); \
3156 TCGLabel *l1 = gen_new_label(); \
3157 TCGLabel *l2 = gen_new_label(); \
3159 tcg_gen_andi_tl(t0, arg2, almask); \
3160 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
3161 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
3162 generate_exception(ctx, EXCP_AdES); \
3163 gen_set_label(l1); \
3164 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3165 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
3166 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
3167 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
3168 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
3169 generate_exception_end(ctx, EXCP_SC); \
3170 gen_set_label(l2); \
3171 tcg_gen_movi_tl(t0, 0); \
3172 gen_store_gpr(t0, rt); \
3173 tcg_temp_free(t0); \
3175 #else
3176 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
3177 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
3178 DisasContext *ctx) \
3180 TCGv t0 = tcg_temp_new(); \
3181 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3182 gen_store_gpr(t0, rt); \
3183 tcg_temp_free(t0); \
3185 #endif
3186 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3187 #if defined(TARGET_MIPS64)
3188 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3189 #endif
3190 #undef OP_ST_ATOMIC
3192 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3193 int base, int offset)
3195 if (base == 0) {
3196 tcg_gen_movi_tl(addr, offset);
3197 } else if (offset == 0) {
3198 gen_load_gpr(addr, base);
3199 } else {
3200 tcg_gen_movi_tl(addr, offset);
3201 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3205 static target_ulong pc_relative_pc (DisasContext *ctx)
3207 target_ulong pc = ctx->base.pc_next;
3209 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3210 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3212 pc -= branch_bytes;
3215 pc &= ~(target_ulong)3;
3216 return pc;
3219 /* Load */
3220 static void gen_ld(DisasContext *ctx, uint32_t opc,
3221 int rt, int base, int offset)
3223 TCGv t0, t1, t2;
3224 int mem_idx = ctx->mem_idx;
3226 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3227 /* Loongson CPU uses a load to zero register for prefetch.
3228 We emulate it as a NOP. On other CPU we must perform the
3229 actual memory access. */
3230 return;
3233 t0 = tcg_temp_new();
3234 gen_base_offset_addr(ctx, t0, base, offset);
3236 switch (opc) {
3237 #if defined(TARGET_MIPS64)
3238 case OPC_LWU:
3239 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3240 ctx->default_tcg_memop_mask);
3241 gen_store_gpr(t0, rt);
3242 break;
3243 case OPC_LD:
3244 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3245 ctx->default_tcg_memop_mask);
3246 gen_store_gpr(t0, rt);
3247 break;
3248 case OPC_LLD:
3249 case R6_OPC_LLD:
3250 op_ld_lld(t0, t0, mem_idx, ctx);
3251 gen_store_gpr(t0, rt);
3252 break;
3253 case OPC_LDL:
3254 t1 = tcg_temp_new();
3255 /* Do a byte access to possibly trigger a page
3256 fault with the unaligned address. */
3257 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3258 tcg_gen_andi_tl(t1, t0, 7);
3259 #ifndef TARGET_WORDS_BIGENDIAN
3260 tcg_gen_xori_tl(t1, t1, 7);
3261 #endif
3262 tcg_gen_shli_tl(t1, t1, 3);
3263 tcg_gen_andi_tl(t0, t0, ~7);
3264 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3265 tcg_gen_shl_tl(t0, t0, t1);
3266 t2 = tcg_const_tl(-1);
3267 tcg_gen_shl_tl(t2, t2, t1);
3268 gen_load_gpr(t1, rt);
3269 tcg_gen_andc_tl(t1, t1, t2);
3270 tcg_temp_free(t2);
3271 tcg_gen_or_tl(t0, t0, t1);
3272 tcg_temp_free(t1);
3273 gen_store_gpr(t0, rt);
3274 break;
3275 case OPC_LDR:
3276 t1 = tcg_temp_new();
3277 /* Do a byte access to possibly trigger a page
3278 fault with the unaligned address. */
3279 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3280 tcg_gen_andi_tl(t1, t0, 7);
3281 #ifdef TARGET_WORDS_BIGENDIAN
3282 tcg_gen_xori_tl(t1, t1, 7);
3283 #endif
3284 tcg_gen_shli_tl(t1, t1, 3);
3285 tcg_gen_andi_tl(t0, t0, ~7);
3286 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3287 tcg_gen_shr_tl(t0, t0, t1);
3288 tcg_gen_xori_tl(t1, t1, 63);
3289 t2 = tcg_const_tl(0xfffffffffffffffeull);
3290 tcg_gen_shl_tl(t2, t2, t1);
3291 gen_load_gpr(t1, rt);
3292 tcg_gen_and_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_LDPC:
3299 t1 = tcg_const_tl(pc_relative_pc(ctx));
3300 gen_op_addr_add(ctx, t0, t0, t1);
3301 tcg_temp_free(t1);
3302 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3303 gen_store_gpr(t0, rt);
3304 break;
3305 #endif
3306 case OPC_LWPC:
3307 t1 = tcg_const_tl(pc_relative_pc(ctx));
3308 gen_op_addr_add(ctx, t0, t0, t1);
3309 tcg_temp_free(t1);
3310 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3311 gen_store_gpr(t0, rt);
3312 break;
3313 case OPC_LWE:
3314 mem_idx = MIPS_HFLAG_UM;
3315 /* fall through */
3316 case OPC_LW:
3317 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3318 ctx->default_tcg_memop_mask);
3319 gen_store_gpr(t0, rt);
3320 break;
3321 case OPC_LHE:
3322 mem_idx = MIPS_HFLAG_UM;
3323 /* fall through */
3324 case OPC_LH:
3325 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3326 ctx->default_tcg_memop_mask);
3327 gen_store_gpr(t0, rt);
3328 break;
3329 case OPC_LHUE:
3330 mem_idx = MIPS_HFLAG_UM;
3331 /* fall through */
3332 case OPC_LHU:
3333 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3334 ctx->default_tcg_memop_mask);
3335 gen_store_gpr(t0, rt);
3336 break;
3337 case OPC_LBE:
3338 mem_idx = MIPS_HFLAG_UM;
3339 /* fall through */
3340 case OPC_LB:
3341 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3342 gen_store_gpr(t0, rt);
3343 break;
3344 case OPC_LBUE:
3345 mem_idx = MIPS_HFLAG_UM;
3346 /* fall through */
3347 case OPC_LBU:
3348 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3349 gen_store_gpr(t0, rt);
3350 break;
3351 case OPC_LWLE:
3352 mem_idx = MIPS_HFLAG_UM;
3353 /* fall through */
3354 case OPC_LWL:
3355 t1 = tcg_temp_new();
3356 /* Do a byte access to possibly trigger a page
3357 fault with the unaligned address. */
3358 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3359 tcg_gen_andi_tl(t1, t0, 3);
3360 #ifndef TARGET_WORDS_BIGENDIAN
3361 tcg_gen_xori_tl(t1, t1, 3);
3362 #endif
3363 tcg_gen_shli_tl(t1, t1, 3);
3364 tcg_gen_andi_tl(t0, t0, ~3);
3365 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3366 tcg_gen_shl_tl(t0, t0, t1);
3367 t2 = tcg_const_tl(-1);
3368 tcg_gen_shl_tl(t2, t2, t1);
3369 gen_load_gpr(t1, rt);
3370 tcg_gen_andc_tl(t1, t1, t2);
3371 tcg_temp_free(t2);
3372 tcg_gen_or_tl(t0, t0, t1);
3373 tcg_temp_free(t1);
3374 tcg_gen_ext32s_tl(t0, t0);
3375 gen_store_gpr(t0, rt);
3376 break;
3377 case OPC_LWRE:
3378 mem_idx = MIPS_HFLAG_UM;
3379 /* fall through */
3380 case OPC_LWR:
3381 t1 = tcg_temp_new();
3382 /* Do a byte access to possibly trigger a page
3383 fault with the unaligned address. */
3384 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3385 tcg_gen_andi_tl(t1, t0, 3);
3386 #ifdef TARGET_WORDS_BIGENDIAN
3387 tcg_gen_xori_tl(t1, t1, 3);
3388 #endif
3389 tcg_gen_shli_tl(t1, t1, 3);
3390 tcg_gen_andi_tl(t0, t0, ~3);
3391 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3392 tcg_gen_shr_tl(t0, t0, t1);
3393 tcg_gen_xori_tl(t1, t1, 31);
3394 t2 = tcg_const_tl(0xfffffffeull);
3395 tcg_gen_shl_tl(t2, t2, t1);
3396 gen_load_gpr(t1, rt);
3397 tcg_gen_and_tl(t1, t1, t2);
3398 tcg_temp_free(t2);
3399 tcg_gen_or_tl(t0, t0, t1);
3400 tcg_temp_free(t1);
3401 tcg_gen_ext32s_tl(t0, t0);
3402 gen_store_gpr(t0, rt);
3403 break;
3404 case OPC_LLE:
3405 mem_idx = MIPS_HFLAG_UM;
3406 /* fall through */
3407 case OPC_LL:
3408 case R6_OPC_LL:
3409 op_ld_ll(t0, t0, mem_idx, ctx);
3410 gen_store_gpr(t0, rt);
3411 break;
3413 tcg_temp_free(t0);
3416 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3417 uint32_t reg1, uint32_t reg2)
3419 TCGv taddr = tcg_temp_new();
3420 TCGv_i64 tval = tcg_temp_new_i64();
3421 TCGv tmp1 = tcg_temp_new();
3422 TCGv tmp2 = tcg_temp_new();
3424 gen_base_offset_addr(ctx, taddr, base, offset);
3425 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3426 #ifdef TARGET_WORDS_BIGENDIAN
3427 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3428 #else
3429 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3430 #endif
3431 gen_store_gpr(tmp1, reg1);
3432 tcg_temp_free(tmp1);
3433 gen_store_gpr(tmp2, reg2);
3434 tcg_temp_free(tmp2);
3435 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3436 tcg_temp_free_i64(tval);
3437 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3438 tcg_temp_free(taddr);
3441 /* Store */
3442 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3443 int base, int offset)
3445 TCGv t0 = tcg_temp_new();
3446 TCGv t1 = tcg_temp_new();
3447 int mem_idx = ctx->mem_idx;
3449 gen_base_offset_addr(ctx, t0, base, offset);
3450 gen_load_gpr(t1, rt);
3451 switch (opc) {
3452 #if defined(TARGET_MIPS64)
3453 case OPC_SD:
3454 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3455 ctx->default_tcg_memop_mask);
3456 break;
3457 case OPC_SDL:
3458 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3459 break;
3460 case OPC_SDR:
3461 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3462 break;
3463 #endif
3464 case OPC_SWE:
3465 mem_idx = MIPS_HFLAG_UM;
3466 /* fall through */
3467 case OPC_SW:
3468 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3469 ctx->default_tcg_memop_mask);
3470 break;
3471 case OPC_SHE:
3472 mem_idx = MIPS_HFLAG_UM;
3473 /* fall through */
3474 case OPC_SH:
3475 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3476 ctx->default_tcg_memop_mask);
3477 break;
3478 case OPC_SBE:
3479 mem_idx = MIPS_HFLAG_UM;
3480 /* fall through */
3481 case OPC_SB:
3482 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3483 break;
3484 case OPC_SWLE:
3485 mem_idx = MIPS_HFLAG_UM;
3486 /* fall through */
3487 case OPC_SWL:
3488 gen_helper_0e2i(swl, t1, t0, mem_idx);
3489 break;
3490 case OPC_SWRE:
3491 mem_idx = MIPS_HFLAG_UM;
3492 /* fall through */
3493 case OPC_SWR:
3494 gen_helper_0e2i(swr, t1, t0, mem_idx);
3495 break;
3497 tcg_temp_free(t0);
3498 tcg_temp_free(t1);
3502 /* Store conditional */
3503 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3504 int base, int16_t offset)
3506 TCGv t0, t1;
3507 int mem_idx = ctx->mem_idx;
3509 #ifdef CONFIG_USER_ONLY
3510 t0 = tcg_temp_local_new();
3511 t1 = tcg_temp_local_new();
3512 #else
3513 t0 = tcg_temp_new();
3514 t1 = tcg_temp_new();
3515 #endif
3516 gen_base_offset_addr(ctx, t0, base, offset);
3517 gen_load_gpr(t1, rt);
3518 switch (opc) {
3519 #if defined(TARGET_MIPS64)
3520 case OPC_SCD:
3521 case R6_OPC_SCD:
3522 op_st_scd(t1, t0, rt, mem_idx, ctx);
3523 break;
3524 #endif
3525 case OPC_SCE:
3526 mem_idx = MIPS_HFLAG_UM;
3527 /* fall through */
3528 case OPC_SC:
3529 case R6_OPC_SC:
3530 op_st_sc(t1, t0, rt, mem_idx, ctx);
3531 break;
3533 tcg_temp_free(t1);
3534 tcg_temp_free(t0);
3537 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3538 uint32_t reg1, uint32_t reg2)
3540 TCGv taddr = tcg_temp_local_new();
3541 TCGv lladdr = tcg_temp_local_new();
3542 TCGv_i64 tval = tcg_temp_new_i64();
3543 TCGv_i64 llval = tcg_temp_new_i64();
3544 TCGv_i64 val = tcg_temp_new_i64();
3545 TCGv tmp1 = tcg_temp_new();
3546 TCGv tmp2 = tcg_temp_new();
3547 TCGLabel *lab_fail = gen_new_label();
3548 TCGLabel *lab_done = gen_new_label();
3550 gen_base_offset_addr(ctx, taddr, base, offset);
3552 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3553 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3555 gen_load_gpr(tmp1, reg1);
3556 gen_load_gpr(tmp2, reg2);
3558 #ifdef TARGET_WORDS_BIGENDIAN
3559 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3560 #else
3561 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3562 #endif
3564 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3565 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3566 ctx->mem_idx, MO_64);
3567 if (reg1 != 0) {
3568 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3570 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3572 gen_set_label(lab_fail);
3574 if (reg1 != 0) {
3575 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3577 gen_set_label(lab_done);
3578 tcg_gen_movi_tl(lladdr, -1);
3579 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3582 /* Load and store */
3583 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3584 TCGv t0)
3586 /* Don't do NOP if destination is zero: we must perform the actual
3587 memory access. */
3588 switch (opc) {
3589 case OPC_LWC1:
3591 TCGv_i32 fp0 = tcg_temp_new_i32();
3592 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3593 ctx->default_tcg_memop_mask);
3594 gen_store_fpr32(ctx, fp0, ft);
3595 tcg_temp_free_i32(fp0);
3597 break;
3598 case OPC_SWC1:
3600 TCGv_i32 fp0 = tcg_temp_new_i32();
3601 gen_load_fpr32(ctx, fp0, ft);
3602 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3603 ctx->default_tcg_memop_mask);
3604 tcg_temp_free_i32(fp0);
3606 break;
3607 case OPC_LDC1:
3609 TCGv_i64 fp0 = tcg_temp_new_i64();
3610 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3611 ctx->default_tcg_memop_mask);
3612 gen_store_fpr64(ctx, fp0, ft);
3613 tcg_temp_free_i64(fp0);
3615 break;
3616 case OPC_SDC1:
3618 TCGv_i64 fp0 = tcg_temp_new_i64();
3619 gen_load_fpr64(ctx, fp0, ft);
3620 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3621 ctx->default_tcg_memop_mask);
3622 tcg_temp_free_i64(fp0);
3624 break;
3625 default:
3626 MIPS_INVAL("flt_ldst");
3627 generate_exception_end(ctx, EXCP_RI);
3628 break;
3632 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3633 int rs, int16_t imm)
3635 TCGv t0 = tcg_temp_new();
3637 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3638 check_cp1_enabled(ctx);
3639 switch (op) {
3640 case OPC_LDC1:
3641 case OPC_SDC1:
3642 check_insn(ctx, ISA_MIPS2);
3643 /* Fallthrough */
3644 default:
3645 gen_base_offset_addr(ctx, t0, rs, imm);
3646 gen_flt_ldst(ctx, op, rt, t0);
3648 } else {
3649 generate_exception_err(ctx, EXCP_CpU, 1);
3651 tcg_temp_free(t0);
3654 /* Arithmetic with immediate operand */
3655 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3656 int rt, int rs, int imm)
3658 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3660 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3661 /* If no destination, treat it as a NOP.
3662 For addi, we must generate the overflow exception when needed. */
3663 return;
3665 switch (opc) {
3666 case OPC_ADDI:
3668 TCGv t0 = tcg_temp_local_new();
3669 TCGv t1 = tcg_temp_new();
3670 TCGv t2 = tcg_temp_new();
3671 TCGLabel *l1 = gen_new_label();
3673 gen_load_gpr(t1, rs);
3674 tcg_gen_addi_tl(t0, t1, uimm);
3675 tcg_gen_ext32s_tl(t0, t0);
3677 tcg_gen_xori_tl(t1, t1, ~uimm);
3678 tcg_gen_xori_tl(t2, t0, uimm);
3679 tcg_gen_and_tl(t1, t1, t2);
3680 tcg_temp_free(t2);
3681 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3682 tcg_temp_free(t1);
3683 /* operands of same sign, result different sign */
3684 generate_exception(ctx, EXCP_OVERFLOW);
3685 gen_set_label(l1);
3686 tcg_gen_ext32s_tl(t0, t0);
3687 gen_store_gpr(t0, rt);
3688 tcg_temp_free(t0);
3690 break;
3691 case OPC_ADDIU:
3692 if (rs != 0) {
3693 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3694 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3695 } else {
3696 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3698 break;
3699 #if defined(TARGET_MIPS64)
3700 case OPC_DADDI:
3702 TCGv t0 = tcg_temp_local_new();
3703 TCGv t1 = tcg_temp_new();
3704 TCGv t2 = tcg_temp_new();
3705 TCGLabel *l1 = gen_new_label();
3707 gen_load_gpr(t1, rs);
3708 tcg_gen_addi_tl(t0, t1, uimm);
3710 tcg_gen_xori_tl(t1, t1, ~uimm);
3711 tcg_gen_xori_tl(t2, t0, uimm);
3712 tcg_gen_and_tl(t1, t1, t2);
3713 tcg_temp_free(t2);
3714 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3715 tcg_temp_free(t1);
3716 /* operands of same sign, result different sign */
3717 generate_exception(ctx, EXCP_OVERFLOW);
3718 gen_set_label(l1);
3719 gen_store_gpr(t0, rt);
3720 tcg_temp_free(t0);
3722 break;
3723 case OPC_DADDIU:
3724 if (rs != 0) {
3725 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3726 } else {
3727 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3729 break;
3730 #endif
3734 /* Logic with immediate operand */
3735 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3736 int rt, int rs, int16_t imm)
3738 target_ulong uimm;
3740 if (rt == 0) {
3741 /* If no destination, treat it as a NOP. */
3742 return;
3744 uimm = (uint16_t)imm;
3745 switch (opc) {
3746 case OPC_ANDI:
3747 if (likely(rs != 0))
3748 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3749 else
3750 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3751 break;
3752 case OPC_ORI:
3753 if (rs != 0)
3754 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3755 else
3756 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3757 break;
3758 case OPC_XORI:
3759 if (likely(rs != 0))
3760 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3761 else
3762 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3763 break;
3764 case OPC_LUI:
3765 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3766 /* OPC_AUI */
3767 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3768 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3769 } else {
3770 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3772 break;
3774 default:
3775 break;
3779 /* Set on less than with immediate operand */
3780 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3781 int rt, int rs, int16_t imm)
3783 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3784 TCGv t0;
3786 if (rt == 0) {
3787 /* If no destination, treat it as a NOP. */
3788 return;
3790 t0 = tcg_temp_new();
3791 gen_load_gpr(t0, rs);
3792 switch (opc) {
3793 case OPC_SLTI:
3794 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3795 break;
3796 case OPC_SLTIU:
3797 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3798 break;
3800 tcg_temp_free(t0);
3803 /* Shifts with immediate operand */
3804 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3805 int rt, int rs, int16_t imm)
3807 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3808 TCGv t0;
3810 if (rt == 0) {
3811 /* If no destination, treat it as a NOP. */
3812 return;
3815 t0 = tcg_temp_new();
3816 gen_load_gpr(t0, rs);
3817 switch (opc) {
3818 case OPC_SLL:
3819 tcg_gen_shli_tl(t0, t0, uimm);
3820 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3821 break;
3822 case OPC_SRA:
3823 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3824 break;
3825 case OPC_SRL:
3826 if (uimm != 0) {
3827 tcg_gen_ext32u_tl(t0, t0);
3828 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3829 } else {
3830 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3832 break;
3833 case OPC_ROTR:
3834 if (uimm != 0) {
3835 TCGv_i32 t1 = tcg_temp_new_i32();
3837 tcg_gen_trunc_tl_i32(t1, t0);
3838 tcg_gen_rotri_i32(t1, t1, uimm);
3839 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3840 tcg_temp_free_i32(t1);
3841 } else {
3842 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3844 break;
3845 #if defined(TARGET_MIPS64)
3846 case OPC_DSLL:
3847 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3848 break;
3849 case OPC_DSRA:
3850 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3851 break;
3852 case OPC_DSRL:
3853 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3854 break;
3855 case OPC_DROTR:
3856 if (uimm != 0) {
3857 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3858 } else {
3859 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3861 break;
3862 case OPC_DSLL32:
3863 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3864 break;
3865 case OPC_DSRA32:
3866 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3867 break;
3868 case OPC_DSRL32:
3869 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3870 break;
3871 case OPC_DROTR32:
3872 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3873 break;
3874 #endif
3876 tcg_temp_free(t0);
3879 /* Arithmetic */
3880 static void gen_arith(DisasContext *ctx, uint32_t opc,
3881 int rd, int rs, int rt)
3883 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3884 && opc != OPC_DADD && opc != OPC_DSUB) {
3885 /* If no destination, treat it as a NOP.
3886 For add & sub, we must generate the overflow exception when needed. */
3887 return;
3890 switch (opc) {
3891 case OPC_ADD:
3893 TCGv t0 = tcg_temp_local_new();
3894 TCGv t1 = tcg_temp_new();
3895 TCGv t2 = tcg_temp_new();
3896 TCGLabel *l1 = gen_new_label();
3898 gen_load_gpr(t1, rs);
3899 gen_load_gpr(t2, rt);
3900 tcg_gen_add_tl(t0, t1, t2);
3901 tcg_gen_ext32s_tl(t0, t0);
3902 tcg_gen_xor_tl(t1, t1, t2);
3903 tcg_gen_xor_tl(t2, t0, t2);
3904 tcg_gen_andc_tl(t1, t2, t1);
3905 tcg_temp_free(t2);
3906 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3907 tcg_temp_free(t1);
3908 /* operands of same sign, result different sign */
3909 generate_exception(ctx, EXCP_OVERFLOW);
3910 gen_set_label(l1);
3911 gen_store_gpr(t0, rd);
3912 tcg_temp_free(t0);
3914 break;
3915 case OPC_ADDU:
3916 if (rs != 0 && rt != 0) {
3917 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3918 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3919 } else if (rs == 0 && rt != 0) {
3920 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3921 } else if (rs != 0 && rt == 0) {
3922 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3923 } else {
3924 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3926 break;
3927 case OPC_SUB:
3929 TCGv t0 = tcg_temp_local_new();
3930 TCGv t1 = tcg_temp_new();
3931 TCGv t2 = tcg_temp_new();
3932 TCGLabel *l1 = gen_new_label();
3934 gen_load_gpr(t1, rs);
3935 gen_load_gpr(t2, rt);
3936 tcg_gen_sub_tl(t0, t1, t2);
3937 tcg_gen_ext32s_tl(t0, t0);
3938 tcg_gen_xor_tl(t2, t1, t2);
3939 tcg_gen_xor_tl(t1, t0, t1);
3940 tcg_gen_and_tl(t1, t1, t2);
3941 tcg_temp_free(t2);
3942 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3943 tcg_temp_free(t1);
3944 /* operands of different sign, first operand and result different sign */
3945 generate_exception(ctx, EXCP_OVERFLOW);
3946 gen_set_label(l1);
3947 gen_store_gpr(t0, rd);
3948 tcg_temp_free(t0);
3950 break;
3951 case OPC_SUBU:
3952 if (rs != 0 && rt != 0) {
3953 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3954 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3955 } else if (rs == 0 && rt != 0) {
3956 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3957 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3958 } else if (rs != 0 && rt == 0) {
3959 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3960 } else {
3961 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3963 break;
3964 #if defined(TARGET_MIPS64)
3965 case OPC_DADD:
3967 TCGv t0 = tcg_temp_local_new();
3968 TCGv t1 = tcg_temp_new();
3969 TCGv t2 = tcg_temp_new();
3970 TCGLabel *l1 = gen_new_label();
3972 gen_load_gpr(t1, rs);
3973 gen_load_gpr(t2, rt);
3974 tcg_gen_add_tl(t0, t1, t2);
3975 tcg_gen_xor_tl(t1, t1, t2);
3976 tcg_gen_xor_tl(t2, t0, t2);
3977 tcg_gen_andc_tl(t1, t2, t1);
3978 tcg_temp_free(t2);
3979 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3980 tcg_temp_free(t1);
3981 /* operands of same sign, result different sign */
3982 generate_exception(ctx, EXCP_OVERFLOW);
3983 gen_set_label(l1);
3984 gen_store_gpr(t0, rd);
3985 tcg_temp_free(t0);
3987 break;
3988 case OPC_DADDU:
3989 if (rs != 0 && rt != 0) {
3990 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3991 } else if (rs == 0 && rt != 0) {
3992 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3993 } else if (rs != 0 && rt == 0) {
3994 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3995 } else {
3996 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3998 break;
3999 case OPC_DSUB:
4001 TCGv t0 = tcg_temp_local_new();
4002 TCGv t1 = tcg_temp_new();
4003 TCGv t2 = tcg_temp_new();
4004 TCGLabel *l1 = gen_new_label();
4006 gen_load_gpr(t1, rs);
4007 gen_load_gpr(t2, rt);
4008 tcg_gen_sub_tl(t0, t1, t2);
4009 tcg_gen_xor_tl(t2, t1, t2);
4010 tcg_gen_xor_tl(t1, t0, t1);
4011 tcg_gen_and_tl(t1, t1, t2);
4012 tcg_temp_free(t2);
4013 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4014 tcg_temp_free(t1);
4015 /* operands of different sign, first operand and result different sign */
4016 generate_exception(ctx, EXCP_OVERFLOW);
4017 gen_set_label(l1);
4018 gen_store_gpr(t0, rd);
4019 tcg_temp_free(t0);
4021 break;
4022 case OPC_DSUBU:
4023 if (rs != 0 && rt != 0) {
4024 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4025 } else if (rs == 0 && rt != 0) {
4026 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4027 } else if (rs != 0 && rt == 0) {
4028 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4029 } else {
4030 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4032 break;
4033 #endif
4034 case OPC_MUL:
4035 if (likely(rs != 0 && rt != 0)) {
4036 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4037 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4038 } else {
4039 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4041 break;
4045 /* Conditional move */
4046 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4047 int rd, int rs, int rt)
4049 TCGv t0, t1, t2;
4051 if (rd == 0) {
4052 /* If no destination, treat it as a NOP. */
4053 return;
4056 t0 = tcg_temp_new();
4057 gen_load_gpr(t0, rt);
4058 t1 = tcg_const_tl(0);
4059 t2 = tcg_temp_new();
4060 gen_load_gpr(t2, rs);
4061 switch (opc) {
4062 case OPC_MOVN:
4063 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4064 break;
4065 case OPC_MOVZ:
4066 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4067 break;
4068 case OPC_SELNEZ:
4069 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4070 break;
4071 case OPC_SELEQZ:
4072 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4073 break;
4075 tcg_temp_free(t2);
4076 tcg_temp_free(t1);
4077 tcg_temp_free(t0);
4080 /* Logic */
4081 static void gen_logic(DisasContext *ctx, uint32_t opc,
4082 int rd, int rs, int rt)
4084 if (rd == 0) {
4085 /* If no destination, treat it as a NOP. */
4086 return;
4089 switch (opc) {
4090 case OPC_AND:
4091 if (likely(rs != 0 && rt != 0)) {
4092 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4093 } else {
4094 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4096 break;
4097 case OPC_NOR:
4098 if (rs != 0 && rt != 0) {
4099 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4100 } else if (rs == 0 && rt != 0) {
4101 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4102 } else if (rs != 0 && rt == 0) {
4103 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4104 } else {
4105 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4107 break;
4108 case OPC_OR:
4109 if (likely(rs != 0 && rt != 0)) {
4110 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4111 } else if (rs == 0 && rt != 0) {
4112 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4113 } else if (rs != 0 && rt == 0) {
4114 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4115 } else {
4116 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4118 break;
4119 case OPC_XOR:
4120 if (likely(rs != 0 && rt != 0)) {
4121 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4122 } else if (rs == 0 && rt != 0) {
4123 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4124 } else if (rs != 0 && rt == 0) {
4125 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4126 } else {
4127 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4129 break;
4133 /* Set on lower than */
4134 static void gen_slt(DisasContext *ctx, uint32_t opc,
4135 int rd, int rs, int rt)
4137 TCGv t0, t1;
4139 if (rd == 0) {
4140 /* If no destination, treat it as a NOP. */
4141 return;
4144 t0 = tcg_temp_new();
4145 t1 = tcg_temp_new();
4146 gen_load_gpr(t0, rs);
4147 gen_load_gpr(t1, rt);
4148 switch (opc) {
4149 case OPC_SLT:
4150 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4151 break;
4152 case OPC_SLTU:
4153 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4154 break;
4156 tcg_temp_free(t0);
4157 tcg_temp_free(t1);
4160 /* Shifts */
4161 static void gen_shift(DisasContext *ctx, uint32_t opc,
4162 int rd, int rs, int rt)
4164 TCGv t0, t1;
4166 if (rd == 0) {
4167 /* If no destination, treat it as a NOP.
4168 For add & sub, we must generate the overflow exception when needed. */
4169 return;
4172 t0 = tcg_temp_new();
4173 t1 = tcg_temp_new();
4174 gen_load_gpr(t0, rs);
4175 gen_load_gpr(t1, rt);
4176 switch (opc) {
4177 case OPC_SLLV:
4178 tcg_gen_andi_tl(t0, t0, 0x1f);
4179 tcg_gen_shl_tl(t0, t1, t0);
4180 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4181 break;
4182 case OPC_SRAV:
4183 tcg_gen_andi_tl(t0, t0, 0x1f);
4184 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4185 break;
4186 case OPC_SRLV:
4187 tcg_gen_ext32u_tl(t1, t1);
4188 tcg_gen_andi_tl(t0, t0, 0x1f);
4189 tcg_gen_shr_tl(t0, t1, t0);
4190 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4191 break;
4192 case OPC_ROTRV:
4194 TCGv_i32 t2 = tcg_temp_new_i32();
4195 TCGv_i32 t3 = tcg_temp_new_i32();
4197 tcg_gen_trunc_tl_i32(t2, t0);
4198 tcg_gen_trunc_tl_i32(t3, t1);
4199 tcg_gen_andi_i32(t2, t2, 0x1f);
4200 tcg_gen_rotr_i32(t2, t3, t2);
4201 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4202 tcg_temp_free_i32(t2);
4203 tcg_temp_free_i32(t3);
4205 break;
4206 #if defined(TARGET_MIPS64)
4207 case OPC_DSLLV:
4208 tcg_gen_andi_tl(t0, t0, 0x3f);
4209 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4210 break;
4211 case OPC_DSRAV:
4212 tcg_gen_andi_tl(t0, t0, 0x3f);
4213 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4214 break;
4215 case OPC_DSRLV:
4216 tcg_gen_andi_tl(t0, t0, 0x3f);
4217 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4218 break;
4219 case OPC_DROTRV:
4220 tcg_gen_andi_tl(t0, t0, 0x3f);
4221 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4222 break;
4223 #endif
4225 tcg_temp_free(t0);
4226 tcg_temp_free(t1);
4229 /* Arithmetic on HI/LO registers */
4230 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4232 if (reg == 0 && (opc == OPC_MFHI || opc == TX79_MMI_MFHI1 ||
4233 opc == OPC_MFLO || opc == TX79_MMI_MFLO1)) {
4234 /* Treat as NOP. */
4235 return;
4238 if (acc != 0) {
4239 if (!(ctx->insn_flags & INSN_R5900)) {
4240 check_dsp(ctx);
4244 switch (opc) {
4245 case OPC_MFHI:
4246 case TX79_MMI_MFHI1:
4247 #if defined(TARGET_MIPS64)
4248 if (acc != 0) {
4249 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4250 } else
4251 #endif
4253 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4255 break;
4256 case OPC_MFLO:
4257 case TX79_MMI_MFLO1:
4258 #if defined(TARGET_MIPS64)
4259 if (acc != 0) {
4260 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4261 } else
4262 #endif
4264 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4266 break;
4267 case OPC_MTHI:
4268 case TX79_MMI_MTHI1:
4269 if (reg != 0) {
4270 #if defined(TARGET_MIPS64)
4271 if (acc != 0) {
4272 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4273 } else
4274 #endif
4276 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4278 } else {
4279 tcg_gen_movi_tl(cpu_HI[acc], 0);
4281 break;
4282 case OPC_MTLO:
4283 case TX79_MMI_MTLO1:
4284 if (reg != 0) {
4285 #if defined(TARGET_MIPS64)
4286 if (acc != 0) {
4287 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4288 } else
4289 #endif
4291 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4293 } else {
4294 tcg_gen_movi_tl(cpu_LO[acc], 0);
4296 break;
4300 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4301 TCGMemOp memop)
4303 TCGv t0 = tcg_const_tl(addr);
4304 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4305 gen_store_gpr(t0, reg);
4306 tcg_temp_free(t0);
4309 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4310 int rs)
4312 target_long offset;
4313 target_long addr;
4315 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4316 case OPC_ADDIUPC:
4317 if (rs != 0) {
4318 offset = sextract32(ctx->opcode << 2, 0, 21);
4319 addr = addr_add(ctx, pc, offset);
4320 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4322 break;
4323 case R6_OPC_LWPC:
4324 offset = sextract32(ctx->opcode << 2, 0, 21);
4325 addr = addr_add(ctx, pc, offset);
4326 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4327 break;
4328 #if defined(TARGET_MIPS64)
4329 case OPC_LWUPC:
4330 check_mips_64(ctx);
4331 offset = sextract32(ctx->opcode << 2, 0, 21);
4332 addr = addr_add(ctx, pc, offset);
4333 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4334 break;
4335 #endif
4336 default:
4337 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4338 case OPC_AUIPC:
4339 if (rs != 0) {
4340 offset = sextract32(ctx->opcode, 0, 16) << 16;
4341 addr = addr_add(ctx, pc, offset);
4342 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4344 break;
4345 case OPC_ALUIPC:
4346 if (rs != 0) {
4347 offset = sextract32(ctx->opcode, 0, 16) << 16;
4348 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4349 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4351 break;
4352 #if defined(TARGET_MIPS64)
4353 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4354 case R6_OPC_LDPC + (1 << 16):
4355 case R6_OPC_LDPC + (2 << 16):
4356 case R6_OPC_LDPC + (3 << 16):
4357 check_mips_64(ctx);
4358 offset = sextract32(ctx->opcode << 3, 0, 21);
4359 addr = addr_add(ctx, (pc & ~0x7), offset);
4360 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4361 break;
4362 #endif
4363 default:
4364 MIPS_INVAL("OPC_PCREL");
4365 generate_exception_end(ctx, EXCP_RI);
4366 break;
4368 break;
4372 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4374 TCGv t0, t1;
4376 if (rd == 0) {
4377 /* Treat as NOP. */
4378 return;
4381 t0 = tcg_temp_new();
4382 t1 = tcg_temp_new();
4384 gen_load_gpr(t0, rs);
4385 gen_load_gpr(t1, rt);
4387 switch (opc) {
4388 case R6_OPC_DIV:
4390 TCGv t2 = tcg_temp_new();
4391 TCGv t3 = tcg_temp_new();
4392 tcg_gen_ext32s_tl(t0, t0);
4393 tcg_gen_ext32s_tl(t1, t1);
4394 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4395 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4396 tcg_gen_and_tl(t2, t2, t3);
4397 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4398 tcg_gen_or_tl(t2, t2, t3);
4399 tcg_gen_movi_tl(t3, 0);
4400 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4401 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4402 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4403 tcg_temp_free(t3);
4404 tcg_temp_free(t2);
4406 break;
4407 case R6_OPC_MOD:
4409 TCGv t2 = tcg_temp_new();
4410 TCGv t3 = tcg_temp_new();
4411 tcg_gen_ext32s_tl(t0, t0);
4412 tcg_gen_ext32s_tl(t1, t1);
4413 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4414 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4415 tcg_gen_and_tl(t2, t2, t3);
4416 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4417 tcg_gen_or_tl(t2, t2, t3);
4418 tcg_gen_movi_tl(t3, 0);
4419 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4420 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4421 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4422 tcg_temp_free(t3);
4423 tcg_temp_free(t2);
4425 break;
4426 case R6_OPC_DIVU:
4428 TCGv t2 = tcg_const_tl(0);
4429 TCGv t3 = tcg_const_tl(1);
4430 tcg_gen_ext32u_tl(t0, t0);
4431 tcg_gen_ext32u_tl(t1, t1);
4432 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4433 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4434 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4435 tcg_temp_free(t3);
4436 tcg_temp_free(t2);
4438 break;
4439 case R6_OPC_MODU:
4441 TCGv t2 = tcg_const_tl(0);
4442 TCGv t3 = tcg_const_tl(1);
4443 tcg_gen_ext32u_tl(t0, t0);
4444 tcg_gen_ext32u_tl(t1, t1);
4445 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4446 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4447 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4448 tcg_temp_free(t3);
4449 tcg_temp_free(t2);
4451 break;
4452 case R6_OPC_MUL:
4454 TCGv_i32 t2 = tcg_temp_new_i32();
4455 TCGv_i32 t3 = tcg_temp_new_i32();
4456 tcg_gen_trunc_tl_i32(t2, t0);
4457 tcg_gen_trunc_tl_i32(t3, t1);
4458 tcg_gen_mul_i32(t2, t2, t3);
4459 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4460 tcg_temp_free_i32(t2);
4461 tcg_temp_free_i32(t3);
4463 break;
4464 case R6_OPC_MUH:
4466 TCGv_i32 t2 = tcg_temp_new_i32();
4467 TCGv_i32 t3 = tcg_temp_new_i32();
4468 tcg_gen_trunc_tl_i32(t2, t0);
4469 tcg_gen_trunc_tl_i32(t3, t1);
4470 tcg_gen_muls2_i32(t2, t3, t2, t3);
4471 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4472 tcg_temp_free_i32(t2);
4473 tcg_temp_free_i32(t3);
4475 break;
4476 case R6_OPC_MULU:
4478 TCGv_i32 t2 = tcg_temp_new_i32();
4479 TCGv_i32 t3 = tcg_temp_new_i32();
4480 tcg_gen_trunc_tl_i32(t2, t0);
4481 tcg_gen_trunc_tl_i32(t3, t1);
4482 tcg_gen_mul_i32(t2, t2, t3);
4483 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4484 tcg_temp_free_i32(t2);
4485 tcg_temp_free_i32(t3);
4487 break;
4488 case R6_OPC_MUHU:
4490 TCGv_i32 t2 = tcg_temp_new_i32();
4491 TCGv_i32 t3 = tcg_temp_new_i32();
4492 tcg_gen_trunc_tl_i32(t2, t0);
4493 tcg_gen_trunc_tl_i32(t3, t1);
4494 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4495 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4496 tcg_temp_free_i32(t2);
4497 tcg_temp_free_i32(t3);
4499 break;
4500 #if defined(TARGET_MIPS64)
4501 case R6_OPC_DDIV:
4503 TCGv t2 = tcg_temp_new();
4504 TCGv t3 = tcg_temp_new();
4505 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4506 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4507 tcg_gen_and_tl(t2, t2, t3);
4508 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4509 tcg_gen_or_tl(t2, t2, t3);
4510 tcg_gen_movi_tl(t3, 0);
4511 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4512 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4513 tcg_temp_free(t3);
4514 tcg_temp_free(t2);
4516 break;
4517 case R6_OPC_DMOD:
4519 TCGv t2 = tcg_temp_new();
4520 TCGv t3 = tcg_temp_new();
4521 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4522 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4523 tcg_gen_and_tl(t2, t2, t3);
4524 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4525 tcg_gen_or_tl(t2, t2, t3);
4526 tcg_gen_movi_tl(t3, 0);
4527 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4528 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4529 tcg_temp_free(t3);
4530 tcg_temp_free(t2);
4532 break;
4533 case R6_OPC_DDIVU:
4535 TCGv t2 = tcg_const_tl(0);
4536 TCGv t3 = tcg_const_tl(1);
4537 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4538 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4539 tcg_temp_free(t3);
4540 tcg_temp_free(t2);
4542 break;
4543 case R6_OPC_DMODU:
4545 TCGv t2 = tcg_const_tl(0);
4546 TCGv t3 = tcg_const_tl(1);
4547 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4548 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4549 tcg_temp_free(t3);
4550 tcg_temp_free(t2);
4552 break;
4553 case R6_OPC_DMUL:
4554 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4555 break;
4556 case R6_OPC_DMUH:
4558 TCGv t2 = tcg_temp_new();
4559 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4560 tcg_temp_free(t2);
4562 break;
4563 case R6_OPC_DMULU:
4564 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4565 break;
4566 case R6_OPC_DMUHU:
4568 TCGv t2 = tcg_temp_new();
4569 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4570 tcg_temp_free(t2);
4572 break;
4573 #endif
4574 default:
4575 MIPS_INVAL("r6 mul/div");
4576 generate_exception_end(ctx, EXCP_RI);
4577 goto out;
4579 out:
4580 tcg_temp_free(t0);
4581 tcg_temp_free(t1);
4584 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4585 int acc, int rs, int rt)
4587 TCGv t0, t1;
4589 t0 = tcg_temp_new();
4590 t1 = tcg_temp_new();
4592 gen_load_gpr(t0, rs);
4593 gen_load_gpr(t1, rt);
4595 if (acc != 0) {
4596 if (!(ctx->insn_flags & INSN_R5900)) {
4597 check_dsp(ctx);
4601 switch (opc) {
4602 case OPC_DIV:
4603 case TX79_MMI_DIV1:
4605 TCGv t2 = tcg_temp_new();
4606 TCGv t3 = tcg_temp_new();
4607 tcg_gen_ext32s_tl(t0, t0);
4608 tcg_gen_ext32s_tl(t1, t1);
4609 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4610 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4611 tcg_gen_and_tl(t2, t2, t3);
4612 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4613 tcg_gen_or_tl(t2, t2, t3);
4614 tcg_gen_movi_tl(t3, 0);
4615 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4616 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4617 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4618 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4619 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4620 tcg_temp_free(t3);
4621 tcg_temp_free(t2);
4623 break;
4624 case OPC_DIVU:
4625 case TX79_MMI_DIVU1:
4627 TCGv t2 = tcg_const_tl(0);
4628 TCGv t3 = tcg_const_tl(1);
4629 tcg_gen_ext32u_tl(t0, t0);
4630 tcg_gen_ext32u_tl(t1, t1);
4631 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4632 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4633 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4634 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4635 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4636 tcg_temp_free(t3);
4637 tcg_temp_free(t2);
4639 break;
4640 case OPC_MULT:
4642 TCGv_i32 t2 = tcg_temp_new_i32();
4643 TCGv_i32 t3 = tcg_temp_new_i32();
4644 tcg_gen_trunc_tl_i32(t2, t0);
4645 tcg_gen_trunc_tl_i32(t3, t1);
4646 tcg_gen_muls2_i32(t2, t3, t2, t3);
4647 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4648 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4649 tcg_temp_free_i32(t2);
4650 tcg_temp_free_i32(t3);
4652 break;
4653 case OPC_MULTU:
4655 TCGv_i32 t2 = tcg_temp_new_i32();
4656 TCGv_i32 t3 = tcg_temp_new_i32();
4657 tcg_gen_trunc_tl_i32(t2, t0);
4658 tcg_gen_trunc_tl_i32(t3, t1);
4659 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4660 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4661 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4662 tcg_temp_free_i32(t2);
4663 tcg_temp_free_i32(t3);
4665 break;
4666 #if defined(TARGET_MIPS64)
4667 case OPC_DDIV:
4669 TCGv t2 = tcg_temp_new();
4670 TCGv t3 = tcg_temp_new();
4671 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4672 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4673 tcg_gen_and_tl(t2, t2, t3);
4674 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4675 tcg_gen_or_tl(t2, t2, t3);
4676 tcg_gen_movi_tl(t3, 0);
4677 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4678 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4679 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4680 tcg_temp_free(t3);
4681 tcg_temp_free(t2);
4683 break;
4684 case OPC_DDIVU:
4686 TCGv t2 = tcg_const_tl(0);
4687 TCGv t3 = tcg_const_tl(1);
4688 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4689 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4690 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4691 tcg_temp_free(t3);
4692 tcg_temp_free(t2);
4694 break;
4695 case OPC_DMULT:
4696 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4697 break;
4698 case OPC_DMULTU:
4699 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4700 break;
4701 #endif
4702 case OPC_MADD:
4704 TCGv_i64 t2 = tcg_temp_new_i64();
4705 TCGv_i64 t3 = tcg_temp_new_i64();
4707 tcg_gen_ext_tl_i64(t2, t0);
4708 tcg_gen_ext_tl_i64(t3, t1);
4709 tcg_gen_mul_i64(t2, t2, t3);
4710 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4711 tcg_gen_add_i64(t2, t2, t3);
4712 tcg_temp_free_i64(t3);
4713 gen_move_low32(cpu_LO[acc], t2);
4714 gen_move_high32(cpu_HI[acc], t2);
4715 tcg_temp_free_i64(t2);
4717 break;
4718 case OPC_MADDU:
4720 TCGv_i64 t2 = tcg_temp_new_i64();
4721 TCGv_i64 t3 = tcg_temp_new_i64();
4723 tcg_gen_ext32u_tl(t0, t0);
4724 tcg_gen_ext32u_tl(t1, t1);
4725 tcg_gen_extu_tl_i64(t2, t0);
4726 tcg_gen_extu_tl_i64(t3, t1);
4727 tcg_gen_mul_i64(t2, t2, t3);
4728 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4729 tcg_gen_add_i64(t2, t2, t3);
4730 tcg_temp_free_i64(t3);
4731 gen_move_low32(cpu_LO[acc], t2);
4732 gen_move_high32(cpu_HI[acc], t2);
4733 tcg_temp_free_i64(t2);
4735 break;
4736 case OPC_MSUB:
4738 TCGv_i64 t2 = tcg_temp_new_i64();
4739 TCGv_i64 t3 = tcg_temp_new_i64();
4741 tcg_gen_ext_tl_i64(t2, t0);
4742 tcg_gen_ext_tl_i64(t3, t1);
4743 tcg_gen_mul_i64(t2, t2, t3);
4744 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4745 tcg_gen_sub_i64(t2, t3, t2);
4746 tcg_temp_free_i64(t3);
4747 gen_move_low32(cpu_LO[acc], t2);
4748 gen_move_high32(cpu_HI[acc], t2);
4749 tcg_temp_free_i64(t2);
4751 break;
4752 case OPC_MSUBU:
4754 TCGv_i64 t2 = tcg_temp_new_i64();
4755 TCGv_i64 t3 = tcg_temp_new_i64();
4757 tcg_gen_ext32u_tl(t0, t0);
4758 tcg_gen_ext32u_tl(t1, t1);
4759 tcg_gen_extu_tl_i64(t2, t0);
4760 tcg_gen_extu_tl_i64(t3, t1);
4761 tcg_gen_mul_i64(t2, t2, t3);
4762 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4763 tcg_gen_sub_i64(t2, t3, t2);
4764 tcg_temp_free_i64(t3);
4765 gen_move_low32(cpu_LO[acc], t2);
4766 gen_move_high32(cpu_HI[acc], t2);
4767 tcg_temp_free_i64(t2);
4769 break;
4770 default:
4771 MIPS_INVAL("mul/div");
4772 generate_exception_end(ctx, EXCP_RI);
4773 goto out;
4775 out:
4776 tcg_temp_free(t0);
4777 tcg_temp_free(t1);
4781 * These MULT and MULTU instructions implemented in for example the
4782 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4783 * architectures are special three-operand variants with the syntax
4785 * MULT[U][1] rd, rs, rt
4787 * such that
4789 * (rd, LO, HI) <- rs * rt
4791 * where the low-order 32-bits of the result is placed into both the
4792 * GPR rd and the special register LO. The high-order 32-bits of the
4793 * result is placed into the special register HI.
4795 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4796 * which is the zero register that always reads as 0.
4798 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4799 int rd, int rs, int rt)
4801 TCGv t0 = tcg_temp_new();
4802 TCGv t1 = tcg_temp_new();
4803 int acc = 0;
4805 gen_load_gpr(t0, rs);
4806 gen_load_gpr(t1, rt);
4808 switch (opc) {
4809 case TX79_MMI_MULT1:
4810 acc = 1;
4811 /* Fall through */
4812 case OPC_MULT:
4814 TCGv_i32 t2 = tcg_temp_new_i32();
4815 TCGv_i32 t3 = tcg_temp_new_i32();
4816 tcg_gen_trunc_tl_i32(t2, t0);
4817 tcg_gen_trunc_tl_i32(t3, t1);
4818 tcg_gen_muls2_i32(t2, t3, t2, t3);
4819 if (rd) {
4820 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4822 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4823 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4824 tcg_temp_free_i32(t2);
4825 tcg_temp_free_i32(t3);
4827 break;
4828 case TX79_MMI_MULTU1:
4829 acc = 1;
4830 /* Fall through */
4831 case OPC_MULTU:
4833 TCGv_i32 t2 = tcg_temp_new_i32();
4834 TCGv_i32 t3 = tcg_temp_new_i32();
4835 tcg_gen_trunc_tl_i32(t2, t0);
4836 tcg_gen_trunc_tl_i32(t3, t1);
4837 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4838 if (rd) {
4839 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4841 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4842 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4843 tcg_temp_free_i32(t2);
4844 tcg_temp_free_i32(t3);
4846 break;
4847 default:
4848 MIPS_INVAL("mul TXx9");
4849 generate_exception_end(ctx, EXCP_RI);
4850 goto out;
4853 out:
4854 tcg_temp_free(t0);
4855 tcg_temp_free(t1);
4858 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4859 int rd, int rs, int rt)
4861 TCGv t0 = tcg_temp_new();
4862 TCGv t1 = tcg_temp_new();
4864 gen_load_gpr(t0, rs);
4865 gen_load_gpr(t1, rt);
4867 switch (opc) {
4868 case OPC_VR54XX_MULS:
4869 gen_helper_muls(t0, cpu_env, t0, t1);
4870 break;
4871 case OPC_VR54XX_MULSU:
4872 gen_helper_mulsu(t0, cpu_env, t0, t1);
4873 break;
4874 case OPC_VR54XX_MACC:
4875 gen_helper_macc(t0, cpu_env, t0, t1);
4876 break;
4877 case OPC_VR54XX_MACCU:
4878 gen_helper_maccu(t0, cpu_env, t0, t1);
4879 break;
4880 case OPC_VR54XX_MSAC:
4881 gen_helper_msac(t0, cpu_env, t0, t1);
4882 break;
4883 case OPC_VR54XX_MSACU:
4884 gen_helper_msacu(t0, cpu_env, t0, t1);
4885 break;
4886 case OPC_VR54XX_MULHI:
4887 gen_helper_mulhi(t0, cpu_env, t0, t1);
4888 break;
4889 case OPC_VR54XX_MULHIU:
4890 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4891 break;
4892 case OPC_VR54XX_MULSHI:
4893 gen_helper_mulshi(t0, cpu_env, t0, t1);
4894 break;
4895 case OPC_VR54XX_MULSHIU:
4896 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4897 break;
4898 case OPC_VR54XX_MACCHI:
4899 gen_helper_macchi(t0, cpu_env, t0, t1);
4900 break;
4901 case OPC_VR54XX_MACCHIU:
4902 gen_helper_macchiu(t0, cpu_env, t0, t1);
4903 break;
4904 case OPC_VR54XX_MSACHI:
4905 gen_helper_msachi(t0, cpu_env, t0, t1);
4906 break;
4907 case OPC_VR54XX_MSACHIU:
4908 gen_helper_msachiu(t0, cpu_env, t0, t1);
4909 break;
4910 default:
4911 MIPS_INVAL("mul vr54xx");
4912 generate_exception_end(ctx, EXCP_RI);
4913 goto out;
4915 gen_store_gpr(t0, rd);
4917 out:
4918 tcg_temp_free(t0);
4919 tcg_temp_free(t1);
4922 static void gen_cl (DisasContext *ctx, uint32_t opc,
4923 int rd, int rs)
4925 TCGv t0;
4927 if (rd == 0) {
4928 /* Treat as NOP. */
4929 return;
4931 t0 = cpu_gpr[rd];
4932 gen_load_gpr(t0, rs);
4934 switch (opc) {
4935 case OPC_CLO:
4936 case R6_OPC_CLO:
4937 #if defined(TARGET_MIPS64)
4938 case OPC_DCLO:
4939 case R6_OPC_DCLO:
4940 #endif
4941 tcg_gen_not_tl(t0, t0);
4942 break;
4945 switch (opc) {
4946 case OPC_CLO:
4947 case R6_OPC_CLO:
4948 case OPC_CLZ:
4949 case R6_OPC_CLZ:
4950 tcg_gen_ext32u_tl(t0, t0);
4951 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4952 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4953 break;
4954 #if defined(TARGET_MIPS64)
4955 case OPC_DCLO:
4956 case R6_OPC_DCLO:
4957 case OPC_DCLZ:
4958 case R6_OPC_DCLZ:
4959 tcg_gen_clzi_i64(t0, t0, 64);
4960 break;
4961 #endif
4965 /* Godson integer instructions */
4966 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4967 int rd, int rs, int rt)
4969 TCGv t0, t1;
4971 if (rd == 0) {
4972 /* Treat as NOP. */
4973 return;
4976 switch (opc) {
4977 case OPC_MULT_G_2E:
4978 case OPC_MULT_G_2F:
4979 case OPC_MULTU_G_2E:
4980 case OPC_MULTU_G_2F:
4981 #if defined(TARGET_MIPS64)
4982 case OPC_DMULT_G_2E:
4983 case OPC_DMULT_G_2F:
4984 case OPC_DMULTU_G_2E:
4985 case OPC_DMULTU_G_2F:
4986 #endif
4987 t0 = tcg_temp_new();
4988 t1 = tcg_temp_new();
4989 break;
4990 default:
4991 t0 = tcg_temp_local_new();
4992 t1 = tcg_temp_local_new();
4993 break;
4996 gen_load_gpr(t0, rs);
4997 gen_load_gpr(t1, rt);
4999 switch (opc) {
5000 case OPC_MULT_G_2E:
5001 case OPC_MULT_G_2F:
5002 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5003 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5004 break;
5005 case OPC_MULTU_G_2E:
5006 case OPC_MULTU_G_2F:
5007 tcg_gen_ext32u_tl(t0, t0);
5008 tcg_gen_ext32u_tl(t1, t1);
5009 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5010 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5011 break;
5012 case OPC_DIV_G_2E:
5013 case OPC_DIV_G_2F:
5015 TCGLabel *l1 = gen_new_label();
5016 TCGLabel *l2 = gen_new_label();
5017 TCGLabel *l3 = gen_new_label();
5018 tcg_gen_ext32s_tl(t0, t0);
5019 tcg_gen_ext32s_tl(t1, t1);
5020 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5021 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5022 tcg_gen_br(l3);
5023 gen_set_label(l1);
5024 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5025 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5026 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5027 tcg_gen_br(l3);
5028 gen_set_label(l2);
5029 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5030 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5031 gen_set_label(l3);
5033 break;
5034 case OPC_DIVU_G_2E:
5035 case OPC_DIVU_G_2F:
5037 TCGLabel *l1 = gen_new_label();
5038 TCGLabel *l2 = gen_new_label();
5039 tcg_gen_ext32u_tl(t0, t0);
5040 tcg_gen_ext32u_tl(t1, t1);
5041 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5042 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5043 tcg_gen_br(l2);
5044 gen_set_label(l1);
5045 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5046 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5047 gen_set_label(l2);
5049 break;
5050 case OPC_MOD_G_2E:
5051 case OPC_MOD_G_2F:
5053 TCGLabel *l1 = gen_new_label();
5054 TCGLabel *l2 = gen_new_label();
5055 TCGLabel *l3 = gen_new_label();
5056 tcg_gen_ext32u_tl(t0, t0);
5057 tcg_gen_ext32u_tl(t1, t1);
5058 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5059 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5060 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5061 gen_set_label(l1);
5062 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5063 tcg_gen_br(l3);
5064 gen_set_label(l2);
5065 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5066 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5067 gen_set_label(l3);
5069 break;
5070 case OPC_MODU_G_2E:
5071 case OPC_MODU_G_2F:
5073 TCGLabel *l1 = gen_new_label();
5074 TCGLabel *l2 = gen_new_label();
5075 tcg_gen_ext32u_tl(t0, t0);
5076 tcg_gen_ext32u_tl(t1, t1);
5077 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5078 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5079 tcg_gen_br(l2);
5080 gen_set_label(l1);
5081 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5082 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5083 gen_set_label(l2);
5085 break;
5086 #if defined(TARGET_MIPS64)
5087 case OPC_DMULT_G_2E:
5088 case OPC_DMULT_G_2F:
5089 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5090 break;
5091 case OPC_DMULTU_G_2E:
5092 case OPC_DMULTU_G_2F:
5093 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5094 break;
5095 case OPC_DDIV_G_2E:
5096 case OPC_DDIV_G_2F:
5098 TCGLabel *l1 = gen_new_label();
5099 TCGLabel *l2 = gen_new_label();
5100 TCGLabel *l3 = gen_new_label();
5101 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5102 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5103 tcg_gen_br(l3);
5104 gen_set_label(l1);
5105 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5106 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5107 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5108 tcg_gen_br(l3);
5109 gen_set_label(l2);
5110 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5111 gen_set_label(l3);
5113 break;
5114 case OPC_DDIVU_G_2E:
5115 case OPC_DDIVU_G_2F:
5117 TCGLabel *l1 = gen_new_label();
5118 TCGLabel *l2 = gen_new_label();
5119 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5120 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5121 tcg_gen_br(l2);
5122 gen_set_label(l1);
5123 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5124 gen_set_label(l2);
5126 break;
5127 case OPC_DMOD_G_2E:
5128 case OPC_DMOD_G_2F:
5130 TCGLabel *l1 = gen_new_label();
5131 TCGLabel *l2 = gen_new_label();
5132 TCGLabel *l3 = gen_new_label();
5133 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5134 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5135 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5136 gen_set_label(l1);
5137 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5138 tcg_gen_br(l3);
5139 gen_set_label(l2);
5140 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5141 gen_set_label(l3);
5143 break;
5144 case OPC_DMODU_G_2E:
5145 case OPC_DMODU_G_2F:
5147 TCGLabel *l1 = gen_new_label();
5148 TCGLabel *l2 = gen_new_label();
5149 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5150 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5151 tcg_gen_br(l2);
5152 gen_set_label(l1);
5153 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5154 gen_set_label(l2);
5156 break;
5157 #endif
5160 tcg_temp_free(t0);
5161 tcg_temp_free(t1);
5164 /* Loongson multimedia instructions */
5165 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5167 uint32_t opc, shift_max;
5168 TCGv_i64 t0, t1;
5170 opc = MASK_LMI(ctx->opcode);
5171 switch (opc) {
5172 case OPC_ADD_CP2:
5173 case OPC_SUB_CP2:
5174 case OPC_DADD_CP2:
5175 case OPC_DSUB_CP2:
5176 t0 = tcg_temp_local_new_i64();
5177 t1 = tcg_temp_local_new_i64();
5178 break;
5179 default:
5180 t0 = tcg_temp_new_i64();
5181 t1 = tcg_temp_new_i64();
5182 break;
5185 check_cp1_enabled(ctx);
5186 gen_load_fpr64(ctx, t0, rs);
5187 gen_load_fpr64(ctx, t1, rt);
5189 #define LMI_HELPER(UP, LO) \
5190 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5191 #define LMI_HELPER_1(UP, LO) \
5192 case OPC_##UP: gen_helper_##LO(t0, t0); break
5193 #define LMI_DIRECT(UP, LO, OP) \
5194 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5196 switch (opc) {
5197 LMI_HELPER(PADDSH, paddsh);
5198 LMI_HELPER(PADDUSH, paddush);
5199 LMI_HELPER(PADDH, paddh);
5200 LMI_HELPER(PADDW, paddw);
5201 LMI_HELPER(PADDSB, paddsb);
5202 LMI_HELPER(PADDUSB, paddusb);
5203 LMI_HELPER(PADDB, paddb);
5205 LMI_HELPER(PSUBSH, psubsh);
5206 LMI_HELPER(PSUBUSH, psubush);
5207 LMI_HELPER(PSUBH, psubh);
5208 LMI_HELPER(PSUBW, psubw);
5209 LMI_HELPER(PSUBSB, psubsb);
5210 LMI_HELPER(PSUBUSB, psubusb);
5211 LMI_HELPER(PSUBB, psubb);
5213 LMI_HELPER(PSHUFH, pshufh);
5214 LMI_HELPER(PACKSSWH, packsswh);
5215 LMI_HELPER(PACKSSHB, packsshb);
5216 LMI_HELPER(PACKUSHB, packushb);
5218 LMI_HELPER(PUNPCKLHW, punpcklhw);
5219 LMI_HELPER(PUNPCKHHW, punpckhhw);
5220 LMI_HELPER(PUNPCKLBH, punpcklbh);
5221 LMI_HELPER(PUNPCKHBH, punpckhbh);
5222 LMI_HELPER(PUNPCKLWD, punpcklwd);
5223 LMI_HELPER(PUNPCKHWD, punpckhwd);
5225 LMI_HELPER(PAVGH, pavgh);
5226 LMI_HELPER(PAVGB, pavgb);
5227 LMI_HELPER(PMAXSH, pmaxsh);
5228 LMI_HELPER(PMINSH, pminsh);
5229 LMI_HELPER(PMAXUB, pmaxub);
5230 LMI_HELPER(PMINUB, pminub);
5232 LMI_HELPER(PCMPEQW, pcmpeqw);
5233 LMI_HELPER(PCMPGTW, pcmpgtw);
5234 LMI_HELPER(PCMPEQH, pcmpeqh);
5235 LMI_HELPER(PCMPGTH, pcmpgth);
5236 LMI_HELPER(PCMPEQB, pcmpeqb);
5237 LMI_HELPER(PCMPGTB, pcmpgtb);
5239 LMI_HELPER(PSLLW, psllw);
5240 LMI_HELPER(PSLLH, psllh);
5241 LMI_HELPER(PSRLW, psrlw);
5242 LMI_HELPER(PSRLH, psrlh);
5243 LMI_HELPER(PSRAW, psraw);
5244 LMI_HELPER(PSRAH, psrah);
5246 LMI_HELPER(PMULLH, pmullh);
5247 LMI_HELPER(PMULHH, pmulhh);
5248 LMI_HELPER(PMULHUH, pmulhuh);
5249 LMI_HELPER(PMADDHW, pmaddhw);
5251 LMI_HELPER(PASUBUB, pasubub);
5252 LMI_HELPER_1(BIADD, biadd);
5253 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5255 LMI_DIRECT(PADDD, paddd, add);
5256 LMI_DIRECT(PSUBD, psubd, sub);
5257 LMI_DIRECT(XOR_CP2, xor, xor);
5258 LMI_DIRECT(NOR_CP2, nor, nor);
5259 LMI_DIRECT(AND_CP2, and, and);
5260 LMI_DIRECT(OR_CP2, or, or);
5262 case OPC_PANDN:
5263 tcg_gen_andc_i64(t0, t1, t0);
5264 break;
5266 case OPC_PINSRH_0:
5267 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5268 break;
5269 case OPC_PINSRH_1:
5270 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5271 break;
5272 case OPC_PINSRH_2:
5273 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5274 break;
5275 case OPC_PINSRH_3:
5276 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5277 break;
5279 case OPC_PEXTRH:
5280 tcg_gen_andi_i64(t1, t1, 3);
5281 tcg_gen_shli_i64(t1, t1, 4);
5282 tcg_gen_shr_i64(t0, t0, t1);
5283 tcg_gen_ext16u_i64(t0, t0);
5284 break;
5286 case OPC_ADDU_CP2:
5287 tcg_gen_add_i64(t0, t0, t1);
5288 tcg_gen_ext32s_i64(t0, t0);
5289 break;
5290 case OPC_SUBU_CP2:
5291 tcg_gen_sub_i64(t0, t0, t1);
5292 tcg_gen_ext32s_i64(t0, t0);
5293 break;
5295 case OPC_SLL_CP2:
5296 shift_max = 32;
5297 goto do_shift;
5298 case OPC_SRL_CP2:
5299 shift_max = 32;
5300 goto do_shift;
5301 case OPC_SRA_CP2:
5302 shift_max = 32;
5303 goto do_shift;
5304 case OPC_DSLL_CP2:
5305 shift_max = 64;
5306 goto do_shift;
5307 case OPC_DSRL_CP2:
5308 shift_max = 64;
5309 goto do_shift;
5310 case OPC_DSRA_CP2:
5311 shift_max = 64;
5312 goto do_shift;
5313 do_shift:
5314 /* Make sure shift count isn't TCG undefined behaviour. */
5315 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5317 switch (opc) {
5318 case OPC_SLL_CP2:
5319 case OPC_DSLL_CP2:
5320 tcg_gen_shl_i64(t0, t0, t1);
5321 break;
5322 case OPC_SRA_CP2:
5323 case OPC_DSRA_CP2:
5324 /* Since SRA is UndefinedResult without sign-extended inputs,
5325 we can treat SRA and DSRA the same. */
5326 tcg_gen_sar_i64(t0, t0, t1);
5327 break;
5328 case OPC_SRL_CP2:
5329 /* We want to shift in zeros for SRL; zero-extend first. */
5330 tcg_gen_ext32u_i64(t0, t0);
5331 /* FALLTHRU */
5332 case OPC_DSRL_CP2:
5333 tcg_gen_shr_i64(t0, t0, t1);
5334 break;
5337 if (shift_max == 32) {
5338 tcg_gen_ext32s_i64(t0, t0);
5341 /* Shifts larger than MAX produce zero. */
5342 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5343 tcg_gen_neg_i64(t1, t1);
5344 tcg_gen_and_i64(t0, t0, t1);
5345 break;
5347 case OPC_ADD_CP2:
5348 case OPC_DADD_CP2:
5350 TCGv_i64 t2 = tcg_temp_new_i64();
5351 TCGLabel *lab = gen_new_label();
5353 tcg_gen_mov_i64(t2, t0);
5354 tcg_gen_add_i64(t0, t1, t2);
5355 if (opc == OPC_ADD_CP2) {
5356 tcg_gen_ext32s_i64(t0, t0);
5358 tcg_gen_xor_i64(t1, t1, t2);
5359 tcg_gen_xor_i64(t2, t2, t0);
5360 tcg_gen_andc_i64(t1, t2, t1);
5361 tcg_temp_free_i64(t2);
5362 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5363 generate_exception(ctx, EXCP_OVERFLOW);
5364 gen_set_label(lab);
5365 break;
5368 case OPC_SUB_CP2:
5369 case OPC_DSUB_CP2:
5371 TCGv_i64 t2 = tcg_temp_new_i64();
5372 TCGLabel *lab = gen_new_label();
5374 tcg_gen_mov_i64(t2, t0);
5375 tcg_gen_sub_i64(t0, t1, t2);
5376 if (opc == OPC_SUB_CP2) {
5377 tcg_gen_ext32s_i64(t0, t0);
5379 tcg_gen_xor_i64(t1, t1, t2);
5380 tcg_gen_xor_i64(t2, t2, t0);
5381 tcg_gen_and_i64(t1, t1, t2);
5382 tcg_temp_free_i64(t2);
5383 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5384 generate_exception(ctx, EXCP_OVERFLOW);
5385 gen_set_label(lab);
5386 break;
5389 case OPC_PMULUW:
5390 tcg_gen_ext32u_i64(t0, t0);
5391 tcg_gen_ext32u_i64(t1, t1);
5392 tcg_gen_mul_i64(t0, t0, t1);
5393 break;
5395 case OPC_SEQU_CP2:
5396 case OPC_SEQ_CP2:
5397 case OPC_SLTU_CP2:
5398 case OPC_SLT_CP2:
5399 case OPC_SLEU_CP2:
5400 case OPC_SLE_CP2:
5401 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5402 FD field is the CC field? */
5403 default:
5404 MIPS_INVAL("loongson_cp2");
5405 generate_exception_end(ctx, EXCP_RI);
5406 return;
5409 #undef LMI_HELPER
5410 #undef LMI_DIRECT
5412 gen_store_fpr64(ctx, t0, rd);
5414 tcg_temp_free_i64(t0);
5415 tcg_temp_free_i64(t1);
5418 /* Traps */
5419 static void gen_trap (DisasContext *ctx, uint32_t opc,
5420 int rs, int rt, int16_t imm)
5422 int cond;
5423 TCGv t0 = tcg_temp_new();
5424 TCGv t1 = tcg_temp_new();
5426 cond = 0;
5427 /* Load needed operands */
5428 switch (opc) {
5429 case OPC_TEQ:
5430 case OPC_TGE:
5431 case OPC_TGEU:
5432 case OPC_TLT:
5433 case OPC_TLTU:
5434 case OPC_TNE:
5435 /* Compare two registers */
5436 if (rs != rt) {
5437 gen_load_gpr(t0, rs);
5438 gen_load_gpr(t1, rt);
5439 cond = 1;
5441 break;
5442 case OPC_TEQI:
5443 case OPC_TGEI:
5444 case OPC_TGEIU:
5445 case OPC_TLTI:
5446 case OPC_TLTIU:
5447 case OPC_TNEI:
5448 /* Compare register to immediate */
5449 if (rs != 0 || imm != 0) {
5450 gen_load_gpr(t0, rs);
5451 tcg_gen_movi_tl(t1, (int32_t)imm);
5452 cond = 1;
5454 break;
5456 if (cond == 0) {
5457 switch (opc) {
5458 case OPC_TEQ: /* rs == rs */
5459 case OPC_TEQI: /* r0 == 0 */
5460 case OPC_TGE: /* rs >= rs */
5461 case OPC_TGEI: /* r0 >= 0 */
5462 case OPC_TGEU: /* rs >= rs unsigned */
5463 case OPC_TGEIU: /* r0 >= 0 unsigned */
5464 /* Always trap */
5465 generate_exception_end(ctx, EXCP_TRAP);
5466 break;
5467 case OPC_TLT: /* rs < rs */
5468 case OPC_TLTI: /* r0 < 0 */
5469 case OPC_TLTU: /* rs < rs unsigned */
5470 case OPC_TLTIU: /* r0 < 0 unsigned */
5471 case OPC_TNE: /* rs != rs */
5472 case OPC_TNEI: /* r0 != 0 */
5473 /* Never trap: treat as NOP. */
5474 break;
5476 } else {
5477 TCGLabel *l1 = gen_new_label();
5479 switch (opc) {
5480 case OPC_TEQ:
5481 case OPC_TEQI:
5482 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5483 break;
5484 case OPC_TGE:
5485 case OPC_TGEI:
5486 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5487 break;
5488 case OPC_TGEU:
5489 case OPC_TGEIU:
5490 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5491 break;
5492 case OPC_TLT:
5493 case OPC_TLTI:
5494 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5495 break;
5496 case OPC_TLTU:
5497 case OPC_TLTIU:
5498 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5499 break;
5500 case OPC_TNE:
5501 case OPC_TNEI:
5502 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5503 break;
5505 generate_exception(ctx, EXCP_TRAP);
5506 gen_set_label(l1);
5508 tcg_temp_free(t0);
5509 tcg_temp_free(t1);
5512 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5514 if (unlikely(ctx->base.singlestep_enabled)) {
5515 return false;
5518 #ifndef CONFIG_USER_ONLY
5519 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5520 #else
5521 return true;
5522 #endif
5525 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5527 if (use_goto_tb(ctx, dest)) {
5528 tcg_gen_goto_tb(n);
5529 gen_save_pc(dest);
5530 tcg_gen_exit_tb(ctx->base.tb, n);
5531 } else {
5532 gen_save_pc(dest);
5533 if (ctx->base.singlestep_enabled) {
5534 save_cpu_state(ctx, 0);
5535 gen_helper_raise_exception_debug(cpu_env);
5537 tcg_gen_lookup_and_goto_ptr();
5541 /* Branches (before delay slot) */
5542 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5543 int insn_bytes,
5544 int rs, int rt, int32_t offset,
5545 int delayslot_size)
5547 target_ulong btgt = -1;
5548 int blink = 0;
5549 int bcond_compute = 0;
5550 TCGv t0 = tcg_temp_new();
5551 TCGv t1 = tcg_temp_new();
5553 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5554 #ifdef MIPS_DEBUG_DISAS
5555 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5556 TARGET_FMT_lx "\n", ctx->base.pc_next);
5557 #endif
5558 generate_exception_end(ctx, EXCP_RI);
5559 goto out;
5562 /* Load needed operands */
5563 switch (opc) {
5564 case OPC_BEQ:
5565 case OPC_BEQL:
5566 case OPC_BNE:
5567 case OPC_BNEL:
5568 /* Compare two registers */
5569 if (rs != rt) {
5570 gen_load_gpr(t0, rs);
5571 gen_load_gpr(t1, rt);
5572 bcond_compute = 1;
5574 btgt = ctx->base.pc_next + insn_bytes + offset;
5575 break;
5576 case OPC_BGEZ:
5577 case OPC_BGEZAL:
5578 case OPC_BGEZALL:
5579 case OPC_BGEZL:
5580 case OPC_BGTZ:
5581 case OPC_BGTZL:
5582 case OPC_BLEZ:
5583 case OPC_BLEZL:
5584 case OPC_BLTZ:
5585 case OPC_BLTZAL:
5586 case OPC_BLTZALL:
5587 case OPC_BLTZL:
5588 /* Compare to zero */
5589 if (rs != 0) {
5590 gen_load_gpr(t0, rs);
5591 bcond_compute = 1;
5593 btgt = ctx->base.pc_next + insn_bytes + offset;
5594 break;
5595 case OPC_BPOSGE32:
5596 #if defined(TARGET_MIPS64)
5597 case OPC_BPOSGE64:
5598 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5599 #else
5600 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5601 #endif
5602 bcond_compute = 1;
5603 btgt = ctx->base.pc_next + insn_bytes + offset;
5604 break;
5605 case OPC_J:
5606 case OPC_JAL:
5607 case OPC_JALX:
5608 /* Jump to immediate */
5609 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5610 (uint32_t)offset;
5611 break;
5612 case OPC_JR:
5613 case OPC_JALR:
5614 /* Jump to register */
5615 if (offset != 0 && offset != 16) {
5616 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5617 others are reserved. */
5618 MIPS_INVAL("jump hint");
5619 generate_exception_end(ctx, EXCP_RI);
5620 goto out;
5622 gen_load_gpr(btarget, rs);
5623 break;
5624 default:
5625 MIPS_INVAL("branch/jump");
5626 generate_exception_end(ctx, EXCP_RI);
5627 goto out;
5629 if (bcond_compute == 0) {
5630 /* No condition to be computed */
5631 switch (opc) {
5632 case OPC_BEQ: /* rx == rx */
5633 case OPC_BEQL: /* rx == rx likely */
5634 case OPC_BGEZ: /* 0 >= 0 */
5635 case OPC_BGEZL: /* 0 >= 0 likely */
5636 case OPC_BLEZ: /* 0 <= 0 */
5637 case OPC_BLEZL: /* 0 <= 0 likely */
5638 /* Always take */
5639 ctx->hflags |= MIPS_HFLAG_B;
5640 break;
5641 case OPC_BGEZAL: /* 0 >= 0 */
5642 case OPC_BGEZALL: /* 0 >= 0 likely */
5643 /* Always take and link */
5644 blink = 31;
5645 ctx->hflags |= MIPS_HFLAG_B;
5646 break;
5647 case OPC_BNE: /* rx != rx */
5648 case OPC_BGTZ: /* 0 > 0 */
5649 case OPC_BLTZ: /* 0 < 0 */
5650 /* Treat as NOP. */
5651 goto out;
5652 case OPC_BLTZAL: /* 0 < 0 */
5653 /* Handle as an unconditional branch to get correct delay
5654 slot checking. */
5655 blink = 31;
5656 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5657 ctx->hflags |= MIPS_HFLAG_B;
5658 break;
5659 case OPC_BLTZALL: /* 0 < 0 likely */
5660 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5661 /* Skip the instruction in the delay slot */
5662 ctx->base.pc_next += 4;
5663 goto out;
5664 case OPC_BNEL: /* rx != rx likely */
5665 case OPC_BGTZL: /* 0 > 0 likely */
5666 case OPC_BLTZL: /* 0 < 0 likely */
5667 /* Skip the instruction in the delay slot */
5668 ctx->base.pc_next += 4;
5669 goto out;
5670 case OPC_J:
5671 ctx->hflags |= MIPS_HFLAG_B;
5672 break;
5673 case OPC_JALX:
5674 ctx->hflags |= MIPS_HFLAG_BX;
5675 /* Fallthrough */
5676 case OPC_JAL:
5677 blink = 31;
5678 ctx->hflags |= MIPS_HFLAG_B;
5679 break;
5680 case OPC_JR:
5681 ctx->hflags |= MIPS_HFLAG_BR;
5682 break;
5683 case OPC_JALR:
5684 blink = rt;
5685 ctx->hflags |= MIPS_HFLAG_BR;
5686 break;
5687 default:
5688 MIPS_INVAL("branch/jump");
5689 generate_exception_end(ctx, EXCP_RI);
5690 goto out;
5692 } else {
5693 switch (opc) {
5694 case OPC_BEQ:
5695 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5696 goto not_likely;
5697 case OPC_BEQL:
5698 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5699 goto likely;
5700 case OPC_BNE:
5701 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5702 goto not_likely;
5703 case OPC_BNEL:
5704 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5705 goto likely;
5706 case OPC_BGEZ:
5707 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5708 goto not_likely;
5709 case OPC_BGEZL:
5710 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5711 goto likely;
5712 case OPC_BGEZAL:
5713 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5714 blink = 31;
5715 goto not_likely;
5716 case OPC_BGEZALL:
5717 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5718 blink = 31;
5719 goto likely;
5720 case OPC_BGTZ:
5721 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5722 goto not_likely;
5723 case OPC_BGTZL:
5724 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5725 goto likely;
5726 case OPC_BLEZ:
5727 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5728 goto not_likely;
5729 case OPC_BLEZL:
5730 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5731 goto likely;
5732 case OPC_BLTZ:
5733 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5734 goto not_likely;
5735 case OPC_BLTZL:
5736 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5737 goto likely;
5738 case OPC_BPOSGE32:
5739 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5740 goto not_likely;
5741 #if defined(TARGET_MIPS64)
5742 case OPC_BPOSGE64:
5743 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5744 goto not_likely;
5745 #endif
5746 case OPC_BLTZAL:
5747 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5748 blink = 31;
5749 not_likely:
5750 ctx->hflags |= MIPS_HFLAG_BC;
5751 break;
5752 case OPC_BLTZALL:
5753 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5754 blink = 31;
5755 likely:
5756 ctx->hflags |= MIPS_HFLAG_BL;
5757 break;
5758 default:
5759 MIPS_INVAL("conditional branch/jump");
5760 generate_exception_end(ctx, EXCP_RI);
5761 goto out;
5765 ctx->btarget = btgt;
5767 switch (delayslot_size) {
5768 case 2:
5769 ctx->hflags |= MIPS_HFLAG_BDS16;
5770 break;
5771 case 4:
5772 ctx->hflags |= MIPS_HFLAG_BDS32;
5773 break;
5776 if (blink > 0) {
5777 int post_delay = insn_bytes + delayslot_size;
5778 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5780 tcg_gen_movi_tl(cpu_gpr[blink],
5781 ctx->base.pc_next + post_delay + lowbit);
5784 out:
5785 if (insn_bytes == 2)
5786 ctx->hflags |= MIPS_HFLAG_B16;
5787 tcg_temp_free(t0);
5788 tcg_temp_free(t1);
5792 /* nanoMIPS Branches */
5793 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5794 int insn_bytes,
5795 int rs, int rt, int32_t offset)
5797 target_ulong btgt = -1;
5798 int bcond_compute = 0;
5799 TCGv t0 = tcg_temp_new();
5800 TCGv t1 = tcg_temp_new();
5802 /* Load needed operands */
5803 switch (opc) {
5804 case OPC_BEQ:
5805 case OPC_BNE:
5806 /* Compare two registers */
5807 if (rs != rt) {
5808 gen_load_gpr(t0, rs);
5809 gen_load_gpr(t1, rt);
5810 bcond_compute = 1;
5812 btgt = ctx->base.pc_next + insn_bytes + offset;
5813 break;
5814 case OPC_BGEZAL:
5815 /* Compare to zero */
5816 if (rs != 0) {
5817 gen_load_gpr(t0, rs);
5818 bcond_compute = 1;
5820 btgt = ctx->base.pc_next + insn_bytes + offset;
5821 break;
5822 case OPC_BPOSGE32:
5823 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5824 bcond_compute = 1;
5825 btgt = ctx->base.pc_next + insn_bytes + offset;
5826 break;
5827 case OPC_JR:
5828 case OPC_JALR:
5829 /* Jump to register */
5830 if (offset != 0 && offset != 16) {
5831 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5832 others are reserved. */
5833 MIPS_INVAL("jump hint");
5834 generate_exception_end(ctx, EXCP_RI);
5835 goto out;
5837 gen_load_gpr(btarget, rs);
5838 break;
5839 default:
5840 MIPS_INVAL("branch/jump");
5841 generate_exception_end(ctx, EXCP_RI);
5842 goto out;
5844 if (bcond_compute == 0) {
5845 /* No condition to be computed */
5846 switch (opc) {
5847 case OPC_BEQ: /* rx == rx */
5848 /* Always take */
5849 ctx->hflags |= MIPS_HFLAG_B;
5850 break;
5851 case OPC_BGEZAL: /* 0 >= 0 */
5852 /* Always take and link */
5853 tcg_gen_movi_tl(cpu_gpr[31],
5854 ctx->base.pc_next + insn_bytes);
5855 ctx->hflags |= MIPS_HFLAG_B;
5856 break;
5857 case OPC_BNE: /* rx != rx */
5858 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5859 /* Skip the instruction in the delay slot */
5860 ctx->base.pc_next += 4;
5861 goto out;
5862 case OPC_JR:
5863 ctx->hflags |= MIPS_HFLAG_BR;
5864 break;
5865 case OPC_JALR:
5866 if (rt > 0) {
5867 tcg_gen_movi_tl(cpu_gpr[rt],
5868 ctx->base.pc_next + insn_bytes);
5870 ctx->hflags |= MIPS_HFLAG_BR;
5871 break;
5872 default:
5873 MIPS_INVAL("branch/jump");
5874 generate_exception_end(ctx, EXCP_RI);
5875 goto out;
5877 } else {
5878 switch (opc) {
5879 case OPC_BEQ:
5880 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5881 goto not_likely;
5882 case OPC_BNE:
5883 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5884 goto not_likely;
5885 case OPC_BGEZAL:
5886 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5887 tcg_gen_movi_tl(cpu_gpr[31],
5888 ctx->base.pc_next + insn_bytes);
5889 goto not_likely;
5890 case OPC_BPOSGE32:
5891 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5892 not_likely:
5893 ctx->hflags |= MIPS_HFLAG_BC;
5894 break;
5895 default:
5896 MIPS_INVAL("conditional branch/jump");
5897 generate_exception_end(ctx, EXCP_RI);
5898 goto out;
5902 ctx->btarget = btgt;
5904 out:
5905 if (insn_bytes == 2) {
5906 ctx->hflags |= MIPS_HFLAG_B16;
5908 tcg_temp_free(t0);
5909 tcg_temp_free(t1);
5913 /* special3 bitfield operations */
5914 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5915 int rs, int lsb, int msb)
5917 TCGv t0 = tcg_temp_new();
5918 TCGv t1 = tcg_temp_new();
5920 gen_load_gpr(t1, rs);
5921 switch (opc) {
5922 case OPC_EXT:
5923 if (lsb + msb > 31) {
5924 goto fail;
5926 if (msb != 31) {
5927 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5928 } else {
5929 /* The two checks together imply that lsb == 0,
5930 so this is a simple sign-extension. */
5931 tcg_gen_ext32s_tl(t0, t1);
5933 break;
5934 #if defined(TARGET_MIPS64)
5935 case OPC_DEXTU:
5936 lsb += 32;
5937 goto do_dext;
5938 case OPC_DEXTM:
5939 msb += 32;
5940 goto do_dext;
5941 case OPC_DEXT:
5942 do_dext:
5943 if (lsb + msb > 63) {
5944 goto fail;
5946 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5947 break;
5948 #endif
5949 case OPC_INS:
5950 if (lsb > msb) {
5951 goto fail;
5953 gen_load_gpr(t0, rt);
5954 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5955 tcg_gen_ext32s_tl(t0, t0);
5956 break;
5957 #if defined(TARGET_MIPS64)
5958 case OPC_DINSU:
5959 lsb += 32;
5960 /* FALLTHRU */
5961 case OPC_DINSM:
5962 msb += 32;
5963 /* FALLTHRU */
5964 case OPC_DINS:
5965 if (lsb > msb) {
5966 goto fail;
5968 gen_load_gpr(t0, rt);
5969 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5970 break;
5971 #endif
5972 default:
5973 fail:
5974 MIPS_INVAL("bitops");
5975 generate_exception_end(ctx, EXCP_RI);
5976 tcg_temp_free(t0);
5977 tcg_temp_free(t1);
5978 return;
5980 gen_store_gpr(t0, rt);
5981 tcg_temp_free(t0);
5982 tcg_temp_free(t1);
5985 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
5987 TCGv t0;
5989 if (rd == 0) {
5990 /* If no destination, treat it as a NOP. */
5991 return;
5994 t0 = tcg_temp_new();
5995 gen_load_gpr(t0, rt);
5996 switch (op2) {
5997 case OPC_WSBH:
5999 TCGv t1 = tcg_temp_new();
6000 TCGv t2 = tcg_const_tl(0x00FF00FF);
6002 tcg_gen_shri_tl(t1, t0, 8);
6003 tcg_gen_and_tl(t1, t1, t2);
6004 tcg_gen_and_tl(t0, t0, t2);
6005 tcg_gen_shli_tl(t0, t0, 8);
6006 tcg_gen_or_tl(t0, t0, t1);
6007 tcg_temp_free(t2);
6008 tcg_temp_free(t1);
6009 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6011 break;
6012 case OPC_SEB:
6013 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6014 break;
6015 case OPC_SEH:
6016 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6017 break;
6018 #if defined(TARGET_MIPS64)
6019 case OPC_DSBH:
6021 TCGv t1 = tcg_temp_new();
6022 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6024 tcg_gen_shri_tl(t1, t0, 8);
6025 tcg_gen_and_tl(t1, t1, t2);
6026 tcg_gen_and_tl(t0, t0, t2);
6027 tcg_gen_shli_tl(t0, t0, 8);
6028 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6029 tcg_temp_free(t2);
6030 tcg_temp_free(t1);
6032 break;
6033 case OPC_DSHD:
6035 TCGv t1 = tcg_temp_new();
6036 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6038 tcg_gen_shri_tl(t1, t0, 16);
6039 tcg_gen_and_tl(t1, t1, t2);
6040 tcg_gen_and_tl(t0, t0, t2);
6041 tcg_gen_shli_tl(t0, t0, 16);
6042 tcg_gen_or_tl(t0, t0, t1);
6043 tcg_gen_shri_tl(t1, t0, 32);
6044 tcg_gen_shli_tl(t0, t0, 32);
6045 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6046 tcg_temp_free(t2);
6047 tcg_temp_free(t1);
6049 break;
6050 #endif
6051 default:
6052 MIPS_INVAL("bsfhl");
6053 generate_exception_end(ctx, EXCP_RI);
6054 tcg_temp_free(t0);
6055 return;
6057 tcg_temp_free(t0);
6060 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6061 int imm2)
6063 TCGv t0;
6064 TCGv t1;
6065 if (rd == 0) {
6066 /* Treat as NOP. */
6067 return;
6069 t0 = tcg_temp_new();
6070 t1 = tcg_temp_new();
6071 gen_load_gpr(t0, rs);
6072 gen_load_gpr(t1, rt);
6073 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6074 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6075 if (opc == OPC_LSA) {
6076 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6079 tcg_temp_free(t1);
6080 tcg_temp_free(t0);
6082 return;
6085 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6086 int rt, int bits)
6088 TCGv t0;
6089 if (rd == 0) {
6090 /* Treat as NOP. */
6091 return;
6093 t0 = tcg_temp_new();
6094 if (bits == 0 || bits == wordsz) {
6095 if (bits == 0) {
6096 gen_load_gpr(t0, rt);
6097 } else {
6098 gen_load_gpr(t0, rs);
6100 switch (wordsz) {
6101 case 32:
6102 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6103 break;
6104 #if defined(TARGET_MIPS64)
6105 case 64:
6106 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6107 break;
6108 #endif
6110 } else {
6111 TCGv t1 = tcg_temp_new();
6112 gen_load_gpr(t0, rt);
6113 gen_load_gpr(t1, rs);
6114 switch (wordsz) {
6115 case 32:
6117 TCGv_i64 t2 = tcg_temp_new_i64();
6118 tcg_gen_concat_tl_i64(t2, t1, t0);
6119 tcg_gen_shri_i64(t2, t2, 32 - bits);
6120 gen_move_low32(cpu_gpr[rd], t2);
6121 tcg_temp_free_i64(t2);
6123 break;
6124 #if defined(TARGET_MIPS64)
6125 case 64:
6126 tcg_gen_shli_tl(t0, t0, bits);
6127 tcg_gen_shri_tl(t1, t1, 64 - bits);
6128 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6129 break;
6130 #endif
6132 tcg_temp_free(t1);
6135 tcg_temp_free(t0);
6138 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6139 int bp)
6141 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6144 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6145 int shift)
6147 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6150 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6152 TCGv t0;
6153 if (rd == 0) {
6154 /* Treat as NOP. */
6155 return;
6157 t0 = tcg_temp_new();
6158 gen_load_gpr(t0, rt);
6159 switch (opc) {
6160 case OPC_BITSWAP:
6161 gen_helper_bitswap(cpu_gpr[rd], t0);
6162 break;
6163 #if defined(TARGET_MIPS64)
6164 case OPC_DBITSWAP:
6165 gen_helper_dbitswap(cpu_gpr[rd], t0);
6166 break;
6167 #endif
6169 tcg_temp_free(t0);
6172 #ifndef CONFIG_USER_ONLY
6173 /* CP0 (MMU and control) */
6174 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6176 TCGv_i64 t0 = tcg_temp_new_i64();
6177 TCGv_i64 t1 = tcg_temp_new_i64();
6179 tcg_gen_ext_tl_i64(t0, arg);
6180 tcg_gen_ld_i64(t1, cpu_env, off);
6181 #if defined(TARGET_MIPS64)
6182 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6183 #else
6184 tcg_gen_concat32_i64(t1, t1, t0);
6185 #endif
6186 tcg_gen_st_i64(t1, cpu_env, off);
6187 tcg_temp_free_i64(t1);
6188 tcg_temp_free_i64(t0);
6191 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6193 TCGv_i64 t0 = tcg_temp_new_i64();
6194 TCGv_i64 t1 = tcg_temp_new_i64();
6196 tcg_gen_ext_tl_i64(t0, arg);
6197 tcg_gen_ld_i64(t1, cpu_env, off);
6198 tcg_gen_concat32_i64(t1, t1, t0);
6199 tcg_gen_st_i64(t1, cpu_env, off);
6200 tcg_temp_free_i64(t1);
6201 tcg_temp_free_i64(t0);
6204 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6206 TCGv_i64 t0 = tcg_temp_new_i64();
6208 tcg_gen_ld_i64(t0, cpu_env, off);
6209 #if defined(TARGET_MIPS64)
6210 tcg_gen_shri_i64(t0, t0, 30);
6211 #else
6212 tcg_gen_shri_i64(t0, t0, 32);
6213 #endif
6214 gen_move_low32(arg, t0);
6215 tcg_temp_free_i64(t0);
6218 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6220 TCGv_i64 t0 = tcg_temp_new_i64();
6222 tcg_gen_ld_i64(t0, cpu_env, off);
6223 tcg_gen_shri_i64(t0, t0, 32 + shift);
6224 gen_move_low32(arg, t0);
6225 tcg_temp_free_i64(t0);
6228 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6230 TCGv_i32 t0 = tcg_temp_new_i32();
6232 tcg_gen_ld_i32(t0, cpu_env, off);
6233 tcg_gen_ext_i32_tl(arg, t0);
6234 tcg_temp_free_i32(t0);
6237 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6239 tcg_gen_ld_tl(arg, cpu_env, off);
6240 tcg_gen_ext32s_tl(arg, arg);
6243 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6245 TCGv_i32 t0 = tcg_temp_new_i32();
6247 tcg_gen_trunc_tl_i32(t0, arg);
6248 tcg_gen_st_i32(t0, cpu_env, off);
6249 tcg_temp_free_i32(t0);
6252 #define CP0_CHECK(c) \
6253 do { \
6254 if (!(c)) { \
6255 goto cp0_unimplemented; \
6257 } while (0)
6259 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6261 const char *rn = "invalid";
6263 switch (reg) {
6264 case 2:
6265 switch (sel) {
6266 case 0:
6267 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6268 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6269 rn = "EntryLo0";
6270 break;
6271 default:
6272 goto cp0_unimplemented;
6274 break;
6275 case 3:
6276 switch (sel) {
6277 case 0:
6278 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6279 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6280 rn = "EntryLo1";
6281 break;
6282 default:
6283 goto cp0_unimplemented;
6285 break;
6286 case 17:
6287 switch (sel) {
6288 case 0:
6289 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6290 ctx->CP0_LLAddr_shift);
6291 rn = "LLAddr";
6292 break;
6293 case 1:
6294 CP0_CHECK(ctx->mrp);
6295 gen_helper_mfhc0_maar(arg, cpu_env);
6296 rn = "MAAR";
6297 break;
6298 default:
6299 goto cp0_unimplemented;
6301 break;
6302 case 28:
6303 switch (sel) {
6304 case 0:
6305 case 2:
6306 case 4:
6307 case 6:
6308 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6309 rn = "TagLo";
6310 break;
6311 default:
6312 goto cp0_unimplemented;
6314 break;
6315 default:
6316 goto cp0_unimplemented;
6318 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6319 return;
6321 cp0_unimplemented:
6322 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6323 tcg_gen_movi_tl(arg, 0);
6326 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6328 const char *rn = "invalid";
6329 uint64_t mask = ctx->PAMask >> 36;
6331 switch (reg) {
6332 case 2:
6333 switch (sel) {
6334 case 0:
6335 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6336 tcg_gen_andi_tl(arg, arg, mask);
6337 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6338 rn = "EntryLo0";
6339 break;
6340 default:
6341 goto cp0_unimplemented;
6343 break;
6344 case 3:
6345 switch (sel) {
6346 case 0:
6347 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6348 tcg_gen_andi_tl(arg, arg, mask);
6349 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6350 rn = "EntryLo1";
6351 break;
6352 default:
6353 goto cp0_unimplemented;
6355 break;
6356 case 17:
6357 switch (sel) {
6358 case 0:
6359 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6360 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6361 relevant for modern MIPS cores supporting MTHC0, therefore
6362 treating MTHC0 to LLAddr as NOP. */
6363 rn = "LLAddr";
6364 break;
6365 case 1:
6366 CP0_CHECK(ctx->mrp);
6367 gen_helper_mthc0_maar(cpu_env, arg);
6368 rn = "MAAR";
6369 break;
6370 default:
6371 goto cp0_unimplemented;
6373 break;
6374 case 28:
6375 switch (sel) {
6376 case 0:
6377 case 2:
6378 case 4:
6379 case 6:
6380 tcg_gen_andi_tl(arg, arg, mask);
6381 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6382 rn = "TagLo";
6383 break;
6384 default:
6385 goto cp0_unimplemented;
6387 break;
6388 default:
6389 goto cp0_unimplemented;
6391 trace_mips_translate_c0("mthc0", rn, reg, sel);
6393 cp0_unimplemented:
6394 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6397 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6399 if (ctx->insn_flags & ISA_MIPS32R6) {
6400 tcg_gen_movi_tl(arg, 0);
6401 } else {
6402 tcg_gen_movi_tl(arg, ~0);
6406 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6408 const char *rn = "invalid";
6410 if (sel != 0)
6411 check_insn(ctx, ISA_MIPS32);
6413 switch (reg) {
6414 case 0:
6415 switch (sel) {
6416 case 0:
6417 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6418 rn = "Index";
6419 break;
6420 case 1:
6421 CP0_CHECK(ctx->insn_flags & ASE_MT);
6422 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6423 rn = "MVPControl";
6424 break;
6425 case 2:
6426 CP0_CHECK(ctx->insn_flags & ASE_MT);
6427 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6428 rn = "MVPConf0";
6429 break;
6430 case 3:
6431 CP0_CHECK(ctx->insn_flags & ASE_MT);
6432 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6433 rn = "MVPConf1";
6434 break;
6435 case 4:
6436 CP0_CHECK(ctx->vp);
6437 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6438 rn = "VPControl";
6439 break;
6440 default:
6441 goto cp0_unimplemented;
6443 break;
6444 case 1:
6445 switch (sel) {
6446 case 0:
6447 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6448 gen_helper_mfc0_random(arg, cpu_env);
6449 rn = "Random";
6450 break;
6451 case 1:
6452 CP0_CHECK(ctx->insn_flags & ASE_MT);
6453 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6454 rn = "VPEControl";
6455 break;
6456 case 2:
6457 CP0_CHECK(ctx->insn_flags & ASE_MT);
6458 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6459 rn = "VPEConf0";
6460 break;
6461 case 3:
6462 CP0_CHECK(ctx->insn_flags & ASE_MT);
6463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6464 rn = "VPEConf1";
6465 break;
6466 case 4:
6467 CP0_CHECK(ctx->insn_flags & ASE_MT);
6468 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6469 rn = "YQMask";
6470 break;
6471 case 5:
6472 CP0_CHECK(ctx->insn_flags & ASE_MT);
6473 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6474 rn = "VPESchedule";
6475 break;
6476 case 6:
6477 CP0_CHECK(ctx->insn_flags & ASE_MT);
6478 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6479 rn = "VPEScheFBack";
6480 break;
6481 case 7:
6482 CP0_CHECK(ctx->insn_flags & ASE_MT);
6483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6484 rn = "VPEOpt";
6485 break;
6486 default:
6487 goto cp0_unimplemented;
6489 break;
6490 case 2:
6491 switch (sel) {
6492 case 0:
6494 TCGv_i64 tmp = tcg_temp_new_i64();
6495 tcg_gen_ld_i64(tmp, cpu_env,
6496 offsetof(CPUMIPSState, CP0_EntryLo0));
6497 #if defined(TARGET_MIPS64)
6498 if (ctx->rxi) {
6499 /* Move RI/XI fields to bits 31:30 */
6500 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6501 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6503 #endif
6504 gen_move_low32(arg, tmp);
6505 tcg_temp_free_i64(tmp);
6507 rn = "EntryLo0";
6508 break;
6509 case 1:
6510 CP0_CHECK(ctx->insn_flags & ASE_MT);
6511 gen_helper_mfc0_tcstatus(arg, cpu_env);
6512 rn = "TCStatus";
6513 break;
6514 case 2:
6515 CP0_CHECK(ctx->insn_flags & ASE_MT);
6516 gen_helper_mfc0_tcbind(arg, cpu_env);
6517 rn = "TCBind";
6518 break;
6519 case 3:
6520 CP0_CHECK(ctx->insn_flags & ASE_MT);
6521 gen_helper_mfc0_tcrestart(arg, cpu_env);
6522 rn = "TCRestart";
6523 break;
6524 case 4:
6525 CP0_CHECK(ctx->insn_flags & ASE_MT);
6526 gen_helper_mfc0_tchalt(arg, cpu_env);
6527 rn = "TCHalt";
6528 break;
6529 case 5:
6530 CP0_CHECK(ctx->insn_flags & ASE_MT);
6531 gen_helper_mfc0_tccontext(arg, cpu_env);
6532 rn = "TCContext";
6533 break;
6534 case 6:
6535 CP0_CHECK(ctx->insn_flags & ASE_MT);
6536 gen_helper_mfc0_tcschedule(arg, cpu_env);
6537 rn = "TCSchedule";
6538 break;
6539 case 7:
6540 CP0_CHECK(ctx->insn_flags & ASE_MT);
6541 gen_helper_mfc0_tcschefback(arg, cpu_env);
6542 rn = "TCScheFBack";
6543 break;
6544 default:
6545 goto cp0_unimplemented;
6547 break;
6548 case 3:
6549 switch (sel) {
6550 case 0:
6552 TCGv_i64 tmp = tcg_temp_new_i64();
6553 tcg_gen_ld_i64(tmp, cpu_env,
6554 offsetof(CPUMIPSState, CP0_EntryLo1));
6555 #if defined(TARGET_MIPS64)
6556 if (ctx->rxi) {
6557 /* Move RI/XI fields to bits 31:30 */
6558 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6559 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6561 #endif
6562 gen_move_low32(arg, tmp);
6563 tcg_temp_free_i64(tmp);
6565 rn = "EntryLo1";
6566 break;
6567 case 1:
6568 CP0_CHECK(ctx->vp);
6569 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6570 rn = "GlobalNumber";
6571 break;
6572 default:
6573 goto cp0_unimplemented;
6575 break;
6576 case 4:
6577 switch (sel) {
6578 case 0:
6579 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6580 tcg_gen_ext32s_tl(arg, arg);
6581 rn = "Context";
6582 break;
6583 case 1:
6584 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6585 rn = "ContextConfig";
6586 goto cp0_unimplemented;
6587 case 2:
6588 CP0_CHECK(ctx->ulri);
6589 tcg_gen_ld_tl(arg, cpu_env,
6590 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6591 tcg_gen_ext32s_tl(arg, arg);
6592 rn = "UserLocal";
6593 break;
6594 default:
6595 goto cp0_unimplemented;
6597 break;
6598 case 5:
6599 switch (sel) {
6600 case 0:
6601 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6602 rn = "PageMask";
6603 break;
6604 case 1:
6605 check_insn(ctx, ISA_MIPS32R2);
6606 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6607 rn = "PageGrain";
6608 break;
6609 case 2:
6610 CP0_CHECK(ctx->sc);
6611 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6612 tcg_gen_ext32s_tl(arg, arg);
6613 rn = "SegCtl0";
6614 break;
6615 case 3:
6616 CP0_CHECK(ctx->sc);
6617 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6618 tcg_gen_ext32s_tl(arg, arg);
6619 rn = "SegCtl1";
6620 break;
6621 case 4:
6622 CP0_CHECK(ctx->sc);
6623 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6624 tcg_gen_ext32s_tl(arg, arg);
6625 rn = "SegCtl2";
6626 break;
6627 case 5:
6628 check_pw(ctx);
6629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6630 rn = "PWBase";
6631 break;
6632 case 6:
6633 check_pw(ctx);
6634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6635 rn = "PWField";
6636 break;
6637 case 7:
6638 check_pw(ctx);
6639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6640 rn = "PWSize";
6641 break;
6642 default:
6643 goto cp0_unimplemented;
6645 break;
6646 case 6:
6647 switch (sel) {
6648 case 0:
6649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6650 rn = "Wired";
6651 break;
6652 case 1:
6653 check_insn(ctx, ISA_MIPS32R2);
6654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6655 rn = "SRSConf0";
6656 break;
6657 case 2:
6658 check_insn(ctx, ISA_MIPS32R2);
6659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6660 rn = "SRSConf1";
6661 break;
6662 case 3:
6663 check_insn(ctx, ISA_MIPS32R2);
6664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6665 rn = "SRSConf2";
6666 break;
6667 case 4:
6668 check_insn(ctx, ISA_MIPS32R2);
6669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6670 rn = "SRSConf3";
6671 break;
6672 case 5:
6673 check_insn(ctx, ISA_MIPS32R2);
6674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6675 rn = "SRSConf4";
6676 break;
6677 case 6:
6678 check_pw(ctx);
6679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6680 rn = "PWCtl";
6681 break;
6682 default:
6683 goto cp0_unimplemented;
6685 break;
6686 case 7:
6687 switch (sel) {
6688 case 0:
6689 check_insn(ctx, ISA_MIPS32R2);
6690 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6691 rn = "HWREna";
6692 break;
6693 default:
6694 goto cp0_unimplemented;
6696 break;
6697 case 8:
6698 switch (sel) {
6699 case 0:
6700 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6701 tcg_gen_ext32s_tl(arg, arg);
6702 rn = "BadVAddr";
6703 break;
6704 case 1:
6705 CP0_CHECK(ctx->bi);
6706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6707 rn = "BadInstr";
6708 break;
6709 case 2:
6710 CP0_CHECK(ctx->bp);
6711 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6712 rn = "BadInstrP";
6713 break;
6714 case 3:
6715 CP0_CHECK(ctx->bi);
6716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6717 tcg_gen_andi_tl(arg, arg, ~0xffff);
6718 rn = "BadInstrX";
6719 break;
6720 default:
6721 goto cp0_unimplemented;
6723 break;
6724 case 9:
6725 switch (sel) {
6726 case 0:
6727 /* Mark as an IO operation because we read the time. */
6728 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6729 gen_io_start();
6731 gen_helper_mfc0_count(arg, cpu_env);
6732 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6733 gen_io_end();
6735 /* Break the TB to be able to take timer interrupts immediately
6736 after reading count. DISAS_STOP isn't sufficient, we need to
6737 ensure we break completely out of translated code. */
6738 gen_save_pc(ctx->base.pc_next + 4);
6739 ctx->base.is_jmp = DISAS_EXIT;
6740 rn = "Count";
6741 break;
6742 /* 6,7 are implementation dependent */
6743 default:
6744 goto cp0_unimplemented;
6746 break;
6747 case 10:
6748 switch (sel) {
6749 case 0:
6750 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6751 tcg_gen_ext32s_tl(arg, arg);
6752 rn = "EntryHi";
6753 break;
6754 default:
6755 goto cp0_unimplemented;
6757 break;
6758 case 11:
6759 switch (sel) {
6760 case 0:
6761 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6762 rn = "Compare";
6763 break;
6764 /* 6,7 are implementation dependent */
6765 default:
6766 goto cp0_unimplemented;
6768 break;
6769 case 12:
6770 switch (sel) {
6771 case 0:
6772 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6773 rn = "Status";
6774 break;
6775 case 1:
6776 check_insn(ctx, ISA_MIPS32R2);
6777 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6778 rn = "IntCtl";
6779 break;
6780 case 2:
6781 check_insn(ctx, ISA_MIPS32R2);
6782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6783 rn = "SRSCtl";
6784 break;
6785 case 3:
6786 check_insn(ctx, ISA_MIPS32R2);
6787 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6788 rn = "SRSMap";
6789 break;
6790 default:
6791 goto cp0_unimplemented;
6793 break;
6794 case 13:
6795 switch (sel) {
6796 case 0:
6797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6798 rn = "Cause";
6799 break;
6800 default:
6801 goto cp0_unimplemented;
6803 break;
6804 case 14:
6805 switch (sel) {
6806 case 0:
6807 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6808 tcg_gen_ext32s_tl(arg, arg);
6809 rn = "EPC";
6810 break;
6811 default:
6812 goto cp0_unimplemented;
6814 break;
6815 case 15:
6816 switch (sel) {
6817 case 0:
6818 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6819 rn = "PRid";
6820 break;
6821 case 1:
6822 check_insn(ctx, ISA_MIPS32R2);
6823 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6824 tcg_gen_ext32s_tl(arg, arg);
6825 rn = "EBase";
6826 break;
6827 case 3:
6828 check_insn(ctx, ISA_MIPS32R2);
6829 CP0_CHECK(ctx->cmgcr);
6830 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6831 tcg_gen_ext32s_tl(arg, arg);
6832 rn = "CMGCRBase";
6833 break;
6834 default:
6835 goto cp0_unimplemented;
6837 break;
6838 case 16:
6839 switch (sel) {
6840 case 0:
6841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6842 rn = "Config";
6843 break;
6844 case 1:
6845 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6846 rn = "Config1";
6847 break;
6848 case 2:
6849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6850 rn = "Config2";
6851 break;
6852 case 3:
6853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6854 rn = "Config3";
6855 break;
6856 case 4:
6857 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6858 rn = "Config4";
6859 break;
6860 case 5:
6861 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6862 rn = "Config5";
6863 break;
6864 /* 6,7 are implementation dependent */
6865 case 6:
6866 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6867 rn = "Config6";
6868 break;
6869 case 7:
6870 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6871 rn = "Config7";
6872 break;
6873 default:
6874 goto cp0_unimplemented;
6876 break;
6877 case 17:
6878 switch (sel) {
6879 case 0:
6880 gen_helper_mfc0_lladdr(arg, cpu_env);
6881 rn = "LLAddr";
6882 break;
6883 case 1:
6884 CP0_CHECK(ctx->mrp);
6885 gen_helper_mfc0_maar(arg, cpu_env);
6886 rn = "MAAR";
6887 break;
6888 case 2:
6889 CP0_CHECK(ctx->mrp);
6890 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6891 rn = "MAARI";
6892 break;
6893 default:
6894 goto cp0_unimplemented;
6896 break;
6897 case 18:
6898 switch (sel) {
6899 case 0:
6900 case 1:
6901 case 2:
6902 case 3:
6903 case 4:
6904 case 5:
6905 case 6:
6906 case 7:
6907 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6908 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6909 rn = "WatchLo";
6910 break;
6911 default:
6912 goto cp0_unimplemented;
6914 break;
6915 case 19:
6916 switch (sel) {
6917 case 0:
6918 case 1:
6919 case 2:
6920 case 3:
6921 case 4:
6922 case 5:
6923 case 6:
6924 case 7:
6925 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6926 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6927 rn = "WatchHi";
6928 break;
6929 default:
6930 goto cp0_unimplemented;
6932 break;
6933 case 20:
6934 switch (sel) {
6935 case 0:
6936 #if defined(TARGET_MIPS64)
6937 check_insn(ctx, ISA_MIPS3);
6938 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6939 tcg_gen_ext32s_tl(arg, arg);
6940 rn = "XContext";
6941 break;
6942 #endif
6943 default:
6944 goto cp0_unimplemented;
6946 break;
6947 case 21:
6948 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6949 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6950 switch (sel) {
6951 case 0:
6952 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6953 rn = "Framemask";
6954 break;
6955 default:
6956 goto cp0_unimplemented;
6958 break;
6959 case 22:
6960 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6961 rn = "'Diagnostic"; /* implementation dependent */
6962 break;
6963 case 23:
6964 switch (sel) {
6965 case 0:
6966 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6967 rn = "Debug";
6968 break;
6969 case 1:
6970 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
6971 rn = "TraceControl";
6972 goto cp0_unimplemented;
6973 case 2:
6974 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
6975 rn = "TraceControl2";
6976 goto cp0_unimplemented;
6977 case 3:
6978 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
6979 rn = "UserTraceData";
6980 goto cp0_unimplemented;
6981 case 4:
6982 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
6983 rn = "TraceBPC";
6984 goto cp0_unimplemented;
6985 default:
6986 goto cp0_unimplemented;
6988 break;
6989 case 24:
6990 switch (sel) {
6991 case 0:
6992 /* EJTAG support */
6993 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6994 tcg_gen_ext32s_tl(arg, arg);
6995 rn = "DEPC";
6996 break;
6997 default:
6998 goto cp0_unimplemented;
7000 break;
7001 case 25:
7002 switch (sel) {
7003 case 0:
7004 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7005 rn = "Performance0";
7006 break;
7007 case 1:
7008 // gen_helper_mfc0_performance1(arg);
7009 rn = "Performance1";
7010 goto cp0_unimplemented;
7011 case 2:
7012 // gen_helper_mfc0_performance2(arg);
7013 rn = "Performance2";
7014 goto cp0_unimplemented;
7015 case 3:
7016 // gen_helper_mfc0_performance3(arg);
7017 rn = "Performance3";
7018 goto cp0_unimplemented;
7019 case 4:
7020 // gen_helper_mfc0_performance4(arg);
7021 rn = "Performance4";
7022 goto cp0_unimplemented;
7023 case 5:
7024 // gen_helper_mfc0_performance5(arg);
7025 rn = "Performance5";
7026 goto cp0_unimplemented;
7027 case 6:
7028 // gen_helper_mfc0_performance6(arg);
7029 rn = "Performance6";
7030 goto cp0_unimplemented;
7031 case 7:
7032 // gen_helper_mfc0_performance7(arg);
7033 rn = "Performance7";
7034 goto cp0_unimplemented;
7035 default:
7036 goto cp0_unimplemented;
7038 break;
7039 case 26:
7040 switch (sel) {
7041 case 0:
7042 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7043 rn = "ErrCtl";
7044 break;
7045 default:
7046 goto cp0_unimplemented;
7048 break;
7049 case 27:
7050 switch (sel) {
7051 case 0:
7052 case 1:
7053 case 2:
7054 case 3:
7055 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7056 rn = "CacheErr";
7057 break;
7058 default:
7059 goto cp0_unimplemented;
7061 break;
7062 case 28:
7063 switch (sel) {
7064 case 0:
7065 case 2:
7066 case 4:
7067 case 6:
7069 TCGv_i64 tmp = tcg_temp_new_i64();
7070 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7071 gen_move_low32(arg, tmp);
7072 tcg_temp_free_i64(tmp);
7074 rn = "TagLo";
7075 break;
7076 case 1:
7077 case 3:
7078 case 5:
7079 case 7:
7080 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7081 rn = "DataLo";
7082 break;
7083 default:
7084 goto cp0_unimplemented;
7086 break;
7087 case 29:
7088 switch (sel) {
7089 case 0:
7090 case 2:
7091 case 4:
7092 case 6:
7093 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7094 rn = "TagHi";
7095 break;
7096 case 1:
7097 case 3:
7098 case 5:
7099 case 7:
7100 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7101 rn = "DataHi";
7102 break;
7103 default:
7104 goto cp0_unimplemented;
7106 break;
7107 case 30:
7108 switch (sel) {
7109 case 0:
7110 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7111 tcg_gen_ext32s_tl(arg, arg);
7112 rn = "ErrorEPC";
7113 break;
7114 default:
7115 goto cp0_unimplemented;
7117 break;
7118 case 31:
7119 switch (sel) {
7120 case 0:
7121 /* EJTAG support */
7122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7123 rn = "DESAVE";
7124 break;
7125 case 2:
7126 case 3:
7127 case 4:
7128 case 5:
7129 case 6:
7130 case 7:
7131 CP0_CHECK(ctx->kscrexist & (1 << sel));
7132 tcg_gen_ld_tl(arg, cpu_env,
7133 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7134 tcg_gen_ext32s_tl(arg, arg);
7135 rn = "KScratch";
7136 break;
7137 default:
7138 goto cp0_unimplemented;
7140 break;
7141 default:
7142 goto cp0_unimplemented;
7144 trace_mips_translate_c0("mfc0", rn, reg, sel);
7145 return;
7147 cp0_unimplemented:
7148 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7149 gen_mfc0_unimplemented(ctx, arg);
7152 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7154 const char *rn = "invalid";
7156 if (sel != 0)
7157 check_insn(ctx, ISA_MIPS32);
7159 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7160 gen_io_start();
7163 switch (reg) {
7164 case 0:
7165 switch (sel) {
7166 case 0:
7167 gen_helper_mtc0_index(cpu_env, arg);
7168 rn = "Index";
7169 break;
7170 case 1:
7171 CP0_CHECK(ctx->insn_flags & ASE_MT);
7172 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7173 rn = "MVPControl";
7174 break;
7175 case 2:
7176 CP0_CHECK(ctx->insn_flags & ASE_MT);
7177 /* ignored */
7178 rn = "MVPConf0";
7179 break;
7180 case 3:
7181 CP0_CHECK(ctx->insn_flags & ASE_MT);
7182 /* ignored */
7183 rn = "MVPConf1";
7184 break;
7185 case 4:
7186 CP0_CHECK(ctx->vp);
7187 /* ignored */
7188 rn = "VPControl";
7189 break;
7190 default:
7191 goto cp0_unimplemented;
7193 break;
7194 case 1:
7195 switch (sel) {
7196 case 0:
7197 /* ignored */
7198 rn = "Random";
7199 break;
7200 case 1:
7201 CP0_CHECK(ctx->insn_flags & ASE_MT);
7202 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7203 rn = "VPEControl";
7204 break;
7205 case 2:
7206 CP0_CHECK(ctx->insn_flags & ASE_MT);
7207 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7208 rn = "VPEConf0";
7209 break;
7210 case 3:
7211 CP0_CHECK(ctx->insn_flags & ASE_MT);
7212 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7213 rn = "VPEConf1";
7214 break;
7215 case 4:
7216 CP0_CHECK(ctx->insn_flags & ASE_MT);
7217 gen_helper_mtc0_yqmask(cpu_env, arg);
7218 rn = "YQMask";
7219 break;
7220 case 5:
7221 CP0_CHECK(ctx->insn_flags & ASE_MT);
7222 tcg_gen_st_tl(arg, cpu_env,
7223 offsetof(CPUMIPSState, CP0_VPESchedule));
7224 rn = "VPESchedule";
7225 break;
7226 case 6:
7227 CP0_CHECK(ctx->insn_flags & ASE_MT);
7228 tcg_gen_st_tl(arg, cpu_env,
7229 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7230 rn = "VPEScheFBack";
7231 break;
7232 case 7:
7233 CP0_CHECK(ctx->insn_flags & ASE_MT);
7234 gen_helper_mtc0_vpeopt(cpu_env, arg);
7235 rn = "VPEOpt";
7236 break;
7237 default:
7238 goto cp0_unimplemented;
7240 break;
7241 case 2:
7242 switch (sel) {
7243 case 0:
7244 gen_helper_mtc0_entrylo0(cpu_env, arg);
7245 rn = "EntryLo0";
7246 break;
7247 case 1:
7248 CP0_CHECK(ctx->insn_flags & ASE_MT);
7249 gen_helper_mtc0_tcstatus(cpu_env, arg);
7250 rn = "TCStatus";
7251 break;
7252 case 2:
7253 CP0_CHECK(ctx->insn_flags & ASE_MT);
7254 gen_helper_mtc0_tcbind(cpu_env, arg);
7255 rn = "TCBind";
7256 break;
7257 case 3:
7258 CP0_CHECK(ctx->insn_flags & ASE_MT);
7259 gen_helper_mtc0_tcrestart(cpu_env, arg);
7260 rn = "TCRestart";
7261 break;
7262 case 4:
7263 CP0_CHECK(ctx->insn_flags & ASE_MT);
7264 gen_helper_mtc0_tchalt(cpu_env, arg);
7265 rn = "TCHalt";
7266 break;
7267 case 5:
7268 CP0_CHECK(ctx->insn_flags & ASE_MT);
7269 gen_helper_mtc0_tccontext(cpu_env, arg);
7270 rn = "TCContext";
7271 break;
7272 case 6:
7273 CP0_CHECK(ctx->insn_flags & ASE_MT);
7274 gen_helper_mtc0_tcschedule(cpu_env, arg);
7275 rn = "TCSchedule";
7276 break;
7277 case 7:
7278 CP0_CHECK(ctx->insn_flags & ASE_MT);
7279 gen_helper_mtc0_tcschefback(cpu_env, arg);
7280 rn = "TCScheFBack";
7281 break;
7282 default:
7283 goto cp0_unimplemented;
7285 break;
7286 case 3:
7287 switch (sel) {
7288 case 0:
7289 gen_helper_mtc0_entrylo1(cpu_env, arg);
7290 rn = "EntryLo1";
7291 break;
7292 case 1:
7293 CP0_CHECK(ctx->vp);
7294 /* ignored */
7295 rn = "GlobalNumber";
7296 break;
7297 default:
7298 goto cp0_unimplemented;
7300 break;
7301 case 4:
7302 switch (sel) {
7303 case 0:
7304 gen_helper_mtc0_context(cpu_env, arg);
7305 rn = "Context";
7306 break;
7307 case 1:
7308 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7309 rn = "ContextConfig";
7310 goto cp0_unimplemented;
7311 case 2:
7312 CP0_CHECK(ctx->ulri);
7313 tcg_gen_st_tl(arg, cpu_env,
7314 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7315 rn = "UserLocal";
7316 break;
7317 default:
7318 goto cp0_unimplemented;
7320 break;
7321 case 5:
7322 switch (sel) {
7323 case 0:
7324 gen_helper_mtc0_pagemask(cpu_env, arg);
7325 rn = "PageMask";
7326 break;
7327 case 1:
7328 check_insn(ctx, ISA_MIPS32R2);
7329 gen_helper_mtc0_pagegrain(cpu_env, arg);
7330 rn = "PageGrain";
7331 ctx->base.is_jmp = DISAS_STOP;
7332 break;
7333 case 2:
7334 CP0_CHECK(ctx->sc);
7335 gen_helper_mtc0_segctl0(cpu_env, arg);
7336 rn = "SegCtl0";
7337 break;
7338 case 3:
7339 CP0_CHECK(ctx->sc);
7340 gen_helper_mtc0_segctl1(cpu_env, arg);
7341 rn = "SegCtl1";
7342 break;
7343 case 4:
7344 CP0_CHECK(ctx->sc);
7345 gen_helper_mtc0_segctl2(cpu_env, arg);
7346 rn = "SegCtl2";
7347 break;
7348 case 5:
7349 check_pw(ctx);
7350 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7351 rn = "PWBase";
7352 break;
7353 case 6:
7354 check_pw(ctx);
7355 gen_helper_mtc0_pwfield(cpu_env, arg);
7356 rn = "PWField";
7357 break;
7358 case 7:
7359 check_pw(ctx);
7360 gen_helper_mtc0_pwsize(cpu_env, arg);
7361 rn = "PWSize";
7362 break;
7363 default:
7364 goto cp0_unimplemented;
7366 break;
7367 case 6:
7368 switch (sel) {
7369 case 0:
7370 gen_helper_mtc0_wired(cpu_env, arg);
7371 rn = "Wired";
7372 break;
7373 case 1:
7374 check_insn(ctx, ISA_MIPS32R2);
7375 gen_helper_mtc0_srsconf0(cpu_env, arg);
7376 rn = "SRSConf0";
7377 break;
7378 case 2:
7379 check_insn(ctx, ISA_MIPS32R2);
7380 gen_helper_mtc0_srsconf1(cpu_env, arg);
7381 rn = "SRSConf1";
7382 break;
7383 case 3:
7384 check_insn(ctx, ISA_MIPS32R2);
7385 gen_helper_mtc0_srsconf2(cpu_env, arg);
7386 rn = "SRSConf2";
7387 break;
7388 case 4:
7389 check_insn(ctx, ISA_MIPS32R2);
7390 gen_helper_mtc0_srsconf3(cpu_env, arg);
7391 rn = "SRSConf3";
7392 break;
7393 case 5:
7394 check_insn(ctx, ISA_MIPS32R2);
7395 gen_helper_mtc0_srsconf4(cpu_env, arg);
7396 rn = "SRSConf4";
7397 break;
7398 case 6:
7399 check_pw(ctx);
7400 gen_helper_mtc0_pwctl(cpu_env, arg);
7401 rn = "PWCtl";
7402 break;
7403 default:
7404 goto cp0_unimplemented;
7406 break;
7407 case 7:
7408 switch (sel) {
7409 case 0:
7410 check_insn(ctx, ISA_MIPS32R2);
7411 gen_helper_mtc0_hwrena(cpu_env, arg);
7412 ctx->base.is_jmp = DISAS_STOP;
7413 rn = "HWREna";
7414 break;
7415 default:
7416 goto cp0_unimplemented;
7418 break;
7419 case 8:
7420 switch (sel) {
7421 case 0:
7422 /* ignored */
7423 rn = "BadVAddr";
7424 break;
7425 case 1:
7426 /* ignored */
7427 rn = "BadInstr";
7428 break;
7429 case 2:
7430 /* ignored */
7431 rn = "BadInstrP";
7432 break;
7433 case 3:
7434 /* ignored */
7435 rn = "BadInstrX";
7436 break;
7437 default:
7438 goto cp0_unimplemented;
7440 break;
7441 case 9:
7442 switch (sel) {
7443 case 0:
7444 gen_helper_mtc0_count(cpu_env, arg);
7445 rn = "Count";
7446 break;
7447 /* 6,7 are implementation dependent */
7448 default:
7449 goto cp0_unimplemented;
7451 break;
7452 case 10:
7453 switch (sel) {
7454 case 0:
7455 gen_helper_mtc0_entryhi(cpu_env, arg);
7456 rn = "EntryHi";
7457 break;
7458 default:
7459 goto cp0_unimplemented;
7461 break;
7462 case 11:
7463 switch (sel) {
7464 case 0:
7465 gen_helper_mtc0_compare(cpu_env, arg);
7466 rn = "Compare";
7467 break;
7468 /* 6,7 are implementation dependent */
7469 default:
7470 goto cp0_unimplemented;
7472 break;
7473 case 12:
7474 switch (sel) {
7475 case 0:
7476 save_cpu_state(ctx, 1);
7477 gen_helper_mtc0_status(cpu_env, arg);
7478 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7479 gen_save_pc(ctx->base.pc_next + 4);
7480 ctx->base.is_jmp = DISAS_EXIT;
7481 rn = "Status";
7482 break;
7483 case 1:
7484 check_insn(ctx, ISA_MIPS32R2);
7485 gen_helper_mtc0_intctl(cpu_env, arg);
7486 /* Stop translation as we may have switched the execution mode */
7487 ctx->base.is_jmp = DISAS_STOP;
7488 rn = "IntCtl";
7489 break;
7490 case 2:
7491 check_insn(ctx, ISA_MIPS32R2);
7492 gen_helper_mtc0_srsctl(cpu_env, arg);
7493 /* Stop translation as we may have switched the execution mode */
7494 ctx->base.is_jmp = DISAS_STOP;
7495 rn = "SRSCtl";
7496 break;
7497 case 3:
7498 check_insn(ctx, ISA_MIPS32R2);
7499 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7500 /* Stop translation as we may have switched the execution mode */
7501 ctx->base.is_jmp = DISAS_STOP;
7502 rn = "SRSMap";
7503 break;
7504 default:
7505 goto cp0_unimplemented;
7507 break;
7508 case 13:
7509 switch (sel) {
7510 case 0:
7511 save_cpu_state(ctx, 1);
7512 gen_helper_mtc0_cause(cpu_env, arg);
7513 /* Stop translation as we may have triggered an interrupt.
7514 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7515 * translated code to check for pending interrupts. */
7516 gen_save_pc(ctx->base.pc_next + 4);
7517 ctx->base.is_jmp = DISAS_EXIT;
7518 rn = "Cause";
7519 break;
7520 default:
7521 goto cp0_unimplemented;
7523 break;
7524 case 14:
7525 switch (sel) {
7526 case 0:
7527 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7528 rn = "EPC";
7529 break;
7530 default:
7531 goto cp0_unimplemented;
7533 break;
7534 case 15:
7535 switch (sel) {
7536 case 0:
7537 /* ignored */
7538 rn = "PRid";
7539 break;
7540 case 1:
7541 check_insn(ctx, ISA_MIPS32R2);
7542 gen_helper_mtc0_ebase(cpu_env, arg);
7543 rn = "EBase";
7544 break;
7545 default:
7546 goto cp0_unimplemented;
7548 break;
7549 case 16:
7550 switch (sel) {
7551 case 0:
7552 gen_helper_mtc0_config0(cpu_env, arg);
7553 rn = "Config";
7554 /* Stop translation as we may have switched the execution mode */
7555 ctx->base.is_jmp = DISAS_STOP;
7556 break;
7557 case 1:
7558 /* ignored, read only */
7559 rn = "Config1";
7560 break;
7561 case 2:
7562 gen_helper_mtc0_config2(cpu_env, arg);
7563 rn = "Config2";
7564 /* Stop translation as we may have switched the execution mode */
7565 ctx->base.is_jmp = DISAS_STOP;
7566 break;
7567 case 3:
7568 gen_helper_mtc0_config3(cpu_env, arg);
7569 rn = "Config3";
7570 /* Stop translation as we may have switched the execution mode */
7571 ctx->base.is_jmp = DISAS_STOP;
7572 break;
7573 case 4:
7574 gen_helper_mtc0_config4(cpu_env, arg);
7575 rn = "Config4";
7576 ctx->base.is_jmp = DISAS_STOP;
7577 break;
7578 case 5:
7579 gen_helper_mtc0_config5(cpu_env, arg);
7580 rn = "Config5";
7581 /* Stop translation as we may have switched the execution mode */
7582 ctx->base.is_jmp = DISAS_STOP;
7583 break;
7584 /* 6,7 are implementation dependent */
7585 case 6:
7586 /* ignored */
7587 rn = "Config6";
7588 break;
7589 case 7:
7590 /* ignored */
7591 rn = "Config7";
7592 break;
7593 default:
7594 rn = "Invalid config selector";
7595 goto cp0_unimplemented;
7597 break;
7598 case 17:
7599 switch (sel) {
7600 case 0:
7601 gen_helper_mtc0_lladdr(cpu_env, arg);
7602 rn = "LLAddr";
7603 break;
7604 case 1:
7605 CP0_CHECK(ctx->mrp);
7606 gen_helper_mtc0_maar(cpu_env, arg);
7607 rn = "MAAR";
7608 break;
7609 case 2:
7610 CP0_CHECK(ctx->mrp);
7611 gen_helper_mtc0_maari(cpu_env, arg);
7612 rn = "MAARI";
7613 break;
7614 default:
7615 goto cp0_unimplemented;
7617 break;
7618 case 18:
7619 switch (sel) {
7620 case 0:
7621 case 1:
7622 case 2:
7623 case 3:
7624 case 4:
7625 case 5:
7626 case 6:
7627 case 7:
7628 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7629 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7630 rn = "WatchLo";
7631 break;
7632 default:
7633 goto cp0_unimplemented;
7635 break;
7636 case 19:
7637 switch (sel) {
7638 case 0:
7639 case 1:
7640 case 2:
7641 case 3:
7642 case 4:
7643 case 5:
7644 case 6:
7645 case 7:
7646 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7647 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7648 rn = "WatchHi";
7649 break;
7650 default:
7651 goto cp0_unimplemented;
7653 break;
7654 case 20:
7655 switch (sel) {
7656 case 0:
7657 #if defined(TARGET_MIPS64)
7658 check_insn(ctx, ISA_MIPS3);
7659 gen_helper_mtc0_xcontext(cpu_env, arg);
7660 rn = "XContext";
7661 break;
7662 #endif
7663 default:
7664 goto cp0_unimplemented;
7666 break;
7667 case 21:
7668 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7669 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7670 switch (sel) {
7671 case 0:
7672 gen_helper_mtc0_framemask(cpu_env, arg);
7673 rn = "Framemask";
7674 break;
7675 default:
7676 goto cp0_unimplemented;
7678 break;
7679 case 22:
7680 /* ignored */
7681 rn = "Diagnostic"; /* implementation dependent */
7682 break;
7683 case 23:
7684 switch (sel) {
7685 case 0:
7686 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7687 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7688 gen_save_pc(ctx->base.pc_next + 4);
7689 ctx->base.is_jmp = DISAS_EXIT;
7690 rn = "Debug";
7691 break;
7692 case 1:
7693 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7694 rn = "TraceControl";
7695 /* Stop translation as we may have switched the execution mode */
7696 ctx->base.is_jmp = DISAS_STOP;
7697 goto cp0_unimplemented;
7698 case 2:
7699 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7700 rn = "TraceControl2";
7701 /* Stop translation as we may have switched the execution mode */
7702 ctx->base.is_jmp = DISAS_STOP;
7703 goto cp0_unimplemented;
7704 case 3:
7705 /* Stop translation as we may have switched the execution mode */
7706 ctx->base.is_jmp = DISAS_STOP;
7707 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7708 rn = "UserTraceData";
7709 /* Stop translation as we may have switched the execution mode */
7710 ctx->base.is_jmp = DISAS_STOP;
7711 goto cp0_unimplemented;
7712 case 4:
7713 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7714 /* Stop translation as we may have switched the execution mode */
7715 ctx->base.is_jmp = DISAS_STOP;
7716 rn = "TraceBPC";
7717 goto cp0_unimplemented;
7718 default:
7719 goto cp0_unimplemented;
7721 break;
7722 case 24:
7723 switch (sel) {
7724 case 0:
7725 /* EJTAG support */
7726 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7727 rn = "DEPC";
7728 break;
7729 default:
7730 goto cp0_unimplemented;
7732 break;
7733 case 25:
7734 switch (sel) {
7735 case 0:
7736 gen_helper_mtc0_performance0(cpu_env, arg);
7737 rn = "Performance0";
7738 break;
7739 case 1:
7740 // gen_helper_mtc0_performance1(arg);
7741 rn = "Performance1";
7742 goto cp0_unimplemented;
7743 case 2:
7744 // gen_helper_mtc0_performance2(arg);
7745 rn = "Performance2";
7746 goto cp0_unimplemented;
7747 case 3:
7748 // gen_helper_mtc0_performance3(arg);
7749 rn = "Performance3";
7750 goto cp0_unimplemented;
7751 case 4:
7752 // gen_helper_mtc0_performance4(arg);
7753 rn = "Performance4";
7754 goto cp0_unimplemented;
7755 case 5:
7756 // gen_helper_mtc0_performance5(arg);
7757 rn = "Performance5";
7758 goto cp0_unimplemented;
7759 case 6:
7760 // gen_helper_mtc0_performance6(arg);
7761 rn = "Performance6";
7762 goto cp0_unimplemented;
7763 case 7:
7764 // gen_helper_mtc0_performance7(arg);
7765 rn = "Performance7";
7766 goto cp0_unimplemented;
7767 default:
7768 goto cp0_unimplemented;
7770 break;
7771 case 26:
7772 switch (sel) {
7773 case 0:
7774 gen_helper_mtc0_errctl(cpu_env, arg);
7775 ctx->base.is_jmp = DISAS_STOP;
7776 rn = "ErrCtl";
7777 break;
7778 default:
7779 goto cp0_unimplemented;
7781 break;
7782 case 27:
7783 switch (sel) {
7784 case 0:
7785 case 1:
7786 case 2:
7787 case 3:
7788 /* ignored */
7789 rn = "CacheErr";
7790 break;
7791 default:
7792 goto cp0_unimplemented;
7794 break;
7795 case 28:
7796 switch (sel) {
7797 case 0:
7798 case 2:
7799 case 4:
7800 case 6:
7801 gen_helper_mtc0_taglo(cpu_env, arg);
7802 rn = "TagLo";
7803 break;
7804 case 1:
7805 case 3:
7806 case 5:
7807 case 7:
7808 gen_helper_mtc0_datalo(cpu_env, arg);
7809 rn = "DataLo";
7810 break;
7811 default:
7812 goto cp0_unimplemented;
7814 break;
7815 case 29:
7816 switch (sel) {
7817 case 0:
7818 case 2:
7819 case 4:
7820 case 6:
7821 gen_helper_mtc0_taghi(cpu_env, arg);
7822 rn = "TagHi";
7823 break;
7824 case 1:
7825 case 3:
7826 case 5:
7827 case 7:
7828 gen_helper_mtc0_datahi(cpu_env, arg);
7829 rn = "DataHi";
7830 break;
7831 default:
7832 rn = "invalid sel";
7833 goto cp0_unimplemented;
7835 break;
7836 case 30:
7837 switch (sel) {
7838 case 0:
7839 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7840 rn = "ErrorEPC";
7841 break;
7842 default:
7843 goto cp0_unimplemented;
7845 break;
7846 case 31:
7847 switch (sel) {
7848 case 0:
7849 /* EJTAG support */
7850 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7851 rn = "DESAVE";
7852 break;
7853 case 2:
7854 case 3:
7855 case 4:
7856 case 5:
7857 case 6:
7858 case 7:
7859 CP0_CHECK(ctx->kscrexist & (1 << sel));
7860 tcg_gen_st_tl(arg, cpu_env,
7861 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7862 rn = "KScratch";
7863 break;
7864 default:
7865 goto cp0_unimplemented;
7867 break;
7868 default:
7869 goto cp0_unimplemented;
7871 trace_mips_translate_c0("mtc0", rn, reg, sel);
7873 /* For simplicity assume that all writes can cause interrupts. */
7874 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7875 gen_io_end();
7876 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7877 * translated code to check for pending interrupts. */
7878 gen_save_pc(ctx->base.pc_next + 4);
7879 ctx->base.is_jmp = DISAS_EXIT;
7881 return;
7883 cp0_unimplemented:
7884 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7887 #if defined(TARGET_MIPS64)
7888 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7890 const char *rn = "invalid";
7892 if (sel != 0)
7893 check_insn(ctx, ISA_MIPS64);
7895 switch (reg) {
7896 case 0:
7897 switch (sel) {
7898 case 0:
7899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7900 rn = "Index";
7901 break;
7902 case 1:
7903 CP0_CHECK(ctx->insn_flags & ASE_MT);
7904 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7905 rn = "MVPControl";
7906 break;
7907 case 2:
7908 CP0_CHECK(ctx->insn_flags & ASE_MT);
7909 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7910 rn = "MVPConf0";
7911 break;
7912 case 3:
7913 CP0_CHECK(ctx->insn_flags & ASE_MT);
7914 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7915 rn = "MVPConf1";
7916 break;
7917 case 4:
7918 CP0_CHECK(ctx->vp);
7919 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7920 rn = "VPControl";
7921 break;
7922 default:
7923 goto cp0_unimplemented;
7925 break;
7926 case 1:
7927 switch (sel) {
7928 case 0:
7929 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7930 gen_helper_mfc0_random(arg, cpu_env);
7931 rn = "Random";
7932 break;
7933 case 1:
7934 CP0_CHECK(ctx->insn_flags & ASE_MT);
7935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7936 rn = "VPEControl";
7937 break;
7938 case 2:
7939 CP0_CHECK(ctx->insn_flags & ASE_MT);
7940 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7941 rn = "VPEConf0";
7942 break;
7943 case 3:
7944 CP0_CHECK(ctx->insn_flags & ASE_MT);
7945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7946 rn = "VPEConf1";
7947 break;
7948 case 4:
7949 CP0_CHECK(ctx->insn_flags & ASE_MT);
7950 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7951 rn = "YQMask";
7952 break;
7953 case 5:
7954 CP0_CHECK(ctx->insn_flags & ASE_MT);
7955 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7956 rn = "VPESchedule";
7957 break;
7958 case 6:
7959 CP0_CHECK(ctx->insn_flags & ASE_MT);
7960 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7961 rn = "VPEScheFBack";
7962 break;
7963 case 7:
7964 CP0_CHECK(ctx->insn_flags & ASE_MT);
7965 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7966 rn = "VPEOpt";
7967 break;
7968 default:
7969 goto cp0_unimplemented;
7971 break;
7972 case 2:
7973 switch (sel) {
7974 case 0:
7975 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7976 rn = "EntryLo0";
7977 break;
7978 case 1:
7979 CP0_CHECK(ctx->insn_flags & ASE_MT);
7980 gen_helper_mfc0_tcstatus(arg, cpu_env);
7981 rn = "TCStatus";
7982 break;
7983 case 2:
7984 CP0_CHECK(ctx->insn_flags & ASE_MT);
7985 gen_helper_mfc0_tcbind(arg, cpu_env);
7986 rn = "TCBind";
7987 break;
7988 case 3:
7989 CP0_CHECK(ctx->insn_flags & ASE_MT);
7990 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7991 rn = "TCRestart";
7992 break;
7993 case 4:
7994 CP0_CHECK(ctx->insn_flags & ASE_MT);
7995 gen_helper_dmfc0_tchalt(arg, cpu_env);
7996 rn = "TCHalt";
7997 break;
7998 case 5:
7999 CP0_CHECK(ctx->insn_flags & ASE_MT);
8000 gen_helper_dmfc0_tccontext(arg, cpu_env);
8001 rn = "TCContext";
8002 break;
8003 case 6:
8004 CP0_CHECK(ctx->insn_flags & ASE_MT);
8005 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8006 rn = "TCSchedule";
8007 break;
8008 case 7:
8009 CP0_CHECK(ctx->insn_flags & ASE_MT);
8010 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8011 rn = "TCScheFBack";
8012 break;
8013 default:
8014 goto cp0_unimplemented;
8016 break;
8017 case 3:
8018 switch (sel) {
8019 case 0:
8020 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8021 rn = "EntryLo1";
8022 break;
8023 case 1:
8024 CP0_CHECK(ctx->vp);
8025 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8026 rn = "GlobalNumber";
8027 break;
8028 default:
8029 goto cp0_unimplemented;
8031 break;
8032 case 4:
8033 switch (sel) {
8034 case 0:
8035 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8036 rn = "Context";
8037 break;
8038 case 1:
8039 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8040 rn = "ContextConfig";
8041 goto cp0_unimplemented;
8042 case 2:
8043 CP0_CHECK(ctx->ulri);
8044 tcg_gen_ld_tl(arg, cpu_env,
8045 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8046 rn = "UserLocal";
8047 break;
8048 default:
8049 goto cp0_unimplemented;
8051 break;
8052 case 5:
8053 switch (sel) {
8054 case 0:
8055 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8056 rn = "PageMask";
8057 break;
8058 case 1:
8059 check_insn(ctx, ISA_MIPS32R2);
8060 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8061 rn = "PageGrain";
8062 break;
8063 case 2:
8064 CP0_CHECK(ctx->sc);
8065 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8066 rn = "SegCtl0";
8067 break;
8068 case 3:
8069 CP0_CHECK(ctx->sc);
8070 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8071 rn = "SegCtl1";
8072 break;
8073 case 4:
8074 CP0_CHECK(ctx->sc);
8075 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8076 rn = "SegCtl2";
8077 break;
8078 case 5:
8079 check_pw(ctx);
8080 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8081 rn = "PWBase";
8082 break;
8083 case 6:
8084 check_pw(ctx);
8085 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8086 rn = "PWField";
8087 break;
8088 case 7:
8089 check_pw(ctx);
8090 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8091 rn = "PWSize";
8092 break;
8093 default:
8094 goto cp0_unimplemented;
8096 break;
8097 case 6:
8098 switch (sel) {
8099 case 0:
8100 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8101 rn = "Wired";
8102 break;
8103 case 1:
8104 check_insn(ctx, ISA_MIPS32R2);
8105 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8106 rn = "SRSConf0";
8107 break;
8108 case 2:
8109 check_insn(ctx, ISA_MIPS32R2);
8110 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8111 rn = "SRSConf1";
8112 break;
8113 case 3:
8114 check_insn(ctx, ISA_MIPS32R2);
8115 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8116 rn = "SRSConf2";
8117 break;
8118 case 4:
8119 check_insn(ctx, ISA_MIPS32R2);
8120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8121 rn = "SRSConf3";
8122 break;
8123 case 5:
8124 check_insn(ctx, ISA_MIPS32R2);
8125 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8126 rn = "SRSConf4";
8127 break;
8128 case 6:
8129 check_pw(ctx);
8130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8131 rn = "PWCtl";
8132 break;
8133 default:
8134 goto cp0_unimplemented;
8136 break;
8137 case 7:
8138 switch (sel) {
8139 case 0:
8140 check_insn(ctx, ISA_MIPS32R2);
8141 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8142 rn = "HWREna";
8143 break;
8144 default:
8145 goto cp0_unimplemented;
8147 break;
8148 case 8:
8149 switch (sel) {
8150 case 0:
8151 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8152 rn = "BadVAddr";
8153 break;
8154 case 1:
8155 CP0_CHECK(ctx->bi);
8156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8157 rn = "BadInstr";
8158 break;
8159 case 2:
8160 CP0_CHECK(ctx->bp);
8161 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8162 rn = "BadInstrP";
8163 break;
8164 case 3:
8165 CP0_CHECK(ctx->bi);
8166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8167 tcg_gen_andi_tl(arg, arg, ~0xffff);
8168 rn = "BadInstrX";
8169 break;
8170 default:
8171 goto cp0_unimplemented;
8173 break;
8174 case 9:
8175 switch (sel) {
8176 case 0:
8177 /* Mark as an IO operation because we read the time. */
8178 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8179 gen_io_start();
8181 gen_helper_mfc0_count(arg, cpu_env);
8182 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8183 gen_io_end();
8185 /* Break the TB to be able to take timer interrupts immediately
8186 after reading count. DISAS_STOP isn't sufficient, we need to
8187 ensure we break completely out of translated code. */
8188 gen_save_pc(ctx->base.pc_next + 4);
8189 ctx->base.is_jmp = DISAS_EXIT;
8190 rn = "Count";
8191 break;
8192 /* 6,7 are implementation dependent */
8193 default:
8194 goto cp0_unimplemented;
8196 break;
8197 case 10:
8198 switch (sel) {
8199 case 0:
8200 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8201 rn = "EntryHi";
8202 break;
8203 default:
8204 goto cp0_unimplemented;
8206 break;
8207 case 11:
8208 switch (sel) {
8209 case 0:
8210 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8211 rn = "Compare";
8212 break;
8213 /* 6,7 are implementation dependent */
8214 default:
8215 goto cp0_unimplemented;
8217 break;
8218 case 12:
8219 switch (sel) {
8220 case 0:
8221 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8222 rn = "Status";
8223 break;
8224 case 1:
8225 check_insn(ctx, ISA_MIPS32R2);
8226 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8227 rn = "IntCtl";
8228 break;
8229 case 2:
8230 check_insn(ctx, ISA_MIPS32R2);
8231 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8232 rn = "SRSCtl";
8233 break;
8234 case 3:
8235 check_insn(ctx, ISA_MIPS32R2);
8236 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8237 rn = "SRSMap";
8238 break;
8239 default:
8240 goto cp0_unimplemented;
8242 break;
8243 case 13:
8244 switch (sel) {
8245 case 0:
8246 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8247 rn = "Cause";
8248 break;
8249 default:
8250 goto cp0_unimplemented;
8252 break;
8253 case 14:
8254 switch (sel) {
8255 case 0:
8256 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8257 rn = "EPC";
8258 break;
8259 default:
8260 goto cp0_unimplemented;
8262 break;
8263 case 15:
8264 switch (sel) {
8265 case 0:
8266 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8267 rn = "PRid";
8268 break;
8269 case 1:
8270 check_insn(ctx, ISA_MIPS32R2);
8271 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8272 rn = "EBase";
8273 break;
8274 case 3:
8275 check_insn(ctx, ISA_MIPS32R2);
8276 CP0_CHECK(ctx->cmgcr);
8277 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8278 rn = "CMGCRBase";
8279 break;
8280 default:
8281 goto cp0_unimplemented;
8283 break;
8284 case 16:
8285 switch (sel) {
8286 case 0:
8287 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8288 rn = "Config";
8289 break;
8290 case 1:
8291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8292 rn = "Config1";
8293 break;
8294 case 2:
8295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8296 rn = "Config2";
8297 break;
8298 case 3:
8299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8300 rn = "Config3";
8301 break;
8302 case 4:
8303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8304 rn = "Config4";
8305 break;
8306 case 5:
8307 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8308 rn = "Config5";
8309 break;
8310 /* 6,7 are implementation dependent */
8311 case 6:
8312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8313 rn = "Config6";
8314 break;
8315 case 7:
8316 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8317 rn = "Config7";
8318 break;
8319 default:
8320 goto cp0_unimplemented;
8322 break;
8323 case 17:
8324 switch (sel) {
8325 case 0:
8326 gen_helper_dmfc0_lladdr(arg, cpu_env);
8327 rn = "LLAddr";
8328 break;
8329 case 1:
8330 CP0_CHECK(ctx->mrp);
8331 gen_helper_dmfc0_maar(arg, cpu_env);
8332 rn = "MAAR";
8333 break;
8334 case 2:
8335 CP0_CHECK(ctx->mrp);
8336 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8337 rn = "MAARI";
8338 break;
8339 default:
8340 goto cp0_unimplemented;
8342 break;
8343 case 18:
8344 switch (sel) {
8345 case 0:
8346 case 1:
8347 case 2:
8348 case 3:
8349 case 4:
8350 case 5:
8351 case 6:
8352 case 7:
8353 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8354 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8355 rn = "WatchLo";
8356 break;
8357 default:
8358 goto cp0_unimplemented;
8360 break;
8361 case 19:
8362 switch (sel) {
8363 case 0:
8364 case 1:
8365 case 2:
8366 case 3:
8367 case 4:
8368 case 5:
8369 case 6:
8370 case 7:
8371 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8372 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8373 rn = "WatchHi";
8374 break;
8375 default:
8376 goto cp0_unimplemented;
8378 break;
8379 case 20:
8380 switch (sel) {
8381 case 0:
8382 check_insn(ctx, ISA_MIPS3);
8383 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8384 rn = "XContext";
8385 break;
8386 default:
8387 goto cp0_unimplemented;
8389 break;
8390 case 21:
8391 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8392 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8393 switch (sel) {
8394 case 0:
8395 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8396 rn = "Framemask";
8397 break;
8398 default:
8399 goto cp0_unimplemented;
8401 break;
8402 case 22:
8403 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8404 rn = "'Diagnostic"; /* implementation dependent */
8405 break;
8406 case 23:
8407 switch (sel) {
8408 case 0:
8409 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8410 rn = "Debug";
8411 break;
8412 case 1:
8413 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8414 rn = "TraceControl";
8415 goto cp0_unimplemented;
8416 case 2:
8417 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8418 rn = "TraceControl2";
8419 goto cp0_unimplemented;
8420 case 3:
8421 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8422 rn = "UserTraceData";
8423 goto cp0_unimplemented;
8424 case 4:
8425 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8426 rn = "TraceBPC";
8427 goto cp0_unimplemented;
8428 default:
8429 goto cp0_unimplemented;
8431 break;
8432 case 24:
8433 switch (sel) {
8434 case 0:
8435 /* EJTAG support */
8436 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8437 rn = "DEPC";
8438 break;
8439 default:
8440 goto cp0_unimplemented;
8442 break;
8443 case 25:
8444 switch (sel) {
8445 case 0:
8446 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8447 rn = "Performance0";
8448 break;
8449 case 1:
8450 // gen_helper_dmfc0_performance1(arg);
8451 rn = "Performance1";
8452 goto cp0_unimplemented;
8453 case 2:
8454 // gen_helper_dmfc0_performance2(arg);
8455 rn = "Performance2";
8456 goto cp0_unimplemented;
8457 case 3:
8458 // gen_helper_dmfc0_performance3(arg);
8459 rn = "Performance3";
8460 goto cp0_unimplemented;
8461 case 4:
8462 // gen_helper_dmfc0_performance4(arg);
8463 rn = "Performance4";
8464 goto cp0_unimplemented;
8465 case 5:
8466 // gen_helper_dmfc0_performance5(arg);
8467 rn = "Performance5";
8468 goto cp0_unimplemented;
8469 case 6:
8470 // gen_helper_dmfc0_performance6(arg);
8471 rn = "Performance6";
8472 goto cp0_unimplemented;
8473 case 7:
8474 // gen_helper_dmfc0_performance7(arg);
8475 rn = "Performance7";
8476 goto cp0_unimplemented;
8477 default:
8478 goto cp0_unimplemented;
8480 break;
8481 case 26:
8482 switch (sel) {
8483 case 0:
8484 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8485 rn = "ErrCtl";
8486 break;
8487 default:
8488 goto cp0_unimplemented;
8490 break;
8491 case 27:
8492 switch (sel) {
8493 /* ignored */
8494 case 0:
8495 case 1:
8496 case 2:
8497 case 3:
8498 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8499 rn = "CacheErr";
8500 break;
8501 default:
8502 goto cp0_unimplemented;
8504 break;
8505 case 28:
8506 switch (sel) {
8507 case 0:
8508 case 2:
8509 case 4:
8510 case 6:
8511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8512 rn = "TagLo";
8513 break;
8514 case 1:
8515 case 3:
8516 case 5:
8517 case 7:
8518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8519 rn = "DataLo";
8520 break;
8521 default:
8522 goto cp0_unimplemented;
8524 break;
8525 case 29:
8526 switch (sel) {
8527 case 0:
8528 case 2:
8529 case 4:
8530 case 6:
8531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8532 rn = "TagHi";
8533 break;
8534 case 1:
8535 case 3:
8536 case 5:
8537 case 7:
8538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8539 rn = "DataHi";
8540 break;
8541 default:
8542 goto cp0_unimplemented;
8544 break;
8545 case 30:
8546 switch (sel) {
8547 case 0:
8548 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8549 rn = "ErrorEPC";
8550 break;
8551 default:
8552 goto cp0_unimplemented;
8554 break;
8555 case 31:
8556 switch (sel) {
8557 case 0:
8558 /* EJTAG support */
8559 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8560 rn = "DESAVE";
8561 break;
8562 case 2:
8563 case 3:
8564 case 4:
8565 case 5:
8566 case 6:
8567 case 7:
8568 CP0_CHECK(ctx->kscrexist & (1 << sel));
8569 tcg_gen_ld_tl(arg, cpu_env,
8570 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8571 rn = "KScratch";
8572 break;
8573 default:
8574 goto cp0_unimplemented;
8576 break;
8577 default:
8578 goto cp0_unimplemented;
8580 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8581 return;
8583 cp0_unimplemented:
8584 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8585 gen_mfc0_unimplemented(ctx, arg);
8588 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8590 const char *rn = "invalid";
8592 if (sel != 0)
8593 check_insn(ctx, ISA_MIPS64);
8595 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8596 gen_io_start();
8599 switch (reg) {
8600 case 0:
8601 switch (sel) {
8602 case 0:
8603 gen_helper_mtc0_index(cpu_env, arg);
8604 rn = "Index";
8605 break;
8606 case 1:
8607 CP0_CHECK(ctx->insn_flags & ASE_MT);
8608 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8609 rn = "MVPControl";
8610 break;
8611 case 2:
8612 CP0_CHECK(ctx->insn_flags & ASE_MT);
8613 /* ignored */
8614 rn = "MVPConf0";
8615 break;
8616 case 3:
8617 CP0_CHECK(ctx->insn_flags & ASE_MT);
8618 /* ignored */
8619 rn = "MVPConf1";
8620 break;
8621 case 4:
8622 CP0_CHECK(ctx->vp);
8623 /* ignored */
8624 rn = "VPControl";
8625 break;
8626 default:
8627 goto cp0_unimplemented;
8629 break;
8630 case 1:
8631 switch (sel) {
8632 case 0:
8633 /* ignored */
8634 rn = "Random";
8635 break;
8636 case 1:
8637 CP0_CHECK(ctx->insn_flags & ASE_MT);
8638 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8639 rn = "VPEControl";
8640 break;
8641 case 2:
8642 CP0_CHECK(ctx->insn_flags & ASE_MT);
8643 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8644 rn = "VPEConf0";
8645 break;
8646 case 3:
8647 CP0_CHECK(ctx->insn_flags & ASE_MT);
8648 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8649 rn = "VPEConf1";
8650 break;
8651 case 4:
8652 CP0_CHECK(ctx->insn_flags & ASE_MT);
8653 gen_helper_mtc0_yqmask(cpu_env, arg);
8654 rn = "YQMask";
8655 break;
8656 case 5:
8657 CP0_CHECK(ctx->insn_flags & ASE_MT);
8658 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8659 rn = "VPESchedule";
8660 break;
8661 case 6:
8662 CP0_CHECK(ctx->insn_flags & ASE_MT);
8663 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8664 rn = "VPEScheFBack";
8665 break;
8666 case 7:
8667 CP0_CHECK(ctx->insn_flags & ASE_MT);
8668 gen_helper_mtc0_vpeopt(cpu_env, arg);
8669 rn = "VPEOpt";
8670 break;
8671 default:
8672 goto cp0_unimplemented;
8674 break;
8675 case 2:
8676 switch (sel) {
8677 case 0:
8678 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8679 rn = "EntryLo0";
8680 break;
8681 case 1:
8682 CP0_CHECK(ctx->insn_flags & ASE_MT);
8683 gen_helper_mtc0_tcstatus(cpu_env, arg);
8684 rn = "TCStatus";
8685 break;
8686 case 2:
8687 CP0_CHECK(ctx->insn_flags & ASE_MT);
8688 gen_helper_mtc0_tcbind(cpu_env, arg);
8689 rn = "TCBind";
8690 break;
8691 case 3:
8692 CP0_CHECK(ctx->insn_flags & ASE_MT);
8693 gen_helper_mtc0_tcrestart(cpu_env, arg);
8694 rn = "TCRestart";
8695 break;
8696 case 4:
8697 CP0_CHECK(ctx->insn_flags & ASE_MT);
8698 gen_helper_mtc0_tchalt(cpu_env, arg);
8699 rn = "TCHalt";
8700 break;
8701 case 5:
8702 CP0_CHECK(ctx->insn_flags & ASE_MT);
8703 gen_helper_mtc0_tccontext(cpu_env, arg);
8704 rn = "TCContext";
8705 break;
8706 case 6:
8707 CP0_CHECK(ctx->insn_flags & ASE_MT);
8708 gen_helper_mtc0_tcschedule(cpu_env, arg);
8709 rn = "TCSchedule";
8710 break;
8711 case 7:
8712 CP0_CHECK(ctx->insn_flags & ASE_MT);
8713 gen_helper_mtc0_tcschefback(cpu_env, arg);
8714 rn = "TCScheFBack";
8715 break;
8716 default:
8717 goto cp0_unimplemented;
8719 break;
8720 case 3:
8721 switch (sel) {
8722 case 0:
8723 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8724 rn = "EntryLo1";
8725 break;
8726 case 1:
8727 CP0_CHECK(ctx->vp);
8728 /* ignored */
8729 rn = "GlobalNumber";
8730 break;
8731 default:
8732 goto cp0_unimplemented;
8734 break;
8735 case 4:
8736 switch (sel) {
8737 case 0:
8738 gen_helper_mtc0_context(cpu_env, arg);
8739 rn = "Context";
8740 break;
8741 case 1:
8742 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8743 rn = "ContextConfig";
8744 goto cp0_unimplemented;
8745 case 2:
8746 CP0_CHECK(ctx->ulri);
8747 tcg_gen_st_tl(arg, cpu_env,
8748 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8749 rn = "UserLocal";
8750 break;
8751 default:
8752 goto cp0_unimplemented;
8754 break;
8755 case 5:
8756 switch (sel) {
8757 case 0:
8758 gen_helper_mtc0_pagemask(cpu_env, arg);
8759 rn = "PageMask";
8760 break;
8761 case 1:
8762 check_insn(ctx, ISA_MIPS32R2);
8763 gen_helper_mtc0_pagegrain(cpu_env, arg);
8764 rn = "PageGrain";
8765 break;
8766 case 2:
8767 CP0_CHECK(ctx->sc);
8768 gen_helper_mtc0_segctl0(cpu_env, arg);
8769 rn = "SegCtl0";
8770 break;
8771 case 3:
8772 CP0_CHECK(ctx->sc);
8773 gen_helper_mtc0_segctl1(cpu_env, arg);
8774 rn = "SegCtl1";
8775 break;
8776 case 4:
8777 CP0_CHECK(ctx->sc);
8778 gen_helper_mtc0_segctl2(cpu_env, arg);
8779 rn = "SegCtl2";
8780 break;
8781 case 5:
8782 check_pw(ctx);
8783 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8784 rn = "PWBase";
8785 break;
8786 case 6:
8787 check_pw(ctx);
8788 gen_helper_mtc0_pwfield(cpu_env, arg);
8789 rn = "PWField";
8790 break;
8791 case 7:
8792 check_pw(ctx);
8793 gen_helper_mtc0_pwsize(cpu_env, arg);
8794 rn = "PWSize";
8795 break;
8796 default:
8797 goto cp0_unimplemented;
8799 break;
8800 case 6:
8801 switch (sel) {
8802 case 0:
8803 gen_helper_mtc0_wired(cpu_env, arg);
8804 rn = "Wired";
8805 break;
8806 case 1:
8807 check_insn(ctx, ISA_MIPS32R2);
8808 gen_helper_mtc0_srsconf0(cpu_env, arg);
8809 rn = "SRSConf0";
8810 break;
8811 case 2:
8812 check_insn(ctx, ISA_MIPS32R2);
8813 gen_helper_mtc0_srsconf1(cpu_env, arg);
8814 rn = "SRSConf1";
8815 break;
8816 case 3:
8817 check_insn(ctx, ISA_MIPS32R2);
8818 gen_helper_mtc0_srsconf2(cpu_env, arg);
8819 rn = "SRSConf2";
8820 break;
8821 case 4:
8822 check_insn(ctx, ISA_MIPS32R2);
8823 gen_helper_mtc0_srsconf3(cpu_env, arg);
8824 rn = "SRSConf3";
8825 break;
8826 case 5:
8827 check_insn(ctx, ISA_MIPS32R2);
8828 gen_helper_mtc0_srsconf4(cpu_env, arg);
8829 rn = "SRSConf4";
8830 break;
8831 case 6:
8832 check_pw(ctx);
8833 gen_helper_mtc0_pwctl(cpu_env, arg);
8834 rn = "PWCtl";
8835 break;
8836 default:
8837 goto cp0_unimplemented;
8839 break;
8840 case 7:
8841 switch (sel) {
8842 case 0:
8843 check_insn(ctx, ISA_MIPS32R2);
8844 gen_helper_mtc0_hwrena(cpu_env, arg);
8845 ctx->base.is_jmp = DISAS_STOP;
8846 rn = "HWREna";
8847 break;
8848 default:
8849 goto cp0_unimplemented;
8851 break;
8852 case 8:
8853 switch (sel) {
8854 case 0:
8855 /* ignored */
8856 rn = "BadVAddr";
8857 break;
8858 case 1:
8859 /* ignored */
8860 rn = "BadInstr";
8861 break;
8862 case 2:
8863 /* ignored */
8864 rn = "BadInstrP";
8865 break;
8866 case 3:
8867 /* ignored */
8868 rn = "BadInstrX";
8869 break;
8870 default:
8871 goto cp0_unimplemented;
8873 break;
8874 case 9:
8875 switch (sel) {
8876 case 0:
8877 gen_helper_mtc0_count(cpu_env, arg);
8878 rn = "Count";
8879 break;
8880 /* 6,7 are implementation dependent */
8881 default:
8882 goto cp0_unimplemented;
8884 /* Stop translation as we may have switched the execution mode */
8885 ctx->base.is_jmp = DISAS_STOP;
8886 break;
8887 case 10:
8888 switch (sel) {
8889 case 0:
8890 gen_helper_mtc0_entryhi(cpu_env, arg);
8891 rn = "EntryHi";
8892 break;
8893 default:
8894 goto cp0_unimplemented;
8896 break;
8897 case 11:
8898 switch (sel) {
8899 case 0:
8900 gen_helper_mtc0_compare(cpu_env, arg);
8901 rn = "Compare";
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 12:
8911 switch (sel) {
8912 case 0:
8913 save_cpu_state(ctx, 1);
8914 gen_helper_mtc0_status(cpu_env, arg);
8915 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8916 gen_save_pc(ctx->base.pc_next + 4);
8917 ctx->base.is_jmp = DISAS_EXIT;
8918 rn = "Status";
8919 break;
8920 case 1:
8921 check_insn(ctx, ISA_MIPS32R2);
8922 gen_helper_mtc0_intctl(cpu_env, arg);
8923 /* Stop translation as we may have switched the execution mode */
8924 ctx->base.is_jmp = DISAS_STOP;
8925 rn = "IntCtl";
8926 break;
8927 case 2:
8928 check_insn(ctx, ISA_MIPS32R2);
8929 gen_helper_mtc0_srsctl(cpu_env, arg);
8930 /* Stop translation as we may have switched the execution mode */
8931 ctx->base.is_jmp = DISAS_STOP;
8932 rn = "SRSCtl";
8933 break;
8934 case 3:
8935 check_insn(ctx, ISA_MIPS32R2);
8936 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8937 /* Stop translation as we may have switched the execution mode */
8938 ctx->base.is_jmp = DISAS_STOP;
8939 rn = "SRSMap";
8940 break;
8941 default:
8942 goto cp0_unimplemented;
8944 break;
8945 case 13:
8946 switch (sel) {
8947 case 0:
8948 save_cpu_state(ctx, 1);
8949 gen_helper_mtc0_cause(cpu_env, arg);
8950 /* Stop translation as we may have triggered an interrupt.
8951 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8952 * translated code to check for pending interrupts. */
8953 gen_save_pc(ctx->base.pc_next + 4);
8954 ctx->base.is_jmp = DISAS_EXIT;
8955 rn = "Cause";
8956 break;
8957 default:
8958 goto cp0_unimplemented;
8960 break;
8961 case 14:
8962 switch (sel) {
8963 case 0:
8964 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8965 rn = "EPC";
8966 break;
8967 default:
8968 goto cp0_unimplemented;
8970 break;
8971 case 15:
8972 switch (sel) {
8973 case 0:
8974 /* ignored */
8975 rn = "PRid";
8976 break;
8977 case 1:
8978 check_insn(ctx, ISA_MIPS32R2);
8979 gen_helper_mtc0_ebase(cpu_env, arg);
8980 rn = "EBase";
8981 break;
8982 default:
8983 goto cp0_unimplemented;
8985 break;
8986 case 16:
8987 switch (sel) {
8988 case 0:
8989 gen_helper_mtc0_config0(cpu_env, arg);
8990 rn = "Config";
8991 /* Stop translation as we may have switched the execution mode */
8992 ctx->base.is_jmp = DISAS_STOP;
8993 break;
8994 case 1:
8995 /* ignored, read only */
8996 rn = "Config1";
8997 break;
8998 case 2:
8999 gen_helper_mtc0_config2(cpu_env, arg);
9000 rn = "Config2";
9001 /* Stop translation as we may have switched the execution mode */
9002 ctx->base.is_jmp = DISAS_STOP;
9003 break;
9004 case 3:
9005 gen_helper_mtc0_config3(cpu_env, arg);
9006 rn = "Config3";
9007 /* Stop translation as we may have switched the execution mode */
9008 ctx->base.is_jmp = DISAS_STOP;
9009 break;
9010 case 4:
9011 /* currently ignored */
9012 rn = "Config4";
9013 break;
9014 case 5:
9015 gen_helper_mtc0_config5(cpu_env, arg);
9016 rn = "Config5";
9017 /* Stop translation as we may have switched the execution mode */
9018 ctx->base.is_jmp = DISAS_STOP;
9019 break;
9020 /* 6,7 are implementation dependent */
9021 default:
9022 rn = "Invalid config selector";
9023 goto cp0_unimplemented;
9025 break;
9026 case 17:
9027 switch (sel) {
9028 case 0:
9029 gen_helper_mtc0_lladdr(cpu_env, arg);
9030 rn = "LLAddr";
9031 break;
9032 case 1:
9033 CP0_CHECK(ctx->mrp);
9034 gen_helper_mtc0_maar(cpu_env, arg);
9035 rn = "MAAR";
9036 break;
9037 case 2:
9038 CP0_CHECK(ctx->mrp);
9039 gen_helper_mtc0_maari(cpu_env, arg);
9040 rn = "MAARI";
9041 break;
9042 default:
9043 goto cp0_unimplemented;
9045 break;
9046 case 18:
9047 switch (sel) {
9048 case 0:
9049 case 1:
9050 case 2:
9051 case 3:
9052 case 4:
9053 case 5:
9054 case 6:
9055 case 7:
9056 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9057 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9058 rn = "WatchLo";
9059 break;
9060 default:
9061 goto cp0_unimplemented;
9063 break;
9064 case 19:
9065 switch (sel) {
9066 case 0:
9067 case 1:
9068 case 2:
9069 case 3:
9070 case 4:
9071 case 5:
9072 case 6:
9073 case 7:
9074 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9075 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9076 rn = "WatchHi";
9077 break;
9078 default:
9079 goto cp0_unimplemented;
9081 break;
9082 case 20:
9083 switch (sel) {
9084 case 0:
9085 check_insn(ctx, ISA_MIPS3);
9086 gen_helper_mtc0_xcontext(cpu_env, arg);
9087 rn = "XContext";
9088 break;
9089 default:
9090 goto cp0_unimplemented;
9092 break;
9093 case 21:
9094 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9095 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9096 switch (sel) {
9097 case 0:
9098 gen_helper_mtc0_framemask(cpu_env, arg);
9099 rn = "Framemask";
9100 break;
9101 default:
9102 goto cp0_unimplemented;
9104 break;
9105 case 22:
9106 /* ignored */
9107 rn = "Diagnostic"; /* implementation dependent */
9108 break;
9109 case 23:
9110 switch (sel) {
9111 case 0:
9112 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9113 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9114 gen_save_pc(ctx->base.pc_next + 4);
9115 ctx->base.is_jmp = DISAS_EXIT;
9116 rn = "Debug";
9117 break;
9118 case 1:
9119 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9120 /* Stop translation as we may have switched the execution mode */
9121 ctx->base.is_jmp = DISAS_STOP;
9122 rn = "TraceControl";
9123 goto cp0_unimplemented;
9124 case 2:
9125 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9126 /* Stop translation as we may have switched the execution mode */
9127 ctx->base.is_jmp = DISAS_STOP;
9128 rn = "TraceControl2";
9129 goto cp0_unimplemented;
9130 case 3:
9131 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9132 /* Stop translation as we may have switched the execution mode */
9133 ctx->base.is_jmp = DISAS_STOP;
9134 rn = "UserTraceData";
9135 goto cp0_unimplemented;
9136 case 4:
9137 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9138 /* Stop translation as we may have switched the execution mode */
9139 ctx->base.is_jmp = DISAS_STOP;
9140 rn = "TraceBPC";
9141 goto cp0_unimplemented;
9142 default:
9143 goto cp0_unimplemented;
9145 break;
9146 case 24:
9147 switch (sel) {
9148 case 0:
9149 /* EJTAG support */
9150 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9151 rn = "DEPC";
9152 break;
9153 default:
9154 goto cp0_unimplemented;
9156 break;
9157 case 25:
9158 switch (sel) {
9159 case 0:
9160 gen_helper_mtc0_performance0(cpu_env, arg);
9161 rn = "Performance0";
9162 break;
9163 case 1:
9164 // gen_helper_mtc0_performance1(cpu_env, arg);
9165 rn = "Performance1";
9166 goto cp0_unimplemented;
9167 case 2:
9168 // gen_helper_mtc0_performance2(cpu_env, arg);
9169 rn = "Performance2";
9170 goto cp0_unimplemented;
9171 case 3:
9172 // gen_helper_mtc0_performance3(cpu_env, arg);
9173 rn = "Performance3";
9174 goto cp0_unimplemented;
9175 case 4:
9176 // gen_helper_mtc0_performance4(cpu_env, arg);
9177 rn = "Performance4";
9178 goto cp0_unimplemented;
9179 case 5:
9180 // gen_helper_mtc0_performance5(cpu_env, arg);
9181 rn = "Performance5";
9182 goto cp0_unimplemented;
9183 case 6:
9184 // gen_helper_mtc0_performance6(cpu_env, arg);
9185 rn = "Performance6";
9186 goto cp0_unimplemented;
9187 case 7:
9188 // gen_helper_mtc0_performance7(cpu_env, arg);
9189 rn = "Performance7";
9190 goto cp0_unimplemented;
9191 default:
9192 goto cp0_unimplemented;
9194 break;
9195 case 26:
9196 switch (sel) {
9197 case 0:
9198 gen_helper_mtc0_errctl(cpu_env, arg);
9199 ctx->base.is_jmp = DISAS_STOP;
9200 rn = "ErrCtl";
9201 break;
9202 default:
9203 goto cp0_unimplemented;
9205 break;
9206 case 27:
9207 switch (sel) {
9208 case 0:
9209 case 1:
9210 case 2:
9211 case 3:
9212 /* ignored */
9213 rn = "CacheErr";
9214 break;
9215 default:
9216 goto cp0_unimplemented;
9218 break;
9219 case 28:
9220 switch (sel) {
9221 case 0:
9222 case 2:
9223 case 4:
9224 case 6:
9225 gen_helper_mtc0_taglo(cpu_env, arg);
9226 rn = "TagLo";
9227 break;
9228 case 1:
9229 case 3:
9230 case 5:
9231 case 7:
9232 gen_helper_mtc0_datalo(cpu_env, arg);
9233 rn = "DataLo";
9234 break;
9235 default:
9236 goto cp0_unimplemented;
9238 break;
9239 case 29:
9240 switch (sel) {
9241 case 0:
9242 case 2:
9243 case 4:
9244 case 6:
9245 gen_helper_mtc0_taghi(cpu_env, arg);
9246 rn = "TagHi";
9247 break;
9248 case 1:
9249 case 3:
9250 case 5:
9251 case 7:
9252 gen_helper_mtc0_datahi(cpu_env, arg);
9253 rn = "DataHi";
9254 break;
9255 default:
9256 rn = "invalid sel";
9257 goto cp0_unimplemented;
9259 break;
9260 case 30:
9261 switch (sel) {
9262 case 0:
9263 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9264 rn = "ErrorEPC";
9265 break;
9266 default:
9267 goto cp0_unimplemented;
9269 break;
9270 case 31:
9271 switch (sel) {
9272 case 0:
9273 /* EJTAG support */
9274 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9275 rn = "DESAVE";
9276 break;
9277 case 2:
9278 case 3:
9279 case 4:
9280 case 5:
9281 case 6:
9282 case 7:
9283 CP0_CHECK(ctx->kscrexist & (1 << sel));
9284 tcg_gen_st_tl(arg, cpu_env,
9285 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9286 rn = "KScratch";
9287 break;
9288 default:
9289 goto cp0_unimplemented;
9291 break;
9292 default:
9293 goto cp0_unimplemented;
9295 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9297 /* For simplicity assume that all writes can cause interrupts. */
9298 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9299 gen_io_end();
9300 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9301 * translated code to check for pending interrupts. */
9302 gen_save_pc(ctx->base.pc_next + 4);
9303 ctx->base.is_jmp = DISAS_EXIT;
9305 return;
9307 cp0_unimplemented:
9308 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9310 #endif /* TARGET_MIPS64 */
9312 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9313 int u, int sel, int h)
9315 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9316 TCGv t0 = tcg_temp_local_new();
9318 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9319 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9320 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9321 tcg_gen_movi_tl(t0, -1);
9322 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9323 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9324 tcg_gen_movi_tl(t0, -1);
9325 else if (u == 0) {
9326 switch (rt) {
9327 case 1:
9328 switch (sel) {
9329 case 1:
9330 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9331 break;
9332 case 2:
9333 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9334 break;
9335 default:
9336 goto die;
9337 break;
9339 break;
9340 case 2:
9341 switch (sel) {
9342 case 1:
9343 gen_helper_mftc0_tcstatus(t0, cpu_env);
9344 break;
9345 case 2:
9346 gen_helper_mftc0_tcbind(t0, cpu_env);
9347 break;
9348 case 3:
9349 gen_helper_mftc0_tcrestart(t0, cpu_env);
9350 break;
9351 case 4:
9352 gen_helper_mftc0_tchalt(t0, cpu_env);
9353 break;
9354 case 5:
9355 gen_helper_mftc0_tccontext(t0, cpu_env);
9356 break;
9357 case 6:
9358 gen_helper_mftc0_tcschedule(t0, cpu_env);
9359 break;
9360 case 7:
9361 gen_helper_mftc0_tcschefback(t0, cpu_env);
9362 break;
9363 default:
9364 gen_mfc0(ctx, t0, rt, sel);
9365 break;
9367 break;
9368 case 10:
9369 switch (sel) {
9370 case 0:
9371 gen_helper_mftc0_entryhi(t0, cpu_env);
9372 break;
9373 default:
9374 gen_mfc0(ctx, t0, rt, sel);
9375 break;
9377 case 12:
9378 switch (sel) {
9379 case 0:
9380 gen_helper_mftc0_status(t0, cpu_env);
9381 break;
9382 default:
9383 gen_mfc0(ctx, t0, rt, sel);
9384 break;
9386 case 13:
9387 switch (sel) {
9388 case 0:
9389 gen_helper_mftc0_cause(t0, cpu_env);
9390 break;
9391 default:
9392 goto die;
9393 break;
9395 break;
9396 case 14:
9397 switch (sel) {
9398 case 0:
9399 gen_helper_mftc0_epc(t0, cpu_env);
9400 break;
9401 default:
9402 goto die;
9403 break;
9405 break;
9406 case 15:
9407 switch (sel) {
9408 case 1:
9409 gen_helper_mftc0_ebase(t0, cpu_env);
9410 break;
9411 default:
9412 goto die;
9413 break;
9415 break;
9416 case 16:
9417 switch (sel) {
9418 case 0:
9419 case 1:
9420 case 2:
9421 case 3:
9422 case 4:
9423 case 5:
9424 case 6:
9425 case 7:
9426 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9427 break;
9428 default:
9429 goto die;
9430 break;
9432 break;
9433 case 23:
9434 switch (sel) {
9435 case 0:
9436 gen_helper_mftc0_debug(t0, cpu_env);
9437 break;
9438 default:
9439 gen_mfc0(ctx, t0, rt, sel);
9440 break;
9442 break;
9443 default:
9444 gen_mfc0(ctx, t0, rt, sel);
9446 } else switch (sel) {
9447 /* GPR registers. */
9448 case 0:
9449 gen_helper_1e0i(mftgpr, t0, rt);
9450 break;
9451 /* Auxiliary CPU registers */
9452 case 1:
9453 switch (rt) {
9454 case 0:
9455 gen_helper_1e0i(mftlo, t0, 0);
9456 break;
9457 case 1:
9458 gen_helper_1e0i(mfthi, t0, 0);
9459 break;
9460 case 2:
9461 gen_helper_1e0i(mftacx, t0, 0);
9462 break;
9463 case 4:
9464 gen_helper_1e0i(mftlo, t0, 1);
9465 break;
9466 case 5:
9467 gen_helper_1e0i(mfthi, t0, 1);
9468 break;
9469 case 6:
9470 gen_helper_1e0i(mftacx, t0, 1);
9471 break;
9472 case 8:
9473 gen_helper_1e0i(mftlo, t0, 2);
9474 break;
9475 case 9:
9476 gen_helper_1e0i(mfthi, t0, 2);
9477 break;
9478 case 10:
9479 gen_helper_1e0i(mftacx, t0, 2);
9480 break;
9481 case 12:
9482 gen_helper_1e0i(mftlo, t0, 3);
9483 break;
9484 case 13:
9485 gen_helper_1e0i(mfthi, t0, 3);
9486 break;
9487 case 14:
9488 gen_helper_1e0i(mftacx, t0, 3);
9489 break;
9490 case 16:
9491 gen_helper_mftdsp(t0, cpu_env);
9492 break;
9493 default:
9494 goto die;
9496 break;
9497 /* Floating point (COP1). */
9498 case 2:
9499 /* XXX: For now we support only a single FPU context. */
9500 if (h == 0) {
9501 TCGv_i32 fp0 = tcg_temp_new_i32();
9503 gen_load_fpr32(ctx, fp0, rt);
9504 tcg_gen_ext_i32_tl(t0, fp0);
9505 tcg_temp_free_i32(fp0);
9506 } else {
9507 TCGv_i32 fp0 = tcg_temp_new_i32();
9509 gen_load_fpr32h(ctx, fp0, rt);
9510 tcg_gen_ext_i32_tl(t0, fp0);
9511 tcg_temp_free_i32(fp0);
9513 break;
9514 case 3:
9515 /* XXX: For now we support only a single FPU context. */
9516 gen_helper_1e0i(cfc1, t0, rt);
9517 break;
9518 /* COP2: Not implemented. */
9519 case 4:
9520 case 5:
9521 /* fall through */
9522 default:
9523 goto die;
9525 trace_mips_translate_tr("mftr", rt, u, sel, h);
9526 gen_store_gpr(t0, rd);
9527 tcg_temp_free(t0);
9528 return;
9530 die:
9531 tcg_temp_free(t0);
9532 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9533 generate_exception_end(ctx, EXCP_RI);
9536 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9537 int u, int sel, int h)
9539 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9540 TCGv t0 = tcg_temp_local_new();
9542 gen_load_gpr(t0, rt);
9543 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9544 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9545 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9546 /* NOP */ ;
9547 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9548 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9549 /* NOP */ ;
9550 else if (u == 0) {
9551 switch (rd) {
9552 case 1:
9553 switch (sel) {
9554 case 1:
9555 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9556 break;
9557 case 2:
9558 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9559 break;
9560 default:
9561 goto die;
9562 break;
9564 break;
9565 case 2:
9566 switch (sel) {
9567 case 1:
9568 gen_helper_mttc0_tcstatus(cpu_env, t0);
9569 break;
9570 case 2:
9571 gen_helper_mttc0_tcbind(cpu_env, t0);
9572 break;
9573 case 3:
9574 gen_helper_mttc0_tcrestart(cpu_env, t0);
9575 break;
9576 case 4:
9577 gen_helper_mttc0_tchalt(cpu_env, t0);
9578 break;
9579 case 5:
9580 gen_helper_mttc0_tccontext(cpu_env, t0);
9581 break;
9582 case 6:
9583 gen_helper_mttc0_tcschedule(cpu_env, t0);
9584 break;
9585 case 7:
9586 gen_helper_mttc0_tcschefback(cpu_env, t0);
9587 break;
9588 default:
9589 gen_mtc0(ctx, t0, rd, sel);
9590 break;
9592 break;
9593 case 10:
9594 switch (sel) {
9595 case 0:
9596 gen_helper_mttc0_entryhi(cpu_env, t0);
9597 break;
9598 default:
9599 gen_mtc0(ctx, t0, rd, sel);
9600 break;
9602 case 12:
9603 switch (sel) {
9604 case 0:
9605 gen_helper_mttc0_status(cpu_env, t0);
9606 break;
9607 default:
9608 gen_mtc0(ctx, t0, rd, sel);
9609 break;
9611 case 13:
9612 switch (sel) {
9613 case 0:
9614 gen_helper_mttc0_cause(cpu_env, t0);
9615 break;
9616 default:
9617 goto die;
9618 break;
9620 break;
9621 case 15:
9622 switch (sel) {
9623 case 1:
9624 gen_helper_mttc0_ebase(cpu_env, t0);
9625 break;
9626 default:
9627 goto die;
9628 break;
9630 break;
9631 case 23:
9632 switch (sel) {
9633 case 0:
9634 gen_helper_mttc0_debug(cpu_env, t0);
9635 break;
9636 default:
9637 gen_mtc0(ctx, t0, rd, sel);
9638 break;
9640 break;
9641 default:
9642 gen_mtc0(ctx, t0, rd, sel);
9644 } else switch (sel) {
9645 /* GPR registers. */
9646 case 0:
9647 gen_helper_0e1i(mttgpr, t0, rd);
9648 break;
9649 /* Auxiliary CPU registers */
9650 case 1:
9651 switch (rd) {
9652 case 0:
9653 gen_helper_0e1i(mttlo, t0, 0);
9654 break;
9655 case 1:
9656 gen_helper_0e1i(mtthi, t0, 0);
9657 break;
9658 case 2:
9659 gen_helper_0e1i(mttacx, t0, 0);
9660 break;
9661 case 4:
9662 gen_helper_0e1i(mttlo, t0, 1);
9663 break;
9664 case 5:
9665 gen_helper_0e1i(mtthi, t0, 1);
9666 break;
9667 case 6:
9668 gen_helper_0e1i(mttacx, t0, 1);
9669 break;
9670 case 8:
9671 gen_helper_0e1i(mttlo, t0, 2);
9672 break;
9673 case 9:
9674 gen_helper_0e1i(mtthi, t0, 2);
9675 break;
9676 case 10:
9677 gen_helper_0e1i(mttacx, t0, 2);
9678 break;
9679 case 12:
9680 gen_helper_0e1i(mttlo, t0, 3);
9681 break;
9682 case 13:
9683 gen_helper_0e1i(mtthi, t0, 3);
9684 break;
9685 case 14:
9686 gen_helper_0e1i(mttacx, t0, 3);
9687 break;
9688 case 16:
9689 gen_helper_mttdsp(cpu_env, t0);
9690 break;
9691 default:
9692 goto die;
9694 break;
9695 /* Floating point (COP1). */
9696 case 2:
9697 /* XXX: For now we support only a single FPU context. */
9698 if (h == 0) {
9699 TCGv_i32 fp0 = tcg_temp_new_i32();
9701 tcg_gen_trunc_tl_i32(fp0, t0);
9702 gen_store_fpr32(ctx, fp0, rd);
9703 tcg_temp_free_i32(fp0);
9704 } else {
9705 TCGv_i32 fp0 = tcg_temp_new_i32();
9707 tcg_gen_trunc_tl_i32(fp0, t0);
9708 gen_store_fpr32h(ctx, fp0, rd);
9709 tcg_temp_free_i32(fp0);
9711 break;
9712 case 3:
9713 /* XXX: For now we support only a single FPU context. */
9715 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9717 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9718 tcg_temp_free_i32(fs_tmp);
9720 /* Stop translation as we may have changed hflags */
9721 ctx->base.is_jmp = DISAS_STOP;
9722 break;
9723 /* COP2: Not implemented. */
9724 case 4:
9725 case 5:
9726 /* fall through */
9727 default:
9728 goto die;
9730 trace_mips_translate_tr("mttr", rd, u, sel, h);
9731 tcg_temp_free(t0);
9732 return;
9734 die:
9735 tcg_temp_free(t0);
9736 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9737 generate_exception_end(ctx, EXCP_RI);
9740 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9742 const char *opn = "ldst";
9744 check_cp0_enabled(ctx);
9745 switch (opc) {
9746 case OPC_MFC0:
9747 if (rt == 0) {
9748 /* Treat as NOP. */
9749 return;
9751 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9752 opn = "mfc0";
9753 break;
9754 case OPC_MTC0:
9756 TCGv t0 = tcg_temp_new();
9758 gen_load_gpr(t0, rt);
9759 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9760 tcg_temp_free(t0);
9762 opn = "mtc0";
9763 break;
9764 #if defined(TARGET_MIPS64)
9765 case OPC_DMFC0:
9766 check_insn(ctx, ISA_MIPS3);
9767 if (rt == 0) {
9768 /* Treat as NOP. */
9769 return;
9771 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9772 opn = "dmfc0";
9773 break;
9774 case OPC_DMTC0:
9775 check_insn(ctx, ISA_MIPS3);
9777 TCGv t0 = tcg_temp_new();
9779 gen_load_gpr(t0, rt);
9780 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9781 tcg_temp_free(t0);
9783 opn = "dmtc0";
9784 break;
9785 #endif
9786 case OPC_MFHC0:
9787 check_mvh(ctx);
9788 if (rt == 0) {
9789 /* Treat as NOP. */
9790 return;
9792 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9793 opn = "mfhc0";
9794 break;
9795 case OPC_MTHC0:
9796 check_mvh(ctx);
9798 TCGv t0 = tcg_temp_new();
9799 gen_load_gpr(t0, rt);
9800 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9801 tcg_temp_free(t0);
9803 opn = "mthc0";
9804 break;
9805 case OPC_MFTR:
9806 check_cp0_enabled(ctx);
9807 if (rd == 0) {
9808 /* Treat as NOP. */
9809 return;
9811 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9812 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9813 opn = "mftr";
9814 break;
9815 case OPC_MTTR:
9816 check_cp0_enabled(ctx);
9817 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9818 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9819 opn = "mttr";
9820 break;
9821 case OPC_TLBWI:
9822 opn = "tlbwi";
9823 if (!env->tlb->helper_tlbwi)
9824 goto die;
9825 gen_helper_tlbwi(cpu_env);
9826 break;
9827 case OPC_TLBINV:
9828 opn = "tlbinv";
9829 if (ctx->ie >= 2) {
9830 if (!env->tlb->helper_tlbinv) {
9831 goto die;
9833 gen_helper_tlbinv(cpu_env);
9834 } /* treat as nop if TLBINV not supported */
9835 break;
9836 case OPC_TLBINVF:
9837 opn = "tlbinvf";
9838 if (ctx->ie >= 2) {
9839 if (!env->tlb->helper_tlbinvf) {
9840 goto die;
9842 gen_helper_tlbinvf(cpu_env);
9843 } /* treat as nop if TLBINV not supported */
9844 break;
9845 case OPC_TLBWR:
9846 opn = "tlbwr";
9847 if (!env->tlb->helper_tlbwr)
9848 goto die;
9849 gen_helper_tlbwr(cpu_env);
9850 break;
9851 case OPC_TLBP:
9852 opn = "tlbp";
9853 if (!env->tlb->helper_tlbp)
9854 goto die;
9855 gen_helper_tlbp(cpu_env);
9856 break;
9857 case OPC_TLBR:
9858 opn = "tlbr";
9859 if (!env->tlb->helper_tlbr)
9860 goto die;
9861 gen_helper_tlbr(cpu_env);
9862 break;
9863 case OPC_ERET: /* OPC_ERETNC */
9864 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9865 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9866 goto die;
9867 } else {
9868 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9869 if (ctx->opcode & (1 << bit_shift)) {
9870 /* OPC_ERETNC */
9871 opn = "eretnc";
9872 check_insn(ctx, ISA_MIPS32R5);
9873 gen_helper_eretnc(cpu_env);
9874 } else {
9875 /* OPC_ERET */
9876 opn = "eret";
9877 check_insn(ctx, ISA_MIPS2);
9878 gen_helper_eret(cpu_env);
9880 ctx->base.is_jmp = DISAS_EXIT;
9882 break;
9883 case OPC_DERET:
9884 opn = "deret";
9885 check_insn(ctx, ISA_MIPS32);
9886 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9887 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9888 goto die;
9890 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9891 MIPS_INVAL(opn);
9892 generate_exception_end(ctx, EXCP_RI);
9893 } else {
9894 gen_helper_deret(cpu_env);
9895 ctx->base.is_jmp = DISAS_EXIT;
9897 break;
9898 case OPC_WAIT:
9899 opn = "wait";
9900 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9901 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9902 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9903 goto die;
9905 /* If we get an exception, we want to restart at next instruction */
9906 ctx->base.pc_next += 4;
9907 save_cpu_state(ctx, 1);
9908 ctx->base.pc_next -= 4;
9909 gen_helper_wait(cpu_env);
9910 ctx->base.is_jmp = DISAS_NORETURN;
9911 break;
9912 default:
9913 die:
9914 MIPS_INVAL(opn);
9915 generate_exception_end(ctx, EXCP_RI);
9916 return;
9918 (void)opn; /* avoid a compiler warning */
9920 #endif /* !CONFIG_USER_ONLY */
9922 /* CP1 Branches (before delay slot) */
9923 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9924 int32_t cc, int32_t offset)
9926 target_ulong btarget;
9927 TCGv_i32 t0 = tcg_temp_new_i32();
9929 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9930 generate_exception_end(ctx, EXCP_RI);
9931 goto out;
9934 if (cc != 0)
9935 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9937 btarget = ctx->base.pc_next + 4 + offset;
9939 switch (op) {
9940 case OPC_BC1F:
9941 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9942 tcg_gen_not_i32(t0, t0);
9943 tcg_gen_andi_i32(t0, t0, 1);
9944 tcg_gen_extu_i32_tl(bcond, t0);
9945 goto not_likely;
9946 case OPC_BC1FL:
9947 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9948 tcg_gen_not_i32(t0, t0);
9949 tcg_gen_andi_i32(t0, t0, 1);
9950 tcg_gen_extu_i32_tl(bcond, t0);
9951 goto likely;
9952 case OPC_BC1T:
9953 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9954 tcg_gen_andi_i32(t0, t0, 1);
9955 tcg_gen_extu_i32_tl(bcond, t0);
9956 goto not_likely;
9957 case OPC_BC1TL:
9958 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9959 tcg_gen_andi_i32(t0, t0, 1);
9960 tcg_gen_extu_i32_tl(bcond, t0);
9961 likely:
9962 ctx->hflags |= MIPS_HFLAG_BL;
9963 break;
9964 case OPC_BC1FANY2:
9966 TCGv_i32 t1 = tcg_temp_new_i32();
9967 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9968 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9969 tcg_gen_nand_i32(t0, t0, t1);
9970 tcg_temp_free_i32(t1);
9971 tcg_gen_andi_i32(t0, t0, 1);
9972 tcg_gen_extu_i32_tl(bcond, t0);
9974 goto not_likely;
9975 case OPC_BC1TANY2:
9977 TCGv_i32 t1 = tcg_temp_new_i32();
9978 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9979 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9980 tcg_gen_or_i32(t0, t0, t1);
9981 tcg_temp_free_i32(t1);
9982 tcg_gen_andi_i32(t0, t0, 1);
9983 tcg_gen_extu_i32_tl(bcond, t0);
9985 goto not_likely;
9986 case OPC_BC1FANY4:
9988 TCGv_i32 t1 = tcg_temp_new_i32();
9989 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9990 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9991 tcg_gen_and_i32(t0, t0, t1);
9992 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9993 tcg_gen_and_i32(t0, t0, t1);
9994 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9995 tcg_gen_nand_i32(t0, t0, t1);
9996 tcg_temp_free_i32(t1);
9997 tcg_gen_andi_i32(t0, t0, 1);
9998 tcg_gen_extu_i32_tl(bcond, t0);
10000 goto not_likely;
10001 case OPC_BC1TANY4:
10003 TCGv_i32 t1 = tcg_temp_new_i32();
10004 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10005 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10006 tcg_gen_or_i32(t0, t0, t1);
10007 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10008 tcg_gen_or_i32(t0, t0, t1);
10009 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10010 tcg_gen_or_i32(t0, t0, t1);
10011 tcg_temp_free_i32(t1);
10012 tcg_gen_andi_i32(t0, t0, 1);
10013 tcg_gen_extu_i32_tl(bcond, t0);
10015 not_likely:
10016 ctx->hflags |= MIPS_HFLAG_BC;
10017 break;
10018 default:
10019 MIPS_INVAL("cp1 cond branch");
10020 generate_exception_end(ctx, EXCP_RI);
10021 goto out;
10023 ctx->btarget = btarget;
10024 ctx->hflags |= MIPS_HFLAG_BDS32;
10025 out:
10026 tcg_temp_free_i32(t0);
10029 /* R6 CP1 Branches */
10030 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10031 int32_t ft, int32_t offset,
10032 int delayslot_size)
10034 target_ulong btarget;
10035 TCGv_i64 t0 = tcg_temp_new_i64();
10037 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10038 #ifdef MIPS_DEBUG_DISAS
10039 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10040 "\n", ctx->base.pc_next);
10041 #endif
10042 generate_exception_end(ctx, EXCP_RI);
10043 goto out;
10046 gen_load_fpr64(ctx, t0, ft);
10047 tcg_gen_andi_i64(t0, t0, 1);
10049 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10051 switch (op) {
10052 case OPC_BC1EQZ:
10053 tcg_gen_xori_i64(t0, t0, 1);
10054 ctx->hflags |= MIPS_HFLAG_BC;
10055 break;
10056 case OPC_BC1NEZ:
10057 /* t0 already set */
10058 ctx->hflags |= MIPS_HFLAG_BC;
10059 break;
10060 default:
10061 MIPS_INVAL("cp1 cond branch");
10062 generate_exception_end(ctx, EXCP_RI);
10063 goto out;
10066 tcg_gen_trunc_i64_tl(bcond, t0);
10068 ctx->btarget = btarget;
10070 switch (delayslot_size) {
10071 case 2:
10072 ctx->hflags |= MIPS_HFLAG_BDS16;
10073 break;
10074 case 4:
10075 ctx->hflags |= MIPS_HFLAG_BDS32;
10076 break;
10079 out:
10080 tcg_temp_free_i64(t0);
10083 /* Coprocessor 1 (FPU) */
10085 #define FOP(func, fmt) (((fmt) << 21) | (func))
10087 enum fopcode {
10088 OPC_ADD_S = FOP(0, FMT_S),
10089 OPC_SUB_S = FOP(1, FMT_S),
10090 OPC_MUL_S = FOP(2, FMT_S),
10091 OPC_DIV_S = FOP(3, FMT_S),
10092 OPC_SQRT_S = FOP(4, FMT_S),
10093 OPC_ABS_S = FOP(5, FMT_S),
10094 OPC_MOV_S = FOP(6, FMT_S),
10095 OPC_NEG_S = FOP(7, FMT_S),
10096 OPC_ROUND_L_S = FOP(8, FMT_S),
10097 OPC_TRUNC_L_S = FOP(9, FMT_S),
10098 OPC_CEIL_L_S = FOP(10, FMT_S),
10099 OPC_FLOOR_L_S = FOP(11, FMT_S),
10100 OPC_ROUND_W_S = FOP(12, FMT_S),
10101 OPC_TRUNC_W_S = FOP(13, FMT_S),
10102 OPC_CEIL_W_S = FOP(14, FMT_S),
10103 OPC_FLOOR_W_S = FOP(15, FMT_S),
10104 OPC_SEL_S = FOP(16, FMT_S),
10105 OPC_MOVCF_S = FOP(17, FMT_S),
10106 OPC_MOVZ_S = FOP(18, FMT_S),
10107 OPC_MOVN_S = FOP(19, FMT_S),
10108 OPC_SELEQZ_S = FOP(20, FMT_S),
10109 OPC_RECIP_S = FOP(21, FMT_S),
10110 OPC_RSQRT_S = FOP(22, FMT_S),
10111 OPC_SELNEZ_S = FOP(23, FMT_S),
10112 OPC_MADDF_S = FOP(24, FMT_S),
10113 OPC_MSUBF_S = FOP(25, FMT_S),
10114 OPC_RINT_S = FOP(26, FMT_S),
10115 OPC_CLASS_S = FOP(27, FMT_S),
10116 OPC_MIN_S = FOP(28, FMT_S),
10117 OPC_RECIP2_S = FOP(28, FMT_S),
10118 OPC_MINA_S = FOP(29, FMT_S),
10119 OPC_RECIP1_S = FOP(29, FMT_S),
10120 OPC_MAX_S = FOP(30, FMT_S),
10121 OPC_RSQRT1_S = FOP(30, FMT_S),
10122 OPC_MAXA_S = FOP(31, FMT_S),
10123 OPC_RSQRT2_S = FOP(31, FMT_S),
10124 OPC_CVT_D_S = FOP(33, FMT_S),
10125 OPC_CVT_W_S = FOP(36, FMT_S),
10126 OPC_CVT_L_S = FOP(37, FMT_S),
10127 OPC_CVT_PS_S = FOP(38, FMT_S),
10128 OPC_CMP_F_S = FOP (48, FMT_S),
10129 OPC_CMP_UN_S = FOP (49, FMT_S),
10130 OPC_CMP_EQ_S = FOP (50, FMT_S),
10131 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10132 OPC_CMP_OLT_S = FOP (52, FMT_S),
10133 OPC_CMP_ULT_S = FOP (53, FMT_S),
10134 OPC_CMP_OLE_S = FOP (54, FMT_S),
10135 OPC_CMP_ULE_S = FOP (55, FMT_S),
10136 OPC_CMP_SF_S = FOP (56, FMT_S),
10137 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10138 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10139 OPC_CMP_NGL_S = FOP (59, FMT_S),
10140 OPC_CMP_LT_S = FOP (60, FMT_S),
10141 OPC_CMP_NGE_S = FOP (61, FMT_S),
10142 OPC_CMP_LE_S = FOP (62, FMT_S),
10143 OPC_CMP_NGT_S = FOP (63, FMT_S),
10145 OPC_ADD_D = FOP(0, FMT_D),
10146 OPC_SUB_D = FOP(1, FMT_D),
10147 OPC_MUL_D = FOP(2, FMT_D),
10148 OPC_DIV_D = FOP(3, FMT_D),
10149 OPC_SQRT_D = FOP(4, FMT_D),
10150 OPC_ABS_D = FOP(5, FMT_D),
10151 OPC_MOV_D = FOP(6, FMT_D),
10152 OPC_NEG_D = FOP(7, FMT_D),
10153 OPC_ROUND_L_D = FOP(8, FMT_D),
10154 OPC_TRUNC_L_D = FOP(9, FMT_D),
10155 OPC_CEIL_L_D = FOP(10, FMT_D),
10156 OPC_FLOOR_L_D = FOP(11, FMT_D),
10157 OPC_ROUND_W_D = FOP(12, FMT_D),
10158 OPC_TRUNC_W_D = FOP(13, FMT_D),
10159 OPC_CEIL_W_D = FOP(14, FMT_D),
10160 OPC_FLOOR_W_D = FOP(15, FMT_D),
10161 OPC_SEL_D = FOP(16, FMT_D),
10162 OPC_MOVCF_D = FOP(17, FMT_D),
10163 OPC_MOVZ_D = FOP(18, FMT_D),
10164 OPC_MOVN_D = FOP(19, FMT_D),
10165 OPC_SELEQZ_D = FOP(20, FMT_D),
10166 OPC_RECIP_D = FOP(21, FMT_D),
10167 OPC_RSQRT_D = FOP(22, FMT_D),
10168 OPC_SELNEZ_D = FOP(23, FMT_D),
10169 OPC_MADDF_D = FOP(24, FMT_D),
10170 OPC_MSUBF_D = FOP(25, FMT_D),
10171 OPC_RINT_D = FOP(26, FMT_D),
10172 OPC_CLASS_D = FOP(27, FMT_D),
10173 OPC_MIN_D = FOP(28, FMT_D),
10174 OPC_RECIP2_D = FOP(28, FMT_D),
10175 OPC_MINA_D = FOP(29, FMT_D),
10176 OPC_RECIP1_D = FOP(29, FMT_D),
10177 OPC_MAX_D = FOP(30, FMT_D),
10178 OPC_RSQRT1_D = FOP(30, FMT_D),
10179 OPC_MAXA_D = FOP(31, FMT_D),
10180 OPC_RSQRT2_D = FOP(31, FMT_D),
10181 OPC_CVT_S_D = FOP(32, FMT_D),
10182 OPC_CVT_W_D = FOP(36, FMT_D),
10183 OPC_CVT_L_D = FOP(37, FMT_D),
10184 OPC_CMP_F_D = FOP (48, FMT_D),
10185 OPC_CMP_UN_D = FOP (49, FMT_D),
10186 OPC_CMP_EQ_D = FOP (50, FMT_D),
10187 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10188 OPC_CMP_OLT_D = FOP (52, FMT_D),
10189 OPC_CMP_ULT_D = FOP (53, FMT_D),
10190 OPC_CMP_OLE_D = FOP (54, FMT_D),
10191 OPC_CMP_ULE_D = FOP (55, FMT_D),
10192 OPC_CMP_SF_D = FOP (56, FMT_D),
10193 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10194 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10195 OPC_CMP_NGL_D = FOP (59, FMT_D),
10196 OPC_CMP_LT_D = FOP (60, FMT_D),
10197 OPC_CMP_NGE_D = FOP (61, FMT_D),
10198 OPC_CMP_LE_D = FOP (62, FMT_D),
10199 OPC_CMP_NGT_D = FOP (63, FMT_D),
10201 OPC_CVT_S_W = FOP(32, FMT_W),
10202 OPC_CVT_D_W = FOP(33, FMT_W),
10203 OPC_CVT_S_L = FOP(32, FMT_L),
10204 OPC_CVT_D_L = FOP(33, FMT_L),
10205 OPC_CVT_PS_PW = FOP(38, FMT_W),
10207 OPC_ADD_PS = FOP(0, FMT_PS),
10208 OPC_SUB_PS = FOP(1, FMT_PS),
10209 OPC_MUL_PS = FOP(2, FMT_PS),
10210 OPC_DIV_PS = FOP(3, FMT_PS),
10211 OPC_ABS_PS = FOP(5, FMT_PS),
10212 OPC_MOV_PS = FOP(6, FMT_PS),
10213 OPC_NEG_PS = FOP(7, FMT_PS),
10214 OPC_MOVCF_PS = FOP(17, FMT_PS),
10215 OPC_MOVZ_PS = FOP(18, FMT_PS),
10216 OPC_MOVN_PS = FOP(19, FMT_PS),
10217 OPC_ADDR_PS = FOP(24, FMT_PS),
10218 OPC_MULR_PS = FOP(26, FMT_PS),
10219 OPC_RECIP2_PS = FOP(28, FMT_PS),
10220 OPC_RECIP1_PS = FOP(29, FMT_PS),
10221 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10222 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10224 OPC_CVT_S_PU = FOP(32, FMT_PS),
10225 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10226 OPC_CVT_S_PL = FOP(40, FMT_PS),
10227 OPC_PLL_PS = FOP(44, FMT_PS),
10228 OPC_PLU_PS = FOP(45, FMT_PS),
10229 OPC_PUL_PS = FOP(46, FMT_PS),
10230 OPC_PUU_PS = FOP(47, FMT_PS),
10231 OPC_CMP_F_PS = FOP (48, FMT_PS),
10232 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10233 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10234 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10235 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10236 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10237 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10238 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10239 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10240 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10241 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10242 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10243 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10244 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10245 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10246 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10249 enum r6_f_cmp_op {
10250 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10251 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10252 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10253 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10254 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10255 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10256 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10257 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10258 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10259 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10260 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10261 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10262 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10263 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10264 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10265 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10266 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10267 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10268 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10269 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10270 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10271 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10273 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10274 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10275 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10276 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10277 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10278 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10279 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10280 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10281 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10282 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10283 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10284 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10285 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10286 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10287 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10288 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10289 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10290 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10291 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10292 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10293 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10294 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10296 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10298 TCGv t0 = tcg_temp_new();
10300 switch (opc) {
10301 case OPC_MFC1:
10303 TCGv_i32 fp0 = tcg_temp_new_i32();
10305 gen_load_fpr32(ctx, fp0, fs);
10306 tcg_gen_ext_i32_tl(t0, fp0);
10307 tcg_temp_free_i32(fp0);
10309 gen_store_gpr(t0, rt);
10310 break;
10311 case OPC_MTC1:
10312 gen_load_gpr(t0, rt);
10314 TCGv_i32 fp0 = tcg_temp_new_i32();
10316 tcg_gen_trunc_tl_i32(fp0, t0);
10317 gen_store_fpr32(ctx, fp0, fs);
10318 tcg_temp_free_i32(fp0);
10320 break;
10321 case OPC_CFC1:
10322 gen_helper_1e0i(cfc1, t0, fs);
10323 gen_store_gpr(t0, rt);
10324 break;
10325 case OPC_CTC1:
10326 gen_load_gpr(t0, rt);
10327 save_cpu_state(ctx, 0);
10329 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10331 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10332 tcg_temp_free_i32(fs_tmp);
10334 /* Stop translation as we may have changed hflags */
10335 ctx->base.is_jmp = DISAS_STOP;
10336 break;
10337 #if defined(TARGET_MIPS64)
10338 case OPC_DMFC1:
10339 gen_load_fpr64(ctx, t0, fs);
10340 gen_store_gpr(t0, rt);
10341 break;
10342 case OPC_DMTC1:
10343 gen_load_gpr(t0, rt);
10344 gen_store_fpr64(ctx, t0, fs);
10345 break;
10346 #endif
10347 case OPC_MFHC1:
10349 TCGv_i32 fp0 = tcg_temp_new_i32();
10351 gen_load_fpr32h(ctx, fp0, fs);
10352 tcg_gen_ext_i32_tl(t0, fp0);
10353 tcg_temp_free_i32(fp0);
10355 gen_store_gpr(t0, rt);
10356 break;
10357 case OPC_MTHC1:
10358 gen_load_gpr(t0, rt);
10360 TCGv_i32 fp0 = tcg_temp_new_i32();
10362 tcg_gen_trunc_tl_i32(fp0, t0);
10363 gen_store_fpr32h(ctx, fp0, fs);
10364 tcg_temp_free_i32(fp0);
10366 break;
10367 default:
10368 MIPS_INVAL("cp1 move");
10369 generate_exception_end(ctx, EXCP_RI);
10370 goto out;
10373 out:
10374 tcg_temp_free(t0);
10377 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10379 TCGLabel *l1;
10380 TCGCond cond;
10381 TCGv_i32 t0;
10383 if (rd == 0) {
10384 /* Treat as NOP. */
10385 return;
10388 if (tf)
10389 cond = TCG_COND_EQ;
10390 else
10391 cond = TCG_COND_NE;
10393 l1 = gen_new_label();
10394 t0 = tcg_temp_new_i32();
10395 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10396 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10397 tcg_temp_free_i32(t0);
10398 if (rs == 0) {
10399 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10400 } else {
10401 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10403 gen_set_label(l1);
10406 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10407 int tf)
10409 int cond;
10410 TCGv_i32 t0 = tcg_temp_new_i32();
10411 TCGLabel *l1 = gen_new_label();
10413 if (tf)
10414 cond = TCG_COND_EQ;
10415 else
10416 cond = TCG_COND_NE;
10418 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10419 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10420 gen_load_fpr32(ctx, t0, fs);
10421 gen_store_fpr32(ctx, t0, fd);
10422 gen_set_label(l1);
10423 tcg_temp_free_i32(t0);
10426 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10428 int cond;
10429 TCGv_i32 t0 = tcg_temp_new_i32();
10430 TCGv_i64 fp0;
10431 TCGLabel *l1 = gen_new_label();
10433 if (tf)
10434 cond = TCG_COND_EQ;
10435 else
10436 cond = TCG_COND_NE;
10438 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10439 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10440 tcg_temp_free_i32(t0);
10441 fp0 = tcg_temp_new_i64();
10442 gen_load_fpr64(ctx, fp0, fs);
10443 gen_store_fpr64(ctx, fp0, fd);
10444 tcg_temp_free_i64(fp0);
10445 gen_set_label(l1);
10448 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10449 int cc, int tf)
10451 int cond;
10452 TCGv_i32 t0 = tcg_temp_new_i32();
10453 TCGLabel *l1 = gen_new_label();
10454 TCGLabel *l2 = 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 gen_load_fpr32(ctx, t0, fs);
10464 gen_store_fpr32(ctx, t0, fd);
10465 gen_set_label(l1);
10467 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10468 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10469 gen_load_fpr32h(ctx, t0, fs);
10470 gen_store_fpr32h(ctx, t0, fd);
10471 tcg_temp_free_i32(t0);
10472 gen_set_label(l2);
10475 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10476 int fs)
10478 TCGv_i32 t1 = tcg_const_i32(0);
10479 TCGv_i32 fp0 = tcg_temp_new_i32();
10480 TCGv_i32 fp1 = tcg_temp_new_i32();
10481 TCGv_i32 fp2 = tcg_temp_new_i32();
10482 gen_load_fpr32(ctx, fp0, fd);
10483 gen_load_fpr32(ctx, fp1, ft);
10484 gen_load_fpr32(ctx, fp2, fs);
10486 switch (op1) {
10487 case OPC_SEL_S:
10488 tcg_gen_andi_i32(fp0, fp0, 1);
10489 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10490 break;
10491 case OPC_SELEQZ_S:
10492 tcg_gen_andi_i32(fp1, fp1, 1);
10493 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10494 break;
10495 case OPC_SELNEZ_S:
10496 tcg_gen_andi_i32(fp1, fp1, 1);
10497 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10498 break;
10499 default:
10500 MIPS_INVAL("gen_sel_s");
10501 generate_exception_end(ctx, EXCP_RI);
10502 break;
10505 gen_store_fpr32(ctx, fp0, fd);
10506 tcg_temp_free_i32(fp2);
10507 tcg_temp_free_i32(fp1);
10508 tcg_temp_free_i32(fp0);
10509 tcg_temp_free_i32(t1);
10512 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10513 int fs)
10515 TCGv_i64 t1 = tcg_const_i64(0);
10516 TCGv_i64 fp0 = tcg_temp_new_i64();
10517 TCGv_i64 fp1 = tcg_temp_new_i64();
10518 TCGv_i64 fp2 = tcg_temp_new_i64();
10519 gen_load_fpr64(ctx, fp0, fd);
10520 gen_load_fpr64(ctx, fp1, ft);
10521 gen_load_fpr64(ctx, fp2, fs);
10523 switch (op1) {
10524 case OPC_SEL_D:
10525 tcg_gen_andi_i64(fp0, fp0, 1);
10526 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10527 break;
10528 case OPC_SELEQZ_D:
10529 tcg_gen_andi_i64(fp1, fp1, 1);
10530 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10531 break;
10532 case OPC_SELNEZ_D:
10533 tcg_gen_andi_i64(fp1, fp1, 1);
10534 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10535 break;
10536 default:
10537 MIPS_INVAL("gen_sel_d");
10538 generate_exception_end(ctx, EXCP_RI);
10539 break;
10542 gen_store_fpr64(ctx, fp0, fd);
10543 tcg_temp_free_i64(fp2);
10544 tcg_temp_free_i64(fp1);
10545 tcg_temp_free_i64(fp0);
10546 tcg_temp_free_i64(t1);
10549 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10550 int ft, int fs, int fd, int cc)
10552 uint32_t func = ctx->opcode & 0x3f;
10553 switch (op1) {
10554 case OPC_ADD_S:
10556 TCGv_i32 fp0 = tcg_temp_new_i32();
10557 TCGv_i32 fp1 = tcg_temp_new_i32();
10559 gen_load_fpr32(ctx, fp0, fs);
10560 gen_load_fpr32(ctx, fp1, ft);
10561 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10562 tcg_temp_free_i32(fp1);
10563 gen_store_fpr32(ctx, fp0, fd);
10564 tcg_temp_free_i32(fp0);
10566 break;
10567 case OPC_SUB_S:
10569 TCGv_i32 fp0 = tcg_temp_new_i32();
10570 TCGv_i32 fp1 = tcg_temp_new_i32();
10572 gen_load_fpr32(ctx, fp0, fs);
10573 gen_load_fpr32(ctx, fp1, ft);
10574 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10575 tcg_temp_free_i32(fp1);
10576 gen_store_fpr32(ctx, fp0, fd);
10577 tcg_temp_free_i32(fp0);
10579 break;
10580 case OPC_MUL_S:
10582 TCGv_i32 fp0 = tcg_temp_new_i32();
10583 TCGv_i32 fp1 = tcg_temp_new_i32();
10585 gen_load_fpr32(ctx, fp0, fs);
10586 gen_load_fpr32(ctx, fp1, ft);
10587 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10588 tcg_temp_free_i32(fp1);
10589 gen_store_fpr32(ctx, fp0, fd);
10590 tcg_temp_free_i32(fp0);
10592 break;
10593 case OPC_DIV_S:
10595 TCGv_i32 fp0 = tcg_temp_new_i32();
10596 TCGv_i32 fp1 = tcg_temp_new_i32();
10598 gen_load_fpr32(ctx, fp0, fs);
10599 gen_load_fpr32(ctx, fp1, ft);
10600 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10601 tcg_temp_free_i32(fp1);
10602 gen_store_fpr32(ctx, fp0, fd);
10603 tcg_temp_free_i32(fp0);
10605 break;
10606 case OPC_SQRT_S:
10608 TCGv_i32 fp0 = tcg_temp_new_i32();
10610 gen_load_fpr32(ctx, fp0, fs);
10611 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10612 gen_store_fpr32(ctx, fp0, fd);
10613 tcg_temp_free_i32(fp0);
10615 break;
10616 case OPC_ABS_S:
10618 TCGv_i32 fp0 = tcg_temp_new_i32();
10620 gen_load_fpr32(ctx, fp0, fs);
10621 if (ctx->abs2008) {
10622 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10623 } else {
10624 gen_helper_float_abs_s(fp0, fp0);
10626 gen_store_fpr32(ctx, fp0, fd);
10627 tcg_temp_free_i32(fp0);
10629 break;
10630 case OPC_MOV_S:
10632 TCGv_i32 fp0 = tcg_temp_new_i32();
10634 gen_load_fpr32(ctx, fp0, fs);
10635 gen_store_fpr32(ctx, fp0, fd);
10636 tcg_temp_free_i32(fp0);
10638 break;
10639 case OPC_NEG_S:
10641 TCGv_i32 fp0 = tcg_temp_new_i32();
10643 gen_load_fpr32(ctx, fp0, fs);
10644 if (ctx->abs2008) {
10645 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10646 } else {
10647 gen_helper_float_chs_s(fp0, fp0);
10649 gen_store_fpr32(ctx, fp0, fd);
10650 tcg_temp_free_i32(fp0);
10652 break;
10653 case OPC_ROUND_L_S:
10654 check_cp1_64bitmode(ctx);
10656 TCGv_i32 fp32 = tcg_temp_new_i32();
10657 TCGv_i64 fp64 = tcg_temp_new_i64();
10659 gen_load_fpr32(ctx, fp32, fs);
10660 if (ctx->nan2008) {
10661 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10662 } else {
10663 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10665 tcg_temp_free_i32(fp32);
10666 gen_store_fpr64(ctx, fp64, fd);
10667 tcg_temp_free_i64(fp64);
10669 break;
10670 case OPC_TRUNC_L_S:
10671 check_cp1_64bitmode(ctx);
10673 TCGv_i32 fp32 = tcg_temp_new_i32();
10674 TCGv_i64 fp64 = tcg_temp_new_i64();
10676 gen_load_fpr32(ctx, fp32, fs);
10677 if (ctx->nan2008) {
10678 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10679 } else {
10680 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10682 tcg_temp_free_i32(fp32);
10683 gen_store_fpr64(ctx, fp64, fd);
10684 tcg_temp_free_i64(fp64);
10686 break;
10687 case OPC_CEIL_L_S:
10688 check_cp1_64bitmode(ctx);
10690 TCGv_i32 fp32 = tcg_temp_new_i32();
10691 TCGv_i64 fp64 = tcg_temp_new_i64();
10693 gen_load_fpr32(ctx, fp32, fs);
10694 if (ctx->nan2008) {
10695 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10696 } else {
10697 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10699 tcg_temp_free_i32(fp32);
10700 gen_store_fpr64(ctx, fp64, fd);
10701 tcg_temp_free_i64(fp64);
10703 break;
10704 case OPC_FLOOR_L_S:
10705 check_cp1_64bitmode(ctx);
10707 TCGv_i32 fp32 = tcg_temp_new_i32();
10708 TCGv_i64 fp64 = tcg_temp_new_i64();
10710 gen_load_fpr32(ctx, fp32, fs);
10711 if (ctx->nan2008) {
10712 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10713 } else {
10714 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10716 tcg_temp_free_i32(fp32);
10717 gen_store_fpr64(ctx, fp64, fd);
10718 tcg_temp_free_i64(fp64);
10720 break;
10721 case OPC_ROUND_W_S:
10723 TCGv_i32 fp0 = tcg_temp_new_i32();
10725 gen_load_fpr32(ctx, fp0, fs);
10726 if (ctx->nan2008) {
10727 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10728 } else {
10729 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10731 gen_store_fpr32(ctx, fp0, fd);
10732 tcg_temp_free_i32(fp0);
10734 break;
10735 case OPC_TRUNC_W_S:
10737 TCGv_i32 fp0 = tcg_temp_new_i32();
10739 gen_load_fpr32(ctx, fp0, fs);
10740 if (ctx->nan2008) {
10741 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10742 } else {
10743 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10745 gen_store_fpr32(ctx, fp0, fd);
10746 tcg_temp_free_i32(fp0);
10748 break;
10749 case OPC_CEIL_W_S:
10751 TCGv_i32 fp0 = tcg_temp_new_i32();
10753 gen_load_fpr32(ctx, fp0, fs);
10754 if (ctx->nan2008) {
10755 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10756 } else {
10757 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10759 gen_store_fpr32(ctx, fp0, fd);
10760 tcg_temp_free_i32(fp0);
10762 break;
10763 case OPC_FLOOR_W_S:
10765 TCGv_i32 fp0 = tcg_temp_new_i32();
10767 gen_load_fpr32(ctx, fp0, fs);
10768 if (ctx->nan2008) {
10769 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10770 } else {
10771 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10773 gen_store_fpr32(ctx, fp0, fd);
10774 tcg_temp_free_i32(fp0);
10776 break;
10777 case OPC_SEL_S:
10778 check_insn(ctx, ISA_MIPS32R6);
10779 gen_sel_s(ctx, op1, fd, ft, fs);
10780 break;
10781 case OPC_SELEQZ_S:
10782 check_insn(ctx, ISA_MIPS32R6);
10783 gen_sel_s(ctx, op1, fd, ft, fs);
10784 break;
10785 case OPC_SELNEZ_S:
10786 check_insn(ctx, ISA_MIPS32R6);
10787 gen_sel_s(ctx, op1, fd, ft, fs);
10788 break;
10789 case OPC_MOVCF_S:
10790 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10791 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10792 break;
10793 case OPC_MOVZ_S:
10794 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10796 TCGLabel *l1 = gen_new_label();
10797 TCGv_i32 fp0;
10799 if (ft != 0) {
10800 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10802 fp0 = tcg_temp_new_i32();
10803 gen_load_fpr32(ctx, fp0, fs);
10804 gen_store_fpr32(ctx, fp0, fd);
10805 tcg_temp_free_i32(fp0);
10806 gen_set_label(l1);
10808 break;
10809 case OPC_MOVN_S:
10810 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10812 TCGLabel *l1 = gen_new_label();
10813 TCGv_i32 fp0;
10815 if (ft != 0) {
10816 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10817 fp0 = tcg_temp_new_i32();
10818 gen_load_fpr32(ctx, fp0, fs);
10819 gen_store_fpr32(ctx, fp0, fd);
10820 tcg_temp_free_i32(fp0);
10821 gen_set_label(l1);
10824 break;
10825 case OPC_RECIP_S:
10827 TCGv_i32 fp0 = tcg_temp_new_i32();
10829 gen_load_fpr32(ctx, fp0, fs);
10830 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10831 gen_store_fpr32(ctx, fp0, fd);
10832 tcg_temp_free_i32(fp0);
10834 break;
10835 case OPC_RSQRT_S:
10837 TCGv_i32 fp0 = tcg_temp_new_i32();
10839 gen_load_fpr32(ctx, fp0, fs);
10840 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10841 gen_store_fpr32(ctx, fp0, fd);
10842 tcg_temp_free_i32(fp0);
10844 break;
10845 case OPC_MADDF_S:
10846 check_insn(ctx, ISA_MIPS32R6);
10848 TCGv_i32 fp0 = tcg_temp_new_i32();
10849 TCGv_i32 fp1 = tcg_temp_new_i32();
10850 TCGv_i32 fp2 = tcg_temp_new_i32();
10851 gen_load_fpr32(ctx, fp0, fs);
10852 gen_load_fpr32(ctx, fp1, ft);
10853 gen_load_fpr32(ctx, fp2, fd);
10854 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10855 gen_store_fpr32(ctx, fp2, fd);
10856 tcg_temp_free_i32(fp2);
10857 tcg_temp_free_i32(fp1);
10858 tcg_temp_free_i32(fp0);
10860 break;
10861 case OPC_MSUBF_S:
10862 check_insn(ctx, ISA_MIPS32R6);
10864 TCGv_i32 fp0 = tcg_temp_new_i32();
10865 TCGv_i32 fp1 = tcg_temp_new_i32();
10866 TCGv_i32 fp2 = tcg_temp_new_i32();
10867 gen_load_fpr32(ctx, fp0, fs);
10868 gen_load_fpr32(ctx, fp1, ft);
10869 gen_load_fpr32(ctx, fp2, fd);
10870 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10871 gen_store_fpr32(ctx, fp2, fd);
10872 tcg_temp_free_i32(fp2);
10873 tcg_temp_free_i32(fp1);
10874 tcg_temp_free_i32(fp0);
10876 break;
10877 case OPC_RINT_S:
10878 check_insn(ctx, ISA_MIPS32R6);
10880 TCGv_i32 fp0 = tcg_temp_new_i32();
10881 gen_load_fpr32(ctx, fp0, fs);
10882 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10883 gen_store_fpr32(ctx, fp0, fd);
10884 tcg_temp_free_i32(fp0);
10886 break;
10887 case OPC_CLASS_S:
10888 check_insn(ctx, ISA_MIPS32R6);
10890 TCGv_i32 fp0 = tcg_temp_new_i32();
10891 gen_load_fpr32(ctx, fp0, fs);
10892 gen_helper_float_class_s(fp0, cpu_env, fp0);
10893 gen_store_fpr32(ctx, fp0, fd);
10894 tcg_temp_free_i32(fp0);
10896 break;
10897 case OPC_MIN_S: /* OPC_RECIP2_S */
10898 if (ctx->insn_flags & ISA_MIPS32R6) {
10899 /* OPC_MIN_S */
10900 TCGv_i32 fp0 = tcg_temp_new_i32();
10901 TCGv_i32 fp1 = tcg_temp_new_i32();
10902 TCGv_i32 fp2 = tcg_temp_new_i32();
10903 gen_load_fpr32(ctx, fp0, fs);
10904 gen_load_fpr32(ctx, fp1, ft);
10905 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10906 gen_store_fpr32(ctx, fp2, fd);
10907 tcg_temp_free_i32(fp2);
10908 tcg_temp_free_i32(fp1);
10909 tcg_temp_free_i32(fp0);
10910 } else {
10911 /* OPC_RECIP2_S */
10912 check_cp1_64bitmode(ctx);
10914 TCGv_i32 fp0 = tcg_temp_new_i32();
10915 TCGv_i32 fp1 = tcg_temp_new_i32();
10917 gen_load_fpr32(ctx, fp0, fs);
10918 gen_load_fpr32(ctx, fp1, ft);
10919 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10920 tcg_temp_free_i32(fp1);
10921 gen_store_fpr32(ctx, fp0, fd);
10922 tcg_temp_free_i32(fp0);
10925 break;
10926 case OPC_MINA_S: /* OPC_RECIP1_S */
10927 if (ctx->insn_flags & ISA_MIPS32R6) {
10928 /* OPC_MINA_S */
10929 TCGv_i32 fp0 = tcg_temp_new_i32();
10930 TCGv_i32 fp1 = tcg_temp_new_i32();
10931 TCGv_i32 fp2 = tcg_temp_new_i32();
10932 gen_load_fpr32(ctx, fp0, fs);
10933 gen_load_fpr32(ctx, fp1, ft);
10934 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10935 gen_store_fpr32(ctx, fp2, fd);
10936 tcg_temp_free_i32(fp2);
10937 tcg_temp_free_i32(fp1);
10938 tcg_temp_free_i32(fp0);
10939 } else {
10940 /* OPC_RECIP1_S */
10941 check_cp1_64bitmode(ctx);
10943 TCGv_i32 fp0 = tcg_temp_new_i32();
10945 gen_load_fpr32(ctx, fp0, fs);
10946 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10947 gen_store_fpr32(ctx, fp0, fd);
10948 tcg_temp_free_i32(fp0);
10951 break;
10952 case OPC_MAX_S: /* OPC_RSQRT1_S */
10953 if (ctx->insn_flags & ISA_MIPS32R6) {
10954 /* OPC_MAX_S */
10955 TCGv_i32 fp0 = tcg_temp_new_i32();
10956 TCGv_i32 fp1 = tcg_temp_new_i32();
10957 gen_load_fpr32(ctx, fp0, fs);
10958 gen_load_fpr32(ctx, fp1, ft);
10959 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10960 gen_store_fpr32(ctx, fp1, fd);
10961 tcg_temp_free_i32(fp1);
10962 tcg_temp_free_i32(fp0);
10963 } else {
10964 /* OPC_RSQRT1_S */
10965 check_cp1_64bitmode(ctx);
10967 TCGv_i32 fp0 = tcg_temp_new_i32();
10969 gen_load_fpr32(ctx, fp0, fs);
10970 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10971 gen_store_fpr32(ctx, fp0, fd);
10972 tcg_temp_free_i32(fp0);
10975 break;
10976 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10977 if (ctx->insn_flags & ISA_MIPS32R6) {
10978 /* OPC_MAXA_S */
10979 TCGv_i32 fp0 = tcg_temp_new_i32();
10980 TCGv_i32 fp1 = tcg_temp_new_i32();
10981 gen_load_fpr32(ctx, fp0, fs);
10982 gen_load_fpr32(ctx, fp1, ft);
10983 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10984 gen_store_fpr32(ctx, fp1, fd);
10985 tcg_temp_free_i32(fp1);
10986 tcg_temp_free_i32(fp0);
10987 } else {
10988 /* OPC_RSQRT2_S */
10989 check_cp1_64bitmode(ctx);
10991 TCGv_i32 fp0 = tcg_temp_new_i32();
10992 TCGv_i32 fp1 = tcg_temp_new_i32();
10994 gen_load_fpr32(ctx, fp0, fs);
10995 gen_load_fpr32(ctx, fp1, ft);
10996 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10997 tcg_temp_free_i32(fp1);
10998 gen_store_fpr32(ctx, fp0, fd);
10999 tcg_temp_free_i32(fp0);
11002 break;
11003 case OPC_CVT_D_S:
11004 check_cp1_registers(ctx, fd);
11006 TCGv_i32 fp32 = tcg_temp_new_i32();
11007 TCGv_i64 fp64 = tcg_temp_new_i64();
11009 gen_load_fpr32(ctx, fp32, fs);
11010 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11011 tcg_temp_free_i32(fp32);
11012 gen_store_fpr64(ctx, fp64, fd);
11013 tcg_temp_free_i64(fp64);
11015 break;
11016 case OPC_CVT_W_S:
11018 TCGv_i32 fp0 = tcg_temp_new_i32();
11020 gen_load_fpr32(ctx, fp0, fs);
11021 if (ctx->nan2008) {
11022 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11023 } else {
11024 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11026 gen_store_fpr32(ctx, fp0, fd);
11027 tcg_temp_free_i32(fp0);
11029 break;
11030 case OPC_CVT_L_S:
11031 check_cp1_64bitmode(ctx);
11033 TCGv_i32 fp32 = tcg_temp_new_i32();
11034 TCGv_i64 fp64 = tcg_temp_new_i64();
11036 gen_load_fpr32(ctx, fp32, fs);
11037 if (ctx->nan2008) {
11038 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11039 } else {
11040 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11042 tcg_temp_free_i32(fp32);
11043 gen_store_fpr64(ctx, fp64, fd);
11044 tcg_temp_free_i64(fp64);
11046 break;
11047 case OPC_CVT_PS_S:
11048 check_ps(ctx);
11050 TCGv_i64 fp64 = tcg_temp_new_i64();
11051 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11052 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11054 gen_load_fpr32(ctx, fp32_0, fs);
11055 gen_load_fpr32(ctx, fp32_1, ft);
11056 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11057 tcg_temp_free_i32(fp32_1);
11058 tcg_temp_free_i32(fp32_0);
11059 gen_store_fpr64(ctx, fp64, fd);
11060 tcg_temp_free_i64(fp64);
11062 break;
11063 case OPC_CMP_F_S:
11064 case OPC_CMP_UN_S:
11065 case OPC_CMP_EQ_S:
11066 case OPC_CMP_UEQ_S:
11067 case OPC_CMP_OLT_S:
11068 case OPC_CMP_ULT_S:
11069 case OPC_CMP_OLE_S:
11070 case OPC_CMP_ULE_S:
11071 case OPC_CMP_SF_S:
11072 case OPC_CMP_NGLE_S:
11073 case OPC_CMP_SEQ_S:
11074 case OPC_CMP_NGL_S:
11075 case OPC_CMP_LT_S:
11076 case OPC_CMP_NGE_S:
11077 case OPC_CMP_LE_S:
11078 case OPC_CMP_NGT_S:
11079 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11080 if (ctx->opcode & (1 << 6)) {
11081 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11082 } else {
11083 gen_cmp_s(ctx, func-48, ft, fs, cc);
11085 break;
11086 case OPC_ADD_D:
11087 check_cp1_registers(ctx, fs | ft | fd);
11089 TCGv_i64 fp0 = tcg_temp_new_i64();
11090 TCGv_i64 fp1 = tcg_temp_new_i64();
11092 gen_load_fpr64(ctx, fp0, fs);
11093 gen_load_fpr64(ctx, fp1, ft);
11094 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11095 tcg_temp_free_i64(fp1);
11096 gen_store_fpr64(ctx, fp0, fd);
11097 tcg_temp_free_i64(fp0);
11099 break;
11100 case OPC_SUB_D:
11101 check_cp1_registers(ctx, fs | ft | fd);
11103 TCGv_i64 fp0 = tcg_temp_new_i64();
11104 TCGv_i64 fp1 = tcg_temp_new_i64();
11106 gen_load_fpr64(ctx, fp0, fs);
11107 gen_load_fpr64(ctx, fp1, ft);
11108 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11109 tcg_temp_free_i64(fp1);
11110 gen_store_fpr64(ctx, fp0, fd);
11111 tcg_temp_free_i64(fp0);
11113 break;
11114 case OPC_MUL_D:
11115 check_cp1_registers(ctx, fs | ft | fd);
11117 TCGv_i64 fp0 = tcg_temp_new_i64();
11118 TCGv_i64 fp1 = tcg_temp_new_i64();
11120 gen_load_fpr64(ctx, fp0, fs);
11121 gen_load_fpr64(ctx, fp1, ft);
11122 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11123 tcg_temp_free_i64(fp1);
11124 gen_store_fpr64(ctx, fp0, fd);
11125 tcg_temp_free_i64(fp0);
11127 break;
11128 case OPC_DIV_D:
11129 check_cp1_registers(ctx, fs | ft | fd);
11131 TCGv_i64 fp0 = tcg_temp_new_i64();
11132 TCGv_i64 fp1 = tcg_temp_new_i64();
11134 gen_load_fpr64(ctx, fp0, fs);
11135 gen_load_fpr64(ctx, fp1, ft);
11136 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11137 tcg_temp_free_i64(fp1);
11138 gen_store_fpr64(ctx, fp0, fd);
11139 tcg_temp_free_i64(fp0);
11141 break;
11142 case OPC_SQRT_D:
11143 check_cp1_registers(ctx, fs | fd);
11145 TCGv_i64 fp0 = tcg_temp_new_i64();
11147 gen_load_fpr64(ctx, fp0, fs);
11148 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11149 gen_store_fpr64(ctx, fp0, fd);
11150 tcg_temp_free_i64(fp0);
11152 break;
11153 case OPC_ABS_D:
11154 check_cp1_registers(ctx, fs | fd);
11156 TCGv_i64 fp0 = tcg_temp_new_i64();
11158 gen_load_fpr64(ctx, fp0, fs);
11159 if (ctx->abs2008) {
11160 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11161 } else {
11162 gen_helper_float_abs_d(fp0, fp0);
11164 gen_store_fpr64(ctx, fp0, fd);
11165 tcg_temp_free_i64(fp0);
11167 break;
11168 case OPC_MOV_D:
11169 check_cp1_registers(ctx, fs | fd);
11171 TCGv_i64 fp0 = tcg_temp_new_i64();
11173 gen_load_fpr64(ctx, fp0, fs);
11174 gen_store_fpr64(ctx, fp0, fd);
11175 tcg_temp_free_i64(fp0);
11177 break;
11178 case OPC_NEG_D:
11179 check_cp1_registers(ctx, fs | fd);
11181 TCGv_i64 fp0 = tcg_temp_new_i64();
11183 gen_load_fpr64(ctx, fp0, fs);
11184 if (ctx->abs2008) {
11185 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11186 } else {
11187 gen_helper_float_chs_d(fp0, fp0);
11189 gen_store_fpr64(ctx, fp0, fd);
11190 tcg_temp_free_i64(fp0);
11192 break;
11193 case OPC_ROUND_L_D:
11194 check_cp1_64bitmode(ctx);
11196 TCGv_i64 fp0 = tcg_temp_new_i64();
11198 gen_load_fpr64(ctx, fp0, fs);
11199 if (ctx->nan2008) {
11200 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11201 } else {
11202 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11204 gen_store_fpr64(ctx, fp0, fd);
11205 tcg_temp_free_i64(fp0);
11207 break;
11208 case OPC_TRUNC_L_D:
11209 check_cp1_64bitmode(ctx);
11211 TCGv_i64 fp0 = tcg_temp_new_i64();
11213 gen_load_fpr64(ctx, fp0, fs);
11214 if (ctx->nan2008) {
11215 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11216 } else {
11217 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11219 gen_store_fpr64(ctx, fp0, fd);
11220 tcg_temp_free_i64(fp0);
11222 break;
11223 case OPC_CEIL_L_D:
11224 check_cp1_64bitmode(ctx);
11226 TCGv_i64 fp0 = tcg_temp_new_i64();
11228 gen_load_fpr64(ctx, fp0, fs);
11229 if (ctx->nan2008) {
11230 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11231 } else {
11232 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11234 gen_store_fpr64(ctx, fp0, fd);
11235 tcg_temp_free_i64(fp0);
11237 break;
11238 case OPC_FLOOR_L_D:
11239 check_cp1_64bitmode(ctx);
11241 TCGv_i64 fp0 = tcg_temp_new_i64();
11243 gen_load_fpr64(ctx, fp0, fs);
11244 if (ctx->nan2008) {
11245 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11246 } else {
11247 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11249 gen_store_fpr64(ctx, fp0, fd);
11250 tcg_temp_free_i64(fp0);
11252 break;
11253 case OPC_ROUND_W_D:
11254 check_cp1_registers(ctx, fs);
11256 TCGv_i32 fp32 = tcg_temp_new_i32();
11257 TCGv_i64 fp64 = tcg_temp_new_i64();
11259 gen_load_fpr64(ctx, fp64, fs);
11260 if (ctx->nan2008) {
11261 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11262 } else {
11263 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11265 tcg_temp_free_i64(fp64);
11266 gen_store_fpr32(ctx, fp32, fd);
11267 tcg_temp_free_i32(fp32);
11269 break;
11270 case OPC_TRUNC_W_D:
11271 check_cp1_registers(ctx, fs);
11273 TCGv_i32 fp32 = tcg_temp_new_i32();
11274 TCGv_i64 fp64 = tcg_temp_new_i64();
11276 gen_load_fpr64(ctx, fp64, fs);
11277 if (ctx->nan2008) {
11278 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11279 } else {
11280 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11282 tcg_temp_free_i64(fp64);
11283 gen_store_fpr32(ctx, fp32, fd);
11284 tcg_temp_free_i32(fp32);
11286 break;
11287 case OPC_CEIL_W_D:
11288 check_cp1_registers(ctx, fs);
11290 TCGv_i32 fp32 = tcg_temp_new_i32();
11291 TCGv_i64 fp64 = tcg_temp_new_i64();
11293 gen_load_fpr64(ctx, fp64, fs);
11294 if (ctx->nan2008) {
11295 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11296 } else {
11297 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11299 tcg_temp_free_i64(fp64);
11300 gen_store_fpr32(ctx, fp32, fd);
11301 tcg_temp_free_i32(fp32);
11303 break;
11304 case OPC_FLOOR_W_D:
11305 check_cp1_registers(ctx, fs);
11307 TCGv_i32 fp32 = tcg_temp_new_i32();
11308 TCGv_i64 fp64 = tcg_temp_new_i64();
11310 gen_load_fpr64(ctx, fp64, fs);
11311 if (ctx->nan2008) {
11312 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11313 } else {
11314 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11316 tcg_temp_free_i64(fp64);
11317 gen_store_fpr32(ctx, fp32, fd);
11318 tcg_temp_free_i32(fp32);
11320 break;
11321 case OPC_SEL_D:
11322 check_insn(ctx, ISA_MIPS32R6);
11323 gen_sel_d(ctx, op1, fd, ft, fs);
11324 break;
11325 case OPC_SELEQZ_D:
11326 check_insn(ctx, ISA_MIPS32R6);
11327 gen_sel_d(ctx, op1, fd, ft, fs);
11328 break;
11329 case OPC_SELNEZ_D:
11330 check_insn(ctx, ISA_MIPS32R6);
11331 gen_sel_d(ctx, op1, fd, ft, fs);
11332 break;
11333 case OPC_MOVCF_D:
11334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11335 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11336 break;
11337 case OPC_MOVZ_D:
11338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11340 TCGLabel *l1 = gen_new_label();
11341 TCGv_i64 fp0;
11343 if (ft != 0) {
11344 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11346 fp0 = tcg_temp_new_i64();
11347 gen_load_fpr64(ctx, fp0, fs);
11348 gen_store_fpr64(ctx, fp0, fd);
11349 tcg_temp_free_i64(fp0);
11350 gen_set_label(l1);
11352 break;
11353 case OPC_MOVN_D:
11354 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11356 TCGLabel *l1 = gen_new_label();
11357 TCGv_i64 fp0;
11359 if (ft != 0) {
11360 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11361 fp0 = tcg_temp_new_i64();
11362 gen_load_fpr64(ctx, fp0, fs);
11363 gen_store_fpr64(ctx, fp0, fd);
11364 tcg_temp_free_i64(fp0);
11365 gen_set_label(l1);
11368 break;
11369 case OPC_RECIP_D:
11370 check_cp1_registers(ctx, fs | fd);
11372 TCGv_i64 fp0 = tcg_temp_new_i64();
11374 gen_load_fpr64(ctx, fp0, fs);
11375 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11376 gen_store_fpr64(ctx, fp0, fd);
11377 tcg_temp_free_i64(fp0);
11379 break;
11380 case OPC_RSQRT_D:
11381 check_cp1_registers(ctx, fs | fd);
11383 TCGv_i64 fp0 = tcg_temp_new_i64();
11385 gen_load_fpr64(ctx, fp0, fs);
11386 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11387 gen_store_fpr64(ctx, fp0, fd);
11388 tcg_temp_free_i64(fp0);
11390 break;
11391 case OPC_MADDF_D:
11392 check_insn(ctx, ISA_MIPS32R6);
11394 TCGv_i64 fp0 = tcg_temp_new_i64();
11395 TCGv_i64 fp1 = tcg_temp_new_i64();
11396 TCGv_i64 fp2 = tcg_temp_new_i64();
11397 gen_load_fpr64(ctx, fp0, fs);
11398 gen_load_fpr64(ctx, fp1, ft);
11399 gen_load_fpr64(ctx, fp2, fd);
11400 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11401 gen_store_fpr64(ctx, fp2, fd);
11402 tcg_temp_free_i64(fp2);
11403 tcg_temp_free_i64(fp1);
11404 tcg_temp_free_i64(fp0);
11406 break;
11407 case OPC_MSUBF_D:
11408 check_insn(ctx, ISA_MIPS32R6);
11410 TCGv_i64 fp0 = tcg_temp_new_i64();
11411 TCGv_i64 fp1 = tcg_temp_new_i64();
11412 TCGv_i64 fp2 = tcg_temp_new_i64();
11413 gen_load_fpr64(ctx, fp0, fs);
11414 gen_load_fpr64(ctx, fp1, ft);
11415 gen_load_fpr64(ctx, fp2, fd);
11416 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11417 gen_store_fpr64(ctx, fp2, fd);
11418 tcg_temp_free_i64(fp2);
11419 tcg_temp_free_i64(fp1);
11420 tcg_temp_free_i64(fp0);
11422 break;
11423 case OPC_RINT_D:
11424 check_insn(ctx, ISA_MIPS32R6);
11426 TCGv_i64 fp0 = tcg_temp_new_i64();
11427 gen_load_fpr64(ctx, fp0, fs);
11428 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11429 gen_store_fpr64(ctx, fp0, fd);
11430 tcg_temp_free_i64(fp0);
11432 break;
11433 case OPC_CLASS_D:
11434 check_insn(ctx, ISA_MIPS32R6);
11436 TCGv_i64 fp0 = tcg_temp_new_i64();
11437 gen_load_fpr64(ctx, fp0, fs);
11438 gen_helper_float_class_d(fp0, cpu_env, fp0);
11439 gen_store_fpr64(ctx, fp0, fd);
11440 tcg_temp_free_i64(fp0);
11442 break;
11443 case OPC_MIN_D: /* OPC_RECIP2_D */
11444 if (ctx->insn_flags & ISA_MIPS32R6) {
11445 /* OPC_MIN_D */
11446 TCGv_i64 fp0 = tcg_temp_new_i64();
11447 TCGv_i64 fp1 = tcg_temp_new_i64();
11448 gen_load_fpr64(ctx, fp0, fs);
11449 gen_load_fpr64(ctx, fp1, ft);
11450 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11451 gen_store_fpr64(ctx, fp1, fd);
11452 tcg_temp_free_i64(fp1);
11453 tcg_temp_free_i64(fp0);
11454 } else {
11455 /* OPC_RECIP2_D */
11456 check_cp1_64bitmode(ctx);
11458 TCGv_i64 fp0 = tcg_temp_new_i64();
11459 TCGv_i64 fp1 = tcg_temp_new_i64();
11461 gen_load_fpr64(ctx, fp0, fs);
11462 gen_load_fpr64(ctx, fp1, ft);
11463 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11464 tcg_temp_free_i64(fp1);
11465 gen_store_fpr64(ctx, fp0, fd);
11466 tcg_temp_free_i64(fp0);
11469 break;
11470 case OPC_MINA_D: /* OPC_RECIP1_D */
11471 if (ctx->insn_flags & ISA_MIPS32R6) {
11472 /* OPC_MINA_D */
11473 TCGv_i64 fp0 = tcg_temp_new_i64();
11474 TCGv_i64 fp1 = tcg_temp_new_i64();
11475 gen_load_fpr64(ctx, fp0, fs);
11476 gen_load_fpr64(ctx, fp1, ft);
11477 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11478 gen_store_fpr64(ctx, fp1, fd);
11479 tcg_temp_free_i64(fp1);
11480 tcg_temp_free_i64(fp0);
11481 } else {
11482 /* OPC_RECIP1_D */
11483 check_cp1_64bitmode(ctx);
11485 TCGv_i64 fp0 = tcg_temp_new_i64();
11487 gen_load_fpr64(ctx, fp0, fs);
11488 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11489 gen_store_fpr64(ctx, fp0, fd);
11490 tcg_temp_free_i64(fp0);
11493 break;
11494 case OPC_MAX_D: /* OPC_RSQRT1_D */
11495 if (ctx->insn_flags & ISA_MIPS32R6) {
11496 /* OPC_MAX_D */
11497 TCGv_i64 fp0 = tcg_temp_new_i64();
11498 TCGv_i64 fp1 = tcg_temp_new_i64();
11499 gen_load_fpr64(ctx, fp0, fs);
11500 gen_load_fpr64(ctx, fp1, ft);
11501 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11502 gen_store_fpr64(ctx, fp1, fd);
11503 tcg_temp_free_i64(fp1);
11504 tcg_temp_free_i64(fp0);
11505 } else {
11506 /* OPC_RSQRT1_D */
11507 check_cp1_64bitmode(ctx);
11509 TCGv_i64 fp0 = tcg_temp_new_i64();
11511 gen_load_fpr64(ctx, fp0, fs);
11512 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11513 gen_store_fpr64(ctx, fp0, fd);
11514 tcg_temp_free_i64(fp0);
11517 break;
11518 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11519 if (ctx->insn_flags & ISA_MIPS32R6) {
11520 /* OPC_MAXA_D */
11521 TCGv_i64 fp0 = tcg_temp_new_i64();
11522 TCGv_i64 fp1 = tcg_temp_new_i64();
11523 gen_load_fpr64(ctx, fp0, fs);
11524 gen_load_fpr64(ctx, fp1, ft);
11525 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11526 gen_store_fpr64(ctx, fp1, fd);
11527 tcg_temp_free_i64(fp1);
11528 tcg_temp_free_i64(fp0);
11529 } else {
11530 /* OPC_RSQRT2_D */
11531 check_cp1_64bitmode(ctx);
11533 TCGv_i64 fp0 = tcg_temp_new_i64();
11534 TCGv_i64 fp1 = tcg_temp_new_i64();
11536 gen_load_fpr64(ctx, fp0, fs);
11537 gen_load_fpr64(ctx, fp1, ft);
11538 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11539 tcg_temp_free_i64(fp1);
11540 gen_store_fpr64(ctx, fp0, fd);
11541 tcg_temp_free_i64(fp0);
11544 break;
11545 case OPC_CMP_F_D:
11546 case OPC_CMP_UN_D:
11547 case OPC_CMP_EQ_D:
11548 case OPC_CMP_UEQ_D:
11549 case OPC_CMP_OLT_D:
11550 case OPC_CMP_ULT_D:
11551 case OPC_CMP_OLE_D:
11552 case OPC_CMP_ULE_D:
11553 case OPC_CMP_SF_D:
11554 case OPC_CMP_NGLE_D:
11555 case OPC_CMP_SEQ_D:
11556 case OPC_CMP_NGL_D:
11557 case OPC_CMP_LT_D:
11558 case OPC_CMP_NGE_D:
11559 case OPC_CMP_LE_D:
11560 case OPC_CMP_NGT_D:
11561 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11562 if (ctx->opcode & (1 << 6)) {
11563 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11564 } else {
11565 gen_cmp_d(ctx, func-48, ft, fs, cc);
11567 break;
11568 case OPC_CVT_S_D:
11569 check_cp1_registers(ctx, fs);
11571 TCGv_i32 fp32 = tcg_temp_new_i32();
11572 TCGv_i64 fp64 = tcg_temp_new_i64();
11574 gen_load_fpr64(ctx, fp64, fs);
11575 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11576 tcg_temp_free_i64(fp64);
11577 gen_store_fpr32(ctx, fp32, fd);
11578 tcg_temp_free_i32(fp32);
11580 break;
11581 case OPC_CVT_W_D:
11582 check_cp1_registers(ctx, fs);
11584 TCGv_i32 fp32 = tcg_temp_new_i32();
11585 TCGv_i64 fp64 = tcg_temp_new_i64();
11587 gen_load_fpr64(ctx, fp64, fs);
11588 if (ctx->nan2008) {
11589 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11590 } else {
11591 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11593 tcg_temp_free_i64(fp64);
11594 gen_store_fpr32(ctx, fp32, fd);
11595 tcg_temp_free_i32(fp32);
11597 break;
11598 case OPC_CVT_L_D:
11599 check_cp1_64bitmode(ctx);
11601 TCGv_i64 fp0 = tcg_temp_new_i64();
11603 gen_load_fpr64(ctx, fp0, fs);
11604 if (ctx->nan2008) {
11605 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11606 } else {
11607 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11609 gen_store_fpr64(ctx, fp0, fd);
11610 tcg_temp_free_i64(fp0);
11612 break;
11613 case OPC_CVT_S_W:
11615 TCGv_i32 fp0 = tcg_temp_new_i32();
11617 gen_load_fpr32(ctx, fp0, fs);
11618 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11619 gen_store_fpr32(ctx, fp0, fd);
11620 tcg_temp_free_i32(fp0);
11622 break;
11623 case OPC_CVT_D_W:
11624 check_cp1_registers(ctx, fd);
11626 TCGv_i32 fp32 = tcg_temp_new_i32();
11627 TCGv_i64 fp64 = tcg_temp_new_i64();
11629 gen_load_fpr32(ctx, fp32, fs);
11630 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11631 tcg_temp_free_i32(fp32);
11632 gen_store_fpr64(ctx, fp64, fd);
11633 tcg_temp_free_i64(fp64);
11635 break;
11636 case OPC_CVT_S_L:
11637 check_cp1_64bitmode(ctx);
11639 TCGv_i32 fp32 = tcg_temp_new_i32();
11640 TCGv_i64 fp64 = tcg_temp_new_i64();
11642 gen_load_fpr64(ctx, fp64, fs);
11643 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11644 tcg_temp_free_i64(fp64);
11645 gen_store_fpr32(ctx, fp32, fd);
11646 tcg_temp_free_i32(fp32);
11648 break;
11649 case OPC_CVT_D_L:
11650 check_cp1_64bitmode(ctx);
11652 TCGv_i64 fp0 = tcg_temp_new_i64();
11654 gen_load_fpr64(ctx, fp0, fs);
11655 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11656 gen_store_fpr64(ctx, fp0, fd);
11657 tcg_temp_free_i64(fp0);
11659 break;
11660 case OPC_CVT_PS_PW:
11661 check_ps(ctx);
11663 TCGv_i64 fp0 = tcg_temp_new_i64();
11665 gen_load_fpr64(ctx, fp0, fs);
11666 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11667 gen_store_fpr64(ctx, fp0, fd);
11668 tcg_temp_free_i64(fp0);
11670 break;
11671 case OPC_ADD_PS:
11672 check_ps(ctx);
11674 TCGv_i64 fp0 = tcg_temp_new_i64();
11675 TCGv_i64 fp1 = tcg_temp_new_i64();
11677 gen_load_fpr64(ctx, fp0, fs);
11678 gen_load_fpr64(ctx, fp1, ft);
11679 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11680 tcg_temp_free_i64(fp1);
11681 gen_store_fpr64(ctx, fp0, fd);
11682 tcg_temp_free_i64(fp0);
11684 break;
11685 case OPC_SUB_PS:
11686 check_ps(ctx);
11688 TCGv_i64 fp0 = tcg_temp_new_i64();
11689 TCGv_i64 fp1 = tcg_temp_new_i64();
11691 gen_load_fpr64(ctx, fp0, fs);
11692 gen_load_fpr64(ctx, fp1, ft);
11693 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11694 tcg_temp_free_i64(fp1);
11695 gen_store_fpr64(ctx, fp0, fd);
11696 tcg_temp_free_i64(fp0);
11698 break;
11699 case OPC_MUL_PS:
11700 check_ps(ctx);
11702 TCGv_i64 fp0 = tcg_temp_new_i64();
11703 TCGv_i64 fp1 = tcg_temp_new_i64();
11705 gen_load_fpr64(ctx, fp0, fs);
11706 gen_load_fpr64(ctx, fp1, ft);
11707 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11708 tcg_temp_free_i64(fp1);
11709 gen_store_fpr64(ctx, fp0, fd);
11710 tcg_temp_free_i64(fp0);
11712 break;
11713 case OPC_ABS_PS:
11714 check_ps(ctx);
11716 TCGv_i64 fp0 = tcg_temp_new_i64();
11718 gen_load_fpr64(ctx, fp0, fs);
11719 gen_helper_float_abs_ps(fp0, fp0);
11720 gen_store_fpr64(ctx, fp0, fd);
11721 tcg_temp_free_i64(fp0);
11723 break;
11724 case OPC_MOV_PS:
11725 check_ps(ctx);
11727 TCGv_i64 fp0 = tcg_temp_new_i64();
11729 gen_load_fpr64(ctx, fp0, fs);
11730 gen_store_fpr64(ctx, fp0, fd);
11731 tcg_temp_free_i64(fp0);
11733 break;
11734 case OPC_NEG_PS:
11735 check_ps(ctx);
11737 TCGv_i64 fp0 = tcg_temp_new_i64();
11739 gen_load_fpr64(ctx, fp0, fs);
11740 gen_helper_float_chs_ps(fp0, fp0);
11741 gen_store_fpr64(ctx, fp0, fd);
11742 tcg_temp_free_i64(fp0);
11744 break;
11745 case OPC_MOVCF_PS:
11746 check_ps(ctx);
11747 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11748 break;
11749 case OPC_MOVZ_PS:
11750 check_ps(ctx);
11752 TCGLabel *l1 = gen_new_label();
11753 TCGv_i64 fp0;
11755 if (ft != 0)
11756 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11757 fp0 = tcg_temp_new_i64();
11758 gen_load_fpr64(ctx, fp0, fs);
11759 gen_store_fpr64(ctx, fp0, fd);
11760 tcg_temp_free_i64(fp0);
11761 gen_set_label(l1);
11763 break;
11764 case OPC_MOVN_PS:
11765 check_ps(ctx);
11767 TCGLabel *l1 = gen_new_label();
11768 TCGv_i64 fp0;
11770 if (ft != 0) {
11771 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11772 fp0 = tcg_temp_new_i64();
11773 gen_load_fpr64(ctx, fp0, fs);
11774 gen_store_fpr64(ctx, fp0, fd);
11775 tcg_temp_free_i64(fp0);
11776 gen_set_label(l1);
11779 break;
11780 case OPC_ADDR_PS:
11781 check_ps(ctx);
11783 TCGv_i64 fp0 = tcg_temp_new_i64();
11784 TCGv_i64 fp1 = tcg_temp_new_i64();
11786 gen_load_fpr64(ctx, fp0, ft);
11787 gen_load_fpr64(ctx, fp1, fs);
11788 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11789 tcg_temp_free_i64(fp1);
11790 gen_store_fpr64(ctx, fp0, fd);
11791 tcg_temp_free_i64(fp0);
11793 break;
11794 case OPC_MULR_PS:
11795 check_ps(ctx);
11797 TCGv_i64 fp0 = tcg_temp_new_i64();
11798 TCGv_i64 fp1 = tcg_temp_new_i64();
11800 gen_load_fpr64(ctx, fp0, ft);
11801 gen_load_fpr64(ctx, fp1, fs);
11802 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11803 tcg_temp_free_i64(fp1);
11804 gen_store_fpr64(ctx, fp0, fd);
11805 tcg_temp_free_i64(fp0);
11807 break;
11808 case OPC_RECIP2_PS:
11809 check_ps(ctx);
11811 TCGv_i64 fp0 = tcg_temp_new_i64();
11812 TCGv_i64 fp1 = tcg_temp_new_i64();
11814 gen_load_fpr64(ctx, fp0, fs);
11815 gen_load_fpr64(ctx, fp1, ft);
11816 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11817 tcg_temp_free_i64(fp1);
11818 gen_store_fpr64(ctx, fp0, fd);
11819 tcg_temp_free_i64(fp0);
11821 break;
11822 case OPC_RECIP1_PS:
11823 check_ps(ctx);
11825 TCGv_i64 fp0 = tcg_temp_new_i64();
11827 gen_load_fpr64(ctx, fp0, fs);
11828 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11829 gen_store_fpr64(ctx, fp0, fd);
11830 tcg_temp_free_i64(fp0);
11832 break;
11833 case OPC_RSQRT1_PS:
11834 check_ps(ctx);
11836 TCGv_i64 fp0 = tcg_temp_new_i64();
11838 gen_load_fpr64(ctx, fp0, fs);
11839 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11840 gen_store_fpr64(ctx, fp0, fd);
11841 tcg_temp_free_i64(fp0);
11843 break;
11844 case OPC_RSQRT2_PS:
11845 check_ps(ctx);
11847 TCGv_i64 fp0 = tcg_temp_new_i64();
11848 TCGv_i64 fp1 = tcg_temp_new_i64();
11850 gen_load_fpr64(ctx, fp0, fs);
11851 gen_load_fpr64(ctx, fp1, ft);
11852 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11853 tcg_temp_free_i64(fp1);
11854 gen_store_fpr64(ctx, fp0, fd);
11855 tcg_temp_free_i64(fp0);
11857 break;
11858 case OPC_CVT_S_PU:
11859 check_cp1_64bitmode(ctx);
11861 TCGv_i32 fp0 = tcg_temp_new_i32();
11863 gen_load_fpr32h(ctx, fp0, fs);
11864 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11865 gen_store_fpr32(ctx, fp0, fd);
11866 tcg_temp_free_i32(fp0);
11868 break;
11869 case OPC_CVT_PW_PS:
11870 check_ps(ctx);
11872 TCGv_i64 fp0 = tcg_temp_new_i64();
11874 gen_load_fpr64(ctx, fp0, fs);
11875 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11876 gen_store_fpr64(ctx, fp0, fd);
11877 tcg_temp_free_i64(fp0);
11879 break;
11880 case OPC_CVT_S_PL:
11881 check_cp1_64bitmode(ctx);
11883 TCGv_i32 fp0 = tcg_temp_new_i32();
11885 gen_load_fpr32(ctx, fp0, fs);
11886 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11887 gen_store_fpr32(ctx, fp0, fd);
11888 tcg_temp_free_i32(fp0);
11890 break;
11891 case OPC_PLL_PS:
11892 check_ps(ctx);
11894 TCGv_i32 fp0 = tcg_temp_new_i32();
11895 TCGv_i32 fp1 = tcg_temp_new_i32();
11897 gen_load_fpr32(ctx, fp0, fs);
11898 gen_load_fpr32(ctx, fp1, ft);
11899 gen_store_fpr32h(ctx, fp0, fd);
11900 gen_store_fpr32(ctx, fp1, fd);
11901 tcg_temp_free_i32(fp0);
11902 tcg_temp_free_i32(fp1);
11904 break;
11905 case OPC_PLU_PS:
11906 check_ps(ctx);
11908 TCGv_i32 fp0 = tcg_temp_new_i32();
11909 TCGv_i32 fp1 = tcg_temp_new_i32();
11911 gen_load_fpr32(ctx, fp0, fs);
11912 gen_load_fpr32h(ctx, fp1, ft);
11913 gen_store_fpr32(ctx, fp1, fd);
11914 gen_store_fpr32h(ctx, fp0, fd);
11915 tcg_temp_free_i32(fp0);
11916 tcg_temp_free_i32(fp1);
11918 break;
11919 case OPC_PUL_PS:
11920 check_ps(ctx);
11922 TCGv_i32 fp0 = tcg_temp_new_i32();
11923 TCGv_i32 fp1 = tcg_temp_new_i32();
11925 gen_load_fpr32h(ctx, fp0, fs);
11926 gen_load_fpr32(ctx, fp1, ft);
11927 gen_store_fpr32(ctx, fp1, fd);
11928 gen_store_fpr32h(ctx, fp0, fd);
11929 tcg_temp_free_i32(fp0);
11930 tcg_temp_free_i32(fp1);
11932 break;
11933 case OPC_PUU_PS:
11934 check_ps(ctx);
11936 TCGv_i32 fp0 = tcg_temp_new_i32();
11937 TCGv_i32 fp1 = tcg_temp_new_i32();
11939 gen_load_fpr32h(ctx, fp0, fs);
11940 gen_load_fpr32h(ctx, fp1, ft);
11941 gen_store_fpr32(ctx, fp1, fd);
11942 gen_store_fpr32h(ctx, fp0, fd);
11943 tcg_temp_free_i32(fp0);
11944 tcg_temp_free_i32(fp1);
11946 break;
11947 case OPC_CMP_F_PS:
11948 case OPC_CMP_UN_PS:
11949 case OPC_CMP_EQ_PS:
11950 case OPC_CMP_UEQ_PS:
11951 case OPC_CMP_OLT_PS:
11952 case OPC_CMP_ULT_PS:
11953 case OPC_CMP_OLE_PS:
11954 case OPC_CMP_ULE_PS:
11955 case OPC_CMP_SF_PS:
11956 case OPC_CMP_NGLE_PS:
11957 case OPC_CMP_SEQ_PS:
11958 case OPC_CMP_NGL_PS:
11959 case OPC_CMP_LT_PS:
11960 case OPC_CMP_NGE_PS:
11961 case OPC_CMP_LE_PS:
11962 case OPC_CMP_NGT_PS:
11963 if (ctx->opcode & (1 << 6)) {
11964 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
11965 } else {
11966 gen_cmp_ps(ctx, func-48, ft, fs, cc);
11968 break;
11969 default:
11970 MIPS_INVAL("farith");
11971 generate_exception_end(ctx, EXCP_RI);
11972 return;
11976 /* Coprocessor 3 (FPU) */
11977 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
11978 int fd, int fs, int base, int index)
11980 TCGv t0 = tcg_temp_new();
11982 if (base == 0) {
11983 gen_load_gpr(t0, index);
11984 } else if (index == 0) {
11985 gen_load_gpr(t0, base);
11986 } else {
11987 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11989 /* Don't do NOP if destination is zero: we must perform the actual
11990 memory access. */
11991 switch (opc) {
11992 case OPC_LWXC1:
11993 check_cop1x(ctx);
11995 TCGv_i32 fp0 = tcg_temp_new_i32();
11997 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11998 tcg_gen_trunc_tl_i32(fp0, t0);
11999 gen_store_fpr32(ctx, fp0, fd);
12000 tcg_temp_free_i32(fp0);
12002 break;
12003 case OPC_LDXC1:
12004 check_cop1x(ctx);
12005 check_cp1_registers(ctx, fd);
12007 TCGv_i64 fp0 = tcg_temp_new_i64();
12008 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12009 gen_store_fpr64(ctx, fp0, fd);
12010 tcg_temp_free_i64(fp0);
12012 break;
12013 case OPC_LUXC1:
12014 check_cp1_64bitmode(ctx);
12015 tcg_gen_andi_tl(t0, t0, ~0x7);
12017 TCGv_i64 fp0 = tcg_temp_new_i64();
12019 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12020 gen_store_fpr64(ctx, fp0, fd);
12021 tcg_temp_free_i64(fp0);
12023 break;
12024 case OPC_SWXC1:
12025 check_cop1x(ctx);
12027 TCGv_i32 fp0 = tcg_temp_new_i32();
12028 gen_load_fpr32(ctx, fp0, fs);
12029 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12030 tcg_temp_free_i32(fp0);
12032 break;
12033 case OPC_SDXC1:
12034 check_cop1x(ctx);
12035 check_cp1_registers(ctx, fs);
12037 TCGv_i64 fp0 = tcg_temp_new_i64();
12038 gen_load_fpr64(ctx, fp0, fs);
12039 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12040 tcg_temp_free_i64(fp0);
12042 break;
12043 case OPC_SUXC1:
12044 check_cp1_64bitmode(ctx);
12045 tcg_gen_andi_tl(t0, t0, ~0x7);
12047 TCGv_i64 fp0 = tcg_temp_new_i64();
12048 gen_load_fpr64(ctx, fp0, fs);
12049 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12050 tcg_temp_free_i64(fp0);
12052 break;
12054 tcg_temp_free(t0);
12057 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12058 int fd, int fr, int fs, int ft)
12060 switch (opc) {
12061 case OPC_ALNV_PS:
12062 check_ps(ctx);
12064 TCGv t0 = tcg_temp_local_new();
12065 TCGv_i32 fp = tcg_temp_new_i32();
12066 TCGv_i32 fph = tcg_temp_new_i32();
12067 TCGLabel *l1 = gen_new_label();
12068 TCGLabel *l2 = gen_new_label();
12070 gen_load_gpr(t0, fr);
12071 tcg_gen_andi_tl(t0, t0, 0x7);
12073 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12074 gen_load_fpr32(ctx, fp, fs);
12075 gen_load_fpr32h(ctx, fph, fs);
12076 gen_store_fpr32(ctx, fp, fd);
12077 gen_store_fpr32h(ctx, fph, fd);
12078 tcg_gen_br(l2);
12079 gen_set_label(l1);
12080 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12081 tcg_temp_free(t0);
12082 #ifdef TARGET_WORDS_BIGENDIAN
12083 gen_load_fpr32(ctx, fp, fs);
12084 gen_load_fpr32h(ctx, fph, ft);
12085 gen_store_fpr32h(ctx, fp, fd);
12086 gen_store_fpr32(ctx, fph, fd);
12087 #else
12088 gen_load_fpr32h(ctx, fph, fs);
12089 gen_load_fpr32(ctx, fp, ft);
12090 gen_store_fpr32(ctx, fph, fd);
12091 gen_store_fpr32h(ctx, fp, fd);
12092 #endif
12093 gen_set_label(l2);
12094 tcg_temp_free_i32(fp);
12095 tcg_temp_free_i32(fph);
12097 break;
12098 case OPC_MADD_S:
12099 check_cop1x(ctx);
12101 TCGv_i32 fp0 = tcg_temp_new_i32();
12102 TCGv_i32 fp1 = tcg_temp_new_i32();
12103 TCGv_i32 fp2 = tcg_temp_new_i32();
12105 gen_load_fpr32(ctx, fp0, fs);
12106 gen_load_fpr32(ctx, fp1, ft);
12107 gen_load_fpr32(ctx, fp2, fr);
12108 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12109 tcg_temp_free_i32(fp0);
12110 tcg_temp_free_i32(fp1);
12111 gen_store_fpr32(ctx, fp2, fd);
12112 tcg_temp_free_i32(fp2);
12114 break;
12115 case OPC_MADD_D:
12116 check_cop1x(ctx);
12117 check_cp1_registers(ctx, fd | fs | ft | fr);
12119 TCGv_i64 fp0 = tcg_temp_new_i64();
12120 TCGv_i64 fp1 = tcg_temp_new_i64();
12121 TCGv_i64 fp2 = tcg_temp_new_i64();
12123 gen_load_fpr64(ctx, fp0, fs);
12124 gen_load_fpr64(ctx, fp1, ft);
12125 gen_load_fpr64(ctx, fp2, fr);
12126 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12127 tcg_temp_free_i64(fp0);
12128 tcg_temp_free_i64(fp1);
12129 gen_store_fpr64(ctx, fp2, fd);
12130 tcg_temp_free_i64(fp2);
12132 break;
12133 case OPC_MADD_PS:
12134 check_ps(ctx);
12136 TCGv_i64 fp0 = tcg_temp_new_i64();
12137 TCGv_i64 fp1 = tcg_temp_new_i64();
12138 TCGv_i64 fp2 = tcg_temp_new_i64();
12140 gen_load_fpr64(ctx, fp0, fs);
12141 gen_load_fpr64(ctx, fp1, ft);
12142 gen_load_fpr64(ctx, fp2, fr);
12143 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12144 tcg_temp_free_i64(fp0);
12145 tcg_temp_free_i64(fp1);
12146 gen_store_fpr64(ctx, fp2, fd);
12147 tcg_temp_free_i64(fp2);
12149 break;
12150 case OPC_MSUB_S:
12151 check_cop1x(ctx);
12153 TCGv_i32 fp0 = tcg_temp_new_i32();
12154 TCGv_i32 fp1 = tcg_temp_new_i32();
12155 TCGv_i32 fp2 = tcg_temp_new_i32();
12157 gen_load_fpr32(ctx, fp0, fs);
12158 gen_load_fpr32(ctx, fp1, ft);
12159 gen_load_fpr32(ctx, fp2, fr);
12160 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12161 tcg_temp_free_i32(fp0);
12162 tcg_temp_free_i32(fp1);
12163 gen_store_fpr32(ctx, fp2, fd);
12164 tcg_temp_free_i32(fp2);
12166 break;
12167 case OPC_MSUB_D:
12168 check_cop1x(ctx);
12169 check_cp1_registers(ctx, fd | fs | ft | fr);
12171 TCGv_i64 fp0 = tcg_temp_new_i64();
12172 TCGv_i64 fp1 = tcg_temp_new_i64();
12173 TCGv_i64 fp2 = tcg_temp_new_i64();
12175 gen_load_fpr64(ctx, fp0, fs);
12176 gen_load_fpr64(ctx, fp1, ft);
12177 gen_load_fpr64(ctx, fp2, fr);
12178 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12179 tcg_temp_free_i64(fp0);
12180 tcg_temp_free_i64(fp1);
12181 gen_store_fpr64(ctx, fp2, fd);
12182 tcg_temp_free_i64(fp2);
12184 break;
12185 case OPC_MSUB_PS:
12186 check_ps(ctx);
12188 TCGv_i64 fp0 = tcg_temp_new_i64();
12189 TCGv_i64 fp1 = tcg_temp_new_i64();
12190 TCGv_i64 fp2 = tcg_temp_new_i64();
12192 gen_load_fpr64(ctx, fp0, fs);
12193 gen_load_fpr64(ctx, fp1, ft);
12194 gen_load_fpr64(ctx, fp2, fr);
12195 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12196 tcg_temp_free_i64(fp0);
12197 tcg_temp_free_i64(fp1);
12198 gen_store_fpr64(ctx, fp2, fd);
12199 tcg_temp_free_i64(fp2);
12201 break;
12202 case OPC_NMADD_S:
12203 check_cop1x(ctx);
12205 TCGv_i32 fp0 = tcg_temp_new_i32();
12206 TCGv_i32 fp1 = tcg_temp_new_i32();
12207 TCGv_i32 fp2 = tcg_temp_new_i32();
12209 gen_load_fpr32(ctx, fp0, fs);
12210 gen_load_fpr32(ctx, fp1, ft);
12211 gen_load_fpr32(ctx, fp2, fr);
12212 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12213 tcg_temp_free_i32(fp0);
12214 tcg_temp_free_i32(fp1);
12215 gen_store_fpr32(ctx, fp2, fd);
12216 tcg_temp_free_i32(fp2);
12218 break;
12219 case OPC_NMADD_D:
12220 check_cop1x(ctx);
12221 check_cp1_registers(ctx, fd | fs | ft | fr);
12223 TCGv_i64 fp0 = tcg_temp_new_i64();
12224 TCGv_i64 fp1 = tcg_temp_new_i64();
12225 TCGv_i64 fp2 = tcg_temp_new_i64();
12227 gen_load_fpr64(ctx, fp0, fs);
12228 gen_load_fpr64(ctx, fp1, ft);
12229 gen_load_fpr64(ctx, fp2, fr);
12230 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12231 tcg_temp_free_i64(fp0);
12232 tcg_temp_free_i64(fp1);
12233 gen_store_fpr64(ctx, fp2, fd);
12234 tcg_temp_free_i64(fp2);
12236 break;
12237 case OPC_NMADD_PS:
12238 check_ps(ctx);
12240 TCGv_i64 fp0 = tcg_temp_new_i64();
12241 TCGv_i64 fp1 = tcg_temp_new_i64();
12242 TCGv_i64 fp2 = tcg_temp_new_i64();
12244 gen_load_fpr64(ctx, fp0, fs);
12245 gen_load_fpr64(ctx, fp1, ft);
12246 gen_load_fpr64(ctx, fp2, fr);
12247 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12248 tcg_temp_free_i64(fp0);
12249 tcg_temp_free_i64(fp1);
12250 gen_store_fpr64(ctx, fp2, fd);
12251 tcg_temp_free_i64(fp2);
12253 break;
12254 case OPC_NMSUB_S:
12255 check_cop1x(ctx);
12257 TCGv_i32 fp0 = tcg_temp_new_i32();
12258 TCGv_i32 fp1 = tcg_temp_new_i32();
12259 TCGv_i32 fp2 = tcg_temp_new_i32();
12261 gen_load_fpr32(ctx, fp0, fs);
12262 gen_load_fpr32(ctx, fp1, ft);
12263 gen_load_fpr32(ctx, fp2, fr);
12264 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12265 tcg_temp_free_i32(fp0);
12266 tcg_temp_free_i32(fp1);
12267 gen_store_fpr32(ctx, fp2, fd);
12268 tcg_temp_free_i32(fp2);
12270 break;
12271 case OPC_NMSUB_D:
12272 check_cop1x(ctx);
12273 check_cp1_registers(ctx, fd | fs | ft | fr);
12275 TCGv_i64 fp0 = tcg_temp_new_i64();
12276 TCGv_i64 fp1 = tcg_temp_new_i64();
12277 TCGv_i64 fp2 = tcg_temp_new_i64();
12279 gen_load_fpr64(ctx, fp0, fs);
12280 gen_load_fpr64(ctx, fp1, ft);
12281 gen_load_fpr64(ctx, fp2, fr);
12282 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12283 tcg_temp_free_i64(fp0);
12284 tcg_temp_free_i64(fp1);
12285 gen_store_fpr64(ctx, fp2, fd);
12286 tcg_temp_free_i64(fp2);
12288 break;
12289 case OPC_NMSUB_PS:
12290 check_ps(ctx);
12292 TCGv_i64 fp0 = tcg_temp_new_i64();
12293 TCGv_i64 fp1 = tcg_temp_new_i64();
12294 TCGv_i64 fp2 = tcg_temp_new_i64();
12296 gen_load_fpr64(ctx, fp0, fs);
12297 gen_load_fpr64(ctx, fp1, ft);
12298 gen_load_fpr64(ctx, fp2, fr);
12299 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12300 tcg_temp_free_i64(fp0);
12301 tcg_temp_free_i64(fp1);
12302 gen_store_fpr64(ctx, fp2, fd);
12303 tcg_temp_free_i64(fp2);
12305 break;
12306 default:
12307 MIPS_INVAL("flt3_arith");
12308 generate_exception_end(ctx, EXCP_RI);
12309 return;
12313 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12315 TCGv t0;
12317 #if !defined(CONFIG_USER_ONLY)
12318 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12319 Therefore only check the ISA in system mode. */
12320 check_insn(ctx, ISA_MIPS32R2);
12321 #endif
12322 t0 = tcg_temp_new();
12324 switch (rd) {
12325 case 0:
12326 gen_helper_rdhwr_cpunum(t0, cpu_env);
12327 gen_store_gpr(t0, rt);
12328 break;
12329 case 1:
12330 gen_helper_rdhwr_synci_step(t0, cpu_env);
12331 gen_store_gpr(t0, rt);
12332 break;
12333 case 2:
12334 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12335 gen_io_start();
12337 gen_helper_rdhwr_cc(t0, cpu_env);
12338 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12339 gen_io_end();
12341 gen_store_gpr(t0, rt);
12342 /* Break the TB to be able to take timer interrupts immediately
12343 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12344 we break completely out of translated code. */
12345 gen_save_pc(ctx->base.pc_next + 4);
12346 ctx->base.is_jmp = DISAS_EXIT;
12347 break;
12348 case 3:
12349 gen_helper_rdhwr_ccres(t0, cpu_env);
12350 gen_store_gpr(t0, rt);
12351 break;
12352 case 4:
12353 check_insn(ctx, ISA_MIPS32R6);
12354 if (sel != 0) {
12355 /* Performance counter registers are not implemented other than
12356 * control register 0.
12358 generate_exception(ctx, EXCP_RI);
12360 gen_helper_rdhwr_performance(t0, cpu_env);
12361 gen_store_gpr(t0, rt);
12362 break;
12363 case 5:
12364 check_insn(ctx, ISA_MIPS32R6);
12365 gen_helper_rdhwr_xnp(t0, cpu_env);
12366 gen_store_gpr(t0, rt);
12367 break;
12368 case 29:
12369 #if defined(CONFIG_USER_ONLY)
12370 tcg_gen_ld_tl(t0, cpu_env,
12371 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12372 gen_store_gpr(t0, rt);
12373 break;
12374 #else
12375 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12376 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12377 tcg_gen_ld_tl(t0, cpu_env,
12378 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12379 gen_store_gpr(t0, rt);
12380 } else {
12381 generate_exception_end(ctx, EXCP_RI);
12383 break;
12384 #endif
12385 default: /* Invalid */
12386 MIPS_INVAL("rdhwr");
12387 generate_exception_end(ctx, EXCP_RI);
12388 break;
12390 tcg_temp_free(t0);
12393 static inline void clear_branch_hflags(DisasContext *ctx)
12395 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12396 if (ctx->base.is_jmp == DISAS_NEXT) {
12397 save_cpu_state(ctx, 0);
12398 } else {
12399 /* it is not safe to save ctx->hflags as hflags may be changed
12400 in execution time by the instruction in delay / forbidden slot. */
12401 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12405 static void gen_branch(DisasContext *ctx, int insn_bytes)
12407 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12408 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12409 /* Branches completion */
12410 clear_branch_hflags(ctx);
12411 ctx->base.is_jmp = DISAS_NORETURN;
12412 /* FIXME: Need to clear can_do_io. */
12413 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12414 case MIPS_HFLAG_FBNSLOT:
12415 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12416 break;
12417 case MIPS_HFLAG_B:
12418 /* unconditional branch */
12419 if (proc_hflags & MIPS_HFLAG_BX) {
12420 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12422 gen_goto_tb(ctx, 0, ctx->btarget);
12423 break;
12424 case MIPS_HFLAG_BL:
12425 /* blikely taken case */
12426 gen_goto_tb(ctx, 0, ctx->btarget);
12427 break;
12428 case MIPS_HFLAG_BC:
12429 /* Conditional branch */
12431 TCGLabel *l1 = gen_new_label();
12433 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12434 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12435 gen_set_label(l1);
12436 gen_goto_tb(ctx, 0, ctx->btarget);
12438 break;
12439 case MIPS_HFLAG_BR:
12440 /* unconditional branch to register */
12441 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12442 TCGv t0 = tcg_temp_new();
12443 TCGv_i32 t1 = tcg_temp_new_i32();
12445 tcg_gen_andi_tl(t0, btarget, 0x1);
12446 tcg_gen_trunc_tl_i32(t1, t0);
12447 tcg_temp_free(t0);
12448 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12449 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12450 tcg_gen_or_i32(hflags, hflags, t1);
12451 tcg_temp_free_i32(t1);
12453 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12454 } else {
12455 tcg_gen_mov_tl(cpu_PC, btarget);
12457 if (ctx->base.singlestep_enabled) {
12458 save_cpu_state(ctx, 0);
12459 gen_helper_raise_exception_debug(cpu_env);
12461 tcg_gen_lookup_and_goto_ptr();
12462 break;
12463 default:
12464 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12465 abort();
12470 /* Compact Branches */
12471 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12472 int rs, int rt, int32_t offset)
12474 int bcond_compute = 0;
12475 TCGv t0 = tcg_temp_new();
12476 TCGv t1 = tcg_temp_new();
12477 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12479 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12480 #ifdef MIPS_DEBUG_DISAS
12481 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12482 "\n", ctx->base.pc_next);
12483 #endif
12484 generate_exception_end(ctx, EXCP_RI);
12485 goto out;
12488 /* Load needed operands and calculate btarget */
12489 switch (opc) {
12490 /* compact branch */
12491 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12492 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12493 gen_load_gpr(t0, rs);
12494 gen_load_gpr(t1, rt);
12495 bcond_compute = 1;
12496 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12497 if (rs <= rt && rs == 0) {
12498 /* OPC_BEQZALC, OPC_BNEZALC */
12499 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12501 break;
12502 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12503 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12504 gen_load_gpr(t0, rs);
12505 gen_load_gpr(t1, rt);
12506 bcond_compute = 1;
12507 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12508 break;
12509 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12510 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12511 if (rs == 0 || rs == rt) {
12512 /* OPC_BLEZALC, OPC_BGEZALC */
12513 /* OPC_BGTZALC, OPC_BLTZALC */
12514 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
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 break;
12521 case OPC_BC:
12522 case OPC_BALC:
12523 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12524 break;
12525 case OPC_BEQZC:
12526 case OPC_BNEZC:
12527 if (rs != 0) {
12528 /* OPC_BEQZC, OPC_BNEZC */
12529 gen_load_gpr(t0, rs);
12530 bcond_compute = 1;
12531 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12532 } else {
12533 /* OPC_JIC, OPC_JIALC */
12534 TCGv tbase = tcg_temp_new();
12535 TCGv toffset = tcg_temp_new();
12537 gen_load_gpr(tbase, rt);
12538 tcg_gen_movi_tl(toffset, offset);
12539 gen_op_addr_add(ctx, btarget, tbase, toffset);
12540 tcg_temp_free(tbase);
12541 tcg_temp_free(toffset);
12543 break;
12544 default:
12545 MIPS_INVAL("Compact branch/jump");
12546 generate_exception_end(ctx, EXCP_RI);
12547 goto out;
12550 if (bcond_compute == 0) {
12551 /* Uncoditional compact branch */
12552 switch (opc) {
12553 case OPC_JIALC:
12554 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12555 /* Fallthrough */
12556 case OPC_JIC:
12557 ctx->hflags |= MIPS_HFLAG_BR;
12558 break;
12559 case OPC_BALC:
12560 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12561 /* Fallthrough */
12562 case OPC_BC:
12563 ctx->hflags |= MIPS_HFLAG_B;
12564 break;
12565 default:
12566 MIPS_INVAL("Compact branch/jump");
12567 generate_exception_end(ctx, EXCP_RI);
12568 goto out;
12571 /* Generating branch here as compact branches don't have delay slot */
12572 gen_branch(ctx, 4);
12573 } else {
12574 /* Conditional compact branch */
12575 TCGLabel *fs = gen_new_label();
12576 save_cpu_state(ctx, 0);
12578 switch (opc) {
12579 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12580 if (rs == 0 && rt != 0) {
12581 /* OPC_BLEZALC */
12582 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12583 } else if (rs != 0 && rt != 0 && rs == rt) {
12584 /* OPC_BGEZALC */
12585 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12586 } else {
12587 /* OPC_BGEUC */
12588 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12590 break;
12591 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12592 if (rs == 0 && rt != 0) {
12593 /* OPC_BGTZALC */
12594 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12595 } else if (rs != 0 && rt != 0 && rs == rt) {
12596 /* OPC_BLTZALC */
12597 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12598 } else {
12599 /* OPC_BLTUC */
12600 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12602 break;
12603 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12604 if (rs == 0 && rt != 0) {
12605 /* OPC_BLEZC */
12606 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12607 } else if (rs != 0 && rt != 0 && rs == rt) {
12608 /* OPC_BGEZC */
12609 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12610 } else {
12611 /* OPC_BGEC */
12612 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12614 break;
12615 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12616 if (rs == 0 && rt != 0) {
12617 /* OPC_BGTZC */
12618 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12619 } else if (rs != 0 && rt != 0 && rs == rt) {
12620 /* OPC_BLTZC */
12621 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12622 } else {
12623 /* OPC_BLTC */
12624 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12626 break;
12627 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12628 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12629 if (rs >= rt) {
12630 /* OPC_BOVC, OPC_BNVC */
12631 TCGv t2 = tcg_temp_new();
12632 TCGv t3 = tcg_temp_new();
12633 TCGv t4 = tcg_temp_new();
12634 TCGv input_overflow = tcg_temp_new();
12636 gen_load_gpr(t0, rs);
12637 gen_load_gpr(t1, rt);
12638 tcg_gen_ext32s_tl(t2, t0);
12639 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12640 tcg_gen_ext32s_tl(t3, t1);
12641 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12642 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12644 tcg_gen_add_tl(t4, t2, t3);
12645 tcg_gen_ext32s_tl(t4, t4);
12646 tcg_gen_xor_tl(t2, t2, t3);
12647 tcg_gen_xor_tl(t3, t4, t3);
12648 tcg_gen_andc_tl(t2, t3, t2);
12649 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12650 tcg_gen_or_tl(t4, t4, input_overflow);
12651 if (opc == OPC_BOVC) {
12652 /* OPC_BOVC */
12653 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12654 } else {
12655 /* OPC_BNVC */
12656 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12658 tcg_temp_free(input_overflow);
12659 tcg_temp_free(t4);
12660 tcg_temp_free(t3);
12661 tcg_temp_free(t2);
12662 } else if (rs < rt && rs == 0) {
12663 /* OPC_BEQZALC, OPC_BNEZALC */
12664 if (opc == OPC_BEQZALC) {
12665 /* OPC_BEQZALC */
12666 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12667 } else {
12668 /* OPC_BNEZALC */
12669 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12671 } else {
12672 /* OPC_BEQC, OPC_BNEC */
12673 if (opc == OPC_BEQC) {
12674 /* OPC_BEQC */
12675 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12676 } else {
12677 /* OPC_BNEC */
12678 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12681 break;
12682 case OPC_BEQZC:
12683 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12684 break;
12685 case OPC_BNEZC:
12686 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12687 break;
12688 default:
12689 MIPS_INVAL("Compact conditional branch/jump");
12690 generate_exception_end(ctx, EXCP_RI);
12691 goto out;
12694 /* Generating branch here as compact branches don't have delay slot */
12695 gen_goto_tb(ctx, 1, ctx->btarget);
12696 gen_set_label(fs);
12698 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12701 out:
12702 tcg_temp_free(t0);
12703 tcg_temp_free(t1);
12706 /* ISA extensions (ASEs) */
12707 /* MIPS16 extension to MIPS32 */
12709 /* MIPS16 major opcodes */
12710 enum {
12711 M16_OPC_ADDIUSP = 0x00,
12712 M16_OPC_ADDIUPC = 0x01,
12713 M16_OPC_B = 0x02,
12714 M16_OPC_JAL = 0x03,
12715 M16_OPC_BEQZ = 0x04,
12716 M16_OPC_BNEQZ = 0x05,
12717 M16_OPC_SHIFT = 0x06,
12718 M16_OPC_LD = 0x07,
12719 M16_OPC_RRIA = 0x08,
12720 M16_OPC_ADDIU8 = 0x09,
12721 M16_OPC_SLTI = 0x0a,
12722 M16_OPC_SLTIU = 0x0b,
12723 M16_OPC_I8 = 0x0c,
12724 M16_OPC_LI = 0x0d,
12725 M16_OPC_CMPI = 0x0e,
12726 M16_OPC_SD = 0x0f,
12727 M16_OPC_LB = 0x10,
12728 M16_OPC_LH = 0x11,
12729 M16_OPC_LWSP = 0x12,
12730 M16_OPC_LW = 0x13,
12731 M16_OPC_LBU = 0x14,
12732 M16_OPC_LHU = 0x15,
12733 M16_OPC_LWPC = 0x16,
12734 M16_OPC_LWU = 0x17,
12735 M16_OPC_SB = 0x18,
12736 M16_OPC_SH = 0x19,
12737 M16_OPC_SWSP = 0x1a,
12738 M16_OPC_SW = 0x1b,
12739 M16_OPC_RRR = 0x1c,
12740 M16_OPC_RR = 0x1d,
12741 M16_OPC_EXTEND = 0x1e,
12742 M16_OPC_I64 = 0x1f
12745 /* I8 funct field */
12746 enum {
12747 I8_BTEQZ = 0x0,
12748 I8_BTNEZ = 0x1,
12749 I8_SWRASP = 0x2,
12750 I8_ADJSP = 0x3,
12751 I8_SVRS = 0x4,
12752 I8_MOV32R = 0x5,
12753 I8_MOVR32 = 0x7
12756 /* RRR f field */
12757 enum {
12758 RRR_DADDU = 0x0,
12759 RRR_ADDU = 0x1,
12760 RRR_DSUBU = 0x2,
12761 RRR_SUBU = 0x3
12764 /* RR funct field */
12765 enum {
12766 RR_JR = 0x00,
12767 RR_SDBBP = 0x01,
12768 RR_SLT = 0x02,
12769 RR_SLTU = 0x03,
12770 RR_SLLV = 0x04,
12771 RR_BREAK = 0x05,
12772 RR_SRLV = 0x06,
12773 RR_SRAV = 0x07,
12774 RR_DSRL = 0x08,
12775 RR_CMP = 0x0a,
12776 RR_NEG = 0x0b,
12777 RR_AND = 0x0c,
12778 RR_OR = 0x0d,
12779 RR_XOR = 0x0e,
12780 RR_NOT = 0x0f,
12781 RR_MFHI = 0x10,
12782 RR_CNVT = 0x11,
12783 RR_MFLO = 0x12,
12784 RR_DSRA = 0x13,
12785 RR_DSLLV = 0x14,
12786 RR_DSRLV = 0x16,
12787 RR_DSRAV = 0x17,
12788 RR_MULT = 0x18,
12789 RR_MULTU = 0x19,
12790 RR_DIV = 0x1a,
12791 RR_DIVU = 0x1b,
12792 RR_DMULT = 0x1c,
12793 RR_DMULTU = 0x1d,
12794 RR_DDIV = 0x1e,
12795 RR_DDIVU = 0x1f
12798 /* I64 funct field */
12799 enum {
12800 I64_LDSP = 0x0,
12801 I64_SDSP = 0x1,
12802 I64_SDRASP = 0x2,
12803 I64_DADJSP = 0x3,
12804 I64_LDPC = 0x4,
12805 I64_DADDIU5 = 0x5,
12806 I64_DADDIUPC = 0x6,
12807 I64_DADDIUSP = 0x7
12810 /* RR ry field for CNVT */
12811 enum {
12812 RR_RY_CNVT_ZEB = 0x0,
12813 RR_RY_CNVT_ZEH = 0x1,
12814 RR_RY_CNVT_ZEW = 0x2,
12815 RR_RY_CNVT_SEB = 0x4,
12816 RR_RY_CNVT_SEH = 0x5,
12817 RR_RY_CNVT_SEW = 0x6,
12820 static int xlat (int r)
12822 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12824 return map[r];
12827 static void gen_mips16_save (DisasContext *ctx,
12828 int xsregs, int aregs,
12829 int do_ra, int do_s0, int do_s1,
12830 int framesize)
12832 TCGv t0 = tcg_temp_new();
12833 TCGv t1 = tcg_temp_new();
12834 TCGv t2 = tcg_temp_new();
12835 int args, astatic;
12837 switch (aregs) {
12838 case 0:
12839 case 1:
12840 case 2:
12841 case 3:
12842 case 11:
12843 args = 0;
12844 break;
12845 case 4:
12846 case 5:
12847 case 6:
12848 case 7:
12849 args = 1;
12850 break;
12851 case 8:
12852 case 9:
12853 case 10:
12854 args = 2;
12855 break;
12856 case 12:
12857 case 13:
12858 args = 3;
12859 break;
12860 case 14:
12861 args = 4;
12862 break;
12863 default:
12864 generate_exception_end(ctx, EXCP_RI);
12865 return;
12868 switch (args) {
12869 case 4:
12870 gen_base_offset_addr(ctx, t0, 29, 12);
12871 gen_load_gpr(t1, 7);
12872 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12873 /* Fall through */
12874 case 3:
12875 gen_base_offset_addr(ctx, t0, 29, 8);
12876 gen_load_gpr(t1, 6);
12877 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12878 /* Fall through */
12879 case 2:
12880 gen_base_offset_addr(ctx, t0, 29, 4);
12881 gen_load_gpr(t1, 5);
12882 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12883 /* Fall through */
12884 case 1:
12885 gen_base_offset_addr(ctx, t0, 29, 0);
12886 gen_load_gpr(t1, 4);
12887 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12890 gen_load_gpr(t0, 29);
12892 #define DECR_AND_STORE(reg) do { \
12893 tcg_gen_movi_tl(t2, -4); \
12894 gen_op_addr_add(ctx, t0, t0, t2); \
12895 gen_load_gpr(t1, reg); \
12896 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12897 } while (0)
12899 if (do_ra) {
12900 DECR_AND_STORE(31);
12903 switch (xsregs) {
12904 case 7:
12905 DECR_AND_STORE(30);
12906 /* Fall through */
12907 case 6:
12908 DECR_AND_STORE(23);
12909 /* Fall through */
12910 case 5:
12911 DECR_AND_STORE(22);
12912 /* Fall through */
12913 case 4:
12914 DECR_AND_STORE(21);
12915 /* Fall through */
12916 case 3:
12917 DECR_AND_STORE(20);
12918 /* Fall through */
12919 case 2:
12920 DECR_AND_STORE(19);
12921 /* Fall through */
12922 case 1:
12923 DECR_AND_STORE(18);
12926 if (do_s1) {
12927 DECR_AND_STORE(17);
12929 if (do_s0) {
12930 DECR_AND_STORE(16);
12933 switch (aregs) {
12934 case 0:
12935 case 4:
12936 case 8:
12937 case 12:
12938 case 14:
12939 astatic = 0;
12940 break;
12941 case 1:
12942 case 5:
12943 case 9:
12944 case 13:
12945 astatic = 1;
12946 break;
12947 case 2:
12948 case 6:
12949 case 10:
12950 astatic = 2;
12951 break;
12952 case 3:
12953 case 7:
12954 astatic = 3;
12955 break;
12956 case 11:
12957 astatic = 4;
12958 break;
12959 default:
12960 generate_exception_end(ctx, EXCP_RI);
12961 return;
12964 if (astatic > 0) {
12965 DECR_AND_STORE(7);
12966 if (astatic > 1) {
12967 DECR_AND_STORE(6);
12968 if (astatic > 2) {
12969 DECR_AND_STORE(5);
12970 if (astatic > 3) {
12971 DECR_AND_STORE(4);
12976 #undef DECR_AND_STORE
12978 tcg_gen_movi_tl(t2, -framesize);
12979 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12980 tcg_temp_free(t0);
12981 tcg_temp_free(t1);
12982 tcg_temp_free(t2);
12985 static void gen_mips16_restore (DisasContext *ctx,
12986 int xsregs, int aregs,
12987 int do_ra, int do_s0, int do_s1,
12988 int framesize)
12990 int astatic;
12991 TCGv t0 = tcg_temp_new();
12992 TCGv t1 = tcg_temp_new();
12993 TCGv t2 = tcg_temp_new();
12995 tcg_gen_movi_tl(t2, framesize);
12996 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12998 #define DECR_AND_LOAD(reg) do { \
12999 tcg_gen_movi_tl(t2, -4); \
13000 gen_op_addr_add(ctx, t0, t0, t2); \
13001 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
13002 gen_store_gpr(t1, reg); \
13003 } while (0)
13005 if (do_ra) {
13006 DECR_AND_LOAD(31);
13009 switch (xsregs) {
13010 case 7:
13011 DECR_AND_LOAD(30);
13012 /* Fall through */
13013 case 6:
13014 DECR_AND_LOAD(23);
13015 /* Fall through */
13016 case 5:
13017 DECR_AND_LOAD(22);
13018 /* Fall through */
13019 case 4:
13020 DECR_AND_LOAD(21);
13021 /* Fall through */
13022 case 3:
13023 DECR_AND_LOAD(20);
13024 /* Fall through */
13025 case 2:
13026 DECR_AND_LOAD(19);
13027 /* Fall through */
13028 case 1:
13029 DECR_AND_LOAD(18);
13032 if (do_s1) {
13033 DECR_AND_LOAD(17);
13035 if (do_s0) {
13036 DECR_AND_LOAD(16);
13039 switch (aregs) {
13040 case 0:
13041 case 4:
13042 case 8:
13043 case 12:
13044 case 14:
13045 astatic = 0;
13046 break;
13047 case 1:
13048 case 5:
13049 case 9:
13050 case 13:
13051 astatic = 1;
13052 break;
13053 case 2:
13054 case 6:
13055 case 10:
13056 astatic = 2;
13057 break;
13058 case 3:
13059 case 7:
13060 astatic = 3;
13061 break;
13062 case 11:
13063 astatic = 4;
13064 break;
13065 default:
13066 generate_exception_end(ctx, EXCP_RI);
13067 return;
13070 if (astatic > 0) {
13071 DECR_AND_LOAD(7);
13072 if (astatic > 1) {
13073 DECR_AND_LOAD(6);
13074 if (astatic > 2) {
13075 DECR_AND_LOAD(5);
13076 if (astatic > 3) {
13077 DECR_AND_LOAD(4);
13082 #undef DECR_AND_LOAD
13084 tcg_gen_movi_tl(t2, framesize);
13085 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13086 tcg_temp_free(t0);
13087 tcg_temp_free(t1);
13088 tcg_temp_free(t2);
13091 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13092 int is_64_bit, int extended)
13094 TCGv t0;
13096 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13097 generate_exception_end(ctx, EXCP_RI);
13098 return;
13101 t0 = tcg_temp_new();
13103 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13104 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13105 if (!is_64_bit) {
13106 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13109 tcg_temp_free(t0);
13112 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13113 int16_t offset)
13115 TCGv_i32 t0 = tcg_const_i32(op);
13116 TCGv t1 = tcg_temp_new();
13117 gen_base_offset_addr(ctx, t1, base, offset);
13118 gen_helper_cache(cpu_env, t1, t0);
13121 #if defined(TARGET_MIPS64)
13122 static void decode_i64_mips16 (DisasContext *ctx,
13123 int ry, int funct, int16_t offset,
13124 int extended)
13126 switch (funct) {
13127 case I64_LDSP:
13128 check_insn(ctx, ISA_MIPS3);
13129 check_mips_64(ctx);
13130 offset = extended ? offset : offset << 3;
13131 gen_ld(ctx, OPC_LD, ry, 29, offset);
13132 break;
13133 case I64_SDSP:
13134 check_insn(ctx, ISA_MIPS3);
13135 check_mips_64(ctx);
13136 offset = extended ? offset : offset << 3;
13137 gen_st(ctx, OPC_SD, ry, 29, offset);
13138 break;
13139 case I64_SDRASP:
13140 check_insn(ctx, ISA_MIPS3);
13141 check_mips_64(ctx);
13142 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13143 gen_st(ctx, OPC_SD, 31, 29, offset);
13144 break;
13145 case I64_DADJSP:
13146 check_insn(ctx, ISA_MIPS3);
13147 check_mips_64(ctx);
13148 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13149 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13150 break;
13151 case I64_LDPC:
13152 check_insn(ctx, ISA_MIPS3);
13153 check_mips_64(ctx);
13154 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13155 generate_exception_end(ctx, EXCP_RI);
13156 } else {
13157 offset = extended ? offset : offset << 3;
13158 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13160 break;
13161 case I64_DADDIU5:
13162 check_insn(ctx, ISA_MIPS3);
13163 check_mips_64(ctx);
13164 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13165 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13166 break;
13167 case I64_DADDIUPC:
13168 check_insn(ctx, ISA_MIPS3);
13169 check_mips_64(ctx);
13170 offset = extended ? offset : offset << 2;
13171 gen_addiupc(ctx, ry, offset, 1, extended);
13172 break;
13173 case I64_DADDIUSP:
13174 check_insn(ctx, ISA_MIPS3);
13175 check_mips_64(ctx);
13176 offset = extended ? offset : offset << 2;
13177 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13178 break;
13181 #endif
13183 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13185 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13186 int op, rx, ry, funct, sa;
13187 int16_t imm, offset;
13189 ctx->opcode = (ctx->opcode << 16) | extend;
13190 op = (ctx->opcode >> 11) & 0x1f;
13191 sa = (ctx->opcode >> 22) & 0x1f;
13192 funct = (ctx->opcode >> 8) & 0x7;
13193 rx = xlat((ctx->opcode >> 8) & 0x7);
13194 ry = xlat((ctx->opcode >> 5) & 0x7);
13195 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13196 | ((ctx->opcode >> 21) & 0x3f) << 5
13197 | (ctx->opcode & 0x1f));
13199 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13200 counterparts. */
13201 switch (op) {
13202 case M16_OPC_ADDIUSP:
13203 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13204 break;
13205 case M16_OPC_ADDIUPC:
13206 gen_addiupc(ctx, rx, imm, 0, 1);
13207 break;
13208 case M16_OPC_B:
13209 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13210 /* No delay slot, so just process as a normal instruction */
13211 break;
13212 case M16_OPC_BEQZ:
13213 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13214 /* No delay slot, so just process as a normal instruction */
13215 break;
13216 case M16_OPC_BNEQZ:
13217 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13218 /* No delay slot, so just process as a normal instruction */
13219 break;
13220 case M16_OPC_SHIFT:
13221 switch (ctx->opcode & 0x3) {
13222 case 0x0:
13223 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13224 break;
13225 case 0x1:
13226 #if defined(TARGET_MIPS64)
13227 check_mips_64(ctx);
13228 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13229 #else
13230 generate_exception_end(ctx, EXCP_RI);
13231 #endif
13232 break;
13233 case 0x2:
13234 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13235 break;
13236 case 0x3:
13237 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13238 break;
13240 break;
13241 #if defined(TARGET_MIPS64)
13242 case M16_OPC_LD:
13243 check_insn(ctx, ISA_MIPS3);
13244 check_mips_64(ctx);
13245 gen_ld(ctx, OPC_LD, ry, rx, offset);
13246 break;
13247 #endif
13248 case M16_OPC_RRIA:
13249 imm = ctx->opcode & 0xf;
13250 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13251 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13252 imm = (int16_t) (imm << 1) >> 1;
13253 if ((ctx->opcode >> 4) & 0x1) {
13254 #if defined(TARGET_MIPS64)
13255 check_mips_64(ctx);
13256 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13257 #else
13258 generate_exception_end(ctx, EXCP_RI);
13259 #endif
13260 } else {
13261 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13263 break;
13264 case M16_OPC_ADDIU8:
13265 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13266 break;
13267 case M16_OPC_SLTI:
13268 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13269 break;
13270 case M16_OPC_SLTIU:
13271 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13272 break;
13273 case M16_OPC_I8:
13274 switch (funct) {
13275 case I8_BTEQZ:
13276 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13277 break;
13278 case I8_BTNEZ:
13279 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13280 break;
13281 case I8_SWRASP:
13282 gen_st(ctx, OPC_SW, 31, 29, imm);
13283 break;
13284 case I8_ADJSP:
13285 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13286 break;
13287 case I8_SVRS:
13288 check_insn(ctx, ISA_MIPS32);
13290 int xsregs = (ctx->opcode >> 24) & 0x7;
13291 int aregs = (ctx->opcode >> 16) & 0xf;
13292 int do_ra = (ctx->opcode >> 6) & 0x1;
13293 int do_s0 = (ctx->opcode >> 5) & 0x1;
13294 int do_s1 = (ctx->opcode >> 4) & 0x1;
13295 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13296 | (ctx->opcode & 0xf)) << 3;
13298 if (ctx->opcode & (1 << 7)) {
13299 gen_mips16_save(ctx, xsregs, aregs,
13300 do_ra, do_s0, do_s1,
13301 framesize);
13302 } else {
13303 gen_mips16_restore(ctx, xsregs, aregs,
13304 do_ra, do_s0, do_s1,
13305 framesize);
13308 break;
13309 default:
13310 generate_exception_end(ctx, EXCP_RI);
13311 break;
13313 break;
13314 case M16_OPC_LI:
13315 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13316 break;
13317 case M16_OPC_CMPI:
13318 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13319 break;
13320 #if defined(TARGET_MIPS64)
13321 case M16_OPC_SD:
13322 check_insn(ctx, ISA_MIPS3);
13323 check_mips_64(ctx);
13324 gen_st(ctx, OPC_SD, ry, rx, offset);
13325 break;
13326 #endif
13327 case M16_OPC_LB:
13328 gen_ld(ctx, OPC_LB, ry, rx, offset);
13329 break;
13330 case M16_OPC_LH:
13331 gen_ld(ctx, OPC_LH, ry, rx, offset);
13332 break;
13333 case M16_OPC_LWSP:
13334 gen_ld(ctx, OPC_LW, rx, 29, offset);
13335 break;
13336 case M16_OPC_LW:
13337 gen_ld(ctx, OPC_LW, ry, rx, offset);
13338 break;
13339 case M16_OPC_LBU:
13340 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13341 break;
13342 case M16_OPC_LHU:
13343 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13344 break;
13345 case M16_OPC_LWPC:
13346 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13347 break;
13348 #if defined(TARGET_MIPS64)
13349 case M16_OPC_LWU:
13350 check_insn(ctx, ISA_MIPS3);
13351 check_mips_64(ctx);
13352 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13353 break;
13354 #endif
13355 case M16_OPC_SB:
13356 gen_st(ctx, OPC_SB, ry, rx, offset);
13357 break;
13358 case M16_OPC_SH:
13359 gen_st(ctx, OPC_SH, ry, rx, offset);
13360 break;
13361 case M16_OPC_SWSP:
13362 gen_st(ctx, OPC_SW, rx, 29, offset);
13363 break;
13364 case M16_OPC_SW:
13365 gen_st(ctx, OPC_SW, ry, rx, offset);
13366 break;
13367 #if defined(TARGET_MIPS64)
13368 case M16_OPC_I64:
13369 decode_i64_mips16(ctx, ry, funct, offset, 1);
13370 break;
13371 #endif
13372 default:
13373 generate_exception_end(ctx, EXCP_RI);
13374 break;
13377 return 4;
13380 static inline bool is_uhi(int sdbbp_code)
13382 #ifdef CONFIG_USER_ONLY
13383 return false;
13384 #else
13385 return semihosting_enabled() && sdbbp_code == 1;
13386 #endif
13389 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13391 int rx, ry;
13392 int sa;
13393 int op, cnvt_op, op1, offset;
13394 int funct;
13395 int n_bytes;
13397 op = (ctx->opcode >> 11) & 0x1f;
13398 sa = (ctx->opcode >> 2) & 0x7;
13399 sa = sa == 0 ? 8 : sa;
13400 rx = xlat((ctx->opcode >> 8) & 0x7);
13401 cnvt_op = (ctx->opcode >> 5) & 0x7;
13402 ry = xlat((ctx->opcode >> 5) & 0x7);
13403 op1 = offset = ctx->opcode & 0x1f;
13405 n_bytes = 2;
13407 switch (op) {
13408 case M16_OPC_ADDIUSP:
13410 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13412 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13414 break;
13415 case M16_OPC_ADDIUPC:
13416 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13417 break;
13418 case M16_OPC_B:
13419 offset = (ctx->opcode & 0x7ff) << 1;
13420 offset = (int16_t)(offset << 4) >> 4;
13421 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13422 /* No delay slot, so just process as a normal instruction */
13423 break;
13424 case M16_OPC_JAL:
13425 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13426 offset = (((ctx->opcode & 0x1f) << 21)
13427 | ((ctx->opcode >> 5) & 0x1f) << 16
13428 | offset) << 2;
13429 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13430 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13431 n_bytes = 4;
13432 break;
13433 case M16_OPC_BEQZ:
13434 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13435 ((int8_t)ctx->opcode) << 1, 0);
13436 /* No delay slot, so just process as a normal instruction */
13437 break;
13438 case M16_OPC_BNEQZ:
13439 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13440 ((int8_t)ctx->opcode) << 1, 0);
13441 /* No delay slot, so just process as a normal instruction */
13442 break;
13443 case M16_OPC_SHIFT:
13444 switch (ctx->opcode & 0x3) {
13445 case 0x0:
13446 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13447 break;
13448 case 0x1:
13449 #if defined(TARGET_MIPS64)
13450 check_insn(ctx, ISA_MIPS3);
13451 check_mips_64(ctx);
13452 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13453 #else
13454 generate_exception_end(ctx, EXCP_RI);
13455 #endif
13456 break;
13457 case 0x2:
13458 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13459 break;
13460 case 0x3:
13461 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13462 break;
13464 break;
13465 #if defined(TARGET_MIPS64)
13466 case M16_OPC_LD:
13467 check_insn(ctx, ISA_MIPS3);
13468 check_mips_64(ctx);
13469 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13470 break;
13471 #endif
13472 case M16_OPC_RRIA:
13474 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13476 if ((ctx->opcode >> 4) & 1) {
13477 #if defined(TARGET_MIPS64)
13478 check_insn(ctx, ISA_MIPS3);
13479 check_mips_64(ctx);
13480 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13481 #else
13482 generate_exception_end(ctx, EXCP_RI);
13483 #endif
13484 } else {
13485 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13488 break;
13489 case M16_OPC_ADDIU8:
13491 int16_t imm = (int8_t) ctx->opcode;
13493 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13495 break;
13496 case M16_OPC_SLTI:
13498 int16_t imm = (uint8_t) ctx->opcode;
13499 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13501 break;
13502 case M16_OPC_SLTIU:
13504 int16_t imm = (uint8_t) ctx->opcode;
13505 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13507 break;
13508 case M16_OPC_I8:
13510 int reg32;
13512 funct = (ctx->opcode >> 8) & 0x7;
13513 switch (funct) {
13514 case I8_BTEQZ:
13515 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13516 ((int8_t)ctx->opcode) << 1, 0);
13517 break;
13518 case I8_BTNEZ:
13519 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13520 ((int8_t)ctx->opcode) << 1, 0);
13521 break;
13522 case I8_SWRASP:
13523 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13524 break;
13525 case I8_ADJSP:
13526 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13527 ((int8_t)ctx->opcode) << 3);
13528 break;
13529 case I8_SVRS:
13530 check_insn(ctx, ISA_MIPS32);
13532 int do_ra = ctx->opcode & (1 << 6);
13533 int do_s0 = ctx->opcode & (1 << 5);
13534 int do_s1 = ctx->opcode & (1 << 4);
13535 int framesize = ctx->opcode & 0xf;
13537 if (framesize == 0) {
13538 framesize = 128;
13539 } else {
13540 framesize = framesize << 3;
13543 if (ctx->opcode & (1 << 7)) {
13544 gen_mips16_save(ctx, 0, 0,
13545 do_ra, do_s0, do_s1, framesize);
13546 } else {
13547 gen_mips16_restore(ctx, 0, 0,
13548 do_ra, do_s0, do_s1, framesize);
13551 break;
13552 case I8_MOV32R:
13554 int rz = xlat(ctx->opcode & 0x7);
13556 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13557 ((ctx->opcode >> 5) & 0x7);
13558 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13560 break;
13561 case I8_MOVR32:
13562 reg32 = ctx->opcode & 0x1f;
13563 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13564 break;
13565 default:
13566 generate_exception_end(ctx, EXCP_RI);
13567 break;
13570 break;
13571 case M16_OPC_LI:
13573 int16_t imm = (uint8_t) ctx->opcode;
13575 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13577 break;
13578 case M16_OPC_CMPI:
13580 int16_t imm = (uint8_t) ctx->opcode;
13581 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13583 break;
13584 #if defined(TARGET_MIPS64)
13585 case M16_OPC_SD:
13586 check_insn(ctx, ISA_MIPS3);
13587 check_mips_64(ctx);
13588 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13589 break;
13590 #endif
13591 case M16_OPC_LB:
13592 gen_ld(ctx, OPC_LB, ry, rx, offset);
13593 break;
13594 case M16_OPC_LH:
13595 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13596 break;
13597 case M16_OPC_LWSP:
13598 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13599 break;
13600 case M16_OPC_LW:
13601 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13602 break;
13603 case M16_OPC_LBU:
13604 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13605 break;
13606 case M16_OPC_LHU:
13607 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13608 break;
13609 case M16_OPC_LWPC:
13610 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13611 break;
13612 #if defined (TARGET_MIPS64)
13613 case M16_OPC_LWU:
13614 check_insn(ctx, ISA_MIPS3);
13615 check_mips_64(ctx);
13616 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13617 break;
13618 #endif
13619 case M16_OPC_SB:
13620 gen_st(ctx, OPC_SB, ry, rx, offset);
13621 break;
13622 case M16_OPC_SH:
13623 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13624 break;
13625 case M16_OPC_SWSP:
13626 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13627 break;
13628 case M16_OPC_SW:
13629 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13630 break;
13631 case M16_OPC_RRR:
13633 int rz = xlat((ctx->opcode >> 2) & 0x7);
13634 int mips32_op;
13636 switch (ctx->opcode & 0x3) {
13637 case RRR_ADDU:
13638 mips32_op = OPC_ADDU;
13639 break;
13640 case RRR_SUBU:
13641 mips32_op = OPC_SUBU;
13642 break;
13643 #if defined(TARGET_MIPS64)
13644 case RRR_DADDU:
13645 mips32_op = OPC_DADDU;
13646 check_insn(ctx, ISA_MIPS3);
13647 check_mips_64(ctx);
13648 break;
13649 case RRR_DSUBU:
13650 mips32_op = OPC_DSUBU;
13651 check_insn(ctx, ISA_MIPS3);
13652 check_mips_64(ctx);
13653 break;
13654 #endif
13655 default:
13656 generate_exception_end(ctx, EXCP_RI);
13657 goto done;
13660 gen_arith(ctx, mips32_op, rz, rx, ry);
13661 done:
13664 break;
13665 case M16_OPC_RR:
13666 switch (op1) {
13667 case RR_JR:
13669 int nd = (ctx->opcode >> 7) & 0x1;
13670 int link = (ctx->opcode >> 6) & 0x1;
13671 int ra = (ctx->opcode >> 5) & 0x1;
13673 if (nd) {
13674 check_insn(ctx, ISA_MIPS32);
13677 if (link) {
13678 op = OPC_JALR;
13679 } else {
13680 op = OPC_JR;
13683 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13684 (nd ? 0 : 2));
13686 break;
13687 case RR_SDBBP:
13688 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13689 gen_helper_do_semihosting(cpu_env);
13690 } else {
13691 /* XXX: not clear which exception should be raised
13692 * when in debug mode...
13694 check_insn(ctx, ISA_MIPS32);
13695 generate_exception_end(ctx, EXCP_DBp);
13697 break;
13698 case RR_SLT:
13699 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13700 break;
13701 case RR_SLTU:
13702 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13703 break;
13704 case RR_BREAK:
13705 generate_exception_end(ctx, EXCP_BREAK);
13706 break;
13707 case RR_SLLV:
13708 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13709 break;
13710 case RR_SRLV:
13711 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13712 break;
13713 case RR_SRAV:
13714 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13715 break;
13716 #if defined (TARGET_MIPS64)
13717 case RR_DSRL:
13718 check_insn(ctx, ISA_MIPS3);
13719 check_mips_64(ctx);
13720 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13721 break;
13722 #endif
13723 case RR_CMP:
13724 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13725 break;
13726 case RR_NEG:
13727 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13728 break;
13729 case RR_AND:
13730 gen_logic(ctx, OPC_AND, rx, rx, ry);
13731 break;
13732 case RR_OR:
13733 gen_logic(ctx, OPC_OR, rx, rx, ry);
13734 break;
13735 case RR_XOR:
13736 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13737 break;
13738 case RR_NOT:
13739 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13740 break;
13741 case RR_MFHI:
13742 gen_HILO(ctx, OPC_MFHI, 0, rx);
13743 break;
13744 case RR_CNVT:
13745 check_insn(ctx, ISA_MIPS32);
13746 switch (cnvt_op) {
13747 case RR_RY_CNVT_ZEB:
13748 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13749 break;
13750 case RR_RY_CNVT_ZEH:
13751 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13752 break;
13753 case RR_RY_CNVT_SEB:
13754 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13755 break;
13756 case RR_RY_CNVT_SEH:
13757 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13758 break;
13759 #if defined (TARGET_MIPS64)
13760 case RR_RY_CNVT_ZEW:
13761 check_insn(ctx, ISA_MIPS64);
13762 check_mips_64(ctx);
13763 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13764 break;
13765 case RR_RY_CNVT_SEW:
13766 check_insn(ctx, ISA_MIPS64);
13767 check_mips_64(ctx);
13768 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13769 break;
13770 #endif
13771 default:
13772 generate_exception_end(ctx, EXCP_RI);
13773 break;
13775 break;
13776 case RR_MFLO:
13777 gen_HILO(ctx, OPC_MFLO, 0, rx);
13778 break;
13779 #if defined (TARGET_MIPS64)
13780 case RR_DSRA:
13781 check_insn(ctx, ISA_MIPS3);
13782 check_mips_64(ctx);
13783 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13784 break;
13785 case RR_DSLLV:
13786 check_insn(ctx, ISA_MIPS3);
13787 check_mips_64(ctx);
13788 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13789 break;
13790 case RR_DSRLV:
13791 check_insn(ctx, ISA_MIPS3);
13792 check_mips_64(ctx);
13793 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13794 break;
13795 case RR_DSRAV:
13796 check_insn(ctx, ISA_MIPS3);
13797 check_mips_64(ctx);
13798 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13799 break;
13800 #endif
13801 case RR_MULT:
13802 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13803 break;
13804 case RR_MULTU:
13805 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13806 break;
13807 case RR_DIV:
13808 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13809 break;
13810 case RR_DIVU:
13811 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13812 break;
13813 #if defined (TARGET_MIPS64)
13814 case RR_DMULT:
13815 check_insn(ctx, ISA_MIPS3);
13816 check_mips_64(ctx);
13817 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13818 break;
13819 case RR_DMULTU:
13820 check_insn(ctx, ISA_MIPS3);
13821 check_mips_64(ctx);
13822 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13823 break;
13824 case RR_DDIV:
13825 check_insn(ctx, ISA_MIPS3);
13826 check_mips_64(ctx);
13827 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13828 break;
13829 case RR_DDIVU:
13830 check_insn(ctx, ISA_MIPS3);
13831 check_mips_64(ctx);
13832 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13833 break;
13834 #endif
13835 default:
13836 generate_exception_end(ctx, EXCP_RI);
13837 break;
13839 break;
13840 case M16_OPC_EXTEND:
13841 decode_extended_mips16_opc(env, ctx);
13842 n_bytes = 4;
13843 break;
13844 #if defined(TARGET_MIPS64)
13845 case M16_OPC_I64:
13846 funct = (ctx->opcode >> 8) & 0x7;
13847 decode_i64_mips16(ctx, ry, funct, offset, 0);
13848 break;
13849 #endif
13850 default:
13851 generate_exception_end(ctx, EXCP_RI);
13852 break;
13855 return n_bytes;
13858 /* microMIPS extension to MIPS32/MIPS64 */
13861 * microMIPS32/microMIPS64 major opcodes
13863 * 1. MIPS Architecture for Programmers Volume II-B:
13864 * The microMIPS32 Instruction Set (Revision 3.05)
13866 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13868 * 2. MIPS Architecture For Programmers Volume II-A:
13869 * The MIPS64 Instruction Set (Revision 3.51)
13872 enum {
13873 POOL32A = 0x00,
13874 POOL16A = 0x01,
13875 LBU16 = 0x02,
13876 MOVE16 = 0x03,
13877 ADDI32 = 0x04,
13878 R6_LUI = 0x04,
13879 AUI = 0x04,
13880 LBU32 = 0x05,
13881 SB32 = 0x06,
13882 LB32 = 0x07,
13884 POOL32B = 0x08,
13885 POOL16B = 0x09,
13886 LHU16 = 0x0a,
13887 ANDI16 = 0x0b,
13888 ADDIU32 = 0x0c,
13889 LHU32 = 0x0d,
13890 SH32 = 0x0e,
13891 LH32 = 0x0f,
13893 POOL32I = 0x10,
13894 POOL16C = 0x11,
13895 LWSP16 = 0x12,
13896 POOL16D = 0x13,
13897 ORI32 = 0x14,
13898 POOL32F = 0x15,
13899 POOL32S = 0x16, /* MIPS64 */
13900 DADDIU32 = 0x17, /* MIPS64 */
13902 POOL32C = 0x18,
13903 LWGP16 = 0x19,
13904 LW16 = 0x1a,
13905 POOL16E = 0x1b,
13906 XORI32 = 0x1c,
13907 JALS32 = 0x1d,
13908 BOVC = 0x1d,
13909 BEQC = 0x1d,
13910 BEQZALC = 0x1d,
13911 ADDIUPC = 0x1e,
13912 PCREL = 0x1e,
13913 BNVC = 0x1f,
13914 BNEC = 0x1f,
13915 BNEZALC = 0x1f,
13917 R6_BEQZC = 0x20,
13918 JIC = 0x20,
13919 POOL16F = 0x21,
13920 SB16 = 0x22,
13921 BEQZ16 = 0x23,
13922 BEQZC16 = 0x23,
13923 SLTI32 = 0x24,
13924 BEQ32 = 0x25,
13925 BC = 0x25,
13926 SWC132 = 0x26,
13927 LWC132 = 0x27,
13929 /* 0x29 is reserved */
13930 RES_29 = 0x29,
13931 R6_BNEZC = 0x28,
13932 JIALC = 0x28,
13933 SH16 = 0x2a,
13934 BNEZ16 = 0x2b,
13935 BNEZC16 = 0x2b,
13936 SLTIU32 = 0x2c,
13937 BNE32 = 0x2d,
13938 BALC = 0x2d,
13939 SDC132 = 0x2e,
13940 LDC132 = 0x2f,
13942 /* 0x31 is reserved */
13943 RES_31 = 0x31,
13944 BLEZALC = 0x30,
13945 BGEZALC = 0x30,
13946 BGEUC = 0x30,
13947 SWSP16 = 0x32,
13948 B16 = 0x33,
13949 BC16 = 0x33,
13950 ANDI32 = 0x34,
13951 J32 = 0x35,
13952 BGTZC = 0x35,
13953 BLTZC = 0x35,
13954 BLTC = 0x35,
13955 SD32 = 0x36, /* MIPS64 */
13956 LD32 = 0x37, /* MIPS64 */
13958 /* 0x39 is reserved */
13959 RES_39 = 0x39,
13960 BGTZALC = 0x38,
13961 BLTZALC = 0x38,
13962 BLTUC = 0x38,
13963 SW16 = 0x3a,
13964 LI16 = 0x3b,
13965 JALX32 = 0x3c,
13966 JAL32 = 0x3d,
13967 BLEZC = 0x3d,
13968 BGEZC = 0x3d,
13969 BGEC = 0x3d,
13970 SW32 = 0x3e,
13971 LW32 = 0x3f
13974 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13975 enum {
13976 ADDIUPC_00 = 0x00,
13977 ADDIUPC_01 = 0x01,
13978 ADDIUPC_02 = 0x02,
13979 ADDIUPC_03 = 0x03,
13980 ADDIUPC_04 = 0x04,
13981 ADDIUPC_05 = 0x05,
13982 ADDIUPC_06 = 0x06,
13983 ADDIUPC_07 = 0x07,
13984 AUIPC = 0x1e,
13985 ALUIPC = 0x1f,
13986 LWPC_08 = 0x08,
13987 LWPC_09 = 0x09,
13988 LWPC_0A = 0x0A,
13989 LWPC_0B = 0x0B,
13990 LWPC_0C = 0x0C,
13991 LWPC_0D = 0x0D,
13992 LWPC_0E = 0x0E,
13993 LWPC_0F = 0x0F,
13996 /* POOL32A encoding of minor opcode field */
13998 enum {
13999 /* These opcodes are distinguished only by bits 9..6; those bits are
14000 * what are recorded below. */
14001 SLL32 = 0x0,
14002 SRL32 = 0x1,
14003 SRA = 0x2,
14004 ROTR = 0x3,
14005 SELEQZ = 0x5,
14006 SELNEZ = 0x6,
14007 R6_RDHWR = 0x7,
14009 SLLV = 0x0,
14010 SRLV = 0x1,
14011 SRAV = 0x2,
14012 ROTRV = 0x3,
14013 ADD = 0x4,
14014 ADDU32 = 0x5,
14015 SUB = 0x6,
14016 SUBU32 = 0x7,
14017 MUL = 0x8,
14018 AND = 0x9,
14019 OR32 = 0xa,
14020 NOR = 0xb,
14021 XOR32 = 0xc,
14022 SLT = 0xd,
14023 SLTU = 0xe,
14025 MOVN = 0x0,
14026 R6_MUL = 0x0,
14027 MOVZ = 0x1,
14028 MUH = 0x1,
14029 MULU = 0x2,
14030 MUHU = 0x3,
14031 LWXS = 0x4,
14032 R6_DIV = 0x4,
14033 MOD = 0x5,
14034 R6_DIVU = 0x6,
14035 MODU = 0x7,
14037 /* The following can be distinguished by their lower 6 bits. */
14038 BREAK32 = 0x07,
14039 INS = 0x0c,
14040 LSA = 0x0f,
14041 ALIGN = 0x1f,
14042 EXT = 0x2c,
14043 POOL32AXF = 0x3c,
14044 SIGRIE = 0x3f
14047 /* POOL32AXF encoding of minor opcode field extension */
14050 * 1. MIPS Architecture for Programmers Volume II-B:
14051 * The microMIPS32 Instruction Set (Revision 3.05)
14053 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14055 * 2. MIPS Architecture for Programmers VolumeIV-e:
14056 * The MIPS DSP Application-Specific Extension
14057 * to the microMIPS32 Architecture (Revision 2.34)
14059 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14062 enum {
14063 /* bits 11..6 */
14064 TEQ = 0x00,
14065 TGE = 0x08,
14066 TGEU = 0x10,
14067 TLT = 0x20,
14068 TLTU = 0x28,
14069 TNE = 0x30,
14071 MFC0 = 0x03,
14072 MTC0 = 0x0b,
14074 /* begin of microMIPS32 DSP */
14076 /* bits 13..12 for 0x01 */
14077 MFHI_ACC = 0x0,
14078 MFLO_ACC = 0x1,
14079 MTHI_ACC = 0x2,
14080 MTLO_ACC = 0x3,
14082 /* bits 13..12 for 0x2a */
14083 MADD_ACC = 0x0,
14084 MADDU_ACC = 0x1,
14085 MSUB_ACC = 0x2,
14086 MSUBU_ACC = 0x3,
14088 /* bits 13..12 for 0x32 */
14089 MULT_ACC = 0x0,
14090 MULTU_ACC = 0x1,
14092 /* end of microMIPS32 DSP */
14094 /* bits 15..12 for 0x2c */
14095 BITSWAP = 0x0,
14096 SEB = 0x2,
14097 SEH = 0x3,
14098 CLO = 0x4,
14099 CLZ = 0x5,
14100 RDHWR = 0x6,
14101 WSBH = 0x7,
14102 MULT = 0x8,
14103 MULTU = 0x9,
14104 DIV = 0xa,
14105 DIVU = 0xb,
14106 MADD = 0xc,
14107 MADDU = 0xd,
14108 MSUB = 0xe,
14109 MSUBU = 0xf,
14111 /* bits 15..12 for 0x34 */
14112 MFC2 = 0x4,
14113 MTC2 = 0x5,
14114 MFHC2 = 0x8,
14115 MTHC2 = 0x9,
14116 CFC2 = 0xc,
14117 CTC2 = 0xd,
14119 /* bits 15..12 for 0x3c */
14120 JALR = 0x0,
14121 JR = 0x0, /* alias */
14122 JALRC = 0x0,
14123 JRC = 0x0,
14124 JALR_HB = 0x1,
14125 JALRC_HB = 0x1,
14126 JALRS = 0x4,
14127 JALRS_HB = 0x5,
14129 /* bits 15..12 for 0x05 */
14130 RDPGPR = 0xe,
14131 WRPGPR = 0xf,
14133 /* bits 15..12 for 0x0d */
14134 TLBP = 0x0,
14135 TLBR = 0x1,
14136 TLBWI = 0x2,
14137 TLBWR = 0x3,
14138 TLBINV = 0x4,
14139 TLBINVF = 0x5,
14140 WAIT = 0x9,
14141 IRET = 0xd,
14142 DERET = 0xe,
14143 ERET = 0xf,
14145 /* bits 15..12 for 0x15 */
14146 DMT = 0x0,
14147 DVPE = 0x1,
14148 EMT = 0x2,
14149 EVPE = 0x3,
14151 /* bits 15..12 for 0x1d */
14152 DI = 0x4,
14153 EI = 0x5,
14155 /* bits 15..12 for 0x2d */
14156 SYNC = 0x6,
14157 SYSCALL = 0x8,
14158 SDBBP = 0xd,
14160 /* bits 15..12 for 0x35 */
14161 MFHI32 = 0x0,
14162 MFLO32 = 0x1,
14163 MTHI32 = 0x2,
14164 MTLO32 = 0x3,
14167 /* POOL32B encoding of minor opcode field (bits 15..12) */
14169 enum {
14170 LWC2 = 0x0,
14171 LWP = 0x1,
14172 LDP = 0x4,
14173 LWM32 = 0x5,
14174 CACHE = 0x6,
14175 LDM = 0x7,
14176 SWC2 = 0x8,
14177 SWP = 0x9,
14178 SDP = 0xc,
14179 SWM32 = 0xd,
14180 SDM = 0xf
14183 /* POOL32C encoding of minor opcode field (bits 15..12) */
14185 enum {
14186 LWL = 0x0,
14187 SWL = 0x8,
14188 LWR = 0x1,
14189 SWR = 0x9,
14190 PREF = 0x2,
14191 ST_EVA = 0xa,
14192 LL = 0x3,
14193 SC = 0xb,
14194 LDL = 0x4,
14195 SDL = 0xc,
14196 LDR = 0x5,
14197 SDR = 0xd,
14198 LD_EVA = 0x6,
14199 LWU = 0xe,
14200 LLD = 0x7,
14201 SCD = 0xf
14204 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14206 enum {
14207 LBUE = 0x0,
14208 LHUE = 0x1,
14209 LWLE = 0x2,
14210 LWRE = 0x3,
14211 LBE = 0x4,
14212 LHE = 0x5,
14213 LLE = 0x6,
14214 LWE = 0x7,
14217 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14219 enum {
14220 SWLE = 0x0,
14221 SWRE = 0x1,
14222 PREFE = 0x2,
14223 CACHEE = 0x3,
14224 SBE = 0x4,
14225 SHE = 0x5,
14226 SCE = 0x6,
14227 SWE = 0x7,
14230 /* POOL32F encoding of minor opcode field (bits 5..0) */
14232 enum {
14233 /* These are the bit 7..6 values */
14234 ADD_FMT = 0x0,
14236 SUB_FMT = 0x1,
14238 MUL_FMT = 0x2,
14240 DIV_FMT = 0x3,
14242 /* These are the bit 8..6 values */
14243 MOVN_FMT = 0x0,
14244 RSQRT2_FMT = 0x0,
14245 MOVF_FMT = 0x0,
14246 RINT_FMT = 0x0,
14247 SELNEZ_FMT = 0x0,
14249 MOVZ_FMT = 0x1,
14250 LWXC1 = 0x1,
14251 MOVT_FMT = 0x1,
14252 CLASS_FMT = 0x1,
14253 SELEQZ_FMT = 0x1,
14255 PLL_PS = 0x2,
14256 SWXC1 = 0x2,
14257 SEL_FMT = 0x2,
14259 PLU_PS = 0x3,
14260 LDXC1 = 0x3,
14262 MOVN_FMT_04 = 0x4,
14263 PUL_PS = 0x4,
14264 SDXC1 = 0x4,
14265 RECIP2_FMT = 0x4,
14267 MOVZ_FMT_05 = 0x05,
14268 PUU_PS = 0x5,
14269 LUXC1 = 0x5,
14271 CVT_PS_S = 0x6,
14272 SUXC1 = 0x6,
14273 ADDR_PS = 0x6,
14274 PREFX = 0x6,
14275 MADDF_FMT = 0x6,
14277 MULR_PS = 0x7,
14278 MSUBF_FMT = 0x7,
14280 MADD_S = 0x01,
14281 MADD_D = 0x09,
14282 MADD_PS = 0x11,
14283 ALNV_PS = 0x19,
14284 MSUB_S = 0x21,
14285 MSUB_D = 0x29,
14286 MSUB_PS = 0x31,
14288 NMADD_S = 0x02,
14289 NMADD_D = 0x0a,
14290 NMADD_PS = 0x12,
14291 NMSUB_S = 0x22,
14292 NMSUB_D = 0x2a,
14293 NMSUB_PS = 0x32,
14295 MIN_FMT = 0x3,
14296 MAX_FMT = 0xb,
14297 MINA_FMT = 0x23,
14298 MAXA_FMT = 0x2b,
14299 POOL32FXF = 0x3b,
14301 CABS_COND_FMT = 0x1c, /* MIPS3D */
14302 C_COND_FMT = 0x3c,
14304 CMP_CONDN_S = 0x5,
14305 CMP_CONDN_D = 0x15
14308 /* POOL32Fxf encoding of minor opcode extension field */
14310 enum {
14311 CVT_L = 0x04,
14312 RSQRT_FMT = 0x08,
14313 FLOOR_L = 0x0c,
14314 CVT_PW_PS = 0x1c,
14315 CVT_W = 0x24,
14316 SQRT_FMT = 0x28,
14317 FLOOR_W = 0x2c,
14318 CVT_PS_PW = 0x3c,
14319 CFC1 = 0x40,
14320 RECIP_FMT = 0x48,
14321 CEIL_L = 0x4c,
14322 CTC1 = 0x60,
14323 CEIL_W = 0x6c,
14324 MFC1 = 0x80,
14325 CVT_S_PL = 0x84,
14326 TRUNC_L = 0x8c,
14327 MTC1 = 0xa0,
14328 CVT_S_PU = 0xa4,
14329 TRUNC_W = 0xac,
14330 MFHC1 = 0xc0,
14331 ROUND_L = 0xcc,
14332 MTHC1 = 0xe0,
14333 ROUND_W = 0xec,
14335 MOV_FMT = 0x01,
14336 MOVF = 0x05,
14337 ABS_FMT = 0x0d,
14338 RSQRT1_FMT = 0x1d,
14339 MOVT = 0x25,
14340 NEG_FMT = 0x2d,
14341 CVT_D = 0x4d,
14342 RECIP1_FMT = 0x5d,
14343 CVT_S = 0x6d
14346 /* POOL32I encoding of minor opcode field (bits 25..21) */
14348 enum {
14349 BLTZ = 0x00,
14350 BLTZAL = 0x01,
14351 BGEZ = 0x02,
14352 BGEZAL = 0x03,
14353 BLEZ = 0x04,
14354 BNEZC = 0x05,
14355 BGTZ = 0x06,
14356 BEQZC = 0x07,
14357 TLTI = 0x08,
14358 BC1EQZC = 0x08,
14359 TGEI = 0x09,
14360 BC1NEZC = 0x09,
14361 TLTIU = 0x0a,
14362 BC2EQZC = 0x0a,
14363 TGEIU = 0x0b,
14364 BC2NEZC = 0x0a,
14365 TNEI = 0x0c,
14366 R6_SYNCI = 0x0c,
14367 LUI = 0x0d,
14368 TEQI = 0x0e,
14369 SYNCI = 0x10,
14370 BLTZALS = 0x11,
14371 BGEZALS = 0x13,
14372 BC2F = 0x14,
14373 BC2T = 0x15,
14374 BPOSGE64 = 0x1a,
14375 BPOSGE32 = 0x1b,
14376 /* These overlap and are distinguished by bit16 of the instruction */
14377 BC1F = 0x1c,
14378 BC1T = 0x1d,
14379 BC1ANY2F = 0x1c,
14380 BC1ANY2T = 0x1d,
14381 BC1ANY4F = 0x1e,
14382 BC1ANY4T = 0x1f
14385 /* POOL16A encoding of minor opcode field */
14387 enum {
14388 ADDU16 = 0x0,
14389 SUBU16 = 0x1
14392 /* POOL16B encoding of minor opcode field */
14394 enum {
14395 SLL16 = 0x0,
14396 SRL16 = 0x1
14399 /* POOL16C encoding of minor opcode field */
14401 enum {
14402 NOT16 = 0x00,
14403 XOR16 = 0x04,
14404 AND16 = 0x08,
14405 OR16 = 0x0c,
14406 LWM16 = 0x10,
14407 SWM16 = 0x14,
14408 JR16 = 0x18,
14409 JRC16 = 0x1a,
14410 JALR16 = 0x1c,
14411 JALR16S = 0x1e,
14412 MFHI16 = 0x20,
14413 MFLO16 = 0x24,
14414 BREAK16 = 0x28,
14415 SDBBP16 = 0x2c,
14416 JRADDIUSP = 0x30
14419 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14421 enum {
14422 R6_NOT16 = 0x00,
14423 R6_AND16 = 0x01,
14424 R6_LWM16 = 0x02,
14425 R6_JRC16 = 0x03,
14426 MOVEP = 0x04,
14427 MOVEP_05 = 0x05,
14428 MOVEP_06 = 0x06,
14429 MOVEP_07 = 0x07,
14430 R6_XOR16 = 0x08,
14431 R6_OR16 = 0x09,
14432 R6_SWM16 = 0x0a,
14433 JALRC16 = 0x0b,
14434 MOVEP_0C = 0x0c,
14435 MOVEP_0D = 0x0d,
14436 MOVEP_0E = 0x0e,
14437 MOVEP_0F = 0x0f,
14438 JRCADDIUSP = 0x13,
14439 R6_BREAK16 = 0x1b,
14440 R6_SDBBP16 = 0x3b
14443 /* POOL16D encoding of minor opcode field */
14445 enum {
14446 ADDIUS5 = 0x0,
14447 ADDIUSP = 0x1
14450 /* POOL16E encoding of minor opcode field */
14452 enum {
14453 ADDIUR2 = 0x0,
14454 ADDIUR1SP = 0x1
14457 static int mmreg (int r)
14459 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14461 return map[r];
14464 /* Used for 16-bit store instructions. */
14465 static int mmreg2 (int r)
14467 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14469 return map[r];
14472 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14473 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14474 #define uMIPS_RS2(op) uMIPS_RS(op)
14475 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14476 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14477 #define uMIPS_RS5(op) (op & 0x1f)
14479 /* Signed immediate */
14480 #define SIMM(op, start, width) \
14481 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14482 << (32-width)) \
14483 >> (32-width))
14484 /* Zero-extended immediate */
14485 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14487 static void gen_addiur1sp(DisasContext *ctx)
14489 int rd = mmreg(uMIPS_RD(ctx->opcode));
14491 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14494 static void gen_addiur2(DisasContext *ctx)
14496 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14497 int rd = mmreg(uMIPS_RD(ctx->opcode));
14498 int rs = mmreg(uMIPS_RS(ctx->opcode));
14500 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14503 static void gen_addiusp(DisasContext *ctx)
14505 int encoded = ZIMM(ctx->opcode, 1, 9);
14506 int decoded;
14508 if (encoded <= 1) {
14509 decoded = 256 + encoded;
14510 } else if (encoded <= 255) {
14511 decoded = encoded;
14512 } else if (encoded <= 509) {
14513 decoded = encoded - 512;
14514 } else {
14515 decoded = encoded - 768;
14518 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14521 static void gen_addius5(DisasContext *ctx)
14523 int imm = SIMM(ctx->opcode, 1, 4);
14524 int rd = (ctx->opcode >> 5) & 0x1f;
14526 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14529 static void gen_andi16(DisasContext *ctx)
14531 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14532 31, 32, 63, 64, 255, 32768, 65535 };
14533 int rd = mmreg(uMIPS_RD(ctx->opcode));
14534 int rs = mmreg(uMIPS_RS(ctx->opcode));
14535 int encoded = ZIMM(ctx->opcode, 0, 4);
14537 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14540 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14541 int base, int16_t offset)
14543 TCGv t0, t1;
14544 TCGv_i32 t2;
14546 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14547 generate_exception_end(ctx, EXCP_RI);
14548 return;
14551 t0 = tcg_temp_new();
14553 gen_base_offset_addr(ctx, t0, base, offset);
14555 t1 = tcg_const_tl(reglist);
14556 t2 = tcg_const_i32(ctx->mem_idx);
14558 save_cpu_state(ctx, 1);
14559 switch (opc) {
14560 case LWM32:
14561 gen_helper_lwm(cpu_env, t0, t1, t2);
14562 break;
14563 case SWM32:
14564 gen_helper_swm(cpu_env, t0, t1, t2);
14565 break;
14566 #ifdef TARGET_MIPS64
14567 case LDM:
14568 gen_helper_ldm(cpu_env, t0, t1, t2);
14569 break;
14570 case SDM:
14571 gen_helper_sdm(cpu_env, t0, t1, t2);
14572 break;
14573 #endif
14575 tcg_temp_free(t0);
14576 tcg_temp_free(t1);
14577 tcg_temp_free_i32(t2);
14581 static void gen_pool16c_insn(DisasContext *ctx)
14583 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14584 int rs = mmreg(ctx->opcode & 0x7);
14586 switch (((ctx->opcode) >> 4) & 0x3f) {
14587 case NOT16 + 0:
14588 case NOT16 + 1:
14589 case NOT16 + 2:
14590 case NOT16 + 3:
14591 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14592 break;
14593 case XOR16 + 0:
14594 case XOR16 + 1:
14595 case XOR16 + 2:
14596 case XOR16 + 3:
14597 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14598 break;
14599 case AND16 + 0:
14600 case AND16 + 1:
14601 case AND16 + 2:
14602 case AND16 + 3:
14603 gen_logic(ctx, OPC_AND, rd, rd, rs);
14604 break;
14605 case OR16 + 0:
14606 case OR16 + 1:
14607 case OR16 + 2:
14608 case OR16 + 3:
14609 gen_logic(ctx, OPC_OR, rd, rd, rs);
14610 break;
14611 case LWM16 + 0:
14612 case LWM16 + 1:
14613 case LWM16 + 2:
14614 case LWM16 + 3:
14616 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14617 int offset = ZIMM(ctx->opcode, 0, 4);
14619 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14620 29, offset << 2);
14622 break;
14623 case SWM16 + 0:
14624 case SWM16 + 1:
14625 case SWM16 + 2:
14626 case SWM16 + 3:
14628 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14629 int offset = ZIMM(ctx->opcode, 0, 4);
14631 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14632 29, offset << 2);
14634 break;
14635 case JR16 + 0:
14636 case JR16 + 1:
14638 int reg = ctx->opcode & 0x1f;
14640 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14642 break;
14643 case JRC16 + 0:
14644 case JRC16 + 1:
14646 int reg = ctx->opcode & 0x1f;
14647 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14648 /* Let normal delay slot handling in our caller take us
14649 to the branch target. */
14651 break;
14652 case JALR16 + 0:
14653 case JALR16 + 1:
14654 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14655 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14656 break;
14657 case JALR16S + 0:
14658 case JALR16S + 1:
14659 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14660 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14661 break;
14662 case MFHI16 + 0:
14663 case MFHI16 + 1:
14664 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14665 break;
14666 case MFLO16 + 0:
14667 case MFLO16 + 1:
14668 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14669 break;
14670 case BREAK16:
14671 generate_exception_end(ctx, EXCP_BREAK);
14672 break;
14673 case SDBBP16:
14674 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14675 gen_helper_do_semihosting(cpu_env);
14676 } else {
14677 /* XXX: not clear which exception should be raised
14678 * when in debug mode...
14680 check_insn(ctx, ISA_MIPS32);
14681 generate_exception_end(ctx, EXCP_DBp);
14683 break;
14684 case JRADDIUSP + 0:
14685 case JRADDIUSP + 1:
14687 int imm = ZIMM(ctx->opcode, 0, 5);
14688 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14689 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14690 /* Let normal delay slot handling in our caller take us
14691 to the branch target. */
14693 break;
14694 default:
14695 generate_exception_end(ctx, EXCP_RI);
14696 break;
14700 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14701 int enc_rs)
14703 int rd, rs, re, rt;
14704 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14705 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14706 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14707 rd = rd_enc[enc_dest];
14708 re = re_enc[enc_dest];
14709 rs = rs_rt_enc[enc_rs];
14710 rt = rs_rt_enc[enc_rt];
14711 if (rs) {
14712 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14713 } else {
14714 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14716 if (rt) {
14717 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14718 } else {
14719 tcg_gen_movi_tl(cpu_gpr[re], 0);
14723 static void gen_pool16c_r6_insn(DisasContext *ctx)
14725 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14726 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14728 switch (ctx->opcode & 0xf) {
14729 case R6_NOT16:
14730 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14731 break;
14732 case R6_AND16:
14733 gen_logic(ctx, OPC_AND, rt, rt, rs);
14734 break;
14735 case R6_LWM16:
14737 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14738 int offset = extract32(ctx->opcode, 4, 4);
14739 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14741 break;
14742 case R6_JRC16: /* JRCADDIUSP */
14743 if ((ctx->opcode >> 4) & 1) {
14744 /* JRCADDIUSP */
14745 int imm = extract32(ctx->opcode, 5, 5);
14746 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14747 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14748 } else {
14749 /* JRC16 */
14750 rs = extract32(ctx->opcode, 5, 5);
14751 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14753 break;
14754 case MOVEP:
14755 case MOVEP_05:
14756 case MOVEP_06:
14757 case MOVEP_07:
14758 case MOVEP_0C:
14759 case MOVEP_0D:
14760 case MOVEP_0E:
14761 case MOVEP_0F:
14763 int enc_dest = uMIPS_RD(ctx->opcode);
14764 int enc_rt = uMIPS_RS2(ctx->opcode);
14765 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14766 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14768 break;
14769 case R6_XOR16:
14770 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14771 break;
14772 case R6_OR16:
14773 gen_logic(ctx, OPC_OR, rt, rt, rs);
14774 break;
14775 case R6_SWM16:
14777 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14778 int offset = extract32(ctx->opcode, 4, 4);
14779 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14781 break;
14782 case JALRC16: /* BREAK16, SDBBP16 */
14783 switch (ctx->opcode & 0x3f) {
14784 case JALRC16:
14785 case JALRC16 + 0x20:
14786 /* JALRC16 */
14787 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14788 31, 0, 0);
14789 break;
14790 case R6_BREAK16:
14791 /* BREAK16 */
14792 generate_exception(ctx, EXCP_BREAK);
14793 break;
14794 case R6_SDBBP16:
14795 /* SDBBP16 */
14796 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14797 gen_helper_do_semihosting(cpu_env);
14798 } else {
14799 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14800 generate_exception(ctx, EXCP_RI);
14801 } else {
14802 generate_exception(ctx, EXCP_DBp);
14805 break;
14807 break;
14808 default:
14809 generate_exception(ctx, EXCP_RI);
14810 break;
14814 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14816 TCGv t0 = tcg_temp_new();
14817 TCGv t1 = tcg_temp_new();
14819 gen_load_gpr(t0, base);
14821 if (index != 0) {
14822 gen_load_gpr(t1, index);
14823 tcg_gen_shli_tl(t1, t1, 2);
14824 gen_op_addr_add(ctx, t0, t1, t0);
14827 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14828 gen_store_gpr(t1, rd);
14830 tcg_temp_free(t0);
14831 tcg_temp_free(t1);
14834 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14835 int base, int16_t offset)
14837 TCGv t0, t1;
14839 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14840 generate_exception_end(ctx, EXCP_RI);
14841 return;
14844 t0 = tcg_temp_new();
14845 t1 = tcg_temp_new();
14847 gen_base_offset_addr(ctx, t0, base, offset);
14849 switch (opc) {
14850 case LWP:
14851 if (rd == base) {
14852 generate_exception_end(ctx, EXCP_RI);
14853 return;
14855 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14856 gen_store_gpr(t1, rd);
14857 tcg_gen_movi_tl(t1, 4);
14858 gen_op_addr_add(ctx, t0, t0, t1);
14859 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14860 gen_store_gpr(t1, rd+1);
14861 break;
14862 case SWP:
14863 gen_load_gpr(t1, rd);
14864 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14865 tcg_gen_movi_tl(t1, 4);
14866 gen_op_addr_add(ctx, t0, t0, t1);
14867 gen_load_gpr(t1, rd+1);
14868 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14869 break;
14870 #ifdef TARGET_MIPS64
14871 case LDP:
14872 if (rd == base) {
14873 generate_exception_end(ctx, EXCP_RI);
14874 return;
14876 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14877 gen_store_gpr(t1, rd);
14878 tcg_gen_movi_tl(t1, 8);
14879 gen_op_addr_add(ctx, t0, t0, t1);
14880 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14881 gen_store_gpr(t1, rd+1);
14882 break;
14883 case SDP:
14884 gen_load_gpr(t1, rd);
14885 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14886 tcg_gen_movi_tl(t1, 8);
14887 gen_op_addr_add(ctx, t0, t0, t1);
14888 gen_load_gpr(t1, rd+1);
14889 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14890 break;
14891 #endif
14893 tcg_temp_free(t0);
14894 tcg_temp_free(t1);
14897 static void gen_sync(int stype)
14899 TCGBar tcg_mo = TCG_BAR_SC;
14901 switch (stype) {
14902 case 0x4: /* SYNC_WMB */
14903 tcg_mo |= TCG_MO_ST_ST;
14904 break;
14905 case 0x10: /* SYNC_MB */
14906 tcg_mo |= TCG_MO_ALL;
14907 break;
14908 case 0x11: /* SYNC_ACQUIRE */
14909 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14910 break;
14911 case 0x12: /* SYNC_RELEASE */
14912 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14913 break;
14914 case 0x13: /* SYNC_RMB */
14915 tcg_mo |= TCG_MO_LD_LD;
14916 break;
14917 default:
14918 tcg_mo |= TCG_MO_ALL;
14919 break;
14922 tcg_gen_mb(tcg_mo);
14925 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14927 int extension = (ctx->opcode >> 6) & 0x3f;
14928 int minor = (ctx->opcode >> 12) & 0xf;
14929 uint32_t mips32_op;
14931 switch (extension) {
14932 case TEQ:
14933 mips32_op = OPC_TEQ;
14934 goto do_trap;
14935 case TGE:
14936 mips32_op = OPC_TGE;
14937 goto do_trap;
14938 case TGEU:
14939 mips32_op = OPC_TGEU;
14940 goto do_trap;
14941 case TLT:
14942 mips32_op = OPC_TLT;
14943 goto do_trap;
14944 case TLTU:
14945 mips32_op = OPC_TLTU;
14946 goto do_trap;
14947 case TNE:
14948 mips32_op = OPC_TNE;
14949 do_trap:
14950 gen_trap(ctx, mips32_op, rs, rt, -1);
14951 break;
14952 #ifndef CONFIG_USER_ONLY
14953 case MFC0:
14954 case MFC0 + 32:
14955 check_cp0_enabled(ctx);
14956 if (rt == 0) {
14957 /* Treat as NOP. */
14958 break;
14960 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14961 break;
14962 case MTC0:
14963 case MTC0 + 32:
14964 check_cp0_enabled(ctx);
14966 TCGv t0 = tcg_temp_new();
14968 gen_load_gpr(t0, rt);
14969 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14970 tcg_temp_free(t0);
14972 break;
14973 #endif
14974 case 0x2a:
14975 switch (minor & 3) {
14976 case MADD_ACC:
14977 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14978 break;
14979 case MADDU_ACC:
14980 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14981 break;
14982 case MSUB_ACC:
14983 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14984 break;
14985 case MSUBU_ACC:
14986 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14987 break;
14988 default:
14989 goto pool32axf_invalid;
14991 break;
14992 case 0x32:
14993 switch (minor & 3) {
14994 case MULT_ACC:
14995 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14996 break;
14997 case MULTU_ACC:
14998 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14999 break;
15000 default:
15001 goto pool32axf_invalid;
15003 break;
15004 case 0x2c:
15005 switch (minor) {
15006 case BITSWAP:
15007 check_insn(ctx, ISA_MIPS32R6);
15008 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15009 break;
15010 case SEB:
15011 gen_bshfl(ctx, OPC_SEB, rs, rt);
15012 break;
15013 case SEH:
15014 gen_bshfl(ctx, OPC_SEH, rs, rt);
15015 break;
15016 case CLO:
15017 mips32_op = OPC_CLO;
15018 goto do_cl;
15019 case CLZ:
15020 mips32_op = OPC_CLZ;
15021 do_cl:
15022 check_insn(ctx, ISA_MIPS32);
15023 gen_cl(ctx, mips32_op, rt, rs);
15024 break;
15025 case RDHWR:
15026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15027 gen_rdhwr(ctx, rt, rs, 0);
15028 break;
15029 case WSBH:
15030 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15031 break;
15032 case MULT:
15033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15034 mips32_op = OPC_MULT;
15035 goto do_mul;
15036 case MULTU:
15037 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15038 mips32_op = OPC_MULTU;
15039 goto do_mul;
15040 case DIV:
15041 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15042 mips32_op = OPC_DIV;
15043 goto do_div;
15044 case DIVU:
15045 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15046 mips32_op = OPC_DIVU;
15047 goto do_div;
15048 do_div:
15049 check_insn(ctx, ISA_MIPS32);
15050 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15051 break;
15052 case MADD:
15053 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15054 mips32_op = OPC_MADD;
15055 goto do_mul;
15056 case MADDU:
15057 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15058 mips32_op = OPC_MADDU;
15059 goto do_mul;
15060 case MSUB:
15061 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15062 mips32_op = OPC_MSUB;
15063 goto do_mul;
15064 case MSUBU:
15065 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15066 mips32_op = OPC_MSUBU;
15067 do_mul:
15068 check_insn(ctx, ISA_MIPS32);
15069 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15070 break;
15071 default:
15072 goto pool32axf_invalid;
15074 break;
15075 case 0x34:
15076 switch (minor) {
15077 case MFC2:
15078 case MTC2:
15079 case MFHC2:
15080 case MTHC2:
15081 case CFC2:
15082 case CTC2:
15083 generate_exception_err(ctx, EXCP_CpU, 2);
15084 break;
15085 default:
15086 goto pool32axf_invalid;
15088 break;
15089 case 0x3c:
15090 switch (minor) {
15091 case JALR: /* JALRC */
15092 case JALR_HB: /* JALRC_HB */
15093 if (ctx->insn_flags & ISA_MIPS32R6) {
15094 /* JALRC, JALRC_HB */
15095 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15096 } else {
15097 /* JALR, JALR_HB */
15098 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15099 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15101 break;
15102 case JALRS:
15103 case JALRS_HB:
15104 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15105 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15106 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15107 break;
15108 default:
15109 goto pool32axf_invalid;
15111 break;
15112 case 0x05:
15113 switch (minor) {
15114 case RDPGPR:
15115 check_cp0_enabled(ctx);
15116 check_insn(ctx, ISA_MIPS32R2);
15117 gen_load_srsgpr(rs, rt);
15118 break;
15119 case WRPGPR:
15120 check_cp0_enabled(ctx);
15121 check_insn(ctx, ISA_MIPS32R2);
15122 gen_store_srsgpr(rs, rt);
15123 break;
15124 default:
15125 goto pool32axf_invalid;
15127 break;
15128 #ifndef CONFIG_USER_ONLY
15129 case 0x0d:
15130 switch (minor) {
15131 case TLBP:
15132 mips32_op = OPC_TLBP;
15133 goto do_cp0;
15134 case TLBR:
15135 mips32_op = OPC_TLBR;
15136 goto do_cp0;
15137 case TLBWI:
15138 mips32_op = OPC_TLBWI;
15139 goto do_cp0;
15140 case TLBWR:
15141 mips32_op = OPC_TLBWR;
15142 goto do_cp0;
15143 case TLBINV:
15144 mips32_op = OPC_TLBINV;
15145 goto do_cp0;
15146 case TLBINVF:
15147 mips32_op = OPC_TLBINVF;
15148 goto do_cp0;
15149 case WAIT:
15150 mips32_op = OPC_WAIT;
15151 goto do_cp0;
15152 case DERET:
15153 mips32_op = OPC_DERET;
15154 goto do_cp0;
15155 case ERET:
15156 mips32_op = OPC_ERET;
15157 do_cp0:
15158 gen_cp0(env, ctx, mips32_op, rt, rs);
15159 break;
15160 default:
15161 goto pool32axf_invalid;
15163 break;
15164 case 0x1d:
15165 switch (minor) {
15166 case DI:
15167 check_cp0_enabled(ctx);
15169 TCGv t0 = tcg_temp_new();
15171 save_cpu_state(ctx, 1);
15172 gen_helper_di(t0, cpu_env);
15173 gen_store_gpr(t0, rs);
15174 /* Stop translation as we may have switched the execution mode */
15175 ctx->base.is_jmp = DISAS_STOP;
15176 tcg_temp_free(t0);
15178 break;
15179 case EI:
15180 check_cp0_enabled(ctx);
15182 TCGv t0 = tcg_temp_new();
15184 save_cpu_state(ctx, 1);
15185 gen_helper_ei(t0, cpu_env);
15186 gen_store_gpr(t0, rs);
15187 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15188 of translated code to check for pending interrupts. */
15189 gen_save_pc(ctx->base.pc_next + 4);
15190 ctx->base.is_jmp = DISAS_EXIT;
15191 tcg_temp_free(t0);
15193 break;
15194 default:
15195 goto pool32axf_invalid;
15197 break;
15198 #endif
15199 case 0x2d:
15200 switch (minor) {
15201 case SYNC:
15202 gen_sync(extract32(ctx->opcode, 16, 5));
15203 break;
15204 case SYSCALL:
15205 generate_exception_end(ctx, EXCP_SYSCALL);
15206 break;
15207 case SDBBP:
15208 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15209 gen_helper_do_semihosting(cpu_env);
15210 } else {
15211 check_insn(ctx, ISA_MIPS32);
15212 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15213 generate_exception_end(ctx, EXCP_RI);
15214 } else {
15215 generate_exception_end(ctx, EXCP_DBp);
15218 break;
15219 default:
15220 goto pool32axf_invalid;
15222 break;
15223 case 0x01:
15224 switch (minor & 3) {
15225 case MFHI_ACC:
15226 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15227 break;
15228 case MFLO_ACC:
15229 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15230 break;
15231 case MTHI_ACC:
15232 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15233 break;
15234 case MTLO_ACC:
15235 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15236 break;
15237 default:
15238 goto pool32axf_invalid;
15240 break;
15241 case 0x35:
15242 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15243 switch (minor) {
15244 case MFHI32:
15245 gen_HILO(ctx, OPC_MFHI, 0, rs);
15246 break;
15247 case MFLO32:
15248 gen_HILO(ctx, OPC_MFLO, 0, rs);
15249 break;
15250 case MTHI32:
15251 gen_HILO(ctx, OPC_MTHI, 0, rs);
15252 break;
15253 case MTLO32:
15254 gen_HILO(ctx, OPC_MTLO, 0, rs);
15255 break;
15256 default:
15257 goto pool32axf_invalid;
15259 break;
15260 default:
15261 pool32axf_invalid:
15262 MIPS_INVAL("pool32axf");
15263 generate_exception_end(ctx, EXCP_RI);
15264 break;
15268 /* Values for microMIPS fmt field. Variable-width, depending on which
15269 formats the instruction supports. */
15271 enum {
15272 FMT_SD_S = 0,
15273 FMT_SD_D = 1,
15275 FMT_SDPS_S = 0,
15276 FMT_SDPS_D = 1,
15277 FMT_SDPS_PS = 2,
15279 FMT_SWL_S = 0,
15280 FMT_SWL_W = 1,
15281 FMT_SWL_L = 2,
15283 FMT_DWL_D = 0,
15284 FMT_DWL_W = 1,
15285 FMT_DWL_L = 2
15288 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15290 int extension = (ctx->opcode >> 6) & 0x3ff;
15291 uint32_t mips32_op;
15293 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15294 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15295 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15297 switch (extension) {
15298 case FLOAT_1BIT_FMT(CFC1, 0):
15299 mips32_op = OPC_CFC1;
15300 goto do_cp1;
15301 case FLOAT_1BIT_FMT(CTC1, 0):
15302 mips32_op = OPC_CTC1;
15303 goto do_cp1;
15304 case FLOAT_1BIT_FMT(MFC1, 0):
15305 mips32_op = OPC_MFC1;
15306 goto do_cp1;
15307 case FLOAT_1BIT_FMT(MTC1, 0):
15308 mips32_op = OPC_MTC1;
15309 goto do_cp1;
15310 case FLOAT_1BIT_FMT(MFHC1, 0):
15311 mips32_op = OPC_MFHC1;
15312 goto do_cp1;
15313 case FLOAT_1BIT_FMT(MTHC1, 0):
15314 mips32_op = OPC_MTHC1;
15315 do_cp1:
15316 gen_cp1(ctx, mips32_op, rt, rs);
15317 break;
15319 /* Reciprocal square root */
15320 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15321 mips32_op = OPC_RSQRT_S;
15322 goto do_unaryfp;
15323 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15324 mips32_op = OPC_RSQRT_D;
15325 goto do_unaryfp;
15327 /* Square root */
15328 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15329 mips32_op = OPC_SQRT_S;
15330 goto do_unaryfp;
15331 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15332 mips32_op = OPC_SQRT_D;
15333 goto do_unaryfp;
15335 /* Reciprocal */
15336 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15337 mips32_op = OPC_RECIP_S;
15338 goto do_unaryfp;
15339 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15340 mips32_op = OPC_RECIP_D;
15341 goto do_unaryfp;
15343 /* Floor */
15344 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15345 mips32_op = OPC_FLOOR_L_S;
15346 goto do_unaryfp;
15347 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15348 mips32_op = OPC_FLOOR_L_D;
15349 goto do_unaryfp;
15350 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15351 mips32_op = OPC_FLOOR_W_S;
15352 goto do_unaryfp;
15353 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15354 mips32_op = OPC_FLOOR_W_D;
15355 goto do_unaryfp;
15357 /* Ceiling */
15358 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15359 mips32_op = OPC_CEIL_L_S;
15360 goto do_unaryfp;
15361 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15362 mips32_op = OPC_CEIL_L_D;
15363 goto do_unaryfp;
15364 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15365 mips32_op = OPC_CEIL_W_S;
15366 goto do_unaryfp;
15367 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15368 mips32_op = OPC_CEIL_W_D;
15369 goto do_unaryfp;
15371 /* Truncation */
15372 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15373 mips32_op = OPC_TRUNC_L_S;
15374 goto do_unaryfp;
15375 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15376 mips32_op = OPC_TRUNC_L_D;
15377 goto do_unaryfp;
15378 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15379 mips32_op = OPC_TRUNC_W_S;
15380 goto do_unaryfp;
15381 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15382 mips32_op = OPC_TRUNC_W_D;
15383 goto do_unaryfp;
15385 /* Round */
15386 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15387 mips32_op = OPC_ROUND_L_S;
15388 goto do_unaryfp;
15389 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15390 mips32_op = OPC_ROUND_L_D;
15391 goto do_unaryfp;
15392 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15393 mips32_op = OPC_ROUND_W_S;
15394 goto do_unaryfp;
15395 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15396 mips32_op = OPC_ROUND_W_D;
15397 goto do_unaryfp;
15399 /* Integer to floating-point conversion */
15400 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15401 mips32_op = OPC_CVT_L_S;
15402 goto do_unaryfp;
15403 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15404 mips32_op = OPC_CVT_L_D;
15405 goto do_unaryfp;
15406 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15407 mips32_op = OPC_CVT_W_S;
15408 goto do_unaryfp;
15409 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15410 mips32_op = OPC_CVT_W_D;
15411 goto do_unaryfp;
15413 /* Paired-foo conversions */
15414 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15415 mips32_op = OPC_CVT_S_PL;
15416 goto do_unaryfp;
15417 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15418 mips32_op = OPC_CVT_S_PU;
15419 goto do_unaryfp;
15420 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15421 mips32_op = OPC_CVT_PW_PS;
15422 goto do_unaryfp;
15423 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15424 mips32_op = OPC_CVT_PS_PW;
15425 goto do_unaryfp;
15427 /* Floating-point moves */
15428 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15429 mips32_op = OPC_MOV_S;
15430 goto do_unaryfp;
15431 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15432 mips32_op = OPC_MOV_D;
15433 goto do_unaryfp;
15434 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15435 mips32_op = OPC_MOV_PS;
15436 goto do_unaryfp;
15438 /* Absolute value */
15439 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15440 mips32_op = OPC_ABS_S;
15441 goto do_unaryfp;
15442 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15443 mips32_op = OPC_ABS_D;
15444 goto do_unaryfp;
15445 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15446 mips32_op = OPC_ABS_PS;
15447 goto do_unaryfp;
15449 /* Negation */
15450 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15451 mips32_op = OPC_NEG_S;
15452 goto do_unaryfp;
15453 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15454 mips32_op = OPC_NEG_D;
15455 goto do_unaryfp;
15456 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15457 mips32_op = OPC_NEG_PS;
15458 goto do_unaryfp;
15460 /* Reciprocal square root step */
15461 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15462 mips32_op = OPC_RSQRT1_S;
15463 goto do_unaryfp;
15464 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15465 mips32_op = OPC_RSQRT1_D;
15466 goto do_unaryfp;
15467 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15468 mips32_op = OPC_RSQRT1_PS;
15469 goto do_unaryfp;
15471 /* Reciprocal step */
15472 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15473 mips32_op = OPC_RECIP1_S;
15474 goto do_unaryfp;
15475 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15476 mips32_op = OPC_RECIP1_S;
15477 goto do_unaryfp;
15478 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15479 mips32_op = OPC_RECIP1_PS;
15480 goto do_unaryfp;
15482 /* Conversions from double */
15483 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15484 mips32_op = OPC_CVT_D_S;
15485 goto do_unaryfp;
15486 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15487 mips32_op = OPC_CVT_D_W;
15488 goto do_unaryfp;
15489 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15490 mips32_op = OPC_CVT_D_L;
15491 goto do_unaryfp;
15493 /* Conversions from single */
15494 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15495 mips32_op = OPC_CVT_S_D;
15496 goto do_unaryfp;
15497 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15498 mips32_op = OPC_CVT_S_W;
15499 goto do_unaryfp;
15500 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15501 mips32_op = OPC_CVT_S_L;
15502 do_unaryfp:
15503 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15504 break;
15506 /* Conditional moves on floating-point codes */
15507 case COND_FLOAT_MOV(MOVT, 0):
15508 case COND_FLOAT_MOV(MOVT, 1):
15509 case COND_FLOAT_MOV(MOVT, 2):
15510 case COND_FLOAT_MOV(MOVT, 3):
15511 case COND_FLOAT_MOV(MOVT, 4):
15512 case COND_FLOAT_MOV(MOVT, 5):
15513 case COND_FLOAT_MOV(MOVT, 6):
15514 case COND_FLOAT_MOV(MOVT, 7):
15515 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15516 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15517 break;
15518 case COND_FLOAT_MOV(MOVF, 0):
15519 case COND_FLOAT_MOV(MOVF, 1):
15520 case COND_FLOAT_MOV(MOVF, 2):
15521 case COND_FLOAT_MOV(MOVF, 3):
15522 case COND_FLOAT_MOV(MOVF, 4):
15523 case COND_FLOAT_MOV(MOVF, 5):
15524 case COND_FLOAT_MOV(MOVF, 6):
15525 case COND_FLOAT_MOV(MOVF, 7):
15526 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15527 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15528 break;
15529 default:
15530 MIPS_INVAL("pool32fxf");
15531 generate_exception_end(ctx, EXCP_RI);
15532 break;
15536 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15538 int32_t offset;
15539 uint16_t insn;
15540 int rt, rs, rd, rr;
15541 int16_t imm;
15542 uint32_t op, minor, minor2, mips32_op;
15543 uint32_t cond, fmt, cc;
15545 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15546 ctx->opcode = (ctx->opcode << 16) | insn;
15548 rt = (ctx->opcode >> 21) & 0x1f;
15549 rs = (ctx->opcode >> 16) & 0x1f;
15550 rd = (ctx->opcode >> 11) & 0x1f;
15551 rr = (ctx->opcode >> 6) & 0x1f;
15552 imm = (int16_t) ctx->opcode;
15554 op = (ctx->opcode >> 26) & 0x3f;
15555 switch (op) {
15556 case POOL32A:
15557 minor = ctx->opcode & 0x3f;
15558 switch (minor) {
15559 case 0x00:
15560 minor = (ctx->opcode >> 6) & 0xf;
15561 switch (minor) {
15562 case SLL32:
15563 mips32_op = OPC_SLL;
15564 goto do_shifti;
15565 case SRA:
15566 mips32_op = OPC_SRA;
15567 goto do_shifti;
15568 case SRL32:
15569 mips32_op = OPC_SRL;
15570 goto do_shifti;
15571 case ROTR:
15572 mips32_op = OPC_ROTR;
15573 do_shifti:
15574 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15575 break;
15576 case SELEQZ:
15577 check_insn(ctx, ISA_MIPS32R6);
15578 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15579 break;
15580 case SELNEZ:
15581 check_insn(ctx, ISA_MIPS32R6);
15582 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15583 break;
15584 case R6_RDHWR:
15585 check_insn(ctx, ISA_MIPS32R6);
15586 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15587 break;
15588 default:
15589 goto pool32a_invalid;
15591 break;
15592 case 0x10:
15593 minor = (ctx->opcode >> 6) & 0xf;
15594 switch (minor) {
15595 /* Arithmetic */
15596 case ADD:
15597 mips32_op = OPC_ADD;
15598 goto do_arith;
15599 case ADDU32:
15600 mips32_op = OPC_ADDU;
15601 goto do_arith;
15602 case SUB:
15603 mips32_op = OPC_SUB;
15604 goto do_arith;
15605 case SUBU32:
15606 mips32_op = OPC_SUBU;
15607 goto do_arith;
15608 case MUL:
15609 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15610 mips32_op = OPC_MUL;
15611 do_arith:
15612 gen_arith(ctx, mips32_op, rd, rs, rt);
15613 break;
15614 /* Shifts */
15615 case SLLV:
15616 mips32_op = OPC_SLLV;
15617 goto do_shift;
15618 case SRLV:
15619 mips32_op = OPC_SRLV;
15620 goto do_shift;
15621 case SRAV:
15622 mips32_op = OPC_SRAV;
15623 goto do_shift;
15624 case ROTRV:
15625 mips32_op = OPC_ROTRV;
15626 do_shift:
15627 gen_shift(ctx, mips32_op, rd, rs, rt);
15628 break;
15629 /* Logical operations */
15630 case AND:
15631 mips32_op = OPC_AND;
15632 goto do_logic;
15633 case OR32:
15634 mips32_op = OPC_OR;
15635 goto do_logic;
15636 case NOR:
15637 mips32_op = OPC_NOR;
15638 goto do_logic;
15639 case XOR32:
15640 mips32_op = OPC_XOR;
15641 do_logic:
15642 gen_logic(ctx, mips32_op, rd, rs, rt);
15643 break;
15644 /* Set less than */
15645 case SLT:
15646 mips32_op = OPC_SLT;
15647 goto do_slt;
15648 case SLTU:
15649 mips32_op = OPC_SLTU;
15650 do_slt:
15651 gen_slt(ctx, mips32_op, rd, rs, rt);
15652 break;
15653 default:
15654 goto pool32a_invalid;
15656 break;
15657 case 0x18:
15658 minor = (ctx->opcode >> 6) & 0xf;
15659 switch (minor) {
15660 /* Conditional moves */
15661 case MOVN: /* MUL */
15662 if (ctx->insn_flags & ISA_MIPS32R6) {
15663 /* MUL */
15664 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15665 } else {
15666 /* MOVN */
15667 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15669 break;
15670 case MOVZ: /* MUH */
15671 if (ctx->insn_flags & ISA_MIPS32R6) {
15672 /* MUH */
15673 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15674 } else {
15675 /* MOVZ */
15676 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15678 break;
15679 case MULU:
15680 check_insn(ctx, ISA_MIPS32R6);
15681 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15682 break;
15683 case MUHU:
15684 check_insn(ctx, ISA_MIPS32R6);
15685 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15686 break;
15687 case LWXS: /* DIV */
15688 if (ctx->insn_flags & ISA_MIPS32R6) {
15689 /* DIV */
15690 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15691 } else {
15692 /* LWXS */
15693 gen_ldxs(ctx, rs, rt, rd);
15695 break;
15696 case MOD:
15697 check_insn(ctx, ISA_MIPS32R6);
15698 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15699 break;
15700 case R6_DIVU:
15701 check_insn(ctx, ISA_MIPS32R6);
15702 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15703 break;
15704 case MODU:
15705 check_insn(ctx, ISA_MIPS32R6);
15706 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15707 break;
15708 default:
15709 goto pool32a_invalid;
15711 break;
15712 case INS:
15713 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15714 return;
15715 case LSA:
15716 check_insn(ctx, ISA_MIPS32R6);
15717 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15718 extract32(ctx->opcode, 9, 2));
15719 break;
15720 case ALIGN:
15721 check_insn(ctx, ISA_MIPS32R6);
15722 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15723 break;
15724 case EXT:
15725 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15726 return;
15727 case POOL32AXF:
15728 gen_pool32axf(env, ctx, rt, rs);
15729 break;
15730 case BREAK32:
15731 generate_exception_end(ctx, EXCP_BREAK);
15732 break;
15733 case SIGRIE:
15734 check_insn(ctx, ISA_MIPS32R6);
15735 generate_exception_end(ctx, EXCP_RI);
15736 break;
15737 default:
15738 pool32a_invalid:
15739 MIPS_INVAL("pool32a");
15740 generate_exception_end(ctx, EXCP_RI);
15741 break;
15743 break;
15744 case POOL32B:
15745 minor = (ctx->opcode >> 12) & 0xf;
15746 switch (minor) {
15747 case CACHE:
15748 check_cp0_enabled(ctx);
15749 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15750 gen_cache_operation(ctx, rt, rs, imm);
15752 break;
15753 case LWC2:
15754 case SWC2:
15755 /* COP2: Not implemented. */
15756 generate_exception_err(ctx, EXCP_CpU, 2);
15757 break;
15758 #ifdef TARGET_MIPS64
15759 case LDP:
15760 case SDP:
15761 check_insn(ctx, ISA_MIPS3);
15762 check_mips_64(ctx);
15763 #endif
15764 /* fall through */
15765 case LWP:
15766 case SWP:
15767 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15768 break;
15769 #ifdef TARGET_MIPS64
15770 case LDM:
15771 case SDM:
15772 check_insn(ctx, ISA_MIPS3);
15773 check_mips_64(ctx);
15774 #endif
15775 /* fall through */
15776 case LWM32:
15777 case SWM32:
15778 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15779 break;
15780 default:
15781 MIPS_INVAL("pool32b");
15782 generate_exception_end(ctx, EXCP_RI);
15783 break;
15785 break;
15786 case POOL32F:
15787 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15788 minor = ctx->opcode & 0x3f;
15789 check_cp1_enabled(ctx);
15790 switch (minor) {
15791 case ALNV_PS:
15792 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15793 mips32_op = OPC_ALNV_PS;
15794 goto do_madd;
15795 case MADD_S:
15796 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15797 mips32_op = OPC_MADD_S;
15798 goto do_madd;
15799 case MADD_D:
15800 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15801 mips32_op = OPC_MADD_D;
15802 goto do_madd;
15803 case MADD_PS:
15804 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15805 mips32_op = OPC_MADD_PS;
15806 goto do_madd;
15807 case MSUB_S:
15808 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15809 mips32_op = OPC_MSUB_S;
15810 goto do_madd;
15811 case MSUB_D:
15812 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15813 mips32_op = OPC_MSUB_D;
15814 goto do_madd;
15815 case MSUB_PS:
15816 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15817 mips32_op = OPC_MSUB_PS;
15818 goto do_madd;
15819 case NMADD_S:
15820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15821 mips32_op = OPC_NMADD_S;
15822 goto do_madd;
15823 case NMADD_D:
15824 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15825 mips32_op = OPC_NMADD_D;
15826 goto do_madd;
15827 case NMADD_PS:
15828 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15829 mips32_op = OPC_NMADD_PS;
15830 goto do_madd;
15831 case NMSUB_S:
15832 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15833 mips32_op = OPC_NMSUB_S;
15834 goto do_madd;
15835 case NMSUB_D:
15836 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15837 mips32_op = OPC_NMSUB_D;
15838 goto do_madd;
15839 case NMSUB_PS:
15840 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15841 mips32_op = OPC_NMSUB_PS;
15842 do_madd:
15843 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15844 break;
15845 case CABS_COND_FMT:
15846 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15847 cond = (ctx->opcode >> 6) & 0xf;
15848 cc = (ctx->opcode >> 13) & 0x7;
15849 fmt = (ctx->opcode >> 10) & 0x3;
15850 switch (fmt) {
15851 case 0x0:
15852 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15853 break;
15854 case 0x1:
15855 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15856 break;
15857 case 0x2:
15858 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15859 break;
15860 default:
15861 goto pool32f_invalid;
15863 break;
15864 case C_COND_FMT:
15865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15866 cond = (ctx->opcode >> 6) & 0xf;
15867 cc = (ctx->opcode >> 13) & 0x7;
15868 fmt = (ctx->opcode >> 10) & 0x3;
15869 switch (fmt) {
15870 case 0x0:
15871 gen_cmp_s(ctx, cond, rt, rs, cc);
15872 break;
15873 case 0x1:
15874 gen_cmp_d(ctx, cond, rt, rs, cc);
15875 break;
15876 case 0x2:
15877 gen_cmp_ps(ctx, cond, rt, rs, cc);
15878 break;
15879 default:
15880 goto pool32f_invalid;
15882 break;
15883 case CMP_CONDN_S:
15884 check_insn(ctx, ISA_MIPS32R6);
15885 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15886 break;
15887 case CMP_CONDN_D:
15888 check_insn(ctx, ISA_MIPS32R6);
15889 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15890 break;
15891 case POOL32FXF:
15892 gen_pool32fxf(ctx, rt, rs);
15893 break;
15894 case 0x00:
15895 /* PLL foo */
15896 switch ((ctx->opcode >> 6) & 0x7) {
15897 case PLL_PS:
15898 mips32_op = OPC_PLL_PS;
15899 goto do_ps;
15900 case PLU_PS:
15901 mips32_op = OPC_PLU_PS;
15902 goto do_ps;
15903 case PUL_PS:
15904 mips32_op = OPC_PUL_PS;
15905 goto do_ps;
15906 case PUU_PS:
15907 mips32_op = OPC_PUU_PS;
15908 goto do_ps;
15909 case CVT_PS_S:
15910 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15911 mips32_op = OPC_CVT_PS_S;
15912 do_ps:
15913 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15914 break;
15915 default:
15916 goto pool32f_invalid;
15918 break;
15919 case MIN_FMT:
15920 check_insn(ctx, ISA_MIPS32R6);
15921 switch ((ctx->opcode >> 9) & 0x3) {
15922 case FMT_SDPS_S:
15923 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15924 break;
15925 case FMT_SDPS_D:
15926 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15927 break;
15928 default:
15929 goto pool32f_invalid;
15931 break;
15932 case 0x08:
15933 /* [LS][WDU]XC1 */
15934 switch ((ctx->opcode >> 6) & 0x7) {
15935 case LWXC1:
15936 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15937 mips32_op = OPC_LWXC1;
15938 goto do_ldst_cp1;
15939 case SWXC1:
15940 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15941 mips32_op = OPC_SWXC1;
15942 goto do_ldst_cp1;
15943 case LDXC1:
15944 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15945 mips32_op = OPC_LDXC1;
15946 goto do_ldst_cp1;
15947 case SDXC1:
15948 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15949 mips32_op = OPC_SDXC1;
15950 goto do_ldst_cp1;
15951 case LUXC1:
15952 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15953 mips32_op = OPC_LUXC1;
15954 goto do_ldst_cp1;
15955 case SUXC1:
15956 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15957 mips32_op = OPC_SUXC1;
15958 do_ldst_cp1:
15959 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15960 break;
15961 default:
15962 goto pool32f_invalid;
15964 break;
15965 case MAX_FMT:
15966 check_insn(ctx, ISA_MIPS32R6);
15967 switch ((ctx->opcode >> 9) & 0x3) {
15968 case FMT_SDPS_S:
15969 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15970 break;
15971 case FMT_SDPS_D:
15972 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15973 break;
15974 default:
15975 goto pool32f_invalid;
15977 break;
15978 case 0x18:
15979 /* 3D insns */
15980 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15981 fmt = (ctx->opcode >> 9) & 0x3;
15982 switch ((ctx->opcode >> 6) & 0x7) {
15983 case RSQRT2_FMT:
15984 switch (fmt) {
15985 case FMT_SDPS_S:
15986 mips32_op = OPC_RSQRT2_S;
15987 goto do_3d;
15988 case FMT_SDPS_D:
15989 mips32_op = OPC_RSQRT2_D;
15990 goto do_3d;
15991 case FMT_SDPS_PS:
15992 mips32_op = OPC_RSQRT2_PS;
15993 goto do_3d;
15994 default:
15995 goto pool32f_invalid;
15997 break;
15998 case RECIP2_FMT:
15999 switch (fmt) {
16000 case FMT_SDPS_S:
16001 mips32_op = OPC_RECIP2_S;
16002 goto do_3d;
16003 case FMT_SDPS_D:
16004 mips32_op = OPC_RECIP2_D;
16005 goto do_3d;
16006 case FMT_SDPS_PS:
16007 mips32_op = OPC_RECIP2_PS;
16008 goto do_3d;
16009 default:
16010 goto pool32f_invalid;
16012 break;
16013 case ADDR_PS:
16014 mips32_op = OPC_ADDR_PS;
16015 goto do_3d;
16016 case MULR_PS:
16017 mips32_op = OPC_MULR_PS;
16018 do_3d:
16019 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16020 break;
16021 default:
16022 goto pool32f_invalid;
16024 break;
16025 case 0x20:
16026 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16027 cc = (ctx->opcode >> 13) & 0x7;
16028 fmt = (ctx->opcode >> 9) & 0x3;
16029 switch ((ctx->opcode >> 6) & 0x7) {
16030 case MOVF_FMT: /* RINT_FMT */
16031 if (ctx->insn_flags & ISA_MIPS32R6) {
16032 /* RINT_FMT */
16033 switch (fmt) {
16034 case FMT_SDPS_S:
16035 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16036 break;
16037 case FMT_SDPS_D:
16038 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16039 break;
16040 default:
16041 goto pool32f_invalid;
16043 } else {
16044 /* MOVF_FMT */
16045 switch (fmt) {
16046 case FMT_SDPS_S:
16047 gen_movcf_s(ctx, rs, rt, cc, 0);
16048 break;
16049 case FMT_SDPS_D:
16050 gen_movcf_d(ctx, rs, rt, cc, 0);
16051 break;
16052 case FMT_SDPS_PS:
16053 check_ps(ctx);
16054 gen_movcf_ps(ctx, rs, rt, cc, 0);
16055 break;
16056 default:
16057 goto pool32f_invalid;
16060 break;
16061 case MOVT_FMT: /* CLASS_FMT */
16062 if (ctx->insn_flags & ISA_MIPS32R6) {
16063 /* CLASS_FMT */
16064 switch (fmt) {
16065 case FMT_SDPS_S:
16066 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16067 break;
16068 case FMT_SDPS_D:
16069 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16070 break;
16071 default:
16072 goto pool32f_invalid;
16074 } else {
16075 /* MOVT_FMT */
16076 switch (fmt) {
16077 case FMT_SDPS_S:
16078 gen_movcf_s(ctx, rs, rt, cc, 1);
16079 break;
16080 case FMT_SDPS_D:
16081 gen_movcf_d(ctx, rs, rt, cc, 1);
16082 break;
16083 case FMT_SDPS_PS:
16084 check_ps(ctx);
16085 gen_movcf_ps(ctx, rs, rt, cc, 1);
16086 break;
16087 default:
16088 goto pool32f_invalid;
16091 break;
16092 case PREFX:
16093 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16094 break;
16095 default:
16096 goto pool32f_invalid;
16098 break;
16099 #define FINSN_3ARG_SDPS(prfx) \
16100 switch ((ctx->opcode >> 8) & 0x3) { \
16101 case FMT_SDPS_S: \
16102 mips32_op = OPC_##prfx##_S; \
16103 goto do_fpop; \
16104 case FMT_SDPS_D: \
16105 mips32_op = OPC_##prfx##_D; \
16106 goto do_fpop; \
16107 case FMT_SDPS_PS: \
16108 check_ps(ctx); \
16109 mips32_op = OPC_##prfx##_PS; \
16110 goto do_fpop; \
16111 default: \
16112 goto pool32f_invalid; \
16114 case MINA_FMT:
16115 check_insn(ctx, ISA_MIPS32R6);
16116 switch ((ctx->opcode >> 9) & 0x3) {
16117 case FMT_SDPS_S:
16118 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16119 break;
16120 case FMT_SDPS_D:
16121 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16122 break;
16123 default:
16124 goto pool32f_invalid;
16126 break;
16127 case MAXA_FMT:
16128 check_insn(ctx, ISA_MIPS32R6);
16129 switch ((ctx->opcode >> 9) & 0x3) {
16130 case FMT_SDPS_S:
16131 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16132 break;
16133 case FMT_SDPS_D:
16134 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16135 break;
16136 default:
16137 goto pool32f_invalid;
16139 break;
16140 case 0x30:
16141 /* regular FP ops */
16142 switch ((ctx->opcode >> 6) & 0x3) {
16143 case ADD_FMT:
16144 FINSN_3ARG_SDPS(ADD);
16145 break;
16146 case SUB_FMT:
16147 FINSN_3ARG_SDPS(SUB);
16148 break;
16149 case MUL_FMT:
16150 FINSN_3ARG_SDPS(MUL);
16151 break;
16152 case DIV_FMT:
16153 fmt = (ctx->opcode >> 8) & 0x3;
16154 if (fmt == 1) {
16155 mips32_op = OPC_DIV_D;
16156 } else if (fmt == 0) {
16157 mips32_op = OPC_DIV_S;
16158 } else {
16159 goto pool32f_invalid;
16161 goto do_fpop;
16162 default:
16163 goto pool32f_invalid;
16165 break;
16166 case 0x38:
16167 /* cmovs */
16168 switch ((ctx->opcode >> 6) & 0x7) {
16169 case MOVN_FMT: /* SELEQZ_FMT */
16170 if (ctx->insn_flags & ISA_MIPS32R6) {
16171 /* SELEQZ_FMT */
16172 switch ((ctx->opcode >> 9) & 0x3) {
16173 case FMT_SDPS_S:
16174 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16175 break;
16176 case FMT_SDPS_D:
16177 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16178 break;
16179 default:
16180 goto pool32f_invalid;
16182 } else {
16183 /* MOVN_FMT */
16184 FINSN_3ARG_SDPS(MOVN);
16186 break;
16187 case MOVN_FMT_04:
16188 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16189 FINSN_3ARG_SDPS(MOVN);
16190 break;
16191 case MOVZ_FMT: /* SELNEZ_FMT */
16192 if (ctx->insn_flags & ISA_MIPS32R6) {
16193 /* SELNEZ_FMT */
16194 switch ((ctx->opcode >> 9) & 0x3) {
16195 case FMT_SDPS_S:
16196 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16197 break;
16198 case FMT_SDPS_D:
16199 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16200 break;
16201 default:
16202 goto pool32f_invalid;
16204 } else {
16205 /* MOVZ_FMT */
16206 FINSN_3ARG_SDPS(MOVZ);
16208 break;
16209 case MOVZ_FMT_05:
16210 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16211 FINSN_3ARG_SDPS(MOVZ);
16212 break;
16213 case SEL_FMT:
16214 check_insn(ctx, ISA_MIPS32R6);
16215 switch ((ctx->opcode >> 9) & 0x3) {
16216 case FMT_SDPS_S:
16217 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16218 break;
16219 case FMT_SDPS_D:
16220 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16221 break;
16222 default:
16223 goto pool32f_invalid;
16225 break;
16226 case MADDF_FMT:
16227 check_insn(ctx, ISA_MIPS32R6);
16228 switch ((ctx->opcode >> 9) & 0x3) {
16229 case FMT_SDPS_S:
16230 mips32_op = OPC_MADDF_S;
16231 goto do_fpop;
16232 case FMT_SDPS_D:
16233 mips32_op = OPC_MADDF_D;
16234 goto do_fpop;
16235 default:
16236 goto pool32f_invalid;
16238 break;
16239 case MSUBF_FMT:
16240 check_insn(ctx, ISA_MIPS32R6);
16241 switch ((ctx->opcode >> 9) & 0x3) {
16242 case FMT_SDPS_S:
16243 mips32_op = OPC_MSUBF_S;
16244 goto do_fpop;
16245 case FMT_SDPS_D:
16246 mips32_op = OPC_MSUBF_D;
16247 goto do_fpop;
16248 default:
16249 goto pool32f_invalid;
16251 break;
16252 default:
16253 goto pool32f_invalid;
16255 break;
16256 do_fpop:
16257 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16258 break;
16259 default:
16260 pool32f_invalid:
16261 MIPS_INVAL("pool32f");
16262 generate_exception_end(ctx, EXCP_RI);
16263 break;
16265 } else {
16266 generate_exception_err(ctx, EXCP_CpU, 1);
16268 break;
16269 case POOL32I:
16270 minor = (ctx->opcode >> 21) & 0x1f;
16271 switch (minor) {
16272 case BLTZ:
16273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16274 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16275 break;
16276 case BLTZAL:
16277 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16278 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16279 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16280 break;
16281 case BLTZALS:
16282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16283 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16284 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16285 break;
16286 case BGEZ:
16287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16288 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16289 break;
16290 case BGEZAL:
16291 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16292 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16293 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16294 break;
16295 case BGEZALS:
16296 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16297 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16298 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16299 break;
16300 case BLEZ:
16301 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16302 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16303 break;
16304 case BGTZ:
16305 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16306 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16307 break;
16309 /* Traps */
16310 case TLTI: /* BC1EQZC */
16311 if (ctx->insn_flags & ISA_MIPS32R6) {
16312 /* BC1EQZC */
16313 check_cp1_enabled(ctx);
16314 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16315 } else {
16316 /* TLTI */
16317 mips32_op = OPC_TLTI;
16318 goto do_trapi;
16320 break;
16321 case TGEI: /* BC1NEZC */
16322 if (ctx->insn_flags & ISA_MIPS32R6) {
16323 /* BC1NEZC */
16324 check_cp1_enabled(ctx);
16325 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16326 } else {
16327 /* TGEI */
16328 mips32_op = OPC_TGEI;
16329 goto do_trapi;
16331 break;
16332 case TLTIU:
16333 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16334 mips32_op = OPC_TLTIU;
16335 goto do_trapi;
16336 case TGEIU:
16337 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16338 mips32_op = OPC_TGEIU;
16339 goto do_trapi;
16340 case TNEI: /* SYNCI */
16341 if (ctx->insn_flags & ISA_MIPS32R6) {
16342 /* SYNCI */
16343 /* Break the TB to be able to sync copied instructions
16344 immediately */
16345 ctx->base.is_jmp = DISAS_STOP;
16346 } else {
16347 /* TNEI */
16348 mips32_op = OPC_TNEI;
16349 goto do_trapi;
16351 break;
16352 case TEQI:
16353 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16354 mips32_op = OPC_TEQI;
16355 do_trapi:
16356 gen_trap(ctx, mips32_op, rs, -1, imm);
16357 break;
16359 case BNEZC:
16360 case BEQZC:
16361 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16362 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16363 4, rs, 0, imm << 1, 0);
16364 /* Compact branches don't have a delay slot, so just let
16365 the normal delay slot handling take us to the branch
16366 target. */
16367 break;
16368 case LUI:
16369 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16370 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16371 break;
16372 case SYNCI:
16373 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16374 /* Break the TB to be able to sync copied instructions
16375 immediately */
16376 ctx->base.is_jmp = DISAS_STOP;
16377 break;
16378 case BC2F:
16379 case BC2T:
16380 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16381 /* COP2: Not implemented. */
16382 generate_exception_err(ctx, EXCP_CpU, 2);
16383 break;
16384 case BC1F:
16385 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16386 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16387 goto do_cp1branch;
16388 case BC1T:
16389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16390 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16391 goto do_cp1branch;
16392 case BC1ANY4F:
16393 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16394 mips32_op = OPC_BC1FANY4;
16395 goto do_cp1mips3d;
16396 case BC1ANY4T:
16397 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16398 mips32_op = OPC_BC1TANY4;
16399 do_cp1mips3d:
16400 check_cop1x(ctx);
16401 check_insn(ctx, ASE_MIPS3D);
16402 /* Fall through */
16403 do_cp1branch:
16404 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16405 check_cp1_enabled(ctx);
16406 gen_compute_branch1(ctx, mips32_op,
16407 (ctx->opcode >> 18) & 0x7, imm << 1);
16408 } else {
16409 generate_exception_err(ctx, EXCP_CpU, 1);
16411 break;
16412 case BPOSGE64:
16413 case BPOSGE32:
16414 /* MIPS DSP: not implemented */
16415 /* Fall through */
16416 default:
16417 MIPS_INVAL("pool32i");
16418 generate_exception_end(ctx, EXCP_RI);
16419 break;
16421 break;
16422 case POOL32C:
16423 minor = (ctx->opcode >> 12) & 0xf;
16424 offset = sextract32(ctx->opcode, 0,
16425 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16426 switch (minor) {
16427 case LWL:
16428 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16429 mips32_op = OPC_LWL;
16430 goto do_ld_lr;
16431 case SWL:
16432 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16433 mips32_op = OPC_SWL;
16434 goto do_st_lr;
16435 case LWR:
16436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16437 mips32_op = OPC_LWR;
16438 goto do_ld_lr;
16439 case SWR:
16440 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16441 mips32_op = OPC_SWR;
16442 goto do_st_lr;
16443 #if defined(TARGET_MIPS64)
16444 case LDL:
16445 check_insn(ctx, ISA_MIPS3);
16446 check_mips_64(ctx);
16447 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16448 mips32_op = OPC_LDL;
16449 goto do_ld_lr;
16450 case SDL:
16451 check_insn(ctx, ISA_MIPS3);
16452 check_mips_64(ctx);
16453 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16454 mips32_op = OPC_SDL;
16455 goto do_st_lr;
16456 case LDR:
16457 check_insn(ctx, ISA_MIPS3);
16458 check_mips_64(ctx);
16459 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16460 mips32_op = OPC_LDR;
16461 goto do_ld_lr;
16462 case SDR:
16463 check_insn(ctx, ISA_MIPS3);
16464 check_mips_64(ctx);
16465 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16466 mips32_op = OPC_SDR;
16467 goto do_st_lr;
16468 case LWU:
16469 check_insn(ctx, ISA_MIPS3);
16470 check_mips_64(ctx);
16471 mips32_op = OPC_LWU;
16472 goto do_ld_lr;
16473 case LLD:
16474 check_insn(ctx, ISA_MIPS3);
16475 check_mips_64(ctx);
16476 mips32_op = OPC_LLD;
16477 goto do_ld_lr;
16478 #endif
16479 case LL:
16480 mips32_op = OPC_LL;
16481 goto do_ld_lr;
16482 do_ld_lr:
16483 gen_ld(ctx, mips32_op, rt, rs, offset);
16484 break;
16485 do_st_lr:
16486 gen_st(ctx, mips32_op, rt, rs, offset);
16487 break;
16488 case SC:
16489 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16490 break;
16491 #if defined(TARGET_MIPS64)
16492 case SCD:
16493 check_insn(ctx, ISA_MIPS3);
16494 check_mips_64(ctx);
16495 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16496 break;
16497 #endif
16498 case LD_EVA:
16499 if (!ctx->eva) {
16500 MIPS_INVAL("pool32c ld-eva");
16501 generate_exception_end(ctx, EXCP_RI);
16502 break;
16504 check_cp0_enabled(ctx);
16506 minor2 = (ctx->opcode >> 9) & 0x7;
16507 offset = sextract32(ctx->opcode, 0, 9);
16508 switch (minor2) {
16509 case LBUE:
16510 mips32_op = OPC_LBUE;
16511 goto do_ld_lr;
16512 case LHUE:
16513 mips32_op = OPC_LHUE;
16514 goto do_ld_lr;
16515 case LWLE:
16516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16517 mips32_op = OPC_LWLE;
16518 goto do_ld_lr;
16519 case LWRE:
16520 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16521 mips32_op = OPC_LWRE;
16522 goto do_ld_lr;
16523 case LBE:
16524 mips32_op = OPC_LBE;
16525 goto do_ld_lr;
16526 case LHE:
16527 mips32_op = OPC_LHE;
16528 goto do_ld_lr;
16529 case LLE:
16530 mips32_op = OPC_LLE;
16531 goto do_ld_lr;
16532 case LWE:
16533 mips32_op = OPC_LWE;
16534 goto do_ld_lr;
16536 break;
16537 case ST_EVA:
16538 if (!ctx->eva) {
16539 MIPS_INVAL("pool32c st-eva");
16540 generate_exception_end(ctx, EXCP_RI);
16541 break;
16543 check_cp0_enabled(ctx);
16545 minor2 = (ctx->opcode >> 9) & 0x7;
16546 offset = sextract32(ctx->opcode, 0, 9);
16547 switch (minor2) {
16548 case SWLE:
16549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16550 mips32_op = OPC_SWLE;
16551 goto do_st_lr;
16552 case SWRE:
16553 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16554 mips32_op = OPC_SWRE;
16555 goto do_st_lr;
16556 case PREFE:
16557 /* Treat as no-op */
16558 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16559 /* hint codes 24-31 are reserved and signal RI */
16560 generate_exception(ctx, EXCP_RI);
16562 break;
16563 case CACHEE:
16564 /* Treat as no-op */
16565 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16566 gen_cache_operation(ctx, rt, rs, offset);
16568 break;
16569 case SBE:
16570 mips32_op = OPC_SBE;
16571 goto do_st_lr;
16572 case SHE:
16573 mips32_op = OPC_SHE;
16574 goto do_st_lr;
16575 case SCE:
16576 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16577 break;
16578 case SWE:
16579 mips32_op = OPC_SWE;
16580 goto do_st_lr;
16582 break;
16583 case PREF:
16584 /* Treat as no-op */
16585 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16586 /* hint codes 24-31 are reserved and signal RI */
16587 generate_exception(ctx, EXCP_RI);
16589 break;
16590 default:
16591 MIPS_INVAL("pool32c");
16592 generate_exception_end(ctx, EXCP_RI);
16593 break;
16595 break;
16596 case ADDI32: /* AUI, LUI */
16597 if (ctx->insn_flags & ISA_MIPS32R6) {
16598 /* AUI, LUI */
16599 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16600 } else {
16601 /* ADDI32 */
16602 mips32_op = OPC_ADDI;
16603 goto do_addi;
16605 break;
16606 case ADDIU32:
16607 mips32_op = OPC_ADDIU;
16608 do_addi:
16609 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16610 break;
16612 /* Logical operations */
16613 case ORI32:
16614 mips32_op = OPC_ORI;
16615 goto do_logici;
16616 case XORI32:
16617 mips32_op = OPC_XORI;
16618 goto do_logici;
16619 case ANDI32:
16620 mips32_op = OPC_ANDI;
16621 do_logici:
16622 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16623 break;
16625 /* Set less than immediate */
16626 case SLTI32:
16627 mips32_op = OPC_SLTI;
16628 goto do_slti;
16629 case SLTIU32:
16630 mips32_op = OPC_SLTIU;
16631 do_slti:
16632 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16633 break;
16634 case JALX32:
16635 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16636 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16637 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16638 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16639 break;
16640 case JALS32: /* BOVC, BEQC, BEQZALC */
16641 if (ctx->insn_flags & ISA_MIPS32R6) {
16642 if (rs >= rt) {
16643 /* BOVC */
16644 mips32_op = OPC_BOVC;
16645 } else if (rs < rt && rs == 0) {
16646 /* BEQZALC */
16647 mips32_op = OPC_BEQZALC;
16648 } else {
16649 /* BEQC */
16650 mips32_op = OPC_BEQC;
16652 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16653 } else {
16654 /* JALS32 */
16655 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16656 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16657 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16659 break;
16660 case BEQ32: /* BC */
16661 if (ctx->insn_flags & ISA_MIPS32R6) {
16662 /* BC */
16663 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16664 sextract32(ctx->opcode << 1, 0, 27));
16665 } else {
16666 /* BEQ32 */
16667 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16669 break;
16670 case BNE32: /* BALC */
16671 if (ctx->insn_flags & ISA_MIPS32R6) {
16672 /* BALC */
16673 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16674 sextract32(ctx->opcode << 1, 0, 27));
16675 } else {
16676 /* BNE32 */
16677 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16679 break;
16680 case J32: /* BGTZC, BLTZC, BLTC */
16681 if (ctx->insn_flags & ISA_MIPS32R6) {
16682 if (rs == 0 && rt != 0) {
16683 /* BGTZC */
16684 mips32_op = OPC_BGTZC;
16685 } else if (rs != 0 && rt != 0 && rs == rt) {
16686 /* BLTZC */
16687 mips32_op = OPC_BLTZC;
16688 } else {
16689 /* BLTC */
16690 mips32_op = OPC_BLTC;
16692 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16693 } else {
16694 /* J32 */
16695 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16696 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16698 break;
16699 case JAL32: /* BLEZC, BGEZC, BGEC */
16700 if (ctx->insn_flags & ISA_MIPS32R6) {
16701 if (rs == 0 && rt != 0) {
16702 /* BLEZC */
16703 mips32_op = OPC_BLEZC;
16704 } else if (rs != 0 && rt != 0 && rs == rt) {
16705 /* BGEZC */
16706 mips32_op = OPC_BGEZC;
16707 } else {
16708 /* BGEC */
16709 mips32_op = OPC_BGEC;
16711 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16712 } else {
16713 /* JAL32 */
16714 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16715 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16716 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16718 break;
16719 /* Floating point (COP1) */
16720 case LWC132:
16721 mips32_op = OPC_LWC1;
16722 goto do_cop1;
16723 case LDC132:
16724 mips32_op = OPC_LDC1;
16725 goto do_cop1;
16726 case SWC132:
16727 mips32_op = OPC_SWC1;
16728 goto do_cop1;
16729 case SDC132:
16730 mips32_op = OPC_SDC1;
16731 do_cop1:
16732 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16733 break;
16734 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16735 if (ctx->insn_flags & ISA_MIPS32R6) {
16736 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16737 switch ((ctx->opcode >> 16) & 0x1f) {
16738 case ADDIUPC_00:
16739 case ADDIUPC_01:
16740 case ADDIUPC_02:
16741 case ADDIUPC_03:
16742 case ADDIUPC_04:
16743 case ADDIUPC_05:
16744 case ADDIUPC_06:
16745 case ADDIUPC_07:
16746 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16747 break;
16748 case AUIPC:
16749 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16750 break;
16751 case ALUIPC:
16752 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16753 break;
16754 case LWPC_08:
16755 case LWPC_09:
16756 case LWPC_0A:
16757 case LWPC_0B:
16758 case LWPC_0C:
16759 case LWPC_0D:
16760 case LWPC_0E:
16761 case LWPC_0F:
16762 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16763 break;
16764 default:
16765 generate_exception(ctx, EXCP_RI);
16766 break;
16768 } else {
16769 /* ADDIUPC */
16770 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16771 offset = SIMM(ctx->opcode, 0, 23) << 2;
16773 gen_addiupc(ctx, reg, offset, 0, 0);
16775 break;
16776 case BNVC: /* BNEC, BNEZALC */
16777 check_insn(ctx, ISA_MIPS32R6);
16778 if (rs >= rt) {
16779 /* BNVC */
16780 mips32_op = OPC_BNVC;
16781 } else if (rs < rt && rs == 0) {
16782 /* BNEZALC */
16783 mips32_op = OPC_BNEZALC;
16784 } else {
16785 /* BNEC */
16786 mips32_op = OPC_BNEC;
16788 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16789 break;
16790 case R6_BNEZC: /* JIALC */
16791 check_insn(ctx, ISA_MIPS32R6);
16792 if (rt != 0) {
16793 /* BNEZC */
16794 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16795 sextract32(ctx->opcode << 1, 0, 22));
16796 } else {
16797 /* JIALC */
16798 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16800 break;
16801 case R6_BEQZC: /* JIC */
16802 check_insn(ctx, ISA_MIPS32R6);
16803 if (rt != 0) {
16804 /* BEQZC */
16805 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16806 sextract32(ctx->opcode << 1, 0, 22));
16807 } else {
16808 /* JIC */
16809 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16811 break;
16812 case BLEZALC: /* BGEZALC, BGEUC */
16813 check_insn(ctx, ISA_MIPS32R6);
16814 if (rs == 0 && rt != 0) {
16815 /* BLEZALC */
16816 mips32_op = OPC_BLEZALC;
16817 } else if (rs != 0 && rt != 0 && rs == rt) {
16818 /* BGEZALC */
16819 mips32_op = OPC_BGEZALC;
16820 } else {
16821 /* BGEUC */
16822 mips32_op = OPC_BGEUC;
16824 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16825 break;
16826 case BGTZALC: /* BLTZALC, BLTUC */
16827 check_insn(ctx, ISA_MIPS32R6);
16828 if (rs == 0 && rt != 0) {
16829 /* BGTZALC */
16830 mips32_op = OPC_BGTZALC;
16831 } else if (rs != 0 && rt != 0 && rs == rt) {
16832 /* BLTZALC */
16833 mips32_op = OPC_BLTZALC;
16834 } else {
16835 /* BLTUC */
16836 mips32_op = OPC_BLTUC;
16838 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16839 break;
16840 /* Loads and stores */
16841 case LB32:
16842 mips32_op = OPC_LB;
16843 goto do_ld;
16844 case LBU32:
16845 mips32_op = OPC_LBU;
16846 goto do_ld;
16847 case LH32:
16848 mips32_op = OPC_LH;
16849 goto do_ld;
16850 case LHU32:
16851 mips32_op = OPC_LHU;
16852 goto do_ld;
16853 case LW32:
16854 mips32_op = OPC_LW;
16855 goto do_ld;
16856 #ifdef TARGET_MIPS64
16857 case LD32:
16858 check_insn(ctx, ISA_MIPS3);
16859 check_mips_64(ctx);
16860 mips32_op = OPC_LD;
16861 goto do_ld;
16862 case SD32:
16863 check_insn(ctx, ISA_MIPS3);
16864 check_mips_64(ctx);
16865 mips32_op = OPC_SD;
16866 goto do_st;
16867 #endif
16868 case SB32:
16869 mips32_op = OPC_SB;
16870 goto do_st;
16871 case SH32:
16872 mips32_op = OPC_SH;
16873 goto do_st;
16874 case SW32:
16875 mips32_op = OPC_SW;
16876 goto do_st;
16877 do_ld:
16878 gen_ld(ctx, mips32_op, rt, rs, imm);
16879 break;
16880 do_st:
16881 gen_st(ctx, mips32_op, rt, rs, imm);
16882 break;
16883 default:
16884 generate_exception_end(ctx, EXCP_RI);
16885 break;
16889 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16891 uint32_t op;
16893 /* make sure instructions are on a halfword boundary */
16894 if (ctx->base.pc_next & 0x1) {
16895 env->CP0_BadVAddr = ctx->base.pc_next;
16896 generate_exception_end(ctx, EXCP_AdEL);
16897 return 2;
16900 op = (ctx->opcode >> 10) & 0x3f;
16901 /* Enforce properly-sized instructions in a delay slot */
16902 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16903 switch (op & 0x7) { /* MSB-3..MSB-5 */
16904 case 0:
16905 /* POOL32A, POOL32B, POOL32I, POOL32C */
16906 case 4:
16907 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16908 case 5:
16909 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16910 case 6:
16911 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16912 case 7:
16913 /* LB32, LH32, LWC132, LDC132, LW32 */
16914 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16915 generate_exception_end(ctx, EXCP_RI);
16916 return 2;
16918 break;
16919 case 1:
16920 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16921 case 2:
16922 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16923 case 3:
16924 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16925 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16926 generate_exception_end(ctx, EXCP_RI);
16927 return 2;
16929 break;
16933 switch (op) {
16934 case POOL16A:
16936 int rd = mmreg(uMIPS_RD(ctx->opcode));
16937 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16938 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16939 uint32_t opc = 0;
16941 switch (ctx->opcode & 0x1) {
16942 case ADDU16:
16943 opc = OPC_ADDU;
16944 break;
16945 case SUBU16:
16946 opc = OPC_SUBU;
16947 break;
16949 if (ctx->insn_flags & ISA_MIPS32R6) {
16950 /* In the Release 6 the register number location in
16951 * the instruction encoding has changed.
16953 gen_arith(ctx, opc, rs1, rd, rs2);
16954 } else {
16955 gen_arith(ctx, opc, rd, rs1, rs2);
16958 break;
16959 case POOL16B:
16961 int rd = mmreg(uMIPS_RD(ctx->opcode));
16962 int rs = mmreg(uMIPS_RS(ctx->opcode));
16963 int amount = (ctx->opcode >> 1) & 0x7;
16964 uint32_t opc = 0;
16965 amount = amount == 0 ? 8 : amount;
16967 switch (ctx->opcode & 0x1) {
16968 case SLL16:
16969 opc = OPC_SLL;
16970 break;
16971 case SRL16:
16972 opc = OPC_SRL;
16973 break;
16976 gen_shift_imm(ctx, opc, rd, rs, amount);
16978 break;
16979 case POOL16C:
16980 if (ctx->insn_flags & ISA_MIPS32R6) {
16981 gen_pool16c_r6_insn(ctx);
16982 } else {
16983 gen_pool16c_insn(ctx);
16985 break;
16986 case LWGP16:
16988 int rd = mmreg(uMIPS_RD(ctx->opcode));
16989 int rb = 28; /* GP */
16990 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16992 gen_ld(ctx, OPC_LW, rd, rb, offset);
16994 break;
16995 case POOL16F:
16996 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16997 if (ctx->opcode & 1) {
16998 generate_exception_end(ctx, EXCP_RI);
16999 } else {
17000 /* MOVEP */
17001 int enc_dest = uMIPS_RD(ctx->opcode);
17002 int enc_rt = uMIPS_RS2(ctx->opcode);
17003 int enc_rs = uMIPS_RS1(ctx->opcode);
17004 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17006 break;
17007 case LBU16:
17009 int rd = mmreg(uMIPS_RD(ctx->opcode));
17010 int rb = mmreg(uMIPS_RS(ctx->opcode));
17011 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17012 offset = (offset == 0xf ? -1 : offset);
17014 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17016 break;
17017 case LHU16:
17019 int rd = mmreg(uMIPS_RD(ctx->opcode));
17020 int rb = mmreg(uMIPS_RS(ctx->opcode));
17021 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17023 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17025 break;
17026 case LWSP16:
17028 int rd = (ctx->opcode >> 5) & 0x1f;
17029 int rb = 29; /* SP */
17030 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17032 gen_ld(ctx, OPC_LW, rd, rb, offset);
17034 break;
17035 case LW16:
17037 int rd = mmreg(uMIPS_RD(ctx->opcode));
17038 int rb = mmreg(uMIPS_RS(ctx->opcode));
17039 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17041 gen_ld(ctx, OPC_LW, rd, rb, offset);
17043 break;
17044 case SB16:
17046 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17047 int rb = mmreg(uMIPS_RS(ctx->opcode));
17048 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17050 gen_st(ctx, OPC_SB, rd, rb, offset);
17052 break;
17053 case SH16:
17055 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17056 int rb = mmreg(uMIPS_RS(ctx->opcode));
17057 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17059 gen_st(ctx, OPC_SH, rd, rb, offset);
17061 break;
17062 case SWSP16:
17064 int rd = (ctx->opcode >> 5) & 0x1f;
17065 int rb = 29; /* SP */
17066 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17068 gen_st(ctx, OPC_SW, rd, rb, offset);
17070 break;
17071 case SW16:
17073 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17074 int rb = mmreg(uMIPS_RS(ctx->opcode));
17075 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17077 gen_st(ctx, OPC_SW, rd, rb, offset);
17079 break;
17080 case MOVE16:
17082 int rd = uMIPS_RD5(ctx->opcode);
17083 int rs = uMIPS_RS5(ctx->opcode);
17085 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17087 break;
17088 case ANDI16:
17089 gen_andi16(ctx);
17090 break;
17091 case POOL16D:
17092 switch (ctx->opcode & 0x1) {
17093 case ADDIUS5:
17094 gen_addius5(ctx);
17095 break;
17096 case ADDIUSP:
17097 gen_addiusp(ctx);
17098 break;
17100 break;
17101 case POOL16E:
17102 switch (ctx->opcode & 0x1) {
17103 case ADDIUR2:
17104 gen_addiur2(ctx);
17105 break;
17106 case ADDIUR1SP:
17107 gen_addiur1sp(ctx);
17108 break;
17110 break;
17111 case B16: /* BC16 */
17112 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17113 sextract32(ctx->opcode, 0, 10) << 1,
17114 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17115 break;
17116 case BNEZ16: /* BNEZC16 */
17117 case BEQZ16: /* BEQZC16 */
17118 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17119 mmreg(uMIPS_RD(ctx->opcode)),
17120 0, sextract32(ctx->opcode, 0, 7) << 1,
17121 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17123 break;
17124 case LI16:
17126 int reg = mmreg(uMIPS_RD(ctx->opcode));
17127 int imm = ZIMM(ctx->opcode, 0, 7);
17129 imm = (imm == 0x7f ? -1 : imm);
17130 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17132 break;
17133 case RES_29:
17134 case RES_31:
17135 case RES_39:
17136 generate_exception_end(ctx, EXCP_RI);
17137 break;
17138 default:
17139 decode_micromips32_opc(env, ctx);
17140 return 4;
17143 return 2;
17148 * nanoMIPS opcodes
17152 /* MAJOR, P16, and P32 pools opcodes */
17153 enum {
17154 NM_P_ADDIU = 0x00,
17155 NM_ADDIUPC = 0x01,
17156 NM_MOVE_BALC = 0x02,
17157 NM_P16_MV = 0x04,
17158 NM_LW16 = 0x05,
17159 NM_BC16 = 0x06,
17160 NM_P16_SR = 0x07,
17162 NM_POOL32A = 0x08,
17163 NM_P_BAL = 0x0a,
17164 NM_P16_SHIFT = 0x0c,
17165 NM_LWSP16 = 0x0d,
17166 NM_BALC16 = 0x0e,
17167 NM_P16_4X4 = 0x0f,
17169 NM_P_GP_W = 0x10,
17170 NM_P_GP_BH = 0x11,
17171 NM_P_J = 0x12,
17172 NM_P16C = 0x14,
17173 NM_LWGP16 = 0x15,
17174 NM_P16_LB = 0x17,
17176 NM_P48I = 0x18,
17177 NM_P16_A1 = 0x1c,
17178 NM_LW4X4 = 0x1d,
17179 NM_P16_LH = 0x1f,
17181 NM_P_U12 = 0x20,
17182 NM_P_LS_U12 = 0x21,
17183 NM_P_BR1 = 0x22,
17184 NM_P16_A2 = 0x24,
17185 NM_SW16 = 0x25,
17186 NM_BEQZC16 = 0x26,
17188 NM_POOL32F = 0x28,
17189 NM_P_LS_S9 = 0x29,
17190 NM_P_BR2 = 0x2a,
17192 NM_P16_ADDU = 0x2c,
17193 NM_SWSP16 = 0x2d,
17194 NM_BNEZC16 = 0x2e,
17195 NM_MOVEP = 0x2f,
17197 NM_POOL32S = 0x30,
17198 NM_P_BRI = 0x32,
17199 NM_LI16 = 0x34,
17200 NM_SWGP16 = 0x35,
17201 NM_P16_BR = 0x36,
17203 NM_P_LUI = 0x38,
17204 NM_ANDI16 = 0x3c,
17205 NM_SW4X4 = 0x3d,
17206 NM_MOVEPREV = 0x3f,
17209 /* POOL32A instruction pool */
17210 enum {
17211 NM_POOL32A0 = 0x00,
17212 NM_SPECIAL2 = 0x01,
17213 NM_COP2_1 = 0x02,
17214 NM_UDI = 0x03,
17215 NM_POOL32A5 = 0x05,
17216 NM_POOL32A7 = 0x07,
17219 /* P.GP.W instruction pool */
17220 enum {
17221 NM_ADDIUGP_W = 0x00,
17222 NM_LWGP = 0x02,
17223 NM_SWGP = 0x03,
17226 /* P48I instruction pool */
17227 enum {
17228 NM_LI48 = 0x00,
17229 NM_ADDIU48 = 0x01,
17230 NM_ADDIUGP48 = 0x02,
17231 NM_ADDIUPC48 = 0x03,
17232 NM_LWPC48 = 0x0b,
17233 NM_SWPC48 = 0x0f,
17236 /* P.U12 instruction pool */
17237 enum {
17238 NM_ORI = 0x00,
17239 NM_XORI = 0x01,
17240 NM_ANDI = 0x02,
17241 NM_P_SR = 0x03,
17242 NM_SLTI = 0x04,
17243 NM_SLTIU = 0x05,
17244 NM_SEQI = 0x06,
17245 NM_ADDIUNEG = 0x08,
17246 NM_P_SHIFT = 0x0c,
17247 NM_P_ROTX = 0x0d,
17248 NM_P_INS = 0x0e,
17249 NM_P_EXT = 0x0f,
17252 /* POOL32F instruction pool */
17253 enum {
17254 NM_POOL32F_0 = 0x00,
17255 NM_POOL32F_3 = 0x03,
17256 NM_POOL32F_5 = 0x05,
17259 /* POOL32S instruction pool */
17260 enum {
17261 NM_POOL32S_0 = 0x00,
17262 NM_POOL32S_4 = 0x04,
17265 /* P.LUI instruction pool */
17266 enum {
17267 NM_LUI = 0x00,
17268 NM_ALUIPC = 0x01,
17271 /* P.GP.BH instruction pool */
17272 enum {
17273 NM_LBGP = 0x00,
17274 NM_SBGP = 0x01,
17275 NM_LBUGP = 0x02,
17276 NM_ADDIUGP_B = 0x03,
17277 NM_P_GP_LH = 0x04,
17278 NM_P_GP_SH = 0x05,
17279 NM_P_GP_CP1 = 0x06,
17282 /* P.LS.U12 instruction pool */
17283 enum {
17284 NM_LB = 0x00,
17285 NM_SB = 0x01,
17286 NM_LBU = 0x02,
17287 NM_P_PREFU12 = 0x03,
17288 NM_LH = 0x04,
17289 NM_SH = 0x05,
17290 NM_LHU = 0x06,
17291 NM_LWU = 0x07,
17292 NM_LW = 0x08,
17293 NM_SW = 0x09,
17294 NM_LWC1 = 0x0a,
17295 NM_SWC1 = 0x0b,
17296 NM_LDC1 = 0x0e,
17297 NM_SDC1 = 0x0f,
17300 /* P.LS.S9 instruction pool */
17301 enum {
17302 NM_P_LS_S0 = 0x00,
17303 NM_P_LS_S1 = 0x01,
17304 NM_P_LS_E0 = 0x02,
17305 NM_P_LS_WM = 0x04,
17306 NM_P_LS_UAWM = 0x05,
17309 /* P.BAL instruction pool */
17310 enum {
17311 NM_BC = 0x00,
17312 NM_BALC = 0x01,
17315 /* P.J instruction pool */
17316 enum {
17317 NM_JALRC = 0x00,
17318 NM_JALRC_HB = 0x01,
17319 NM_P_BALRSC = 0x08,
17322 /* P.BR1 instruction pool */
17323 enum {
17324 NM_BEQC = 0x00,
17325 NM_P_BR3A = 0x01,
17326 NM_BGEC = 0x02,
17327 NM_BGEUC = 0x03,
17330 /* P.BR2 instruction pool */
17331 enum {
17332 NM_BNEC = 0x00,
17333 NM_BLTC = 0x02,
17334 NM_BLTUC = 0x03,
17337 /* P.BRI instruction pool */
17338 enum {
17339 NM_BEQIC = 0x00,
17340 NM_BBEQZC = 0x01,
17341 NM_BGEIC = 0x02,
17342 NM_BGEIUC = 0x03,
17343 NM_BNEIC = 0x04,
17344 NM_BBNEZC = 0x05,
17345 NM_BLTIC = 0x06,
17346 NM_BLTIUC = 0x07,
17349 /* P16.SHIFT instruction pool */
17350 enum {
17351 NM_SLL16 = 0x00,
17352 NM_SRL16 = 0x01,
17355 /* POOL16C instruction pool */
17356 enum {
17357 NM_POOL16C_0 = 0x00,
17358 NM_LWXS16 = 0x01,
17361 /* P16.A1 instruction pool */
17362 enum {
17363 NM_ADDIUR1SP = 0x01,
17366 /* P16.A2 instruction pool */
17367 enum {
17368 NM_ADDIUR2 = 0x00,
17369 NM_P_ADDIURS5 = 0x01,
17372 /* P16.ADDU instruction pool */
17373 enum {
17374 NM_ADDU16 = 0x00,
17375 NM_SUBU16 = 0x01,
17378 /* P16.SR instruction pool */
17379 enum {
17380 NM_SAVE16 = 0x00,
17381 NM_RESTORE_JRC16 = 0x01,
17384 /* P16.4X4 instruction pool */
17385 enum {
17386 NM_ADDU4X4 = 0x00,
17387 NM_MUL4X4 = 0x01,
17390 /* P16.LB instruction pool */
17391 enum {
17392 NM_LB16 = 0x00,
17393 NM_SB16 = 0x01,
17394 NM_LBU16 = 0x02,
17397 /* P16.LH instruction pool */
17398 enum {
17399 NM_LH16 = 0x00,
17400 NM_SH16 = 0x01,
17401 NM_LHU16 = 0x02,
17404 /* P.RI instruction pool */
17405 enum {
17406 NM_SIGRIE = 0x00,
17407 NM_P_SYSCALL = 0x01,
17408 NM_BREAK = 0x02,
17409 NM_SDBBP = 0x03,
17412 /* POOL32A0 instruction pool */
17413 enum {
17414 NM_P_TRAP = 0x00,
17415 NM_SEB = 0x01,
17416 NM_SLLV = 0x02,
17417 NM_MUL = 0x03,
17418 NM_MFC0 = 0x06,
17419 NM_MFHC0 = 0x07,
17420 NM_SEH = 0x09,
17421 NM_SRLV = 0x0a,
17422 NM_MUH = 0x0b,
17423 NM_MTC0 = 0x0e,
17424 NM_MTHC0 = 0x0f,
17425 NM_SRAV = 0x12,
17426 NM_MULU = 0x13,
17427 NM_ROTRV = 0x1a,
17428 NM_MUHU = 0x1b,
17429 NM_ADD = 0x22,
17430 NM_DIV = 0x23,
17431 NM_ADDU = 0x2a,
17432 NM_MOD = 0x2b,
17433 NM_SUB = 0x32,
17434 NM_DIVU = 0x33,
17435 NM_RDHWR = 0x38,
17436 NM_SUBU = 0x3a,
17437 NM_MODU = 0x3b,
17438 NM_P_CMOVE = 0x42,
17439 NM_FORK = 0x45,
17440 NM_MFTR = 0x46,
17441 NM_MFHTR = 0x47,
17442 NM_AND = 0x4a,
17443 NM_YIELD = 0x4d,
17444 NM_MTTR = 0x4e,
17445 NM_MTHTR = 0x4f,
17446 NM_OR = 0x52,
17447 NM_D_E_MT_VPE = 0x56,
17448 NM_NOR = 0x5a,
17449 NM_XOR = 0x62,
17450 NM_SLT = 0x6a,
17451 NM_P_SLTU = 0x72,
17452 NM_SOV = 0x7a,
17455 /* POOL32A5 instruction pool */
17456 enum {
17457 NM_CMP_EQ_PH = 0x00,
17458 NM_CMP_LT_PH = 0x08,
17459 NM_CMP_LE_PH = 0x10,
17460 NM_CMPGU_EQ_QB = 0x18,
17461 NM_CMPGU_LT_QB = 0x20,
17462 NM_CMPGU_LE_QB = 0x28,
17463 NM_CMPGDU_EQ_QB = 0x30,
17464 NM_CMPGDU_LT_QB = 0x38,
17465 NM_CMPGDU_LE_QB = 0x40,
17466 NM_CMPU_EQ_QB = 0x48,
17467 NM_CMPU_LT_QB = 0x50,
17468 NM_CMPU_LE_QB = 0x58,
17469 NM_ADDQ_S_W = 0x60,
17470 NM_SUBQ_S_W = 0x68,
17471 NM_ADDSC = 0x70,
17472 NM_ADDWC = 0x78,
17474 NM_ADDQ_S_PH = 0x01,
17475 NM_ADDQH_R_PH = 0x09,
17476 NM_ADDQH_R_W = 0x11,
17477 NM_ADDU_S_QB = 0x19,
17478 NM_ADDU_S_PH = 0x21,
17479 NM_ADDUH_R_QB = 0x29,
17480 NM_SHRAV_R_PH = 0x31,
17481 NM_SHRAV_R_QB = 0x39,
17482 NM_SUBQ_S_PH = 0x41,
17483 NM_SUBQH_R_PH = 0x49,
17484 NM_SUBQH_R_W = 0x51,
17485 NM_SUBU_S_QB = 0x59,
17486 NM_SUBU_S_PH = 0x61,
17487 NM_SUBUH_R_QB = 0x69,
17488 NM_SHLLV_S_PH = 0x71,
17489 NM_PRECR_SRA_R_PH_W = 0x79,
17491 NM_MULEU_S_PH_QBL = 0x12,
17492 NM_MULEU_S_PH_QBR = 0x1a,
17493 NM_MULQ_RS_PH = 0x22,
17494 NM_MULQ_S_PH = 0x2a,
17495 NM_MULQ_RS_W = 0x32,
17496 NM_MULQ_S_W = 0x3a,
17497 NM_APPEND = 0x42,
17498 NM_MODSUB = 0x52,
17499 NM_SHRAV_R_W = 0x5a,
17500 NM_SHRLV_PH = 0x62,
17501 NM_SHRLV_QB = 0x6a,
17502 NM_SHLLV_QB = 0x72,
17503 NM_SHLLV_S_W = 0x7a,
17505 NM_SHILO = 0x03,
17507 NM_MULEQ_S_W_PHL = 0x04,
17508 NM_MULEQ_S_W_PHR = 0x0c,
17510 NM_MUL_S_PH = 0x05,
17511 NM_PRECR_QB_PH = 0x0d,
17512 NM_PRECRQ_QB_PH = 0x15,
17513 NM_PRECRQ_PH_W = 0x1d,
17514 NM_PRECRQ_RS_PH_W = 0x25,
17515 NM_PRECRQU_S_QB_PH = 0x2d,
17516 NM_PACKRL_PH = 0x35,
17517 NM_PICK_QB = 0x3d,
17518 NM_PICK_PH = 0x45,
17520 NM_SHRA_R_W = 0x5e,
17521 NM_SHRA_R_PH = 0x66,
17522 NM_SHLL_S_PH = 0x76,
17523 NM_SHLL_S_W = 0x7e,
17525 NM_REPL_PH = 0x07
17528 /* POOL32A7 instruction pool */
17529 enum {
17530 NM_P_LSX = 0x00,
17531 NM_LSA = 0x01,
17532 NM_EXTW = 0x03,
17533 NM_POOL32AXF = 0x07,
17536 /* P.SR instruction pool */
17537 enum {
17538 NM_PP_SR = 0x00,
17539 NM_P_SR_F = 0x01,
17542 /* P.SHIFT instruction pool */
17543 enum {
17544 NM_P_SLL = 0x00,
17545 NM_SRL = 0x02,
17546 NM_SRA = 0x04,
17547 NM_ROTR = 0x06,
17550 /* P.ROTX instruction pool */
17551 enum {
17552 NM_ROTX = 0x00,
17555 /* P.INS instruction pool */
17556 enum {
17557 NM_INS = 0x00,
17560 /* P.EXT instruction pool */
17561 enum {
17562 NM_EXT = 0x00,
17565 /* POOL32F_0 (fmt) instruction pool */
17566 enum {
17567 NM_RINT_S = 0x04,
17568 NM_RINT_D = 0x44,
17569 NM_ADD_S = 0x06,
17570 NM_SELEQZ_S = 0x07,
17571 NM_SELEQZ_D = 0x47,
17572 NM_CLASS_S = 0x0c,
17573 NM_CLASS_D = 0x4c,
17574 NM_SUB_S = 0x0e,
17575 NM_SELNEZ_S = 0x0f,
17576 NM_SELNEZ_D = 0x4f,
17577 NM_MUL_S = 0x16,
17578 NM_SEL_S = 0x17,
17579 NM_SEL_D = 0x57,
17580 NM_DIV_S = 0x1e,
17581 NM_ADD_D = 0x26,
17582 NM_SUB_D = 0x2e,
17583 NM_MUL_D = 0x36,
17584 NM_MADDF_S = 0x37,
17585 NM_MADDF_D = 0x77,
17586 NM_DIV_D = 0x3e,
17587 NM_MSUBF_S = 0x3f,
17588 NM_MSUBF_D = 0x7f,
17591 /* POOL32F_3 instruction pool */
17592 enum {
17593 NM_MIN_FMT = 0x00,
17594 NM_MAX_FMT = 0x01,
17595 NM_MINA_FMT = 0x04,
17596 NM_MAXA_FMT = 0x05,
17597 NM_POOL32FXF = 0x07,
17600 /* POOL32F_5 instruction pool */
17601 enum {
17602 NM_CMP_CONDN_S = 0x00,
17603 NM_CMP_CONDN_D = 0x02,
17606 /* P.GP.LH instruction pool */
17607 enum {
17608 NM_LHGP = 0x00,
17609 NM_LHUGP = 0x01,
17612 /* P.GP.SH instruction pool */
17613 enum {
17614 NM_SHGP = 0x00,
17617 /* P.GP.CP1 instruction pool */
17618 enum {
17619 NM_LWC1GP = 0x00,
17620 NM_SWC1GP = 0x01,
17621 NM_LDC1GP = 0x02,
17622 NM_SDC1GP = 0x03,
17625 /* P.LS.S0 instruction pool */
17626 enum {
17627 NM_LBS9 = 0x00,
17628 NM_LHS9 = 0x04,
17629 NM_LWS9 = 0x08,
17630 NM_LDS9 = 0x0c,
17632 NM_SBS9 = 0x01,
17633 NM_SHS9 = 0x05,
17634 NM_SWS9 = 0x09,
17635 NM_SDS9 = 0x0d,
17637 NM_LBUS9 = 0x02,
17638 NM_LHUS9 = 0x06,
17639 NM_LWC1S9 = 0x0a,
17640 NM_LDC1S9 = 0x0e,
17642 NM_P_PREFS9 = 0x03,
17643 NM_LWUS9 = 0x07,
17644 NM_SWC1S9 = 0x0b,
17645 NM_SDC1S9 = 0x0f,
17648 /* P.LS.S1 instruction pool */
17649 enum {
17650 NM_ASET_ACLR = 0x02,
17651 NM_UALH = 0x04,
17652 NM_UASH = 0x05,
17653 NM_CACHE = 0x07,
17654 NM_P_LL = 0x0a,
17655 NM_P_SC = 0x0b,
17658 /* P.LS.E0 instruction pool */
17659 enum {
17660 NM_LBE = 0x00,
17661 NM_SBE = 0x01,
17662 NM_LBUE = 0x02,
17663 NM_P_PREFE = 0x03,
17664 NM_LHE = 0x04,
17665 NM_SHE = 0x05,
17666 NM_LHUE = 0x06,
17667 NM_CACHEE = 0x07,
17668 NM_LWE = 0x08,
17669 NM_SWE = 0x09,
17670 NM_P_LLE = 0x0a,
17671 NM_P_SCE = 0x0b,
17674 /* P.PREFE instruction pool */
17675 enum {
17676 NM_SYNCIE = 0x00,
17677 NM_PREFE = 0x01,
17680 /* P.LLE instruction pool */
17681 enum {
17682 NM_LLE = 0x00,
17683 NM_LLWPE = 0x01,
17686 /* P.SCE instruction pool */
17687 enum {
17688 NM_SCE = 0x00,
17689 NM_SCWPE = 0x01,
17692 /* P.LS.WM instruction pool */
17693 enum {
17694 NM_LWM = 0x00,
17695 NM_SWM = 0x01,
17698 /* P.LS.UAWM instruction pool */
17699 enum {
17700 NM_UALWM = 0x00,
17701 NM_UASWM = 0x01,
17704 /* P.BR3A instruction pool */
17705 enum {
17706 NM_BC1EQZC = 0x00,
17707 NM_BC1NEZC = 0x01,
17708 NM_BC2EQZC = 0x02,
17709 NM_BC2NEZC = 0x03,
17710 NM_BPOSGE32C = 0x04,
17713 /* P16.RI instruction pool */
17714 enum {
17715 NM_P16_SYSCALL = 0x01,
17716 NM_BREAK16 = 0x02,
17717 NM_SDBBP16 = 0x03,
17720 /* POOL16C_0 instruction pool */
17721 enum {
17722 NM_POOL16C_00 = 0x00,
17725 /* P16.JRC instruction pool */
17726 enum {
17727 NM_JRC = 0x00,
17728 NM_JALRC16 = 0x01,
17731 /* P.SYSCALL instruction pool */
17732 enum {
17733 NM_SYSCALL = 0x00,
17734 NM_HYPCALL = 0x01,
17737 /* P.TRAP instruction pool */
17738 enum {
17739 NM_TEQ = 0x00,
17740 NM_TNE = 0x01,
17743 /* P.CMOVE instruction pool */
17744 enum {
17745 NM_MOVZ = 0x00,
17746 NM_MOVN = 0x01,
17749 /* POOL32Axf instruction pool */
17750 enum {
17751 NM_POOL32AXF_1 = 0x01,
17752 NM_POOL32AXF_2 = 0x02,
17753 NM_POOL32AXF_4 = 0x04,
17754 NM_POOL32AXF_5 = 0x05,
17755 NM_POOL32AXF_7 = 0x07,
17758 /* POOL32Axf_1 instruction pool */
17759 enum {
17760 NM_POOL32AXF_1_0 = 0x00,
17761 NM_POOL32AXF_1_1 = 0x01,
17762 NM_POOL32AXF_1_3 = 0x03,
17763 NM_POOL32AXF_1_4 = 0x04,
17764 NM_POOL32AXF_1_5 = 0x05,
17765 NM_POOL32AXF_1_7 = 0x07,
17768 /* POOL32Axf_2 instruction pool */
17769 enum {
17770 NM_POOL32AXF_2_0_7 = 0x00,
17771 NM_POOL32AXF_2_8_15 = 0x01,
17772 NM_POOL32AXF_2_16_23 = 0x02,
17773 NM_POOL32AXF_2_24_31 = 0x03,
17776 /* POOL32Axf_7 instruction pool */
17777 enum {
17778 NM_SHRA_R_QB = 0x0,
17779 NM_SHRL_PH = 0x1,
17780 NM_REPL_QB = 0x2,
17783 /* POOL32Axf_1_0 instruction pool */
17784 enum {
17785 NM_MFHI = 0x0,
17786 NM_MFLO = 0x1,
17787 NM_MTHI = 0x2,
17788 NM_MTLO = 0x3,
17791 /* POOL32Axf_1_1 instruction pool */
17792 enum {
17793 NM_MTHLIP = 0x0,
17794 NM_SHILOV = 0x1,
17797 /* POOL32Axf_1_3 instruction pool */
17798 enum {
17799 NM_RDDSP = 0x0,
17800 NM_WRDSP = 0x1,
17801 NM_EXTP = 0x2,
17802 NM_EXTPDP = 0x3,
17805 /* POOL32Axf_1_4 instruction pool */
17806 enum {
17807 NM_SHLL_QB = 0x0,
17808 NM_SHRL_QB = 0x1,
17811 /* POOL32Axf_1_5 instruction pool */
17812 enum {
17813 NM_MAQ_S_W_PHR = 0x0,
17814 NM_MAQ_S_W_PHL = 0x1,
17815 NM_MAQ_SA_W_PHR = 0x2,
17816 NM_MAQ_SA_W_PHL = 0x3,
17819 /* POOL32Axf_1_7 instruction pool */
17820 enum {
17821 NM_EXTR_W = 0x0,
17822 NM_EXTR_R_W = 0x1,
17823 NM_EXTR_RS_W = 0x2,
17824 NM_EXTR_S_H = 0x3,
17827 /* POOL32Axf_2_0_7 instruction pool */
17828 enum {
17829 NM_DPA_W_PH = 0x0,
17830 NM_DPAQ_S_W_PH = 0x1,
17831 NM_DPS_W_PH = 0x2,
17832 NM_DPSQ_S_W_PH = 0x3,
17833 NM_BALIGN = 0x4,
17834 NM_MADD = 0x5,
17835 NM_MULT = 0x6,
17836 NM_EXTRV_W = 0x7,
17839 /* POOL32Axf_2_8_15 instruction pool */
17840 enum {
17841 NM_DPAX_W_PH = 0x0,
17842 NM_DPAQ_SA_L_W = 0x1,
17843 NM_DPSX_W_PH = 0x2,
17844 NM_DPSQ_SA_L_W = 0x3,
17845 NM_MADDU = 0x5,
17846 NM_MULTU = 0x6,
17847 NM_EXTRV_R_W = 0x7,
17850 /* POOL32Axf_2_16_23 instruction pool */
17851 enum {
17852 NM_DPAU_H_QBL = 0x0,
17853 NM_DPAQX_S_W_PH = 0x1,
17854 NM_DPSU_H_QBL = 0x2,
17855 NM_DPSQX_S_W_PH = 0x3,
17856 NM_EXTPV = 0x4,
17857 NM_MSUB = 0x5,
17858 NM_MULSA_W_PH = 0x6,
17859 NM_EXTRV_RS_W = 0x7,
17862 /* POOL32Axf_2_24_31 instruction pool */
17863 enum {
17864 NM_DPAU_H_QBR = 0x0,
17865 NM_DPAQX_SA_W_PH = 0x1,
17866 NM_DPSU_H_QBR = 0x2,
17867 NM_DPSQX_SA_W_PH = 0x3,
17868 NM_EXTPDPV = 0x4,
17869 NM_MSUBU = 0x5,
17870 NM_MULSAQ_S_W_PH = 0x6,
17871 NM_EXTRV_S_H = 0x7,
17874 /* POOL32Axf_{4, 5} instruction pool */
17875 enum {
17876 NM_CLO = 0x25,
17877 NM_CLZ = 0x2d,
17879 NM_TLBP = 0x01,
17880 NM_TLBR = 0x09,
17881 NM_TLBWI = 0x11,
17882 NM_TLBWR = 0x19,
17883 NM_TLBINV = 0x03,
17884 NM_TLBINVF = 0x0b,
17885 NM_DI = 0x23,
17886 NM_EI = 0x2b,
17887 NM_RDPGPR = 0x70,
17888 NM_WRPGPR = 0x78,
17889 NM_WAIT = 0x61,
17890 NM_DERET = 0x71,
17891 NM_ERETX = 0x79,
17893 /* nanoMIPS DSP instructions */
17894 NM_ABSQ_S_QB = 0x00,
17895 NM_ABSQ_S_PH = 0x08,
17896 NM_ABSQ_S_W = 0x10,
17897 NM_PRECEQ_W_PHL = 0x28,
17898 NM_PRECEQ_W_PHR = 0x30,
17899 NM_PRECEQU_PH_QBL = 0x38,
17900 NM_PRECEQU_PH_QBR = 0x48,
17901 NM_PRECEU_PH_QBL = 0x58,
17902 NM_PRECEU_PH_QBR = 0x68,
17903 NM_PRECEQU_PH_QBLA = 0x39,
17904 NM_PRECEQU_PH_QBRA = 0x49,
17905 NM_PRECEU_PH_QBLA = 0x59,
17906 NM_PRECEU_PH_QBRA = 0x69,
17907 NM_REPLV_PH = 0x01,
17908 NM_REPLV_QB = 0x09,
17909 NM_BITREV = 0x18,
17910 NM_INSV = 0x20,
17911 NM_RADDU_W_QB = 0x78,
17913 NM_BITSWAP = 0x05,
17914 NM_WSBH = 0x3d,
17917 /* PP.SR instruction pool */
17918 enum {
17919 NM_SAVE = 0x00,
17920 NM_RESTORE = 0x02,
17921 NM_RESTORE_JRC = 0x03,
17924 /* P.SR.F instruction pool */
17925 enum {
17926 NM_SAVEF = 0x00,
17927 NM_RESTOREF = 0x01,
17930 /* P16.SYSCALL instruction pool */
17931 enum {
17932 NM_SYSCALL16 = 0x00,
17933 NM_HYPCALL16 = 0x01,
17936 /* POOL16C_00 instruction pool */
17937 enum {
17938 NM_NOT16 = 0x00,
17939 NM_XOR16 = 0x01,
17940 NM_AND16 = 0x02,
17941 NM_OR16 = 0x03,
17944 /* PP.LSX and PP.LSXS instruction pool */
17945 enum {
17946 NM_LBX = 0x00,
17947 NM_LHX = 0x04,
17948 NM_LWX = 0x08,
17949 NM_LDX = 0x0c,
17951 NM_SBX = 0x01,
17952 NM_SHX = 0x05,
17953 NM_SWX = 0x09,
17954 NM_SDX = 0x0d,
17956 NM_LBUX = 0x02,
17957 NM_LHUX = 0x06,
17958 NM_LWC1X = 0x0a,
17959 NM_LDC1X = 0x0e,
17961 NM_LWUX = 0x07,
17962 NM_SWC1X = 0x0b,
17963 NM_SDC1X = 0x0f,
17965 NM_LHXS = 0x04,
17966 NM_LWXS = 0x08,
17967 NM_LDXS = 0x0c,
17969 NM_SHXS = 0x05,
17970 NM_SWXS = 0x09,
17971 NM_SDXS = 0x0d,
17973 NM_LHUXS = 0x06,
17974 NM_LWC1XS = 0x0a,
17975 NM_LDC1XS = 0x0e,
17977 NM_LWUXS = 0x07,
17978 NM_SWC1XS = 0x0b,
17979 NM_SDC1XS = 0x0f,
17982 /* ERETx instruction pool */
17983 enum {
17984 NM_ERET = 0x00,
17985 NM_ERETNC = 0x01,
17988 /* POOL32FxF_{0, 1} insturction pool */
17989 enum {
17990 NM_CFC1 = 0x40,
17991 NM_CTC1 = 0x60,
17992 NM_MFC1 = 0x80,
17993 NM_MTC1 = 0xa0,
17994 NM_MFHC1 = 0xc0,
17995 NM_MTHC1 = 0xe0,
17997 NM_CVT_S_PL = 0x84,
17998 NM_CVT_S_PU = 0xa4,
18000 NM_CVT_L_S = 0x004,
18001 NM_CVT_L_D = 0x104,
18002 NM_CVT_W_S = 0x024,
18003 NM_CVT_W_D = 0x124,
18005 NM_RSQRT_S = 0x008,
18006 NM_RSQRT_D = 0x108,
18008 NM_SQRT_S = 0x028,
18009 NM_SQRT_D = 0x128,
18011 NM_RECIP_S = 0x048,
18012 NM_RECIP_D = 0x148,
18014 NM_FLOOR_L_S = 0x00c,
18015 NM_FLOOR_L_D = 0x10c,
18017 NM_FLOOR_W_S = 0x02c,
18018 NM_FLOOR_W_D = 0x12c,
18020 NM_CEIL_L_S = 0x04c,
18021 NM_CEIL_L_D = 0x14c,
18022 NM_CEIL_W_S = 0x06c,
18023 NM_CEIL_W_D = 0x16c,
18024 NM_TRUNC_L_S = 0x08c,
18025 NM_TRUNC_L_D = 0x18c,
18026 NM_TRUNC_W_S = 0x0ac,
18027 NM_TRUNC_W_D = 0x1ac,
18028 NM_ROUND_L_S = 0x0cc,
18029 NM_ROUND_L_D = 0x1cc,
18030 NM_ROUND_W_S = 0x0ec,
18031 NM_ROUND_W_D = 0x1ec,
18033 NM_MOV_S = 0x01,
18034 NM_MOV_D = 0x81,
18035 NM_ABS_S = 0x0d,
18036 NM_ABS_D = 0x8d,
18037 NM_NEG_S = 0x2d,
18038 NM_NEG_D = 0xad,
18039 NM_CVT_D_S = 0x04d,
18040 NM_CVT_D_W = 0x0cd,
18041 NM_CVT_D_L = 0x14d,
18042 NM_CVT_S_D = 0x06d,
18043 NM_CVT_S_W = 0x0ed,
18044 NM_CVT_S_L = 0x16d,
18047 /* P.LL instruction pool */
18048 enum {
18049 NM_LL = 0x00,
18050 NM_LLWP = 0x01,
18053 /* P.SC instruction pool */
18054 enum {
18055 NM_SC = 0x00,
18056 NM_SCWP = 0x01,
18059 /* P.DVP instruction pool */
18060 enum {
18061 NM_DVP = 0x00,
18062 NM_EVP = 0x01,
18068 * nanoMIPS decoding engine
18073 /* extraction utilities */
18075 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18076 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18077 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18078 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18079 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18080 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18082 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18083 static inline int decode_gpr_gpr3(int r)
18085 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18087 return map[r & 0x7];
18090 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18091 static inline int decode_gpr_gpr3_src_store(int r)
18093 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18095 return map[r & 0x7];
18098 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18099 static inline int decode_gpr_gpr4(int r)
18101 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18102 16, 17, 18, 19, 20, 21, 22, 23 };
18104 return map[r & 0xf];
18107 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18108 static inline int decode_gpr_gpr4_zero(int r)
18110 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18111 16, 17, 18, 19, 20, 21, 22, 23 };
18113 return map[r & 0xf];
18117 /* extraction utilities */
18119 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18120 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18121 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18122 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18123 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18124 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18127 static void gen_adjust_sp(DisasContext *ctx, int u)
18129 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18132 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18133 uint8_t gp, uint16_t u)
18135 int counter = 0;
18136 TCGv va = tcg_temp_new();
18137 TCGv t0 = tcg_temp_new();
18139 while (counter != count) {
18140 bool use_gp = gp && (counter == count - 1);
18141 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18142 int this_offset = -((counter + 1) << 2);
18143 gen_base_offset_addr(ctx, va, 29, this_offset);
18144 gen_load_gpr(t0, this_rt);
18145 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18146 (MO_TEUL | ctx->default_tcg_memop_mask));
18147 counter++;
18150 /* adjust stack pointer */
18151 gen_adjust_sp(ctx, -u);
18153 tcg_temp_free(t0);
18154 tcg_temp_free(va);
18157 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18158 uint8_t gp, uint16_t u)
18160 int counter = 0;
18161 TCGv va = tcg_temp_new();
18162 TCGv t0 = tcg_temp_new();
18164 while (counter != count) {
18165 bool use_gp = gp && (counter == count - 1);
18166 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18167 int this_offset = u - ((counter + 1) << 2);
18168 gen_base_offset_addr(ctx, va, 29, this_offset);
18169 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18170 ctx->default_tcg_memop_mask);
18171 tcg_gen_ext32s_tl(t0, t0);
18172 gen_store_gpr(t0, this_rt);
18173 counter++;
18176 /* adjust stack pointer */
18177 gen_adjust_sp(ctx, u);
18179 tcg_temp_free(t0);
18180 tcg_temp_free(va);
18183 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18185 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18186 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18188 switch (extract32(ctx->opcode, 2, 2)) {
18189 case NM_NOT16:
18190 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18191 break;
18192 case NM_AND16:
18193 gen_logic(ctx, OPC_AND, rt, rt, rs);
18194 break;
18195 case NM_XOR16:
18196 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18197 break;
18198 case NM_OR16:
18199 gen_logic(ctx, OPC_OR, rt, rt, rs);
18200 break;
18204 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18206 int rt = extract32(ctx->opcode, 21, 5);
18207 int rs = extract32(ctx->opcode, 16, 5);
18208 int rd = extract32(ctx->opcode, 11, 5);
18210 switch (extract32(ctx->opcode, 3, 7)) {
18211 case NM_P_TRAP:
18212 switch (extract32(ctx->opcode, 10, 1)) {
18213 case NM_TEQ:
18214 check_nms(ctx);
18215 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18216 break;
18217 case NM_TNE:
18218 check_nms(ctx);
18219 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18220 break;
18222 break;
18223 case NM_RDHWR:
18224 check_nms(ctx);
18225 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18226 break;
18227 case NM_SEB:
18228 check_nms(ctx);
18229 gen_bshfl(ctx, OPC_SEB, rs, rt);
18230 break;
18231 case NM_SEH:
18232 gen_bshfl(ctx, OPC_SEH, rs, rt);
18233 break;
18234 case NM_SLLV:
18235 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18236 break;
18237 case NM_SRLV:
18238 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18239 break;
18240 case NM_SRAV:
18241 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18242 break;
18243 case NM_ROTRV:
18244 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18245 break;
18246 case NM_ADD:
18247 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18248 break;
18249 case NM_ADDU:
18250 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18251 break;
18252 case NM_SUB:
18253 check_nms(ctx);
18254 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18255 break;
18256 case NM_SUBU:
18257 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18258 break;
18259 case NM_P_CMOVE:
18260 switch (extract32(ctx->opcode, 10, 1)) {
18261 case NM_MOVZ:
18262 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18263 break;
18264 case NM_MOVN:
18265 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18266 break;
18268 break;
18269 case NM_AND:
18270 gen_logic(ctx, OPC_AND, rd, rs, rt);
18271 break;
18272 case NM_OR:
18273 gen_logic(ctx, OPC_OR, rd, rs, rt);
18274 break;
18275 case NM_NOR:
18276 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18277 break;
18278 case NM_XOR:
18279 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18280 break;
18281 case NM_SLT:
18282 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18283 break;
18284 case NM_P_SLTU:
18285 if (rd == 0) {
18286 /* P_DVP */
18287 #ifndef CONFIG_USER_ONLY
18288 TCGv t0 = tcg_temp_new();
18289 switch (extract32(ctx->opcode, 10, 1)) {
18290 case NM_DVP:
18291 if (ctx->vp) {
18292 check_cp0_enabled(ctx);
18293 gen_helper_dvp(t0, cpu_env);
18294 gen_store_gpr(t0, rt);
18296 break;
18297 case NM_EVP:
18298 if (ctx->vp) {
18299 check_cp0_enabled(ctx);
18300 gen_helper_evp(t0, cpu_env);
18301 gen_store_gpr(t0, rt);
18303 break;
18305 tcg_temp_free(t0);
18306 #endif
18307 } else {
18308 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18310 break;
18311 case NM_SOV:
18313 TCGv t0 = tcg_temp_new();
18314 TCGv t1 = tcg_temp_new();
18315 TCGv t2 = tcg_temp_new();
18317 gen_load_gpr(t1, rs);
18318 gen_load_gpr(t2, rt);
18319 tcg_gen_add_tl(t0, t1, t2);
18320 tcg_gen_ext32s_tl(t0, t0);
18321 tcg_gen_xor_tl(t1, t1, t2);
18322 tcg_gen_xor_tl(t2, t0, t2);
18323 tcg_gen_andc_tl(t1, t2, t1);
18325 /* operands of same sign, result different sign */
18326 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18327 gen_store_gpr(t0, rd);
18329 tcg_temp_free(t0);
18330 tcg_temp_free(t1);
18331 tcg_temp_free(t2);
18333 break;
18334 case NM_MUL:
18335 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18336 break;
18337 case NM_MUH:
18338 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18339 break;
18340 case NM_MULU:
18341 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18342 break;
18343 case NM_MUHU:
18344 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18345 break;
18346 case NM_DIV:
18347 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18348 break;
18349 case NM_MOD:
18350 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18351 break;
18352 case NM_DIVU:
18353 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18354 break;
18355 case NM_MODU:
18356 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18357 break;
18358 #ifndef CONFIG_USER_ONLY
18359 case NM_MFC0:
18360 check_cp0_enabled(ctx);
18361 if (rt == 0) {
18362 /* Treat as NOP. */
18363 break;
18365 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18366 break;
18367 case NM_MTC0:
18368 check_cp0_enabled(ctx);
18370 TCGv t0 = tcg_temp_new();
18372 gen_load_gpr(t0, rt);
18373 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18374 tcg_temp_free(t0);
18376 break;
18377 case NM_D_E_MT_VPE:
18379 uint8_t sc = extract32(ctx->opcode, 10, 1);
18380 TCGv t0 = tcg_temp_new();
18382 switch (sc) {
18383 case 0:
18384 if (rs == 1) {
18385 /* DMT */
18386 check_cp0_mt(ctx);
18387 gen_helper_dmt(t0);
18388 gen_store_gpr(t0, rt);
18389 } else if (rs == 0) {
18390 /* DVPE */
18391 check_cp0_mt(ctx);
18392 gen_helper_dvpe(t0, cpu_env);
18393 gen_store_gpr(t0, rt);
18394 } else {
18395 generate_exception_end(ctx, EXCP_RI);
18397 break;
18398 case 1:
18399 if (rs == 1) {
18400 /* EMT */
18401 check_cp0_mt(ctx);
18402 gen_helper_emt(t0);
18403 gen_store_gpr(t0, rt);
18404 } else if (rs == 0) {
18405 /* EVPE */
18406 check_cp0_mt(ctx);
18407 gen_helper_evpe(t0, cpu_env);
18408 gen_store_gpr(t0, rt);
18409 } else {
18410 generate_exception_end(ctx, EXCP_RI);
18412 break;
18415 tcg_temp_free(t0);
18417 break;
18418 case NM_FORK:
18419 check_mt(ctx);
18421 TCGv t0 = tcg_temp_new();
18422 TCGv t1 = tcg_temp_new();
18424 gen_load_gpr(t0, rt);
18425 gen_load_gpr(t1, rs);
18426 gen_helper_fork(t0, t1);
18427 tcg_temp_free(t0);
18428 tcg_temp_free(t1);
18430 break;
18431 case NM_MFTR:
18432 case NM_MFHTR:
18433 check_cp0_enabled(ctx);
18434 if (rd == 0) {
18435 /* Treat as NOP. */
18436 return;
18438 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18439 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18440 break;
18441 case NM_MTTR:
18442 case NM_MTHTR:
18443 check_cp0_enabled(ctx);
18444 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18445 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18446 break;
18447 case NM_YIELD:
18448 check_mt(ctx);
18450 TCGv t0 = tcg_temp_new();
18452 gen_load_gpr(t0, rs);
18453 gen_helper_yield(t0, cpu_env, t0);
18454 gen_store_gpr(t0, rt);
18455 tcg_temp_free(t0);
18457 break;
18458 #endif
18459 default:
18460 generate_exception_end(ctx, EXCP_RI);
18461 break;
18465 /* dsp */
18466 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18467 int ret, int v1, int v2)
18469 TCGv_i32 t0;
18470 TCGv v0_t;
18471 TCGv v1_t;
18473 t0 = tcg_temp_new_i32();
18475 v0_t = tcg_temp_new();
18476 v1_t = tcg_temp_new();
18478 tcg_gen_movi_i32(t0, v2 >> 3);
18480 gen_load_gpr(v0_t, ret);
18481 gen_load_gpr(v1_t, v1);
18483 switch (opc) {
18484 case NM_MAQ_S_W_PHR:
18485 check_dsp(ctx);
18486 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18487 break;
18488 case NM_MAQ_S_W_PHL:
18489 check_dsp(ctx);
18490 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18491 break;
18492 case NM_MAQ_SA_W_PHR:
18493 check_dsp(ctx);
18494 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18495 break;
18496 case NM_MAQ_SA_W_PHL:
18497 check_dsp(ctx);
18498 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18499 break;
18500 default:
18501 generate_exception_end(ctx, EXCP_RI);
18502 break;
18505 tcg_temp_free_i32(t0);
18507 tcg_temp_free(v0_t);
18508 tcg_temp_free(v1_t);
18512 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18513 int ret, int v1, int v2)
18515 int16_t imm;
18516 TCGv t0 = tcg_temp_new();
18517 TCGv t1 = tcg_temp_new();
18518 TCGv v0_t = tcg_temp_new();
18520 gen_load_gpr(v0_t, v1);
18522 switch (opc) {
18523 case NM_POOL32AXF_1_0:
18524 check_dsp(ctx);
18525 switch (extract32(ctx->opcode, 12, 2)) {
18526 case NM_MFHI:
18527 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18528 break;
18529 case NM_MFLO:
18530 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18531 break;
18532 case NM_MTHI:
18533 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18534 break;
18535 case NM_MTLO:
18536 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18537 break;
18539 break;
18540 case NM_POOL32AXF_1_1:
18541 check_dsp(ctx);
18542 switch (extract32(ctx->opcode, 12, 2)) {
18543 case NM_MTHLIP:
18544 tcg_gen_movi_tl(t0, v2);
18545 gen_helper_mthlip(t0, v0_t, cpu_env);
18546 break;
18547 case NM_SHILOV:
18548 tcg_gen_movi_tl(t0, v2 >> 3);
18549 gen_helper_shilo(t0, v0_t, cpu_env);
18550 break;
18551 default:
18552 generate_exception_end(ctx, EXCP_RI);
18553 break;
18555 break;
18556 case NM_POOL32AXF_1_3:
18557 check_dsp(ctx);
18558 imm = extract32(ctx->opcode, 14, 7);
18559 switch (extract32(ctx->opcode, 12, 2)) {
18560 case NM_RDDSP:
18561 tcg_gen_movi_tl(t0, imm);
18562 gen_helper_rddsp(t0, t0, cpu_env);
18563 gen_store_gpr(t0, ret);
18564 break;
18565 case NM_WRDSP:
18566 gen_load_gpr(t0, ret);
18567 tcg_gen_movi_tl(t1, imm);
18568 gen_helper_wrdsp(t0, t1, cpu_env);
18569 break;
18570 case NM_EXTP:
18571 tcg_gen_movi_tl(t0, v2 >> 3);
18572 tcg_gen_movi_tl(t1, v1);
18573 gen_helper_extp(t0, t0, t1, cpu_env);
18574 gen_store_gpr(t0, ret);
18575 break;
18576 case NM_EXTPDP:
18577 tcg_gen_movi_tl(t0, v2 >> 3);
18578 tcg_gen_movi_tl(t1, v1);
18579 gen_helper_extpdp(t0, t0, t1, cpu_env);
18580 gen_store_gpr(t0, ret);
18581 break;
18583 break;
18584 case NM_POOL32AXF_1_4:
18585 check_dsp(ctx);
18586 tcg_gen_movi_tl(t0, v2 >> 2);
18587 switch (extract32(ctx->opcode, 12, 1)) {
18588 case NM_SHLL_QB:
18589 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18590 gen_store_gpr(t0, ret);
18591 break;
18592 case NM_SHRL_QB:
18593 gen_helper_shrl_qb(t0, t0, v0_t);
18594 gen_store_gpr(t0, ret);
18595 break;
18597 break;
18598 case NM_POOL32AXF_1_5:
18599 opc = extract32(ctx->opcode, 12, 2);
18600 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18601 break;
18602 case NM_POOL32AXF_1_7:
18603 check_dsp(ctx);
18604 tcg_gen_movi_tl(t0, v2 >> 3);
18605 tcg_gen_movi_tl(t1, v1);
18606 switch (extract32(ctx->opcode, 12, 2)) {
18607 case NM_EXTR_W:
18608 gen_helper_extr_w(t0, t0, t1, cpu_env);
18609 gen_store_gpr(t0, ret);
18610 break;
18611 case NM_EXTR_R_W:
18612 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18613 gen_store_gpr(t0, ret);
18614 break;
18615 case NM_EXTR_RS_W:
18616 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18617 gen_store_gpr(t0, ret);
18618 break;
18619 case NM_EXTR_S_H:
18620 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18621 gen_store_gpr(t0, ret);
18622 break;
18624 break;
18625 default:
18626 generate_exception_end(ctx, EXCP_RI);
18627 break;
18630 tcg_temp_free(t0);
18631 tcg_temp_free(t1);
18632 tcg_temp_free(v0_t);
18635 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18636 TCGv v0, TCGv v1, int rd)
18638 TCGv_i32 t0;
18640 t0 = tcg_temp_new_i32();
18642 tcg_gen_movi_i32(t0, rd >> 3);
18644 switch (opc) {
18645 case NM_POOL32AXF_2_0_7:
18646 switch (extract32(ctx->opcode, 9, 3)) {
18647 case NM_DPA_W_PH:
18648 check_dsp_r2(ctx);
18649 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18650 break;
18651 case NM_DPAQ_S_W_PH:
18652 check_dsp(ctx);
18653 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18654 break;
18655 case NM_DPS_W_PH:
18656 check_dsp_r2(ctx);
18657 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18658 break;
18659 case NM_DPSQ_S_W_PH:
18660 check_dsp(ctx);
18661 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18662 break;
18663 default:
18664 generate_exception_end(ctx, EXCP_RI);
18665 break;
18667 break;
18668 case NM_POOL32AXF_2_8_15:
18669 switch (extract32(ctx->opcode, 9, 3)) {
18670 case NM_DPAX_W_PH:
18671 check_dsp_r2(ctx);
18672 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18673 break;
18674 case NM_DPAQ_SA_L_W:
18675 check_dsp(ctx);
18676 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18677 break;
18678 case NM_DPSX_W_PH:
18679 check_dsp_r2(ctx);
18680 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18681 break;
18682 case NM_DPSQ_SA_L_W:
18683 check_dsp(ctx);
18684 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18685 break;
18686 default:
18687 generate_exception_end(ctx, EXCP_RI);
18688 break;
18690 break;
18691 case NM_POOL32AXF_2_16_23:
18692 switch (extract32(ctx->opcode, 9, 3)) {
18693 case NM_DPAU_H_QBL:
18694 check_dsp(ctx);
18695 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18696 break;
18697 case NM_DPAQX_S_W_PH:
18698 check_dsp_r2(ctx);
18699 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18700 break;
18701 case NM_DPSU_H_QBL:
18702 check_dsp(ctx);
18703 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18704 break;
18705 case NM_DPSQX_S_W_PH:
18706 check_dsp_r2(ctx);
18707 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18708 break;
18709 case NM_MULSA_W_PH:
18710 check_dsp_r2(ctx);
18711 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18712 break;
18713 default:
18714 generate_exception_end(ctx, EXCP_RI);
18715 break;
18717 break;
18718 case NM_POOL32AXF_2_24_31:
18719 switch (extract32(ctx->opcode, 9, 3)) {
18720 case NM_DPAU_H_QBR:
18721 check_dsp(ctx);
18722 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18723 break;
18724 case NM_DPAQX_SA_W_PH:
18725 check_dsp_r2(ctx);
18726 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18727 break;
18728 case NM_DPSU_H_QBR:
18729 check_dsp(ctx);
18730 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18731 break;
18732 case NM_DPSQX_SA_W_PH:
18733 check_dsp_r2(ctx);
18734 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18735 break;
18736 case NM_MULSAQ_S_W_PH:
18737 check_dsp(ctx);
18738 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18739 break;
18740 default:
18741 generate_exception_end(ctx, EXCP_RI);
18742 break;
18744 break;
18745 default:
18746 generate_exception_end(ctx, EXCP_RI);
18747 break;
18750 tcg_temp_free_i32(t0);
18753 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18754 int rt, int rs, int rd)
18756 int ret = rt;
18757 TCGv t0 = tcg_temp_new();
18758 TCGv t1 = tcg_temp_new();
18759 TCGv v0_t = tcg_temp_new();
18760 TCGv v1_t = tcg_temp_new();
18762 gen_load_gpr(v0_t, rt);
18763 gen_load_gpr(v1_t, rs);
18765 switch (opc) {
18766 case NM_POOL32AXF_2_0_7:
18767 switch (extract32(ctx->opcode, 9, 3)) {
18768 case NM_DPA_W_PH:
18769 case NM_DPAQ_S_W_PH:
18770 case NM_DPS_W_PH:
18771 case NM_DPSQ_S_W_PH:
18772 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18773 break;
18774 case NM_BALIGN:
18775 check_dsp_r2(ctx);
18776 if (rt != 0) {
18777 gen_load_gpr(t0, rs);
18778 rd &= 3;
18779 if (rd != 0 && rd != 2) {
18780 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18781 tcg_gen_ext32u_tl(t0, t0);
18782 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18783 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18785 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18787 break;
18788 case NM_MADD:
18789 check_dsp(ctx);
18791 int acc = extract32(ctx->opcode, 14, 2);
18792 TCGv_i64 t2 = tcg_temp_new_i64();
18793 TCGv_i64 t3 = tcg_temp_new_i64();
18795 gen_load_gpr(t0, rt);
18796 gen_load_gpr(t1, rs);
18797 tcg_gen_ext_tl_i64(t2, t0);
18798 tcg_gen_ext_tl_i64(t3, t1);
18799 tcg_gen_mul_i64(t2, t2, t3);
18800 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18801 tcg_gen_add_i64(t2, t2, t3);
18802 tcg_temp_free_i64(t3);
18803 gen_move_low32(cpu_LO[acc], t2);
18804 gen_move_high32(cpu_HI[acc], t2);
18805 tcg_temp_free_i64(t2);
18807 break;
18808 case NM_MULT:
18809 check_dsp(ctx);
18811 int acc = extract32(ctx->opcode, 14, 2);
18812 TCGv_i32 t2 = tcg_temp_new_i32();
18813 TCGv_i32 t3 = tcg_temp_new_i32();
18815 gen_load_gpr(t0, rs);
18816 gen_load_gpr(t1, rt);
18817 tcg_gen_trunc_tl_i32(t2, t0);
18818 tcg_gen_trunc_tl_i32(t3, t1);
18819 tcg_gen_muls2_i32(t2, t3, t2, t3);
18820 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18821 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18822 tcg_temp_free_i32(t2);
18823 tcg_temp_free_i32(t3);
18825 break;
18826 case NM_EXTRV_W:
18827 check_dsp(ctx);
18828 gen_load_gpr(v1_t, rs);
18829 tcg_gen_movi_tl(t0, rd >> 3);
18830 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18831 gen_store_gpr(t0, ret);
18832 break;
18834 break;
18835 case NM_POOL32AXF_2_8_15:
18836 switch (extract32(ctx->opcode, 9, 3)) {
18837 case NM_DPAX_W_PH:
18838 case NM_DPAQ_SA_L_W:
18839 case NM_DPSX_W_PH:
18840 case NM_DPSQ_SA_L_W:
18841 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18842 break;
18843 case NM_MADDU:
18844 check_dsp(ctx);
18846 int acc = extract32(ctx->opcode, 14, 2);
18847 TCGv_i64 t2 = tcg_temp_new_i64();
18848 TCGv_i64 t3 = tcg_temp_new_i64();
18850 gen_load_gpr(t0, rs);
18851 gen_load_gpr(t1, rt);
18852 tcg_gen_ext32u_tl(t0, t0);
18853 tcg_gen_ext32u_tl(t1, t1);
18854 tcg_gen_extu_tl_i64(t2, t0);
18855 tcg_gen_extu_tl_i64(t3, t1);
18856 tcg_gen_mul_i64(t2, t2, t3);
18857 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18858 tcg_gen_add_i64(t2, t2, t3);
18859 tcg_temp_free_i64(t3);
18860 gen_move_low32(cpu_LO[acc], t2);
18861 gen_move_high32(cpu_HI[acc], t2);
18862 tcg_temp_free_i64(t2);
18864 break;
18865 case NM_MULTU:
18866 check_dsp(ctx);
18868 int acc = extract32(ctx->opcode, 14, 2);
18869 TCGv_i32 t2 = tcg_temp_new_i32();
18870 TCGv_i32 t3 = tcg_temp_new_i32();
18872 gen_load_gpr(t0, rs);
18873 gen_load_gpr(t1, rt);
18874 tcg_gen_trunc_tl_i32(t2, t0);
18875 tcg_gen_trunc_tl_i32(t3, t1);
18876 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18877 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18878 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18879 tcg_temp_free_i32(t2);
18880 tcg_temp_free_i32(t3);
18882 break;
18883 case NM_EXTRV_R_W:
18884 check_dsp(ctx);
18885 tcg_gen_movi_tl(t0, rd >> 3);
18886 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18887 gen_store_gpr(t0, ret);
18888 break;
18889 default:
18890 generate_exception_end(ctx, EXCP_RI);
18891 break;
18893 break;
18894 case NM_POOL32AXF_2_16_23:
18895 switch (extract32(ctx->opcode, 9, 3)) {
18896 case NM_DPAU_H_QBL:
18897 case NM_DPAQX_S_W_PH:
18898 case NM_DPSU_H_QBL:
18899 case NM_DPSQX_S_W_PH:
18900 case NM_MULSA_W_PH:
18901 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18902 break;
18903 case NM_EXTPV:
18904 check_dsp(ctx);
18905 tcg_gen_movi_tl(t0, rd >> 3);
18906 gen_helper_extp(t0, t0, v1_t, cpu_env);
18907 gen_store_gpr(t0, ret);
18908 break;
18909 case NM_MSUB:
18910 check_dsp(ctx);
18912 int acc = extract32(ctx->opcode, 14, 2);
18913 TCGv_i64 t2 = tcg_temp_new_i64();
18914 TCGv_i64 t3 = tcg_temp_new_i64();
18916 gen_load_gpr(t0, rs);
18917 gen_load_gpr(t1, rt);
18918 tcg_gen_ext_tl_i64(t2, t0);
18919 tcg_gen_ext_tl_i64(t3, t1);
18920 tcg_gen_mul_i64(t2, t2, t3);
18921 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18922 tcg_gen_sub_i64(t2, t3, t2);
18923 tcg_temp_free_i64(t3);
18924 gen_move_low32(cpu_LO[acc], t2);
18925 gen_move_high32(cpu_HI[acc], t2);
18926 tcg_temp_free_i64(t2);
18928 break;
18929 case NM_EXTRV_RS_W:
18930 check_dsp(ctx);
18931 tcg_gen_movi_tl(t0, rd >> 3);
18932 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18933 gen_store_gpr(t0, ret);
18934 break;
18936 break;
18937 case NM_POOL32AXF_2_24_31:
18938 switch (extract32(ctx->opcode, 9, 3)) {
18939 case NM_DPAU_H_QBR:
18940 case NM_DPAQX_SA_W_PH:
18941 case NM_DPSU_H_QBR:
18942 case NM_DPSQX_SA_W_PH:
18943 case NM_MULSAQ_S_W_PH:
18944 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18945 break;
18946 case NM_EXTPDPV:
18947 check_dsp(ctx);
18948 tcg_gen_movi_tl(t0, rd >> 3);
18949 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18950 gen_store_gpr(t0, ret);
18951 break;
18952 case NM_MSUBU:
18953 check_dsp(ctx);
18955 int acc = extract32(ctx->opcode, 14, 2);
18956 TCGv_i64 t2 = tcg_temp_new_i64();
18957 TCGv_i64 t3 = tcg_temp_new_i64();
18959 gen_load_gpr(t0, rs);
18960 gen_load_gpr(t1, rt);
18961 tcg_gen_ext32u_tl(t0, t0);
18962 tcg_gen_ext32u_tl(t1, t1);
18963 tcg_gen_extu_tl_i64(t2, t0);
18964 tcg_gen_extu_tl_i64(t3, t1);
18965 tcg_gen_mul_i64(t2, t2, t3);
18966 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18967 tcg_gen_sub_i64(t2, t3, t2);
18968 tcg_temp_free_i64(t3);
18969 gen_move_low32(cpu_LO[acc], t2);
18970 gen_move_high32(cpu_HI[acc], t2);
18971 tcg_temp_free_i64(t2);
18973 break;
18974 case NM_EXTRV_S_H:
18975 check_dsp(ctx);
18976 tcg_gen_movi_tl(t0, rd >> 3);
18977 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18978 gen_store_gpr(t0, ret);
18979 break;
18981 break;
18982 default:
18983 generate_exception_end(ctx, EXCP_RI);
18984 break;
18987 tcg_temp_free(t0);
18988 tcg_temp_free(t1);
18990 tcg_temp_free(v0_t);
18991 tcg_temp_free(v1_t);
18994 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18995 int rt, int rs)
18997 int ret = rt;
18998 TCGv t0 = tcg_temp_new();
18999 TCGv v0_t = tcg_temp_new();
19001 gen_load_gpr(v0_t, rs);
19003 switch (opc) {
19004 case NM_ABSQ_S_QB:
19005 check_dsp_r2(ctx);
19006 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19007 gen_store_gpr(v0_t, ret);
19008 break;
19009 case NM_ABSQ_S_PH:
19010 check_dsp(ctx);
19011 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19012 gen_store_gpr(v0_t, ret);
19013 break;
19014 case NM_ABSQ_S_W:
19015 check_dsp(ctx);
19016 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19017 gen_store_gpr(v0_t, ret);
19018 break;
19019 case NM_PRECEQ_W_PHL:
19020 check_dsp(ctx);
19021 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19022 tcg_gen_ext32s_tl(v0_t, v0_t);
19023 gen_store_gpr(v0_t, ret);
19024 break;
19025 case NM_PRECEQ_W_PHR:
19026 check_dsp(ctx);
19027 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19028 tcg_gen_shli_tl(v0_t, v0_t, 16);
19029 tcg_gen_ext32s_tl(v0_t, v0_t);
19030 gen_store_gpr(v0_t, ret);
19031 break;
19032 case NM_PRECEQU_PH_QBL:
19033 check_dsp(ctx);
19034 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19035 gen_store_gpr(v0_t, ret);
19036 break;
19037 case NM_PRECEQU_PH_QBR:
19038 check_dsp(ctx);
19039 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19040 gen_store_gpr(v0_t, ret);
19041 break;
19042 case NM_PRECEQU_PH_QBLA:
19043 check_dsp(ctx);
19044 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19045 gen_store_gpr(v0_t, ret);
19046 break;
19047 case NM_PRECEQU_PH_QBRA:
19048 check_dsp(ctx);
19049 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19050 gen_store_gpr(v0_t, ret);
19051 break;
19052 case NM_PRECEU_PH_QBL:
19053 check_dsp(ctx);
19054 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19055 gen_store_gpr(v0_t, ret);
19056 break;
19057 case NM_PRECEU_PH_QBR:
19058 check_dsp(ctx);
19059 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19060 gen_store_gpr(v0_t, ret);
19061 break;
19062 case NM_PRECEU_PH_QBLA:
19063 check_dsp(ctx);
19064 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19065 gen_store_gpr(v0_t, ret);
19066 break;
19067 case NM_PRECEU_PH_QBRA:
19068 check_dsp(ctx);
19069 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19070 gen_store_gpr(v0_t, ret);
19071 break;
19072 case NM_REPLV_PH:
19073 check_dsp(ctx);
19074 tcg_gen_ext16u_tl(v0_t, v0_t);
19075 tcg_gen_shli_tl(t0, v0_t, 16);
19076 tcg_gen_or_tl(v0_t, v0_t, t0);
19077 tcg_gen_ext32s_tl(v0_t, v0_t);
19078 gen_store_gpr(v0_t, ret);
19079 break;
19080 case NM_REPLV_QB:
19081 check_dsp(ctx);
19082 tcg_gen_ext8u_tl(v0_t, v0_t);
19083 tcg_gen_shli_tl(t0, v0_t, 8);
19084 tcg_gen_or_tl(v0_t, v0_t, t0);
19085 tcg_gen_shli_tl(t0, v0_t, 16);
19086 tcg_gen_or_tl(v0_t, v0_t, t0);
19087 tcg_gen_ext32s_tl(v0_t, v0_t);
19088 gen_store_gpr(v0_t, ret);
19089 break;
19090 case NM_BITREV:
19091 check_dsp(ctx);
19092 gen_helper_bitrev(v0_t, v0_t);
19093 gen_store_gpr(v0_t, ret);
19094 break;
19095 case NM_INSV:
19096 check_dsp(ctx);
19098 TCGv tv0 = tcg_temp_new();
19100 gen_load_gpr(tv0, rt);
19101 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19102 gen_store_gpr(v0_t, ret);
19103 tcg_temp_free(tv0);
19105 break;
19106 case NM_RADDU_W_QB:
19107 check_dsp(ctx);
19108 gen_helper_raddu_w_qb(v0_t, v0_t);
19109 gen_store_gpr(v0_t, ret);
19110 break;
19111 case NM_BITSWAP:
19112 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19113 break;
19114 case NM_CLO:
19115 check_nms(ctx);
19116 gen_cl(ctx, OPC_CLO, ret, rs);
19117 break;
19118 case NM_CLZ:
19119 check_nms(ctx);
19120 gen_cl(ctx, OPC_CLZ, ret, rs);
19121 break;
19122 case NM_WSBH:
19123 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19124 break;
19125 default:
19126 generate_exception_end(ctx, EXCP_RI);
19127 break;
19130 tcg_temp_free(v0_t);
19131 tcg_temp_free(t0);
19134 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19135 int rt, int rs, int rd)
19137 TCGv t0 = tcg_temp_new();
19138 TCGv rs_t = tcg_temp_new();
19140 gen_load_gpr(rs_t, rs);
19142 switch (opc) {
19143 case NM_SHRA_R_QB:
19144 check_dsp_r2(ctx);
19145 tcg_gen_movi_tl(t0, rd >> 2);
19146 switch (extract32(ctx->opcode, 12, 1)) {
19147 case 0:
19148 /* NM_SHRA_QB */
19149 gen_helper_shra_qb(t0, t0, rs_t);
19150 gen_store_gpr(t0, rt);
19151 break;
19152 case 1:
19153 /* NM_SHRA_R_QB */
19154 gen_helper_shra_r_qb(t0, t0, rs_t);
19155 gen_store_gpr(t0, rt);
19156 break;
19158 break;
19159 case NM_SHRL_PH:
19160 check_dsp_r2(ctx);
19161 tcg_gen_movi_tl(t0, rd >> 1);
19162 gen_helper_shrl_ph(t0, t0, rs_t);
19163 gen_store_gpr(t0, rt);
19164 break;
19165 case NM_REPL_QB:
19166 check_dsp(ctx);
19168 int16_t imm;
19169 target_long result;
19170 imm = extract32(ctx->opcode, 13, 8);
19171 result = (uint32_t)imm << 24 |
19172 (uint32_t)imm << 16 |
19173 (uint32_t)imm << 8 |
19174 (uint32_t)imm;
19175 result = (int32_t)result;
19176 tcg_gen_movi_tl(t0, result);
19177 gen_store_gpr(t0, rt);
19179 break;
19180 default:
19181 generate_exception_end(ctx, EXCP_RI);
19182 break;
19184 tcg_temp_free(t0);
19185 tcg_temp_free(rs_t);
19189 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19191 int rt = extract32(ctx->opcode, 21, 5);
19192 int rs = extract32(ctx->opcode, 16, 5);
19193 int rd = extract32(ctx->opcode, 11, 5);
19195 switch (extract32(ctx->opcode, 6, 3)) {
19196 case NM_POOL32AXF_1:
19198 int32_t op1 = extract32(ctx->opcode, 9, 3);
19199 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19201 break;
19202 case NM_POOL32AXF_2:
19204 int32_t op1 = extract32(ctx->opcode, 12, 2);
19205 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19207 break;
19208 case NM_POOL32AXF_4:
19210 int32_t op1 = extract32(ctx->opcode, 9, 7);
19211 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19213 break;
19214 case NM_POOL32AXF_5:
19215 switch (extract32(ctx->opcode, 9, 7)) {
19216 #ifndef CONFIG_USER_ONLY
19217 case NM_TLBP:
19218 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19219 break;
19220 case NM_TLBR:
19221 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19222 break;
19223 case NM_TLBWI:
19224 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19225 break;
19226 case NM_TLBWR:
19227 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19228 break;
19229 case NM_TLBINV:
19230 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19231 break;
19232 case NM_TLBINVF:
19233 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19234 break;
19235 case NM_DI:
19236 check_cp0_enabled(ctx);
19238 TCGv t0 = tcg_temp_new();
19240 save_cpu_state(ctx, 1);
19241 gen_helper_di(t0, cpu_env);
19242 gen_store_gpr(t0, rt);
19243 /* Stop translation as we may have switched the execution mode */
19244 ctx->base.is_jmp = DISAS_STOP;
19245 tcg_temp_free(t0);
19247 break;
19248 case NM_EI:
19249 check_cp0_enabled(ctx);
19251 TCGv t0 = tcg_temp_new();
19253 save_cpu_state(ctx, 1);
19254 gen_helper_ei(t0, cpu_env);
19255 gen_store_gpr(t0, rt);
19256 /* Stop translation as we may have switched the execution mode */
19257 ctx->base.is_jmp = DISAS_STOP;
19258 tcg_temp_free(t0);
19260 break;
19261 case NM_RDPGPR:
19262 gen_load_srsgpr(rs, rt);
19263 break;
19264 case NM_WRPGPR:
19265 gen_store_srsgpr(rs, rt);
19266 break;
19267 case NM_WAIT:
19268 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19269 break;
19270 case NM_DERET:
19271 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19272 break;
19273 case NM_ERETX:
19274 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19275 break;
19276 #endif
19277 default:
19278 generate_exception_end(ctx, EXCP_RI);
19279 break;
19281 break;
19282 case NM_POOL32AXF_7:
19284 int32_t op1 = extract32(ctx->opcode, 9, 3);
19285 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19287 break;
19288 default:
19289 generate_exception_end(ctx, EXCP_RI);
19290 break;
19294 /* Immediate Value Compact Branches */
19295 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19296 int rt, int32_t imm, int32_t offset)
19298 TCGCond cond;
19299 int bcond_compute = 0;
19300 TCGv t0 = tcg_temp_new();
19301 TCGv t1 = tcg_temp_new();
19303 gen_load_gpr(t0, rt);
19304 tcg_gen_movi_tl(t1, imm);
19305 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19307 /* Load needed operands and calculate btarget */
19308 switch (opc) {
19309 case NM_BEQIC:
19310 if (rt == 0 && imm == 0) {
19311 /* Unconditional branch */
19312 } else if (rt == 0 && imm != 0) {
19313 /* Treat as NOP */
19314 goto out;
19315 } else {
19316 bcond_compute = 1;
19317 cond = TCG_COND_EQ;
19319 break;
19320 case NM_BBEQZC:
19321 case NM_BBNEZC:
19322 check_nms(ctx);
19323 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19324 generate_exception_end(ctx, EXCP_RI);
19325 goto out;
19326 } else if (rt == 0 && opc == NM_BBEQZC) {
19327 /* Unconditional branch */
19328 } else if (rt == 0 && opc == NM_BBNEZC) {
19329 /* Treat as NOP */
19330 goto out;
19331 } else {
19332 tcg_gen_shri_tl(t0, t0, imm);
19333 tcg_gen_andi_tl(t0, t0, 1);
19334 tcg_gen_movi_tl(t1, 0);
19335 bcond_compute = 1;
19336 if (opc == NM_BBEQZC) {
19337 cond = TCG_COND_EQ;
19338 } else {
19339 cond = TCG_COND_NE;
19342 break;
19343 case NM_BNEIC:
19344 if (rt == 0 && imm == 0) {
19345 /* Treat as NOP */
19346 goto out;
19347 } else if (rt == 0 && imm != 0) {
19348 /* Unconditional branch */
19349 } else {
19350 bcond_compute = 1;
19351 cond = TCG_COND_NE;
19353 break;
19354 case NM_BGEIC:
19355 if (rt == 0 && imm == 0) {
19356 /* Unconditional branch */
19357 } else {
19358 bcond_compute = 1;
19359 cond = TCG_COND_GE;
19361 break;
19362 case NM_BLTIC:
19363 bcond_compute = 1;
19364 cond = TCG_COND_LT;
19365 break;
19366 case NM_BGEIUC:
19367 if (rt == 0 && imm == 0) {
19368 /* Unconditional branch */
19369 } else {
19370 bcond_compute = 1;
19371 cond = TCG_COND_GEU;
19373 break;
19374 case NM_BLTIUC:
19375 bcond_compute = 1;
19376 cond = TCG_COND_LTU;
19377 break;
19378 default:
19379 MIPS_INVAL("Immediate Value Compact branch");
19380 generate_exception_end(ctx, EXCP_RI);
19381 goto out;
19384 if (bcond_compute == 0) {
19385 /* Uncoditional compact branch */
19386 gen_goto_tb(ctx, 0, ctx->btarget);
19387 } else {
19388 /* Conditional compact branch */
19389 TCGLabel *fs = gen_new_label();
19391 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19393 gen_goto_tb(ctx, 1, ctx->btarget);
19394 gen_set_label(fs);
19396 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19399 out:
19400 tcg_temp_free(t0);
19401 tcg_temp_free(t1);
19404 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19405 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19406 int rt)
19408 TCGv t0 = tcg_temp_new();
19409 TCGv t1 = tcg_temp_new();
19411 /* load rs */
19412 gen_load_gpr(t0, rs);
19414 /* link */
19415 if (rt != 0) {
19416 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19419 /* calculate btarget */
19420 tcg_gen_shli_tl(t0, t0, 1);
19421 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19422 gen_op_addr_add(ctx, btarget, t1, t0);
19424 /* unconditional branch to register */
19425 tcg_gen_mov_tl(cpu_PC, btarget);
19426 tcg_gen_lookup_and_goto_ptr();
19428 tcg_temp_free(t0);
19429 tcg_temp_free(t1);
19432 /* nanoMIPS Branches */
19433 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19434 int rs, int rt, int32_t offset)
19436 int bcond_compute = 0;
19437 TCGv t0 = tcg_temp_new();
19438 TCGv t1 = tcg_temp_new();
19440 /* Load needed operands and calculate btarget */
19441 switch (opc) {
19442 /* compact branch */
19443 case OPC_BGEC:
19444 case OPC_BLTC:
19445 gen_load_gpr(t0, rs);
19446 gen_load_gpr(t1, rt);
19447 bcond_compute = 1;
19448 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19449 break;
19450 case OPC_BGEUC:
19451 case OPC_BLTUC:
19452 if (rs == 0 || rs == rt) {
19453 /* OPC_BLEZALC, OPC_BGEZALC */
19454 /* OPC_BGTZALC, OPC_BLTZALC */
19455 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19457 gen_load_gpr(t0, rs);
19458 gen_load_gpr(t1, rt);
19459 bcond_compute = 1;
19460 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19461 break;
19462 case OPC_BC:
19463 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19464 break;
19465 case OPC_BEQZC:
19466 if (rs != 0) {
19467 /* OPC_BEQZC, OPC_BNEZC */
19468 gen_load_gpr(t0, rs);
19469 bcond_compute = 1;
19470 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19471 } else {
19472 /* OPC_JIC, OPC_JIALC */
19473 TCGv tbase = tcg_temp_new();
19474 TCGv toffset = tcg_temp_new();
19476 gen_load_gpr(tbase, rt);
19477 tcg_gen_movi_tl(toffset, offset);
19478 gen_op_addr_add(ctx, btarget, tbase, toffset);
19479 tcg_temp_free(tbase);
19480 tcg_temp_free(toffset);
19482 break;
19483 default:
19484 MIPS_INVAL("Compact branch/jump");
19485 generate_exception_end(ctx, EXCP_RI);
19486 goto out;
19489 if (bcond_compute == 0) {
19490 /* Uncoditional compact branch */
19491 switch (opc) {
19492 case OPC_BC:
19493 gen_goto_tb(ctx, 0, ctx->btarget);
19494 break;
19495 default:
19496 MIPS_INVAL("Compact branch/jump");
19497 generate_exception_end(ctx, EXCP_RI);
19498 goto out;
19500 } else {
19501 /* Conditional compact branch */
19502 TCGLabel *fs = gen_new_label();
19504 switch (opc) {
19505 case OPC_BGEUC:
19506 if (rs == 0 && rt != 0) {
19507 /* OPC_BLEZALC */
19508 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19509 } else if (rs != 0 && rt != 0 && rs == rt) {
19510 /* OPC_BGEZALC */
19511 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19512 } else {
19513 /* OPC_BGEUC */
19514 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19516 break;
19517 case OPC_BLTUC:
19518 if (rs == 0 && rt != 0) {
19519 /* OPC_BGTZALC */
19520 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19521 } else if (rs != 0 && rt != 0 && rs == rt) {
19522 /* OPC_BLTZALC */
19523 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19524 } else {
19525 /* OPC_BLTUC */
19526 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19528 break;
19529 case OPC_BGEC:
19530 if (rs == 0 && rt != 0) {
19531 /* OPC_BLEZC */
19532 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19533 } else if (rs != 0 && rt != 0 && rs == rt) {
19534 /* OPC_BGEZC */
19535 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19536 } else {
19537 /* OPC_BGEC */
19538 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19540 break;
19541 case OPC_BLTC:
19542 if (rs == 0 && rt != 0) {
19543 /* OPC_BGTZC */
19544 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19545 } else if (rs != 0 && rt != 0 && rs == rt) {
19546 /* OPC_BLTZC */
19547 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19548 } else {
19549 /* OPC_BLTC */
19550 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19552 break;
19553 case OPC_BEQZC:
19554 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19555 break;
19556 default:
19557 MIPS_INVAL("Compact conditional branch/jump");
19558 generate_exception_end(ctx, EXCP_RI);
19559 goto out;
19562 /* Generating branch here as compact branches don't have delay slot */
19563 gen_goto_tb(ctx, 1, ctx->btarget);
19564 gen_set_label(fs);
19566 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19569 out:
19570 tcg_temp_free(t0);
19571 tcg_temp_free(t1);
19575 /* nanoMIPS CP1 Branches */
19576 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19577 int32_t ft, int32_t offset)
19579 target_ulong btarget;
19580 TCGv_i64 t0 = tcg_temp_new_i64();
19582 gen_load_fpr64(ctx, t0, ft);
19583 tcg_gen_andi_i64(t0, t0, 1);
19585 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19587 switch (op) {
19588 case NM_BC1EQZC:
19589 tcg_gen_xori_i64(t0, t0, 1);
19590 ctx->hflags |= MIPS_HFLAG_BC;
19591 break;
19592 case NM_BC1NEZC:
19593 /* t0 already set */
19594 ctx->hflags |= MIPS_HFLAG_BC;
19595 break;
19596 default:
19597 MIPS_INVAL("cp1 cond branch");
19598 generate_exception_end(ctx, EXCP_RI);
19599 goto out;
19602 tcg_gen_trunc_i64_tl(bcond, t0);
19604 ctx->btarget = btarget;
19606 out:
19607 tcg_temp_free_i64(t0);
19611 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19613 TCGv t0, t1;
19614 t0 = tcg_temp_new();
19615 t1 = tcg_temp_new();
19617 gen_load_gpr(t0, rs);
19618 gen_load_gpr(t1, rt);
19620 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19621 /* PP.LSXS instructions require shifting */
19622 switch (extract32(ctx->opcode, 7, 4)) {
19623 case NM_SHXS:
19624 check_nms(ctx);
19625 case NM_LHXS:
19626 case NM_LHUXS:
19627 tcg_gen_shli_tl(t0, t0, 1);
19628 break;
19629 case NM_SWXS:
19630 check_nms(ctx);
19631 case NM_LWXS:
19632 case NM_LWC1XS:
19633 case NM_SWC1XS:
19634 tcg_gen_shli_tl(t0, t0, 2);
19635 break;
19636 case NM_LDC1XS:
19637 case NM_SDC1XS:
19638 tcg_gen_shli_tl(t0, t0, 3);
19639 break;
19642 gen_op_addr_add(ctx, t0, t0, t1);
19644 switch (extract32(ctx->opcode, 7, 4)) {
19645 case NM_LBX:
19646 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19647 MO_SB);
19648 gen_store_gpr(t0, rd);
19649 break;
19650 case NM_LHX:
19651 /*case NM_LHXS:*/
19652 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19653 MO_TESW);
19654 gen_store_gpr(t0, rd);
19655 break;
19656 case NM_LWX:
19657 /*case NM_LWXS:*/
19658 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19659 MO_TESL);
19660 gen_store_gpr(t0, rd);
19661 break;
19662 case NM_LBUX:
19663 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19664 MO_UB);
19665 gen_store_gpr(t0, rd);
19666 break;
19667 case NM_LHUX:
19668 /*case NM_LHUXS:*/
19669 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19670 MO_TEUW);
19671 gen_store_gpr(t0, rd);
19672 break;
19673 case NM_SBX:
19674 check_nms(ctx);
19675 gen_load_gpr(t1, rd);
19676 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19677 MO_8);
19678 break;
19679 case NM_SHX:
19680 /*case NM_SHXS:*/
19681 check_nms(ctx);
19682 gen_load_gpr(t1, rd);
19683 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19684 MO_TEUW);
19685 break;
19686 case NM_SWX:
19687 /*case NM_SWXS:*/
19688 check_nms(ctx);
19689 gen_load_gpr(t1, rd);
19690 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19691 MO_TEUL);
19692 break;
19693 case NM_LWC1X:
19694 /*case NM_LWC1XS:*/
19695 case NM_LDC1X:
19696 /*case NM_LDC1XS:*/
19697 case NM_SWC1X:
19698 /*case NM_SWC1XS:*/
19699 case NM_SDC1X:
19700 /*case NM_SDC1XS:*/
19701 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19702 check_cp1_enabled(ctx);
19703 switch (extract32(ctx->opcode, 7, 4)) {
19704 case NM_LWC1X:
19705 /*case NM_LWC1XS:*/
19706 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19707 break;
19708 case NM_LDC1X:
19709 /*case NM_LDC1XS:*/
19710 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19711 break;
19712 case NM_SWC1X:
19713 /*case NM_SWC1XS:*/
19714 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19715 break;
19716 case NM_SDC1X:
19717 /*case NM_SDC1XS:*/
19718 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19719 break;
19721 } else {
19722 generate_exception_err(ctx, EXCP_CpU, 1);
19724 break;
19725 default:
19726 generate_exception_end(ctx, EXCP_RI);
19727 break;
19730 tcg_temp_free(t0);
19731 tcg_temp_free(t1);
19734 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19736 int rt, rs, rd;
19738 rt = extract32(ctx->opcode, 21, 5);
19739 rs = extract32(ctx->opcode, 16, 5);
19740 rd = extract32(ctx->opcode, 11, 5);
19742 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19743 generate_exception_end(ctx, EXCP_RI);
19744 return;
19746 check_cp1_enabled(ctx);
19747 switch (extract32(ctx->opcode, 0, 3)) {
19748 case NM_POOL32F_0:
19749 switch (extract32(ctx->opcode, 3, 7)) {
19750 case NM_RINT_S:
19751 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19752 break;
19753 case NM_RINT_D:
19754 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19755 break;
19756 case NM_CLASS_S:
19757 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19758 break;
19759 case NM_CLASS_D:
19760 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19761 break;
19762 case NM_ADD_S:
19763 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19764 break;
19765 case NM_ADD_D:
19766 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19767 break;
19768 case NM_SUB_S:
19769 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19770 break;
19771 case NM_SUB_D:
19772 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19773 break;
19774 case NM_MUL_S:
19775 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19776 break;
19777 case NM_MUL_D:
19778 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19779 break;
19780 case NM_DIV_S:
19781 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19782 break;
19783 case NM_DIV_D:
19784 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19785 break;
19786 case NM_SELEQZ_S:
19787 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19788 break;
19789 case NM_SELEQZ_D:
19790 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19791 break;
19792 case NM_SELNEZ_S:
19793 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19794 break;
19795 case NM_SELNEZ_D:
19796 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19797 break;
19798 case NM_SEL_S:
19799 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19800 break;
19801 case NM_SEL_D:
19802 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19803 break;
19804 case NM_MADDF_S:
19805 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19806 break;
19807 case NM_MADDF_D:
19808 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19809 break;
19810 case NM_MSUBF_S:
19811 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19812 break;
19813 case NM_MSUBF_D:
19814 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19815 break;
19816 default:
19817 generate_exception_end(ctx, EXCP_RI);
19818 break;
19820 break;
19821 case NM_POOL32F_3:
19822 switch (extract32(ctx->opcode, 3, 3)) {
19823 case NM_MIN_FMT:
19824 switch (extract32(ctx->opcode, 9, 1)) {
19825 case FMT_SDPS_S:
19826 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19827 break;
19828 case FMT_SDPS_D:
19829 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19830 break;
19832 break;
19833 case NM_MAX_FMT:
19834 switch (extract32(ctx->opcode, 9, 1)) {
19835 case FMT_SDPS_S:
19836 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19837 break;
19838 case FMT_SDPS_D:
19839 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19840 break;
19842 break;
19843 case NM_MINA_FMT:
19844 switch (extract32(ctx->opcode, 9, 1)) {
19845 case FMT_SDPS_S:
19846 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19847 break;
19848 case FMT_SDPS_D:
19849 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19850 break;
19852 break;
19853 case NM_MAXA_FMT:
19854 switch (extract32(ctx->opcode, 9, 1)) {
19855 case FMT_SDPS_S:
19856 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19857 break;
19858 case FMT_SDPS_D:
19859 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19860 break;
19862 break;
19863 case NM_POOL32FXF:
19864 switch (extract32(ctx->opcode, 6, 8)) {
19865 case NM_CFC1:
19866 gen_cp1(ctx, OPC_CFC1, rt, rs);
19867 break;
19868 case NM_CTC1:
19869 gen_cp1(ctx, OPC_CTC1, rt, rs);
19870 break;
19871 case NM_MFC1:
19872 gen_cp1(ctx, OPC_MFC1, rt, rs);
19873 break;
19874 case NM_MTC1:
19875 gen_cp1(ctx, OPC_MTC1, rt, rs);
19876 break;
19877 case NM_MFHC1:
19878 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19879 break;
19880 case NM_MTHC1:
19881 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19882 break;
19883 case NM_CVT_S_PL:
19884 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19885 break;
19886 case NM_CVT_S_PU:
19887 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19888 break;
19889 default:
19890 switch (extract32(ctx->opcode, 6, 9)) {
19891 case NM_CVT_L_S:
19892 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19893 break;
19894 case NM_CVT_L_D:
19895 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19896 break;
19897 case NM_CVT_W_S:
19898 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19899 break;
19900 case NM_CVT_W_D:
19901 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19902 break;
19903 case NM_RSQRT_S:
19904 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19905 break;
19906 case NM_RSQRT_D:
19907 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19908 break;
19909 case NM_SQRT_S:
19910 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19911 break;
19912 case NM_SQRT_D:
19913 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19914 break;
19915 case NM_RECIP_S:
19916 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19917 break;
19918 case NM_RECIP_D:
19919 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19920 break;
19921 case NM_FLOOR_L_S:
19922 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19923 break;
19924 case NM_FLOOR_L_D:
19925 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19926 break;
19927 case NM_FLOOR_W_S:
19928 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19929 break;
19930 case NM_FLOOR_W_D:
19931 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19932 break;
19933 case NM_CEIL_L_S:
19934 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19935 break;
19936 case NM_CEIL_L_D:
19937 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19938 break;
19939 case NM_CEIL_W_S:
19940 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19941 break;
19942 case NM_CEIL_W_D:
19943 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19944 break;
19945 case NM_TRUNC_L_S:
19946 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19947 break;
19948 case NM_TRUNC_L_D:
19949 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19950 break;
19951 case NM_TRUNC_W_S:
19952 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19953 break;
19954 case NM_TRUNC_W_D:
19955 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19956 break;
19957 case NM_ROUND_L_S:
19958 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19959 break;
19960 case NM_ROUND_L_D:
19961 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19962 break;
19963 case NM_ROUND_W_S:
19964 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19965 break;
19966 case NM_ROUND_W_D:
19967 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19968 break;
19969 case NM_MOV_S:
19970 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19971 break;
19972 case NM_MOV_D:
19973 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19974 break;
19975 case NM_ABS_S:
19976 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19977 break;
19978 case NM_ABS_D:
19979 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19980 break;
19981 case NM_NEG_S:
19982 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19983 break;
19984 case NM_NEG_D:
19985 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19986 break;
19987 case NM_CVT_D_S:
19988 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19989 break;
19990 case NM_CVT_D_W:
19991 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19992 break;
19993 case NM_CVT_D_L:
19994 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19995 break;
19996 case NM_CVT_S_D:
19997 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19998 break;
19999 case NM_CVT_S_W:
20000 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
20001 break;
20002 case NM_CVT_S_L:
20003 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20004 break;
20005 default:
20006 generate_exception_end(ctx, EXCP_RI);
20007 break;
20009 break;
20011 break;
20013 break;
20014 case NM_POOL32F_5:
20015 switch (extract32(ctx->opcode, 3, 3)) {
20016 case NM_CMP_CONDN_S:
20017 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20018 break;
20019 case NM_CMP_CONDN_D:
20020 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20021 break;
20022 default:
20023 generate_exception_end(ctx, EXCP_RI);
20024 break;
20026 break;
20027 default:
20028 generate_exception_end(ctx, EXCP_RI);
20029 break;
20033 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20034 int rd, int rs, int rt)
20036 int ret = rd;
20037 TCGv t0 = tcg_temp_new();
20038 TCGv v1_t = tcg_temp_new();
20039 TCGv v2_t = tcg_temp_new();
20041 gen_load_gpr(v1_t, rs);
20042 gen_load_gpr(v2_t, rt);
20044 switch (opc) {
20045 case NM_CMP_EQ_PH:
20046 check_dsp(ctx);
20047 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20048 break;
20049 case NM_CMP_LT_PH:
20050 check_dsp(ctx);
20051 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20052 break;
20053 case NM_CMP_LE_PH:
20054 check_dsp(ctx);
20055 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20056 break;
20057 case NM_CMPU_EQ_QB:
20058 check_dsp(ctx);
20059 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20060 break;
20061 case NM_CMPU_LT_QB:
20062 check_dsp(ctx);
20063 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20064 break;
20065 case NM_CMPU_LE_QB:
20066 check_dsp(ctx);
20067 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20068 break;
20069 case NM_CMPGU_EQ_QB:
20070 check_dsp(ctx);
20071 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20072 gen_store_gpr(v1_t, ret);
20073 break;
20074 case NM_CMPGU_LT_QB:
20075 check_dsp(ctx);
20076 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20077 gen_store_gpr(v1_t, ret);
20078 break;
20079 case NM_CMPGU_LE_QB:
20080 check_dsp(ctx);
20081 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20082 gen_store_gpr(v1_t, ret);
20083 break;
20084 case NM_CMPGDU_EQ_QB:
20085 check_dsp_r2(ctx);
20086 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20087 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20088 gen_store_gpr(v1_t, ret);
20089 break;
20090 case NM_CMPGDU_LT_QB:
20091 check_dsp_r2(ctx);
20092 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20093 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20094 gen_store_gpr(v1_t, ret);
20095 break;
20096 case NM_CMPGDU_LE_QB:
20097 check_dsp_r2(ctx);
20098 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20099 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20100 gen_store_gpr(v1_t, ret);
20101 break;
20102 case NM_PACKRL_PH:
20103 check_dsp(ctx);
20104 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20105 gen_store_gpr(v1_t, ret);
20106 break;
20107 case NM_PICK_QB:
20108 check_dsp(ctx);
20109 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20110 gen_store_gpr(v1_t, ret);
20111 break;
20112 case NM_PICK_PH:
20113 check_dsp(ctx);
20114 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20115 gen_store_gpr(v1_t, ret);
20116 break;
20117 case NM_ADDQ_S_W:
20118 check_dsp(ctx);
20119 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20120 gen_store_gpr(v1_t, ret);
20121 break;
20122 case NM_SUBQ_S_W:
20123 check_dsp(ctx);
20124 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20125 gen_store_gpr(v1_t, ret);
20126 break;
20127 case NM_ADDSC:
20128 check_dsp(ctx);
20129 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20130 gen_store_gpr(v1_t, ret);
20131 break;
20132 case NM_ADDWC:
20133 check_dsp(ctx);
20134 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20135 gen_store_gpr(v1_t, ret);
20136 break;
20137 case NM_ADDQ_S_PH:
20138 check_dsp(ctx);
20139 switch (extract32(ctx->opcode, 10, 1)) {
20140 case 0:
20141 /* ADDQ_PH */
20142 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20143 gen_store_gpr(v1_t, ret);
20144 break;
20145 case 1:
20146 /* ADDQ_S_PH */
20147 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20148 gen_store_gpr(v1_t, ret);
20149 break;
20151 break;
20152 case NM_ADDQH_R_PH:
20153 check_dsp_r2(ctx);
20154 switch (extract32(ctx->opcode, 10, 1)) {
20155 case 0:
20156 /* ADDQH_PH */
20157 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20158 gen_store_gpr(v1_t, ret);
20159 break;
20160 case 1:
20161 /* ADDQH_R_PH */
20162 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20163 gen_store_gpr(v1_t, ret);
20164 break;
20166 break;
20167 case NM_ADDQH_R_W:
20168 check_dsp_r2(ctx);
20169 switch (extract32(ctx->opcode, 10, 1)) {
20170 case 0:
20171 /* ADDQH_W */
20172 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20173 gen_store_gpr(v1_t, ret);
20174 break;
20175 case 1:
20176 /* ADDQH_R_W */
20177 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20178 gen_store_gpr(v1_t, ret);
20179 break;
20181 break;
20182 case NM_ADDU_S_QB:
20183 check_dsp(ctx);
20184 switch (extract32(ctx->opcode, 10, 1)) {
20185 case 0:
20186 /* ADDU_QB */
20187 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20188 gen_store_gpr(v1_t, ret);
20189 break;
20190 case 1:
20191 /* ADDU_S_QB */
20192 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20193 gen_store_gpr(v1_t, ret);
20194 break;
20196 break;
20197 case NM_ADDU_S_PH:
20198 check_dsp_r2(ctx);
20199 switch (extract32(ctx->opcode, 10, 1)) {
20200 case 0:
20201 /* ADDU_PH */
20202 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20203 gen_store_gpr(v1_t, ret);
20204 break;
20205 case 1:
20206 /* ADDU_S_PH */
20207 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20208 gen_store_gpr(v1_t, ret);
20209 break;
20211 break;
20212 case NM_ADDUH_R_QB:
20213 check_dsp_r2(ctx);
20214 switch (extract32(ctx->opcode, 10, 1)) {
20215 case 0:
20216 /* ADDUH_QB */
20217 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20218 gen_store_gpr(v1_t, ret);
20219 break;
20220 case 1:
20221 /* ADDUH_R_QB */
20222 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20223 gen_store_gpr(v1_t, ret);
20224 break;
20226 break;
20227 case NM_SHRAV_R_PH:
20228 check_dsp(ctx);
20229 switch (extract32(ctx->opcode, 10, 1)) {
20230 case 0:
20231 /* SHRAV_PH */
20232 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20233 gen_store_gpr(v1_t, ret);
20234 break;
20235 case 1:
20236 /* SHRAV_R_PH */
20237 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20238 gen_store_gpr(v1_t, ret);
20239 break;
20241 break;
20242 case NM_SHRAV_R_QB:
20243 check_dsp_r2(ctx);
20244 switch (extract32(ctx->opcode, 10, 1)) {
20245 case 0:
20246 /* SHRAV_QB */
20247 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20248 gen_store_gpr(v1_t, ret);
20249 break;
20250 case 1:
20251 /* SHRAV_R_QB */
20252 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20253 gen_store_gpr(v1_t, ret);
20254 break;
20256 break;
20257 case NM_SUBQ_S_PH:
20258 check_dsp(ctx);
20259 switch (extract32(ctx->opcode, 10, 1)) {
20260 case 0:
20261 /* SUBQ_PH */
20262 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20263 gen_store_gpr(v1_t, ret);
20264 break;
20265 case 1:
20266 /* SUBQ_S_PH */
20267 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20268 gen_store_gpr(v1_t, ret);
20269 break;
20271 break;
20272 case NM_SUBQH_R_PH:
20273 check_dsp_r2(ctx);
20274 switch (extract32(ctx->opcode, 10, 1)) {
20275 case 0:
20276 /* SUBQH_PH */
20277 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20278 gen_store_gpr(v1_t, ret);
20279 break;
20280 case 1:
20281 /* SUBQH_R_PH */
20282 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20283 gen_store_gpr(v1_t, ret);
20284 break;
20286 break;
20287 case NM_SUBQH_R_W:
20288 check_dsp_r2(ctx);
20289 switch (extract32(ctx->opcode, 10, 1)) {
20290 case 0:
20291 /* SUBQH_W */
20292 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20293 gen_store_gpr(v1_t, ret);
20294 break;
20295 case 1:
20296 /* SUBQH_R_W */
20297 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20298 gen_store_gpr(v1_t, ret);
20299 break;
20301 break;
20302 case NM_SUBU_S_QB:
20303 check_dsp(ctx);
20304 switch (extract32(ctx->opcode, 10, 1)) {
20305 case 0:
20306 /* SUBU_QB */
20307 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20308 gen_store_gpr(v1_t, ret);
20309 break;
20310 case 1:
20311 /* SUBU_S_QB */
20312 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20313 gen_store_gpr(v1_t, ret);
20314 break;
20316 break;
20317 case NM_SUBU_S_PH:
20318 check_dsp_r2(ctx);
20319 switch (extract32(ctx->opcode, 10, 1)) {
20320 case 0:
20321 /* SUBU_PH */
20322 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20323 gen_store_gpr(v1_t, ret);
20324 break;
20325 case 1:
20326 /* SUBU_S_PH */
20327 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20328 gen_store_gpr(v1_t, ret);
20329 break;
20331 break;
20332 case NM_SUBUH_R_QB:
20333 check_dsp_r2(ctx);
20334 switch (extract32(ctx->opcode, 10, 1)) {
20335 case 0:
20336 /* SUBUH_QB */
20337 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20338 gen_store_gpr(v1_t, ret);
20339 break;
20340 case 1:
20341 /* SUBUH_R_QB */
20342 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20343 gen_store_gpr(v1_t, ret);
20344 break;
20346 break;
20347 case NM_SHLLV_S_PH:
20348 check_dsp(ctx);
20349 switch (extract32(ctx->opcode, 10, 1)) {
20350 case 0:
20351 /* SHLLV_PH */
20352 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20353 gen_store_gpr(v1_t, ret);
20354 break;
20355 case 1:
20356 /* SHLLV_S_PH */
20357 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20358 gen_store_gpr(v1_t, ret);
20359 break;
20361 break;
20362 case NM_PRECR_SRA_R_PH_W:
20363 check_dsp_r2(ctx);
20364 switch (extract32(ctx->opcode, 10, 1)) {
20365 case 0:
20366 /* PRECR_SRA_PH_W */
20368 TCGv_i32 sa_t = tcg_const_i32(rd);
20369 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20370 cpu_gpr[rt]);
20371 gen_store_gpr(v1_t, rt);
20372 tcg_temp_free_i32(sa_t);
20374 break;
20375 case 1:
20376 /* PRECR_SRA_R_PH_W */
20378 TCGv_i32 sa_t = tcg_const_i32(rd);
20379 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20380 cpu_gpr[rt]);
20381 gen_store_gpr(v1_t, rt);
20382 tcg_temp_free_i32(sa_t);
20384 break;
20386 break;
20387 case NM_MULEU_S_PH_QBL:
20388 check_dsp(ctx);
20389 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20390 gen_store_gpr(v1_t, ret);
20391 break;
20392 case NM_MULEU_S_PH_QBR:
20393 check_dsp(ctx);
20394 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20395 gen_store_gpr(v1_t, ret);
20396 break;
20397 case NM_MULQ_RS_PH:
20398 check_dsp(ctx);
20399 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20400 gen_store_gpr(v1_t, ret);
20401 break;
20402 case NM_MULQ_S_PH:
20403 check_dsp_r2(ctx);
20404 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20405 gen_store_gpr(v1_t, ret);
20406 break;
20407 case NM_MULQ_RS_W:
20408 check_dsp_r2(ctx);
20409 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20410 gen_store_gpr(v1_t, ret);
20411 break;
20412 case NM_MULQ_S_W:
20413 check_dsp_r2(ctx);
20414 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20415 gen_store_gpr(v1_t, ret);
20416 break;
20417 case NM_APPEND:
20418 check_dsp_r2(ctx);
20419 gen_load_gpr(t0, rs);
20420 if (rd != 0) {
20421 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20423 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20424 break;
20425 case NM_MODSUB:
20426 check_dsp(ctx);
20427 gen_helper_modsub(v1_t, v1_t, v2_t);
20428 gen_store_gpr(v1_t, ret);
20429 break;
20430 case NM_SHRAV_R_W:
20431 check_dsp(ctx);
20432 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20433 gen_store_gpr(v1_t, ret);
20434 break;
20435 case NM_SHRLV_PH:
20436 check_dsp_r2(ctx);
20437 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20438 gen_store_gpr(v1_t, ret);
20439 break;
20440 case NM_SHRLV_QB:
20441 check_dsp(ctx);
20442 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20443 gen_store_gpr(v1_t, ret);
20444 break;
20445 case NM_SHLLV_QB:
20446 check_dsp(ctx);
20447 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20448 gen_store_gpr(v1_t, ret);
20449 break;
20450 case NM_SHLLV_S_W:
20451 check_dsp(ctx);
20452 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20453 gen_store_gpr(v1_t, ret);
20454 break;
20455 case NM_SHILO:
20456 check_dsp(ctx);
20458 TCGv tv0 = tcg_temp_new();
20459 TCGv tv1 = tcg_temp_new();
20460 int16_t imm = extract32(ctx->opcode, 16, 7);
20462 tcg_gen_movi_tl(tv0, rd >> 3);
20463 tcg_gen_movi_tl(tv1, imm);
20464 gen_helper_shilo(tv0, tv1, cpu_env);
20466 break;
20467 case NM_MULEQ_S_W_PHL:
20468 check_dsp(ctx);
20469 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20470 gen_store_gpr(v1_t, ret);
20471 break;
20472 case NM_MULEQ_S_W_PHR:
20473 check_dsp(ctx);
20474 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20475 gen_store_gpr(v1_t, ret);
20476 break;
20477 case NM_MUL_S_PH:
20478 check_dsp_r2(ctx);
20479 switch (extract32(ctx->opcode, 10, 1)) {
20480 case 0:
20481 /* MUL_PH */
20482 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20483 gen_store_gpr(v1_t, ret);
20484 break;
20485 case 1:
20486 /* MUL_S_PH */
20487 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20488 gen_store_gpr(v1_t, ret);
20489 break;
20491 break;
20492 case NM_PRECR_QB_PH:
20493 check_dsp_r2(ctx);
20494 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20495 gen_store_gpr(v1_t, ret);
20496 break;
20497 case NM_PRECRQ_QB_PH:
20498 check_dsp(ctx);
20499 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20500 gen_store_gpr(v1_t, ret);
20501 break;
20502 case NM_PRECRQ_PH_W:
20503 check_dsp(ctx);
20504 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20505 gen_store_gpr(v1_t, ret);
20506 break;
20507 case NM_PRECRQ_RS_PH_W:
20508 check_dsp(ctx);
20509 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20510 gen_store_gpr(v1_t, ret);
20511 break;
20512 case NM_PRECRQU_S_QB_PH:
20513 check_dsp(ctx);
20514 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20515 gen_store_gpr(v1_t, ret);
20516 break;
20517 case NM_SHRA_R_W:
20518 check_dsp(ctx);
20519 tcg_gen_movi_tl(t0, rd);
20520 gen_helper_shra_r_w(v1_t, t0, v1_t);
20521 gen_store_gpr(v1_t, rt);
20522 break;
20523 case NM_SHRA_R_PH:
20524 check_dsp(ctx);
20525 tcg_gen_movi_tl(t0, rd >> 1);
20526 switch (extract32(ctx->opcode, 10, 1)) {
20527 case 0:
20528 /* SHRA_PH */
20529 gen_helper_shra_ph(v1_t, t0, v1_t);
20530 gen_store_gpr(v1_t, rt);
20531 break;
20532 case 1:
20533 /* SHRA_R_PH */
20534 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20535 gen_store_gpr(v1_t, rt);
20536 break;
20538 break;
20539 case NM_SHLL_S_PH:
20540 check_dsp(ctx);
20541 tcg_gen_movi_tl(t0, rd >> 1);
20542 switch (extract32(ctx->opcode, 10, 2)) {
20543 case 0:
20544 /* SHLL_PH */
20545 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20546 gen_store_gpr(v1_t, rt);
20547 break;
20548 case 2:
20549 /* SHLL_S_PH */
20550 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20551 gen_store_gpr(v1_t, rt);
20552 break;
20553 default:
20554 generate_exception_end(ctx, EXCP_RI);
20555 break;
20557 break;
20558 case NM_SHLL_S_W:
20559 check_dsp(ctx);
20560 tcg_gen_movi_tl(t0, rd);
20561 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20562 gen_store_gpr(v1_t, rt);
20563 break;
20564 case NM_REPL_PH:
20565 check_dsp(ctx);
20567 int16_t imm;
20568 imm = sextract32(ctx->opcode, 11, 11);
20569 imm = (int16_t)(imm << 6) >> 6;
20570 if (rt != 0) {
20571 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20574 break;
20575 default:
20576 generate_exception_end(ctx, EXCP_RI);
20577 break;
20581 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20583 uint16_t insn;
20584 uint32_t op;
20585 int rt, rs, rd;
20586 int offset;
20587 int imm;
20589 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20590 ctx->opcode = (ctx->opcode << 16) | insn;
20592 rt = extract32(ctx->opcode, 21, 5);
20593 rs = extract32(ctx->opcode, 16, 5);
20594 rd = extract32(ctx->opcode, 11, 5);
20596 op = extract32(ctx->opcode, 26, 6);
20597 switch (op) {
20598 case NM_P_ADDIU:
20599 if (rt == 0) {
20600 /* P.RI */
20601 switch (extract32(ctx->opcode, 19, 2)) {
20602 case NM_SIGRIE:
20603 default:
20604 generate_exception_end(ctx, EXCP_RI);
20605 break;
20606 case NM_P_SYSCALL:
20607 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20608 generate_exception_end(ctx, EXCP_SYSCALL);
20609 } else {
20610 generate_exception_end(ctx, EXCP_RI);
20612 break;
20613 case NM_BREAK:
20614 generate_exception_end(ctx, EXCP_BREAK);
20615 break;
20616 case NM_SDBBP:
20617 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20618 gen_helper_do_semihosting(cpu_env);
20619 } else {
20620 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20621 generate_exception_end(ctx, EXCP_RI);
20622 } else {
20623 generate_exception_end(ctx, EXCP_DBp);
20626 break;
20628 } else {
20629 /* NM_ADDIU */
20630 imm = extract32(ctx->opcode, 0, 16);
20631 if (rs != 0) {
20632 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20633 } else {
20634 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20636 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20638 break;
20639 case NM_ADDIUPC:
20640 if (rt != 0) {
20641 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20642 extract32(ctx->opcode, 1, 20) << 1;
20643 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20644 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20646 break;
20647 case NM_POOL32A:
20648 switch (ctx->opcode & 0x07) {
20649 case NM_POOL32A0:
20650 gen_pool32a0_nanomips_insn(env, ctx);
20651 break;
20652 case NM_POOL32A5:
20654 int32_t op1 = extract32(ctx->opcode, 3, 7);
20655 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20657 break;
20658 case NM_POOL32A7:
20659 switch (extract32(ctx->opcode, 3, 3)) {
20660 case NM_P_LSX:
20661 gen_p_lsx(ctx, rd, rs, rt);
20662 break;
20663 case NM_LSA:
20664 /* In nanoMIPS, the shift field directly encodes the shift
20665 * amount, meaning that the supported shift values are in
20666 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20667 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20668 extract32(ctx->opcode, 9, 2) - 1);
20669 break;
20670 case NM_EXTW:
20671 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20672 break;
20673 case NM_POOL32AXF:
20674 gen_pool32axf_nanomips_insn(env, ctx);
20675 break;
20676 default:
20677 generate_exception_end(ctx, EXCP_RI);
20678 break;
20680 break;
20681 default:
20682 generate_exception_end(ctx, EXCP_RI);
20683 break;
20685 break;
20686 case NM_P_GP_W:
20687 switch (ctx->opcode & 0x03) {
20688 case NM_ADDIUGP_W:
20689 if (rt != 0) {
20690 offset = extract32(ctx->opcode, 0, 21);
20691 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20693 break;
20694 case NM_LWGP:
20695 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20696 break;
20697 case NM_SWGP:
20698 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20699 break;
20700 default:
20701 generate_exception_end(ctx, EXCP_RI);
20702 break;
20704 break;
20705 case NM_P48I:
20707 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20708 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20709 switch (extract32(ctx->opcode, 16, 5)) {
20710 case NM_LI48:
20711 check_nms(ctx);
20712 if (rt != 0) {
20713 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20715 break;
20716 case NM_ADDIU48:
20717 check_nms(ctx);
20718 if (rt != 0) {
20719 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20720 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20722 break;
20723 case NM_ADDIUGP48:
20724 check_nms(ctx);
20725 if (rt != 0) {
20726 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20728 break;
20729 case NM_ADDIUPC48:
20730 check_nms(ctx);
20731 if (rt != 0) {
20732 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20733 addr_off);
20735 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20737 break;
20738 case NM_LWPC48:
20739 check_nms(ctx);
20740 if (rt != 0) {
20741 TCGv t0;
20742 t0 = tcg_temp_new();
20744 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20745 addr_off);
20747 tcg_gen_movi_tl(t0, addr);
20748 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20749 tcg_temp_free(t0);
20751 break;
20752 case NM_SWPC48:
20753 check_nms(ctx);
20755 TCGv t0, t1;
20756 t0 = tcg_temp_new();
20757 t1 = tcg_temp_new();
20759 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20760 addr_off);
20762 tcg_gen_movi_tl(t0, addr);
20763 gen_load_gpr(t1, rt);
20765 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20767 tcg_temp_free(t0);
20768 tcg_temp_free(t1);
20770 break;
20771 default:
20772 generate_exception_end(ctx, EXCP_RI);
20773 break;
20775 return 6;
20777 case NM_P_U12:
20778 switch (extract32(ctx->opcode, 12, 4)) {
20779 case NM_ORI:
20780 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20781 break;
20782 case NM_XORI:
20783 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20784 break;
20785 case NM_ANDI:
20786 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20787 break;
20788 case NM_P_SR:
20789 switch (extract32(ctx->opcode, 20, 1)) {
20790 case NM_PP_SR:
20791 switch (ctx->opcode & 3) {
20792 case NM_SAVE:
20793 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20794 extract32(ctx->opcode, 2, 1),
20795 extract32(ctx->opcode, 3, 9) << 3);
20796 break;
20797 case NM_RESTORE:
20798 case NM_RESTORE_JRC:
20799 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20800 extract32(ctx->opcode, 2, 1),
20801 extract32(ctx->opcode, 3, 9) << 3);
20802 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20803 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20805 break;
20806 default:
20807 generate_exception_end(ctx, EXCP_RI);
20808 break;
20810 break;
20811 case NM_P_SR_F:
20812 generate_exception_end(ctx, EXCP_RI);
20813 break;
20815 break;
20816 case NM_SLTI:
20817 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20818 break;
20819 case NM_SLTIU:
20820 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20821 break;
20822 case NM_SEQI:
20824 TCGv t0 = tcg_temp_new();
20826 imm = extract32(ctx->opcode, 0, 12);
20827 gen_load_gpr(t0, rs);
20828 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20829 gen_store_gpr(t0, rt);
20831 tcg_temp_free(t0);
20833 break;
20834 case NM_ADDIUNEG:
20835 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20836 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20837 break;
20838 case NM_P_SHIFT:
20840 int shift = extract32(ctx->opcode, 0, 5);
20841 switch (extract32(ctx->opcode, 5, 4)) {
20842 case NM_P_SLL:
20843 if (rt == 0 && shift == 0) {
20844 /* NOP */
20845 } else if (rt == 0 && shift == 3) {
20846 /* EHB - treat as NOP */
20847 } else if (rt == 0 && shift == 5) {
20848 /* PAUSE - treat as NOP */
20849 } else if (rt == 0 && shift == 6) {
20850 /* SYNC */
20851 gen_sync(extract32(ctx->opcode, 16, 5));
20852 } else {
20853 /* SLL */
20854 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20855 extract32(ctx->opcode, 0, 5));
20857 break;
20858 case NM_SRL:
20859 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20860 extract32(ctx->opcode, 0, 5));
20861 break;
20862 case NM_SRA:
20863 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20864 extract32(ctx->opcode, 0, 5));
20865 break;
20866 case NM_ROTR:
20867 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20868 extract32(ctx->opcode, 0, 5));
20869 break;
20872 break;
20873 case NM_P_ROTX:
20874 check_nms(ctx);
20875 if (rt != 0) {
20876 TCGv t0 = tcg_temp_new();
20877 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20878 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20879 << 1);
20880 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20882 gen_load_gpr(t0, rs);
20883 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20884 tcg_temp_free(t0);
20886 tcg_temp_free_i32(shift);
20887 tcg_temp_free_i32(shiftx);
20888 tcg_temp_free_i32(stripe);
20890 break;
20891 case NM_P_INS:
20892 switch (((ctx->opcode >> 10) & 2) |
20893 (extract32(ctx->opcode, 5, 1))) {
20894 case NM_INS:
20895 check_nms(ctx);
20896 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20897 extract32(ctx->opcode, 6, 5));
20898 break;
20899 default:
20900 generate_exception_end(ctx, EXCP_RI);
20901 break;
20903 break;
20904 case NM_P_EXT:
20905 switch (((ctx->opcode >> 10) & 2) |
20906 (extract32(ctx->opcode, 5, 1))) {
20907 case NM_EXT:
20908 check_nms(ctx);
20909 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20910 extract32(ctx->opcode, 6, 5));
20911 break;
20912 default:
20913 generate_exception_end(ctx, EXCP_RI);
20914 break;
20916 break;
20917 default:
20918 generate_exception_end(ctx, EXCP_RI);
20919 break;
20921 break;
20922 case NM_POOL32F:
20923 gen_pool32f_nanomips_insn(ctx);
20924 break;
20925 case NM_POOL32S:
20926 break;
20927 case NM_P_LUI:
20928 switch (extract32(ctx->opcode, 1, 1)) {
20929 case NM_LUI:
20930 if (rt != 0) {
20931 tcg_gen_movi_tl(cpu_gpr[rt],
20932 sextract32(ctx->opcode, 0, 1) << 31 |
20933 extract32(ctx->opcode, 2, 10) << 21 |
20934 extract32(ctx->opcode, 12, 9) << 12);
20936 break;
20937 case NM_ALUIPC:
20938 if (rt != 0) {
20939 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20940 extract32(ctx->opcode, 2, 10) << 21 |
20941 extract32(ctx->opcode, 12, 9) << 12;
20942 target_long addr;
20943 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20944 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20946 break;
20948 break;
20949 case NM_P_GP_BH:
20951 uint32_t u = extract32(ctx->opcode, 0, 18);
20953 switch (extract32(ctx->opcode, 18, 3)) {
20954 case NM_LBGP:
20955 gen_ld(ctx, OPC_LB, rt, 28, u);
20956 break;
20957 case NM_SBGP:
20958 gen_st(ctx, OPC_SB, rt, 28, u);
20959 break;
20960 case NM_LBUGP:
20961 gen_ld(ctx, OPC_LBU, rt, 28, u);
20962 break;
20963 case NM_ADDIUGP_B:
20964 if (rt != 0) {
20965 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20967 break;
20968 case NM_P_GP_LH:
20969 u &= ~1;
20970 switch (ctx->opcode & 1) {
20971 case NM_LHGP:
20972 gen_ld(ctx, OPC_LH, rt, 28, u);
20973 break;
20974 case NM_LHUGP:
20975 gen_ld(ctx, OPC_LHU, rt, 28, u);
20976 break;
20978 break;
20979 case NM_P_GP_SH:
20980 u &= ~1;
20981 switch (ctx->opcode & 1) {
20982 case NM_SHGP:
20983 gen_st(ctx, OPC_SH, rt, 28, u);
20984 break;
20985 default:
20986 generate_exception_end(ctx, EXCP_RI);
20987 break;
20989 break;
20990 case NM_P_GP_CP1:
20991 u &= ~0x3;
20992 switch (ctx->opcode & 0x3) {
20993 case NM_LWC1GP:
20994 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20995 break;
20996 case NM_LDC1GP:
20997 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20998 break;
20999 case NM_SWC1GP:
21000 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
21001 break;
21002 case NM_SDC1GP:
21003 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21004 break;
21006 break;
21007 default:
21008 generate_exception_end(ctx, EXCP_RI);
21009 break;
21012 break;
21013 case NM_P_LS_U12:
21015 uint32_t u = extract32(ctx->opcode, 0, 12);
21017 switch (extract32(ctx->opcode, 12, 4)) {
21018 case NM_P_PREFU12:
21019 if (rt == 31) {
21020 /* SYNCI */
21021 /* Break the TB to be able to sync copied instructions
21022 immediately */
21023 ctx->base.is_jmp = DISAS_STOP;
21024 } else {
21025 /* PREF */
21026 /* Treat as NOP. */
21028 break;
21029 case NM_LB:
21030 gen_ld(ctx, OPC_LB, rt, rs, u);
21031 break;
21032 case NM_LH:
21033 gen_ld(ctx, OPC_LH, rt, rs, u);
21034 break;
21035 case NM_LW:
21036 gen_ld(ctx, OPC_LW, rt, rs, u);
21037 break;
21038 case NM_LBU:
21039 gen_ld(ctx, OPC_LBU, rt, rs, u);
21040 break;
21041 case NM_LHU:
21042 gen_ld(ctx, OPC_LHU, rt, rs, u);
21043 break;
21044 case NM_SB:
21045 gen_st(ctx, OPC_SB, rt, rs, u);
21046 break;
21047 case NM_SH:
21048 gen_st(ctx, OPC_SH, rt, rs, u);
21049 break;
21050 case NM_SW:
21051 gen_st(ctx, OPC_SW, rt, rs, u);
21052 break;
21053 case NM_LWC1:
21054 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21055 break;
21056 case NM_LDC1:
21057 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21058 break;
21059 case NM_SWC1:
21060 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21061 break;
21062 case NM_SDC1:
21063 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21064 break;
21065 default:
21066 generate_exception_end(ctx, EXCP_RI);
21067 break;
21070 break;
21071 case NM_P_LS_S9:
21073 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21074 extract32(ctx->opcode, 0, 8);
21076 switch (extract32(ctx->opcode, 8, 3)) {
21077 case NM_P_LS_S0:
21078 switch (extract32(ctx->opcode, 11, 4)) {
21079 case NM_LBS9:
21080 gen_ld(ctx, OPC_LB, rt, rs, s);
21081 break;
21082 case NM_LHS9:
21083 gen_ld(ctx, OPC_LH, rt, rs, s);
21084 break;
21085 case NM_LWS9:
21086 gen_ld(ctx, OPC_LW, rt, rs, s);
21087 break;
21088 case NM_LBUS9:
21089 gen_ld(ctx, OPC_LBU, rt, rs, s);
21090 break;
21091 case NM_LHUS9:
21092 gen_ld(ctx, OPC_LHU, rt, rs, s);
21093 break;
21094 case NM_SBS9:
21095 gen_st(ctx, OPC_SB, rt, rs, s);
21096 break;
21097 case NM_SHS9:
21098 gen_st(ctx, OPC_SH, rt, rs, s);
21099 break;
21100 case NM_SWS9:
21101 gen_st(ctx, OPC_SW, rt, rs, s);
21102 break;
21103 case NM_LWC1S9:
21104 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21105 break;
21106 case NM_LDC1S9:
21107 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21108 break;
21109 case NM_SWC1S9:
21110 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21111 break;
21112 case NM_SDC1S9:
21113 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21114 break;
21115 case NM_P_PREFS9:
21116 if (rt == 31) {
21117 /* SYNCI */
21118 /* Break the TB to be able to sync copied instructions
21119 immediately */
21120 ctx->base.is_jmp = DISAS_STOP;
21121 } else {
21122 /* PREF */
21123 /* Treat as NOP. */
21125 break;
21126 default:
21127 generate_exception_end(ctx, EXCP_RI);
21128 break;
21130 break;
21131 case NM_P_LS_S1:
21132 switch (extract32(ctx->opcode, 11, 4)) {
21133 case NM_UALH:
21134 case NM_UASH:
21135 check_nms(ctx);
21137 TCGv t0 = tcg_temp_new();
21138 TCGv t1 = tcg_temp_new();
21140 gen_base_offset_addr(ctx, t0, rs, s);
21142 switch (extract32(ctx->opcode, 11, 4)) {
21143 case NM_UALH:
21144 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21145 MO_UNALN);
21146 gen_store_gpr(t0, rt);
21147 break;
21148 case NM_UASH:
21149 gen_load_gpr(t1, rt);
21150 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21151 MO_UNALN);
21152 break;
21154 tcg_temp_free(t0);
21155 tcg_temp_free(t1);
21157 break;
21158 case NM_P_LL:
21159 switch (ctx->opcode & 0x03) {
21160 case NM_LL:
21161 gen_ld(ctx, OPC_LL, rt, rs, s);
21162 break;
21163 case NM_LLWP:
21164 check_xnp(ctx);
21165 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21166 break;
21168 break;
21169 case NM_P_SC:
21170 switch (ctx->opcode & 0x03) {
21171 case NM_SC:
21172 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21173 break;
21174 case NM_SCWP:
21175 check_xnp(ctx);
21176 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21177 break;
21179 break;
21180 case NM_CACHE:
21181 check_cp0_enabled(ctx);
21182 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21183 gen_cache_operation(ctx, rt, rs, s);
21185 break;
21187 break;
21188 case NM_P_LS_WM:
21189 case NM_P_LS_UAWM:
21190 check_nms(ctx);
21192 int count = extract32(ctx->opcode, 12, 3);
21193 int counter = 0;
21195 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21196 extract32(ctx->opcode, 0, 8);
21197 TCGv va = tcg_temp_new();
21198 TCGv t1 = tcg_temp_new();
21199 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21200 NM_P_LS_UAWM ? MO_UNALN : 0;
21202 count = (count == 0) ? 8 : count;
21203 while (counter != count) {
21204 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21205 int this_offset = offset + (counter << 2);
21207 gen_base_offset_addr(ctx, va, rs, this_offset);
21209 switch (extract32(ctx->opcode, 11, 1)) {
21210 case NM_LWM:
21211 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21212 memop | MO_TESL);
21213 gen_store_gpr(t1, this_rt);
21214 if ((this_rt == rs) &&
21215 (counter != (count - 1))) {
21216 /* UNPREDICTABLE */
21218 break;
21219 case NM_SWM:
21220 this_rt = (rt == 0) ? 0 : this_rt;
21221 gen_load_gpr(t1, this_rt);
21222 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21223 memop | MO_TEUL);
21224 break;
21226 counter++;
21228 tcg_temp_free(va);
21229 tcg_temp_free(t1);
21231 break;
21232 default:
21233 generate_exception_end(ctx, EXCP_RI);
21234 break;
21237 break;
21238 case NM_MOVE_BALC:
21239 check_nms(ctx);
21241 TCGv t0 = tcg_temp_new();
21242 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21243 extract32(ctx->opcode, 1, 20) << 1;
21244 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21245 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21246 extract32(ctx->opcode, 21, 3));
21247 gen_load_gpr(t0, rt);
21248 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21249 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21250 tcg_temp_free(t0);
21252 break;
21253 case NM_P_BAL:
21255 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21256 extract32(ctx->opcode, 1, 24) << 1;
21258 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21259 /* BC */
21260 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21261 } else {
21262 /* BALC */
21263 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21266 break;
21267 case NM_P_J:
21268 switch (extract32(ctx->opcode, 12, 4)) {
21269 case NM_JALRC:
21270 case NM_JALRC_HB:
21271 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21272 break;
21273 case NM_P_BALRSC:
21274 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21275 break;
21276 default:
21277 generate_exception_end(ctx, EXCP_RI);
21278 break;
21280 break;
21281 case NM_P_BR1:
21283 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21284 extract32(ctx->opcode, 1, 13) << 1;
21285 switch (extract32(ctx->opcode, 14, 2)) {
21286 case NM_BEQC:
21287 check_nms(ctx);
21288 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21289 break;
21290 case NM_P_BR3A:
21291 s = sextract32(ctx->opcode, 0, 1) << 14 |
21292 extract32(ctx->opcode, 1, 13) << 1;
21293 check_cp1_enabled(ctx);
21294 switch (extract32(ctx->opcode, 16, 5)) {
21295 case NM_BC1EQZC:
21296 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21297 break;
21298 case NM_BC1NEZC:
21299 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21300 break;
21301 case NM_BPOSGE32C:
21302 check_dsp_r3(ctx);
21304 int32_t imm = extract32(ctx->opcode, 1, 13) |
21305 extract32(ctx->opcode, 0, 1) << 13;
21307 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21308 imm);
21310 break;
21311 default:
21312 generate_exception_end(ctx, EXCP_RI);
21313 break;
21315 break;
21316 case NM_BGEC:
21317 if (rs == rt) {
21318 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21319 } else {
21320 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21322 break;
21323 case NM_BGEUC:
21324 if (rs == rt || rt == 0) {
21325 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21326 } else if (rs == 0) {
21327 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21328 } else {
21329 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21331 break;
21334 break;
21335 case NM_P_BR2:
21337 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21338 extract32(ctx->opcode, 1, 13) << 1;
21339 switch (extract32(ctx->opcode, 14, 2)) {
21340 case NM_BNEC:
21341 check_nms(ctx);
21342 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21343 break;
21344 case NM_BLTC:
21345 if (rs != 0 && rt != 0 && rs == rt) {
21346 /* NOP */
21347 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21348 } else {
21349 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21351 break;
21352 case NM_BLTUC:
21353 if (rs == 0 || rs == rt) {
21354 /* NOP */
21355 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21356 } else {
21357 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21359 break;
21360 default:
21361 generate_exception_end(ctx, EXCP_RI);
21362 break;
21365 break;
21366 case NM_P_BRI:
21368 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21369 extract32(ctx->opcode, 1, 10) << 1;
21370 uint32_t u = extract32(ctx->opcode, 11, 7);
21372 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21373 rt, u, s);
21375 break;
21376 default:
21377 generate_exception_end(ctx, EXCP_RI);
21378 break;
21380 return 4;
21383 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21385 uint32_t op;
21386 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21387 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21388 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21389 int offset;
21390 int imm;
21392 /* make sure instructions are on a halfword boundary */
21393 if (ctx->base.pc_next & 0x1) {
21394 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21395 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21396 tcg_temp_free(tmp);
21397 generate_exception_end(ctx, EXCP_AdEL);
21398 return 2;
21401 op = extract32(ctx->opcode, 10, 6);
21402 switch (op) {
21403 case NM_P16_MV:
21404 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21405 if (rt != 0) {
21406 /* MOVE */
21407 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21408 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21409 } else {
21410 /* P16.RI */
21411 switch (extract32(ctx->opcode, 3, 2)) {
21412 case NM_P16_SYSCALL:
21413 if (extract32(ctx->opcode, 2, 1) == 0) {
21414 generate_exception_end(ctx, EXCP_SYSCALL);
21415 } else {
21416 generate_exception_end(ctx, EXCP_RI);
21418 break;
21419 case NM_BREAK16:
21420 generate_exception_end(ctx, EXCP_BREAK);
21421 break;
21422 case NM_SDBBP16:
21423 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21424 gen_helper_do_semihosting(cpu_env);
21425 } else {
21426 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21427 generate_exception_end(ctx, EXCP_RI);
21428 } else {
21429 generate_exception_end(ctx, EXCP_DBp);
21432 break;
21433 default:
21434 generate_exception_end(ctx, EXCP_RI);
21435 break;
21438 break;
21439 case NM_P16_SHIFT:
21441 int shift = extract32(ctx->opcode, 0, 3);
21442 uint32_t opc = 0;
21443 shift = (shift == 0) ? 8 : shift;
21445 switch (extract32(ctx->opcode, 3, 1)) {
21446 case NM_SLL16:
21447 opc = OPC_SLL;
21448 break;
21449 case NM_SRL16:
21450 opc = OPC_SRL;
21451 break;
21453 gen_shift_imm(ctx, opc, rt, rs, shift);
21455 break;
21456 case NM_P16C:
21457 switch (ctx->opcode & 1) {
21458 case NM_POOL16C_0:
21459 gen_pool16c_nanomips_insn(ctx);
21460 break;
21461 case NM_LWXS16:
21462 gen_ldxs(ctx, rt, rs, rd);
21463 break;
21465 break;
21466 case NM_P16_A1:
21467 switch (extract32(ctx->opcode, 6, 1)) {
21468 case NM_ADDIUR1SP:
21469 imm = extract32(ctx->opcode, 0, 6) << 2;
21470 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21471 break;
21472 default:
21473 generate_exception_end(ctx, EXCP_RI);
21474 break;
21476 break;
21477 case NM_P16_A2:
21478 switch (extract32(ctx->opcode, 3, 1)) {
21479 case NM_ADDIUR2:
21480 imm = extract32(ctx->opcode, 0, 3) << 2;
21481 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21482 break;
21483 case NM_P_ADDIURS5:
21484 rt = extract32(ctx->opcode, 5, 5);
21485 if (rt != 0) {
21486 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21487 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21488 (extract32(ctx->opcode, 0, 3));
21489 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21491 break;
21493 break;
21494 case NM_P16_ADDU:
21495 switch (ctx->opcode & 0x1) {
21496 case NM_ADDU16:
21497 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21498 break;
21499 case NM_SUBU16:
21500 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21501 break;
21503 break;
21504 case NM_P16_4X4:
21505 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21506 extract32(ctx->opcode, 5, 3);
21507 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21508 extract32(ctx->opcode, 0, 3);
21509 rt = decode_gpr_gpr4(rt);
21510 rs = decode_gpr_gpr4(rs);
21511 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21512 (extract32(ctx->opcode, 3, 1))) {
21513 case NM_ADDU4X4:
21514 check_nms(ctx);
21515 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21516 break;
21517 case NM_MUL4X4:
21518 check_nms(ctx);
21519 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21520 break;
21521 default:
21522 generate_exception_end(ctx, EXCP_RI);
21523 break;
21525 break;
21526 case NM_LI16:
21528 int imm = extract32(ctx->opcode, 0, 7);
21529 imm = (imm == 0x7f ? -1 : imm);
21530 if (rt != 0) {
21531 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21534 break;
21535 case NM_ANDI16:
21537 uint32_t u = extract32(ctx->opcode, 0, 4);
21538 u = (u == 12) ? 0xff :
21539 (u == 13) ? 0xffff : u;
21540 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21542 break;
21543 case NM_P16_LB:
21544 offset = extract32(ctx->opcode, 0, 2);
21545 switch (extract32(ctx->opcode, 2, 2)) {
21546 case NM_LB16:
21547 gen_ld(ctx, OPC_LB, rt, rs, offset);
21548 break;
21549 case NM_SB16:
21550 rt = decode_gpr_gpr3_src_store(
21551 NANOMIPS_EXTRACT_RD(ctx->opcode));
21552 gen_st(ctx, OPC_SB, rt, rs, offset);
21553 break;
21554 case NM_LBU16:
21555 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21556 break;
21557 default:
21558 generate_exception_end(ctx, EXCP_RI);
21559 break;
21561 break;
21562 case NM_P16_LH:
21563 offset = extract32(ctx->opcode, 1, 2) << 1;
21564 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21565 case NM_LH16:
21566 gen_ld(ctx, OPC_LH, rt, rs, offset);
21567 break;
21568 case NM_SH16:
21569 rt = decode_gpr_gpr3_src_store(
21570 NANOMIPS_EXTRACT_RD(ctx->opcode));
21571 gen_st(ctx, OPC_SH, rt, rs, offset);
21572 break;
21573 case NM_LHU16:
21574 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21575 break;
21576 default:
21577 generate_exception_end(ctx, EXCP_RI);
21578 break;
21580 break;
21581 case NM_LW16:
21582 offset = extract32(ctx->opcode, 0, 4) << 2;
21583 gen_ld(ctx, OPC_LW, rt, rs, offset);
21584 break;
21585 case NM_LWSP16:
21586 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21587 offset = extract32(ctx->opcode, 0, 5) << 2;
21588 gen_ld(ctx, OPC_LW, rt, 29, offset);
21589 break;
21590 case NM_LW4X4:
21591 check_nms(ctx);
21592 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21593 extract32(ctx->opcode, 5, 3);
21594 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21595 extract32(ctx->opcode, 0, 3);
21596 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21597 (extract32(ctx->opcode, 8, 1) << 2);
21598 rt = decode_gpr_gpr4(rt);
21599 rs = decode_gpr_gpr4(rs);
21600 gen_ld(ctx, OPC_LW, rt, rs, offset);
21601 break;
21602 case NM_SW4X4:
21603 check_nms(ctx);
21604 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21605 extract32(ctx->opcode, 5, 3);
21606 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21607 extract32(ctx->opcode, 0, 3);
21608 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21609 (extract32(ctx->opcode, 8, 1) << 2);
21610 rt = decode_gpr_gpr4_zero(rt);
21611 rs = decode_gpr_gpr4(rs);
21612 gen_st(ctx, OPC_SW, rt, rs, offset);
21613 break;
21614 case NM_LWGP16:
21615 offset = extract32(ctx->opcode, 0, 7) << 2;
21616 gen_ld(ctx, OPC_LW, rt, 28, offset);
21617 break;
21618 case NM_SWSP16:
21619 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21620 offset = extract32(ctx->opcode, 0, 5) << 2;
21621 gen_st(ctx, OPC_SW, rt, 29, offset);
21622 break;
21623 case NM_SW16:
21624 rt = decode_gpr_gpr3_src_store(
21625 NANOMIPS_EXTRACT_RD(ctx->opcode));
21626 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21627 offset = extract32(ctx->opcode, 0, 4) << 2;
21628 gen_st(ctx, OPC_SW, rt, rs, offset);
21629 break;
21630 case NM_SWGP16:
21631 rt = decode_gpr_gpr3_src_store(
21632 NANOMIPS_EXTRACT_RD(ctx->opcode));
21633 offset = extract32(ctx->opcode, 0, 7) << 2;
21634 gen_st(ctx, OPC_SW, rt, 28, offset);
21635 break;
21636 case NM_BC16:
21637 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21638 (sextract32(ctx->opcode, 0, 1) << 10) |
21639 (extract32(ctx->opcode, 1, 9) << 1));
21640 break;
21641 case NM_BALC16:
21642 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21643 (sextract32(ctx->opcode, 0, 1) << 10) |
21644 (extract32(ctx->opcode, 1, 9) << 1));
21645 break;
21646 case NM_BEQZC16:
21647 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21648 (sextract32(ctx->opcode, 0, 1) << 7) |
21649 (extract32(ctx->opcode, 1, 6) << 1));
21650 break;
21651 case NM_BNEZC16:
21652 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21653 (sextract32(ctx->opcode, 0, 1) << 7) |
21654 (extract32(ctx->opcode, 1, 6) << 1));
21655 break;
21656 case NM_P16_BR:
21657 switch (ctx->opcode & 0xf) {
21658 case 0:
21659 /* P16.JRC */
21660 switch (extract32(ctx->opcode, 4, 1)) {
21661 case NM_JRC:
21662 gen_compute_branch_nm(ctx, OPC_JR, 2,
21663 extract32(ctx->opcode, 5, 5), 0, 0);
21664 break;
21665 case NM_JALRC16:
21666 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21667 extract32(ctx->opcode, 5, 5), 31, 0);
21668 break;
21670 break;
21671 default:
21673 /* P16.BRI */
21674 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21675 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21676 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21677 extract32(ctx->opcode, 0, 4) << 1);
21679 break;
21681 break;
21682 case NM_P16_SR:
21684 int count = extract32(ctx->opcode, 0, 4);
21685 int u = extract32(ctx->opcode, 4, 4) << 4;
21687 rt = 30 + extract32(ctx->opcode, 9, 1);
21688 switch (extract32(ctx->opcode, 8, 1)) {
21689 case NM_SAVE16:
21690 gen_save(ctx, rt, count, 0, u);
21691 break;
21692 case NM_RESTORE_JRC16:
21693 gen_restore(ctx, rt, count, 0, u);
21694 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21695 break;
21698 break;
21699 case NM_MOVEP:
21700 case NM_MOVEPREV:
21701 check_nms(ctx);
21703 static const int gpr2reg1[] = {4, 5, 6, 7};
21704 static const int gpr2reg2[] = {5, 6, 7, 8};
21705 int re;
21706 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21707 extract32(ctx->opcode, 8, 1);
21708 int r1 = gpr2reg1[rd2];
21709 int r2 = gpr2reg2[rd2];
21710 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21711 extract32(ctx->opcode, 0, 3);
21712 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21713 extract32(ctx->opcode, 5, 3);
21714 TCGv t0 = tcg_temp_new();
21715 TCGv t1 = tcg_temp_new();
21716 if (op == NM_MOVEP) {
21717 rd = r1;
21718 re = r2;
21719 rs = decode_gpr_gpr4_zero(r3);
21720 rt = decode_gpr_gpr4_zero(r4);
21721 } else {
21722 rd = decode_gpr_gpr4(r3);
21723 re = decode_gpr_gpr4(r4);
21724 rs = r1;
21725 rt = r2;
21727 gen_load_gpr(t0, rs);
21728 gen_load_gpr(t1, rt);
21729 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21730 tcg_gen_mov_tl(cpu_gpr[re], t1);
21731 tcg_temp_free(t0);
21732 tcg_temp_free(t1);
21734 break;
21735 default:
21736 return decode_nanomips_32_48_opc(env, ctx);
21739 return 2;
21743 /* SmartMIPS extension to MIPS32 */
21745 #if defined(TARGET_MIPS64)
21747 /* MDMX extension to MIPS64 */
21749 #endif
21751 /* MIPSDSP functions. */
21752 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21753 int rd, int base, int offset)
21755 TCGv t0;
21757 check_dsp(ctx);
21758 t0 = tcg_temp_new();
21760 if (base == 0) {
21761 gen_load_gpr(t0, offset);
21762 } else if (offset == 0) {
21763 gen_load_gpr(t0, base);
21764 } else {
21765 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21768 switch (opc) {
21769 case OPC_LBUX:
21770 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21771 gen_store_gpr(t0, rd);
21772 break;
21773 case OPC_LHX:
21774 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21775 gen_store_gpr(t0, rd);
21776 break;
21777 case OPC_LWX:
21778 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21779 gen_store_gpr(t0, rd);
21780 break;
21781 #if defined(TARGET_MIPS64)
21782 case OPC_LDX:
21783 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21784 gen_store_gpr(t0, rd);
21785 break;
21786 #endif
21788 tcg_temp_free(t0);
21791 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21792 int ret, int v1, int v2)
21794 TCGv v1_t;
21795 TCGv v2_t;
21797 if (ret == 0) {
21798 /* Treat as NOP. */
21799 return;
21802 v1_t = tcg_temp_new();
21803 v2_t = tcg_temp_new();
21805 gen_load_gpr(v1_t, v1);
21806 gen_load_gpr(v2_t, v2);
21808 switch (op1) {
21809 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21810 case OPC_MULT_G_2E:
21811 check_dsp_r2(ctx);
21812 switch (op2) {
21813 case OPC_ADDUH_QB:
21814 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21815 break;
21816 case OPC_ADDUH_R_QB:
21817 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21818 break;
21819 case OPC_ADDQH_PH:
21820 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21821 break;
21822 case OPC_ADDQH_R_PH:
21823 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21824 break;
21825 case OPC_ADDQH_W:
21826 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21827 break;
21828 case OPC_ADDQH_R_W:
21829 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21830 break;
21831 case OPC_SUBUH_QB:
21832 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21833 break;
21834 case OPC_SUBUH_R_QB:
21835 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21836 break;
21837 case OPC_SUBQH_PH:
21838 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21839 break;
21840 case OPC_SUBQH_R_PH:
21841 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21842 break;
21843 case OPC_SUBQH_W:
21844 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21845 break;
21846 case OPC_SUBQH_R_W:
21847 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21848 break;
21850 break;
21851 case OPC_ABSQ_S_PH_DSP:
21852 switch (op2) {
21853 case OPC_ABSQ_S_QB:
21854 check_dsp_r2(ctx);
21855 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21856 break;
21857 case OPC_ABSQ_S_PH:
21858 check_dsp(ctx);
21859 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21860 break;
21861 case OPC_ABSQ_S_W:
21862 check_dsp(ctx);
21863 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21864 break;
21865 case OPC_PRECEQ_W_PHL:
21866 check_dsp(ctx);
21867 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21868 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21869 break;
21870 case OPC_PRECEQ_W_PHR:
21871 check_dsp(ctx);
21872 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21873 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21874 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21875 break;
21876 case OPC_PRECEQU_PH_QBL:
21877 check_dsp(ctx);
21878 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21879 break;
21880 case OPC_PRECEQU_PH_QBR:
21881 check_dsp(ctx);
21882 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21883 break;
21884 case OPC_PRECEQU_PH_QBLA:
21885 check_dsp(ctx);
21886 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21887 break;
21888 case OPC_PRECEQU_PH_QBRA:
21889 check_dsp(ctx);
21890 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21891 break;
21892 case OPC_PRECEU_PH_QBL:
21893 check_dsp(ctx);
21894 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21895 break;
21896 case OPC_PRECEU_PH_QBR:
21897 check_dsp(ctx);
21898 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21899 break;
21900 case OPC_PRECEU_PH_QBLA:
21901 check_dsp(ctx);
21902 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21903 break;
21904 case OPC_PRECEU_PH_QBRA:
21905 check_dsp(ctx);
21906 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21907 break;
21909 break;
21910 case OPC_ADDU_QB_DSP:
21911 switch (op2) {
21912 case OPC_ADDQ_PH:
21913 check_dsp(ctx);
21914 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21915 break;
21916 case OPC_ADDQ_S_PH:
21917 check_dsp(ctx);
21918 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21919 break;
21920 case OPC_ADDQ_S_W:
21921 check_dsp(ctx);
21922 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21923 break;
21924 case OPC_ADDU_QB:
21925 check_dsp(ctx);
21926 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21927 break;
21928 case OPC_ADDU_S_QB:
21929 check_dsp(ctx);
21930 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21931 break;
21932 case OPC_ADDU_PH:
21933 check_dsp_r2(ctx);
21934 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21935 break;
21936 case OPC_ADDU_S_PH:
21937 check_dsp_r2(ctx);
21938 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21939 break;
21940 case OPC_SUBQ_PH:
21941 check_dsp(ctx);
21942 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21943 break;
21944 case OPC_SUBQ_S_PH:
21945 check_dsp(ctx);
21946 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21947 break;
21948 case OPC_SUBQ_S_W:
21949 check_dsp(ctx);
21950 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21951 break;
21952 case OPC_SUBU_QB:
21953 check_dsp(ctx);
21954 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21955 break;
21956 case OPC_SUBU_S_QB:
21957 check_dsp(ctx);
21958 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21959 break;
21960 case OPC_SUBU_PH:
21961 check_dsp_r2(ctx);
21962 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21963 break;
21964 case OPC_SUBU_S_PH:
21965 check_dsp_r2(ctx);
21966 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21967 break;
21968 case OPC_ADDSC:
21969 check_dsp(ctx);
21970 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21971 break;
21972 case OPC_ADDWC:
21973 check_dsp(ctx);
21974 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21975 break;
21976 case OPC_MODSUB:
21977 check_dsp(ctx);
21978 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21979 break;
21980 case OPC_RADDU_W_QB:
21981 check_dsp(ctx);
21982 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21983 break;
21985 break;
21986 case OPC_CMPU_EQ_QB_DSP:
21987 switch (op2) {
21988 case OPC_PRECR_QB_PH:
21989 check_dsp_r2(ctx);
21990 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21991 break;
21992 case OPC_PRECRQ_QB_PH:
21993 check_dsp(ctx);
21994 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21995 break;
21996 case OPC_PRECR_SRA_PH_W:
21997 check_dsp_r2(ctx);
21999 TCGv_i32 sa_t = tcg_const_i32(v2);
22000 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
22001 cpu_gpr[ret]);
22002 tcg_temp_free_i32(sa_t);
22003 break;
22005 case OPC_PRECR_SRA_R_PH_W:
22006 check_dsp_r2(ctx);
22008 TCGv_i32 sa_t = tcg_const_i32(v2);
22009 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22010 cpu_gpr[ret]);
22011 tcg_temp_free_i32(sa_t);
22012 break;
22014 case OPC_PRECRQ_PH_W:
22015 check_dsp(ctx);
22016 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22017 break;
22018 case OPC_PRECRQ_RS_PH_W:
22019 check_dsp(ctx);
22020 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22021 break;
22022 case OPC_PRECRQU_S_QB_PH:
22023 check_dsp(ctx);
22024 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22025 break;
22027 break;
22028 #ifdef TARGET_MIPS64
22029 case OPC_ABSQ_S_QH_DSP:
22030 switch (op2) {
22031 case OPC_PRECEQ_L_PWL:
22032 check_dsp(ctx);
22033 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22034 break;
22035 case OPC_PRECEQ_L_PWR:
22036 check_dsp(ctx);
22037 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22038 break;
22039 case OPC_PRECEQ_PW_QHL:
22040 check_dsp(ctx);
22041 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22042 break;
22043 case OPC_PRECEQ_PW_QHR:
22044 check_dsp(ctx);
22045 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22046 break;
22047 case OPC_PRECEQ_PW_QHLA:
22048 check_dsp(ctx);
22049 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22050 break;
22051 case OPC_PRECEQ_PW_QHRA:
22052 check_dsp(ctx);
22053 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22054 break;
22055 case OPC_PRECEQU_QH_OBL:
22056 check_dsp(ctx);
22057 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22058 break;
22059 case OPC_PRECEQU_QH_OBR:
22060 check_dsp(ctx);
22061 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22062 break;
22063 case OPC_PRECEQU_QH_OBLA:
22064 check_dsp(ctx);
22065 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22066 break;
22067 case OPC_PRECEQU_QH_OBRA:
22068 check_dsp(ctx);
22069 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22070 break;
22071 case OPC_PRECEU_QH_OBL:
22072 check_dsp(ctx);
22073 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22074 break;
22075 case OPC_PRECEU_QH_OBR:
22076 check_dsp(ctx);
22077 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22078 break;
22079 case OPC_PRECEU_QH_OBLA:
22080 check_dsp(ctx);
22081 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22082 break;
22083 case OPC_PRECEU_QH_OBRA:
22084 check_dsp(ctx);
22085 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22086 break;
22087 case OPC_ABSQ_S_OB:
22088 check_dsp_r2(ctx);
22089 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22090 break;
22091 case OPC_ABSQ_S_PW:
22092 check_dsp(ctx);
22093 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22094 break;
22095 case OPC_ABSQ_S_QH:
22096 check_dsp(ctx);
22097 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22098 break;
22100 break;
22101 case OPC_ADDU_OB_DSP:
22102 switch (op2) {
22103 case OPC_RADDU_L_OB:
22104 check_dsp(ctx);
22105 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22106 break;
22107 case OPC_SUBQ_PW:
22108 check_dsp(ctx);
22109 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22110 break;
22111 case OPC_SUBQ_S_PW:
22112 check_dsp(ctx);
22113 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22114 break;
22115 case OPC_SUBQ_QH:
22116 check_dsp(ctx);
22117 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22118 break;
22119 case OPC_SUBQ_S_QH:
22120 check_dsp(ctx);
22121 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22122 break;
22123 case OPC_SUBU_OB:
22124 check_dsp(ctx);
22125 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22126 break;
22127 case OPC_SUBU_S_OB:
22128 check_dsp(ctx);
22129 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22130 break;
22131 case OPC_SUBU_QH:
22132 check_dsp_r2(ctx);
22133 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22134 break;
22135 case OPC_SUBU_S_QH:
22136 check_dsp_r2(ctx);
22137 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22138 break;
22139 case OPC_SUBUH_OB:
22140 check_dsp_r2(ctx);
22141 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22142 break;
22143 case OPC_SUBUH_R_OB:
22144 check_dsp_r2(ctx);
22145 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22146 break;
22147 case OPC_ADDQ_PW:
22148 check_dsp(ctx);
22149 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22150 break;
22151 case OPC_ADDQ_S_PW:
22152 check_dsp(ctx);
22153 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22154 break;
22155 case OPC_ADDQ_QH:
22156 check_dsp(ctx);
22157 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22158 break;
22159 case OPC_ADDQ_S_QH:
22160 check_dsp(ctx);
22161 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22162 break;
22163 case OPC_ADDU_OB:
22164 check_dsp(ctx);
22165 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22166 break;
22167 case OPC_ADDU_S_OB:
22168 check_dsp(ctx);
22169 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22170 break;
22171 case OPC_ADDU_QH:
22172 check_dsp_r2(ctx);
22173 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22174 break;
22175 case OPC_ADDU_S_QH:
22176 check_dsp_r2(ctx);
22177 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22178 break;
22179 case OPC_ADDUH_OB:
22180 check_dsp_r2(ctx);
22181 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22182 break;
22183 case OPC_ADDUH_R_OB:
22184 check_dsp_r2(ctx);
22185 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22186 break;
22188 break;
22189 case OPC_CMPU_EQ_OB_DSP:
22190 switch (op2) {
22191 case OPC_PRECR_OB_QH:
22192 check_dsp_r2(ctx);
22193 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22194 break;
22195 case OPC_PRECR_SRA_QH_PW:
22196 check_dsp_r2(ctx);
22198 TCGv_i32 ret_t = tcg_const_i32(ret);
22199 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22200 tcg_temp_free_i32(ret_t);
22201 break;
22203 case OPC_PRECR_SRA_R_QH_PW:
22204 check_dsp_r2(ctx);
22206 TCGv_i32 sa_v = tcg_const_i32(ret);
22207 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22208 tcg_temp_free_i32(sa_v);
22209 break;
22211 case OPC_PRECRQ_OB_QH:
22212 check_dsp(ctx);
22213 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22214 break;
22215 case OPC_PRECRQ_PW_L:
22216 check_dsp(ctx);
22217 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22218 break;
22219 case OPC_PRECRQ_QH_PW:
22220 check_dsp(ctx);
22221 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22222 break;
22223 case OPC_PRECRQ_RS_QH_PW:
22224 check_dsp(ctx);
22225 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22226 break;
22227 case OPC_PRECRQU_S_OB_QH:
22228 check_dsp(ctx);
22229 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22230 break;
22232 break;
22233 #endif
22236 tcg_temp_free(v1_t);
22237 tcg_temp_free(v2_t);
22240 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22241 int ret, int v1, int v2)
22243 uint32_t op2;
22244 TCGv t0;
22245 TCGv v1_t;
22246 TCGv v2_t;
22248 if (ret == 0) {
22249 /* Treat as NOP. */
22250 return;
22253 t0 = tcg_temp_new();
22254 v1_t = tcg_temp_new();
22255 v2_t = tcg_temp_new();
22257 tcg_gen_movi_tl(t0, v1);
22258 gen_load_gpr(v1_t, v1);
22259 gen_load_gpr(v2_t, v2);
22261 switch (opc) {
22262 case OPC_SHLL_QB_DSP:
22264 op2 = MASK_SHLL_QB(ctx->opcode);
22265 switch (op2) {
22266 case OPC_SHLL_QB:
22267 check_dsp(ctx);
22268 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22269 break;
22270 case OPC_SHLLV_QB:
22271 check_dsp(ctx);
22272 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22273 break;
22274 case OPC_SHLL_PH:
22275 check_dsp(ctx);
22276 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22277 break;
22278 case OPC_SHLLV_PH:
22279 check_dsp(ctx);
22280 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22281 break;
22282 case OPC_SHLL_S_PH:
22283 check_dsp(ctx);
22284 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22285 break;
22286 case OPC_SHLLV_S_PH:
22287 check_dsp(ctx);
22288 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22289 break;
22290 case OPC_SHLL_S_W:
22291 check_dsp(ctx);
22292 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22293 break;
22294 case OPC_SHLLV_S_W:
22295 check_dsp(ctx);
22296 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22297 break;
22298 case OPC_SHRL_QB:
22299 check_dsp(ctx);
22300 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22301 break;
22302 case OPC_SHRLV_QB:
22303 check_dsp(ctx);
22304 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22305 break;
22306 case OPC_SHRL_PH:
22307 check_dsp_r2(ctx);
22308 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22309 break;
22310 case OPC_SHRLV_PH:
22311 check_dsp_r2(ctx);
22312 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22313 break;
22314 case OPC_SHRA_QB:
22315 check_dsp_r2(ctx);
22316 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22317 break;
22318 case OPC_SHRA_R_QB:
22319 check_dsp_r2(ctx);
22320 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22321 break;
22322 case OPC_SHRAV_QB:
22323 check_dsp_r2(ctx);
22324 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22325 break;
22326 case OPC_SHRAV_R_QB:
22327 check_dsp_r2(ctx);
22328 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22329 break;
22330 case OPC_SHRA_PH:
22331 check_dsp(ctx);
22332 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22333 break;
22334 case OPC_SHRA_R_PH:
22335 check_dsp(ctx);
22336 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22337 break;
22338 case OPC_SHRAV_PH:
22339 check_dsp(ctx);
22340 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22341 break;
22342 case OPC_SHRAV_R_PH:
22343 check_dsp(ctx);
22344 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22345 break;
22346 case OPC_SHRA_R_W:
22347 check_dsp(ctx);
22348 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22349 break;
22350 case OPC_SHRAV_R_W:
22351 check_dsp(ctx);
22352 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22353 break;
22354 default: /* Invalid */
22355 MIPS_INVAL("MASK SHLL.QB");
22356 generate_exception_end(ctx, EXCP_RI);
22357 break;
22359 break;
22361 #ifdef TARGET_MIPS64
22362 case OPC_SHLL_OB_DSP:
22363 op2 = MASK_SHLL_OB(ctx->opcode);
22364 switch (op2) {
22365 case OPC_SHLL_PW:
22366 check_dsp(ctx);
22367 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22368 break;
22369 case OPC_SHLLV_PW:
22370 check_dsp(ctx);
22371 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22372 break;
22373 case OPC_SHLL_S_PW:
22374 check_dsp(ctx);
22375 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22376 break;
22377 case OPC_SHLLV_S_PW:
22378 check_dsp(ctx);
22379 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22380 break;
22381 case OPC_SHLL_OB:
22382 check_dsp(ctx);
22383 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22384 break;
22385 case OPC_SHLLV_OB:
22386 check_dsp(ctx);
22387 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22388 break;
22389 case OPC_SHLL_QH:
22390 check_dsp(ctx);
22391 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22392 break;
22393 case OPC_SHLLV_QH:
22394 check_dsp(ctx);
22395 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22396 break;
22397 case OPC_SHLL_S_QH:
22398 check_dsp(ctx);
22399 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22400 break;
22401 case OPC_SHLLV_S_QH:
22402 check_dsp(ctx);
22403 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22404 break;
22405 case OPC_SHRA_OB:
22406 check_dsp_r2(ctx);
22407 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22408 break;
22409 case OPC_SHRAV_OB:
22410 check_dsp_r2(ctx);
22411 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22412 break;
22413 case OPC_SHRA_R_OB:
22414 check_dsp_r2(ctx);
22415 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22416 break;
22417 case OPC_SHRAV_R_OB:
22418 check_dsp_r2(ctx);
22419 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22420 break;
22421 case OPC_SHRA_PW:
22422 check_dsp(ctx);
22423 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22424 break;
22425 case OPC_SHRAV_PW:
22426 check_dsp(ctx);
22427 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22428 break;
22429 case OPC_SHRA_R_PW:
22430 check_dsp(ctx);
22431 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22432 break;
22433 case OPC_SHRAV_R_PW:
22434 check_dsp(ctx);
22435 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22436 break;
22437 case OPC_SHRA_QH:
22438 check_dsp(ctx);
22439 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22440 break;
22441 case OPC_SHRAV_QH:
22442 check_dsp(ctx);
22443 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22444 break;
22445 case OPC_SHRA_R_QH:
22446 check_dsp(ctx);
22447 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22448 break;
22449 case OPC_SHRAV_R_QH:
22450 check_dsp(ctx);
22451 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22452 break;
22453 case OPC_SHRL_OB:
22454 check_dsp(ctx);
22455 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22456 break;
22457 case OPC_SHRLV_OB:
22458 check_dsp(ctx);
22459 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22460 break;
22461 case OPC_SHRL_QH:
22462 check_dsp_r2(ctx);
22463 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22464 break;
22465 case OPC_SHRLV_QH:
22466 check_dsp_r2(ctx);
22467 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22468 break;
22469 default: /* Invalid */
22470 MIPS_INVAL("MASK SHLL.OB");
22471 generate_exception_end(ctx, EXCP_RI);
22472 break;
22474 break;
22475 #endif
22478 tcg_temp_free(t0);
22479 tcg_temp_free(v1_t);
22480 tcg_temp_free(v2_t);
22483 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22484 int ret, int v1, int v2, int check_ret)
22486 TCGv_i32 t0;
22487 TCGv v1_t;
22488 TCGv v2_t;
22490 if ((ret == 0) && (check_ret == 1)) {
22491 /* Treat as NOP. */
22492 return;
22495 t0 = tcg_temp_new_i32();
22496 v1_t = tcg_temp_new();
22497 v2_t = tcg_temp_new();
22499 tcg_gen_movi_i32(t0, ret);
22500 gen_load_gpr(v1_t, v1);
22501 gen_load_gpr(v2_t, v2);
22503 switch (op1) {
22504 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22505 * the same mask and op1. */
22506 case OPC_MULT_G_2E:
22507 check_dsp_r2(ctx);
22508 switch (op2) {
22509 case OPC_MUL_PH:
22510 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22511 break;
22512 case OPC_MUL_S_PH:
22513 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22514 break;
22515 case OPC_MULQ_S_W:
22516 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22517 break;
22518 case OPC_MULQ_RS_W:
22519 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22520 break;
22522 break;
22523 case OPC_DPA_W_PH_DSP:
22524 switch (op2) {
22525 case OPC_DPAU_H_QBL:
22526 check_dsp(ctx);
22527 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22528 break;
22529 case OPC_DPAU_H_QBR:
22530 check_dsp(ctx);
22531 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22532 break;
22533 case OPC_DPSU_H_QBL:
22534 check_dsp(ctx);
22535 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22536 break;
22537 case OPC_DPSU_H_QBR:
22538 check_dsp(ctx);
22539 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22540 break;
22541 case OPC_DPA_W_PH:
22542 check_dsp_r2(ctx);
22543 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22544 break;
22545 case OPC_DPAX_W_PH:
22546 check_dsp_r2(ctx);
22547 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22548 break;
22549 case OPC_DPAQ_S_W_PH:
22550 check_dsp(ctx);
22551 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22552 break;
22553 case OPC_DPAQX_S_W_PH:
22554 check_dsp_r2(ctx);
22555 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22556 break;
22557 case OPC_DPAQX_SA_W_PH:
22558 check_dsp_r2(ctx);
22559 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22560 break;
22561 case OPC_DPS_W_PH:
22562 check_dsp_r2(ctx);
22563 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22564 break;
22565 case OPC_DPSX_W_PH:
22566 check_dsp_r2(ctx);
22567 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22568 break;
22569 case OPC_DPSQ_S_W_PH:
22570 check_dsp(ctx);
22571 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22572 break;
22573 case OPC_DPSQX_S_W_PH:
22574 check_dsp_r2(ctx);
22575 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22576 break;
22577 case OPC_DPSQX_SA_W_PH:
22578 check_dsp_r2(ctx);
22579 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22580 break;
22581 case OPC_MULSAQ_S_W_PH:
22582 check_dsp(ctx);
22583 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22584 break;
22585 case OPC_DPAQ_SA_L_W:
22586 check_dsp(ctx);
22587 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22588 break;
22589 case OPC_DPSQ_SA_L_W:
22590 check_dsp(ctx);
22591 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22592 break;
22593 case OPC_MAQ_S_W_PHL:
22594 check_dsp(ctx);
22595 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22596 break;
22597 case OPC_MAQ_S_W_PHR:
22598 check_dsp(ctx);
22599 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22600 break;
22601 case OPC_MAQ_SA_W_PHL:
22602 check_dsp(ctx);
22603 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22604 break;
22605 case OPC_MAQ_SA_W_PHR:
22606 check_dsp(ctx);
22607 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22608 break;
22609 case OPC_MULSA_W_PH:
22610 check_dsp_r2(ctx);
22611 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22612 break;
22614 break;
22615 #ifdef TARGET_MIPS64
22616 case OPC_DPAQ_W_QH_DSP:
22618 int ac = ret & 0x03;
22619 tcg_gen_movi_i32(t0, ac);
22621 switch (op2) {
22622 case OPC_DMADD:
22623 check_dsp(ctx);
22624 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22625 break;
22626 case OPC_DMADDU:
22627 check_dsp(ctx);
22628 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22629 break;
22630 case OPC_DMSUB:
22631 check_dsp(ctx);
22632 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22633 break;
22634 case OPC_DMSUBU:
22635 check_dsp(ctx);
22636 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22637 break;
22638 case OPC_DPA_W_QH:
22639 check_dsp_r2(ctx);
22640 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22641 break;
22642 case OPC_DPAQ_S_W_QH:
22643 check_dsp(ctx);
22644 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22645 break;
22646 case OPC_DPAQ_SA_L_PW:
22647 check_dsp(ctx);
22648 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22649 break;
22650 case OPC_DPAU_H_OBL:
22651 check_dsp(ctx);
22652 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22653 break;
22654 case OPC_DPAU_H_OBR:
22655 check_dsp(ctx);
22656 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22657 break;
22658 case OPC_DPS_W_QH:
22659 check_dsp_r2(ctx);
22660 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22661 break;
22662 case OPC_DPSQ_S_W_QH:
22663 check_dsp(ctx);
22664 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22665 break;
22666 case OPC_DPSQ_SA_L_PW:
22667 check_dsp(ctx);
22668 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22669 break;
22670 case OPC_DPSU_H_OBL:
22671 check_dsp(ctx);
22672 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22673 break;
22674 case OPC_DPSU_H_OBR:
22675 check_dsp(ctx);
22676 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22677 break;
22678 case OPC_MAQ_S_L_PWL:
22679 check_dsp(ctx);
22680 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22681 break;
22682 case OPC_MAQ_S_L_PWR:
22683 check_dsp(ctx);
22684 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22685 break;
22686 case OPC_MAQ_S_W_QHLL:
22687 check_dsp(ctx);
22688 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22689 break;
22690 case OPC_MAQ_SA_W_QHLL:
22691 check_dsp(ctx);
22692 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22693 break;
22694 case OPC_MAQ_S_W_QHLR:
22695 check_dsp(ctx);
22696 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22697 break;
22698 case OPC_MAQ_SA_W_QHLR:
22699 check_dsp(ctx);
22700 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22701 break;
22702 case OPC_MAQ_S_W_QHRL:
22703 check_dsp(ctx);
22704 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22705 break;
22706 case OPC_MAQ_SA_W_QHRL:
22707 check_dsp(ctx);
22708 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22709 break;
22710 case OPC_MAQ_S_W_QHRR:
22711 check_dsp(ctx);
22712 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22713 break;
22714 case OPC_MAQ_SA_W_QHRR:
22715 check_dsp(ctx);
22716 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22717 break;
22718 case OPC_MULSAQ_S_L_PW:
22719 check_dsp(ctx);
22720 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22721 break;
22722 case OPC_MULSAQ_S_W_QH:
22723 check_dsp(ctx);
22724 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22725 break;
22728 break;
22729 #endif
22730 case OPC_ADDU_QB_DSP:
22731 switch (op2) {
22732 case OPC_MULEU_S_PH_QBL:
22733 check_dsp(ctx);
22734 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22735 break;
22736 case OPC_MULEU_S_PH_QBR:
22737 check_dsp(ctx);
22738 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22739 break;
22740 case OPC_MULQ_RS_PH:
22741 check_dsp(ctx);
22742 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22743 break;
22744 case OPC_MULEQ_S_W_PHL:
22745 check_dsp(ctx);
22746 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22747 break;
22748 case OPC_MULEQ_S_W_PHR:
22749 check_dsp(ctx);
22750 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22751 break;
22752 case OPC_MULQ_S_PH:
22753 check_dsp_r2(ctx);
22754 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22755 break;
22757 break;
22758 #ifdef TARGET_MIPS64
22759 case OPC_ADDU_OB_DSP:
22760 switch (op2) {
22761 case OPC_MULEQ_S_PW_QHL:
22762 check_dsp(ctx);
22763 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22764 break;
22765 case OPC_MULEQ_S_PW_QHR:
22766 check_dsp(ctx);
22767 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22768 break;
22769 case OPC_MULEU_S_QH_OBL:
22770 check_dsp(ctx);
22771 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22772 break;
22773 case OPC_MULEU_S_QH_OBR:
22774 check_dsp(ctx);
22775 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22776 break;
22777 case OPC_MULQ_RS_QH:
22778 check_dsp(ctx);
22779 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22780 break;
22782 break;
22783 #endif
22786 tcg_temp_free_i32(t0);
22787 tcg_temp_free(v1_t);
22788 tcg_temp_free(v2_t);
22791 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22792 int ret, int val)
22794 int16_t imm;
22795 TCGv t0;
22796 TCGv val_t;
22798 if (ret == 0) {
22799 /* Treat as NOP. */
22800 return;
22803 t0 = tcg_temp_new();
22804 val_t = tcg_temp_new();
22805 gen_load_gpr(val_t, val);
22807 switch (op1) {
22808 case OPC_ABSQ_S_PH_DSP:
22809 switch (op2) {
22810 case OPC_BITREV:
22811 check_dsp(ctx);
22812 gen_helper_bitrev(cpu_gpr[ret], val_t);
22813 break;
22814 case OPC_REPL_QB:
22815 check_dsp(ctx);
22817 target_long result;
22818 imm = (ctx->opcode >> 16) & 0xFF;
22819 result = (uint32_t)imm << 24 |
22820 (uint32_t)imm << 16 |
22821 (uint32_t)imm << 8 |
22822 (uint32_t)imm;
22823 result = (int32_t)result;
22824 tcg_gen_movi_tl(cpu_gpr[ret], result);
22826 break;
22827 case OPC_REPLV_QB:
22828 check_dsp(ctx);
22829 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22830 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22831 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22832 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22833 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22834 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22835 break;
22836 case OPC_REPL_PH:
22837 check_dsp(ctx);
22839 imm = (ctx->opcode >> 16) & 0x03FF;
22840 imm = (int16_t)(imm << 6) >> 6;
22841 tcg_gen_movi_tl(cpu_gpr[ret], \
22842 (target_long)((int32_t)imm << 16 | \
22843 (uint16_t)imm));
22845 break;
22846 case OPC_REPLV_PH:
22847 check_dsp(ctx);
22848 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22849 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22850 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22851 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22852 break;
22854 break;
22855 #ifdef TARGET_MIPS64
22856 case OPC_ABSQ_S_QH_DSP:
22857 switch (op2) {
22858 case OPC_REPL_OB:
22859 check_dsp(ctx);
22861 target_long temp;
22863 imm = (ctx->opcode >> 16) & 0xFF;
22864 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22865 temp = (temp << 16) | temp;
22866 temp = (temp << 32) | temp;
22867 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22868 break;
22870 case OPC_REPL_PW:
22871 check_dsp(ctx);
22873 target_long temp;
22875 imm = (ctx->opcode >> 16) & 0x03FF;
22876 imm = (int16_t)(imm << 6) >> 6;
22877 temp = ((target_long)imm << 32) \
22878 | ((target_long)imm & 0xFFFFFFFF);
22879 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22880 break;
22882 case OPC_REPL_QH:
22883 check_dsp(ctx);
22885 target_long temp;
22887 imm = (ctx->opcode >> 16) & 0x03FF;
22888 imm = (int16_t)(imm << 6) >> 6;
22890 temp = ((uint64_t)(uint16_t)imm << 48) |
22891 ((uint64_t)(uint16_t)imm << 32) |
22892 ((uint64_t)(uint16_t)imm << 16) |
22893 (uint64_t)(uint16_t)imm;
22894 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22895 break;
22897 case OPC_REPLV_OB:
22898 check_dsp(ctx);
22899 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22900 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22901 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22902 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22903 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22904 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22905 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22906 break;
22907 case OPC_REPLV_PW:
22908 check_dsp(ctx);
22909 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22910 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22911 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22912 break;
22913 case OPC_REPLV_QH:
22914 check_dsp(ctx);
22915 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22916 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22917 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22918 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22919 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22920 break;
22922 break;
22923 #endif
22925 tcg_temp_free(t0);
22926 tcg_temp_free(val_t);
22929 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22930 uint32_t op1, uint32_t op2,
22931 int ret, int v1, int v2, int check_ret)
22933 TCGv t1;
22934 TCGv v1_t;
22935 TCGv v2_t;
22937 if ((ret == 0) && (check_ret == 1)) {
22938 /* Treat as NOP. */
22939 return;
22942 t1 = tcg_temp_new();
22943 v1_t = tcg_temp_new();
22944 v2_t = tcg_temp_new();
22946 gen_load_gpr(v1_t, v1);
22947 gen_load_gpr(v2_t, v2);
22949 switch (op1) {
22950 case OPC_CMPU_EQ_QB_DSP:
22951 switch (op2) {
22952 case OPC_CMPU_EQ_QB:
22953 check_dsp(ctx);
22954 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22955 break;
22956 case OPC_CMPU_LT_QB:
22957 check_dsp(ctx);
22958 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22959 break;
22960 case OPC_CMPU_LE_QB:
22961 check_dsp(ctx);
22962 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22963 break;
22964 case OPC_CMPGU_EQ_QB:
22965 check_dsp(ctx);
22966 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22967 break;
22968 case OPC_CMPGU_LT_QB:
22969 check_dsp(ctx);
22970 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22971 break;
22972 case OPC_CMPGU_LE_QB:
22973 check_dsp(ctx);
22974 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22975 break;
22976 case OPC_CMPGDU_EQ_QB:
22977 check_dsp_r2(ctx);
22978 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22979 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22980 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22981 tcg_gen_shli_tl(t1, t1, 24);
22982 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22983 break;
22984 case OPC_CMPGDU_LT_QB:
22985 check_dsp_r2(ctx);
22986 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22987 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22988 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22989 tcg_gen_shli_tl(t1, t1, 24);
22990 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22991 break;
22992 case OPC_CMPGDU_LE_QB:
22993 check_dsp_r2(ctx);
22994 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22995 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22996 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22997 tcg_gen_shli_tl(t1, t1, 24);
22998 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22999 break;
23000 case OPC_CMP_EQ_PH:
23001 check_dsp(ctx);
23002 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
23003 break;
23004 case OPC_CMP_LT_PH:
23005 check_dsp(ctx);
23006 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23007 break;
23008 case OPC_CMP_LE_PH:
23009 check_dsp(ctx);
23010 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23011 break;
23012 case OPC_PICK_QB:
23013 check_dsp(ctx);
23014 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23015 break;
23016 case OPC_PICK_PH:
23017 check_dsp(ctx);
23018 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23019 break;
23020 case OPC_PACKRL_PH:
23021 check_dsp(ctx);
23022 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23023 break;
23025 break;
23026 #ifdef TARGET_MIPS64
23027 case OPC_CMPU_EQ_OB_DSP:
23028 switch (op2) {
23029 case OPC_CMP_EQ_PW:
23030 check_dsp(ctx);
23031 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23032 break;
23033 case OPC_CMP_LT_PW:
23034 check_dsp(ctx);
23035 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23036 break;
23037 case OPC_CMP_LE_PW:
23038 check_dsp(ctx);
23039 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23040 break;
23041 case OPC_CMP_EQ_QH:
23042 check_dsp(ctx);
23043 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23044 break;
23045 case OPC_CMP_LT_QH:
23046 check_dsp(ctx);
23047 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23048 break;
23049 case OPC_CMP_LE_QH:
23050 check_dsp(ctx);
23051 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23052 break;
23053 case OPC_CMPGDU_EQ_OB:
23054 check_dsp_r2(ctx);
23055 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23056 break;
23057 case OPC_CMPGDU_LT_OB:
23058 check_dsp_r2(ctx);
23059 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23060 break;
23061 case OPC_CMPGDU_LE_OB:
23062 check_dsp_r2(ctx);
23063 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23064 break;
23065 case OPC_CMPGU_EQ_OB:
23066 check_dsp(ctx);
23067 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23068 break;
23069 case OPC_CMPGU_LT_OB:
23070 check_dsp(ctx);
23071 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23072 break;
23073 case OPC_CMPGU_LE_OB:
23074 check_dsp(ctx);
23075 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23076 break;
23077 case OPC_CMPU_EQ_OB:
23078 check_dsp(ctx);
23079 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23080 break;
23081 case OPC_CMPU_LT_OB:
23082 check_dsp(ctx);
23083 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23084 break;
23085 case OPC_CMPU_LE_OB:
23086 check_dsp(ctx);
23087 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23088 break;
23089 case OPC_PACKRL_PW:
23090 check_dsp(ctx);
23091 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23092 break;
23093 case OPC_PICK_OB:
23094 check_dsp(ctx);
23095 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23096 break;
23097 case OPC_PICK_PW:
23098 check_dsp(ctx);
23099 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23100 break;
23101 case OPC_PICK_QH:
23102 check_dsp(ctx);
23103 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23104 break;
23106 break;
23107 #endif
23110 tcg_temp_free(t1);
23111 tcg_temp_free(v1_t);
23112 tcg_temp_free(v2_t);
23115 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23116 uint32_t op1, int rt, int rs, int sa)
23118 TCGv t0;
23120 check_dsp_r2(ctx);
23122 if (rt == 0) {
23123 /* Treat as NOP. */
23124 return;
23127 t0 = tcg_temp_new();
23128 gen_load_gpr(t0, rs);
23130 switch (op1) {
23131 case OPC_APPEND_DSP:
23132 switch (MASK_APPEND(ctx->opcode)) {
23133 case OPC_APPEND:
23134 if (sa != 0) {
23135 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23137 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23138 break;
23139 case OPC_PREPEND:
23140 if (sa != 0) {
23141 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23142 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23143 tcg_gen_shli_tl(t0, t0, 32 - sa);
23144 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23146 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23147 break;
23148 case OPC_BALIGN:
23149 sa &= 3;
23150 if (sa != 0 && sa != 2) {
23151 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23152 tcg_gen_ext32u_tl(t0, t0);
23153 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23154 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23156 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23157 break;
23158 default: /* Invalid */
23159 MIPS_INVAL("MASK APPEND");
23160 generate_exception_end(ctx, EXCP_RI);
23161 break;
23163 break;
23164 #ifdef TARGET_MIPS64
23165 case OPC_DAPPEND_DSP:
23166 switch (MASK_DAPPEND(ctx->opcode)) {
23167 case OPC_DAPPEND:
23168 if (sa != 0) {
23169 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23171 break;
23172 case OPC_PREPENDD:
23173 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23174 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23175 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23176 break;
23177 case OPC_PREPENDW:
23178 if (sa != 0) {
23179 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23180 tcg_gen_shli_tl(t0, t0, 64 - sa);
23181 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23183 break;
23184 case OPC_DBALIGN:
23185 sa &= 7;
23186 if (sa != 0 && sa != 2 && sa != 4) {
23187 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23188 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23189 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23191 break;
23192 default: /* Invalid */
23193 MIPS_INVAL("MASK DAPPEND");
23194 generate_exception_end(ctx, EXCP_RI);
23195 break;
23197 break;
23198 #endif
23200 tcg_temp_free(t0);
23203 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23204 int ret, int v1, int v2, int check_ret)
23207 TCGv t0;
23208 TCGv t1;
23209 TCGv v1_t;
23210 TCGv v2_t;
23211 int16_t imm;
23213 if ((ret == 0) && (check_ret == 1)) {
23214 /* Treat as NOP. */
23215 return;
23218 t0 = tcg_temp_new();
23219 t1 = tcg_temp_new();
23220 v1_t = tcg_temp_new();
23221 v2_t = tcg_temp_new();
23223 gen_load_gpr(v1_t, v1);
23224 gen_load_gpr(v2_t, v2);
23226 switch (op1) {
23227 case OPC_EXTR_W_DSP:
23228 check_dsp(ctx);
23229 switch (op2) {
23230 case OPC_EXTR_W:
23231 tcg_gen_movi_tl(t0, v2);
23232 tcg_gen_movi_tl(t1, v1);
23233 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23234 break;
23235 case OPC_EXTR_R_W:
23236 tcg_gen_movi_tl(t0, v2);
23237 tcg_gen_movi_tl(t1, v1);
23238 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23239 break;
23240 case OPC_EXTR_RS_W:
23241 tcg_gen_movi_tl(t0, v2);
23242 tcg_gen_movi_tl(t1, v1);
23243 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23244 break;
23245 case OPC_EXTR_S_H:
23246 tcg_gen_movi_tl(t0, v2);
23247 tcg_gen_movi_tl(t1, v1);
23248 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23249 break;
23250 case OPC_EXTRV_S_H:
23251 tcg_gen_movi_tl(t0, v2);
23252 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23253 break;
23254 case OPC_EXTRV_W:
23255 tcg_gen_movi_tl(t0, v2);
23256 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23257 break;
23258 case OPC_EXTRV_R_W:
23259 tcg_gen_movi_tl(t0, v2);
23260 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23261 break;
23262 case OPC_EXTRV_RS_W:
23263 tcg_gen_movi_tl(t0, v2);
23264 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23265 break;
23266 case OPC_EXTP:
23267 tcg_gen_movi_tl(t0, v2);
23268 tcg_gen_movi_tl(t1, v1);
23269 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23270 break;
23271 case OPC_EXTPV:
23272 tcg_gen_movi_tl(t0, v2);
23273 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23274 break;
23275 case OPC_EXTPDP:
23276 tcg_gen_movi_tl(t0, v2);
23277 tcg_gen_movi_tl(t1, v1);
23278 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23279 break;
23280 case OPC_EXTPDPV:
23281 tcg_gen_movi_tl(t0, v2);
23282 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23283 break;
23284 case OPC_SHILO:
23285 imm = (ctx->opcode >> 20) & 0x3F;
23286 tcg_gen_movi_tl(t0, ret);
23287 tcg_gen_movi_tl(t1, imm);
23288 gen_helper_shilo(t0, t1, cpu_env);
23289 break;
23290 case OPC_SHILOV:
23291 tcg_gen_movi_tl(t0, ret);
23292 gen_helper_shilo(t0, v1_t, cpu_env);
23293 break;
23294 case OPC_MTHLIP:
23295 tcg_gen_movi_tl(t0, ret);
23296 gen_helper_mthlip(t0, v1_t, cpu_env);
23297 break;
23298 case OPC_WRDSP:
23299 imm = (ctx->opcode >> 11) & 0x3FF;
23300 tcg_gen_movi_tl(t0, imm);
23301 gen_helper_wrdsp(v1_t, t0, cpu_env);
23302 break;
23303 case OPC_RDDSP:
23304 imm = (ctx->opcode >> 16) & 0x03FF;
23305 tcg_gen_movi_tl(t0, imm);
23306 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23307 break;
23309 break;
23310 #ifdef TARGET_MIPS64
23311 case OPC_DEXTR_W_DSP:
23312 check_dsp(ctx);
23313 switch (op2) {
23314 case OPC_DMTHLIP:
23315 tcg_gen_movi_tl(t0, ret);
23316 gen_helper_dmthlip(v1_t, t0, cpu_env);
23317 break;
23318 case OPC_DSHILO:
23320 int shift = (ctx->opcode >> 19) & 0x7F;
23321 int ac = (ctx->opcode >> 11) & 0x03;
23322 tcg_gen_movi_tl(t0, shift);
23323 tcg_gen_movi_tl(t1, ac);
23324 gen_helper_dshilo(t0, t1, cpu_env);
23325 break;
23327 case OPC_DSHILOV:
23329 int ac = (ctx->opcode >> 11) & 0x03;
23330 tcg_gen_movi_tl(t0, ac);
23331 gen_helper_dshilo(v1_t, t0, cpu_env);
23332 break;
23334 case OPC_DEXTP:
23335 tcg_gen_movi_tl(t0, v2);
23336 tcg_gen_movi_tl(t1, v1);
23338 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23339 break;
23340 case OPC_DEXTPV:
23341 tcg_gen_movi_tl(t0, v2);
23342 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23343 break;
23344 case OPC_DEXTPDP:
23345 tcg_gen_movi_tl(t0, v2);
23346 tcg_gen_movi_tl(t1, v1);
23347 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23348 break;
23349 case OPC_DEXTPDPV:
23350 tcg_gen_movi_tl(t0, v2);
23351 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23352 break;
23353 case OPC_DEXTR_L:
23354 tcg_gen_movi_tl(t0, v2);
23355 tcg_gen_movi_tl(t1, v1);
23356 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23357 break;
23358 case OPC_DEXTR_R_L:
23359 tcg_gen_movi_tl(t0, v2);
23360 tcg_gen_movi_tl(t1, v1);
23361 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23362 break;
23363 case OPC_DEXTR_RS_L:
23364 tcg_gen_movi_tl(t0, v2);
23365 tcg_gen_movi_tl(t1, v1);
23366 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23367 break;
23368 case OPC_DEXTR_W:
23369 tcg_gen_movi_tl(t0, v2);
23370 tcg_gen_movi_tl(t1, v1);
23371 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23372 break;
23373 case OPC_DEXTR_R_W:
23374 tcg_gen_movi_tl(t0, v2);
23375 tcg_gen_movi_tl(t1, v1);
23376 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23377 break;
23378 case OPC_DEXTR_RS_W:
23379 tcg_gen_movi_tl(t0, v2);
23380 tcg_gen_movi_tl(t1, v1);
23381 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23382 break;
23383 case OPC_DEXTR_S_H:
23384 tcg_gen_movi_tl(t0, v2);
23385 tcg_gen_movi_tl(t1, v1);
23386 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23387 break;
23388 case OPC_DEXTRV_S_H:
23389 tcg_gen_movi_tl(t0, v2);
23390 tcg_gen_movi_tl(t1, v1);
23391 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23392 break;
23393 case OPC_DEXTRV_L:
23394 tcg_gen_movi_tl(t0, v2);
23395 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23396 break;
23397 case OPC_DEXTRV_R_L:
23398 tcg_gen_movi_tl(t0, v2);
23399 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23400 break;
23401 case OPC_DEXTRV_RS_L:
23402 tcg_gen_movi_tl(t0, v2);
23403 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23404 break;
23405 case OPC_DEXTRV_W:
23406 tcg_gen_movi_tl(t0, v2);
23407 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23408 break;
23409 case OPC_DEXTRV_R_W:
23410 tcg_gen_movi_tl(t0, v2);
23411 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23412 break;
23413 case OPC_DEXTRV_RS_W:
23414 tcg_gen_movi_tl(t0, v2);
23415 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23416 break;
23418 break;
23419 #endif
23422 tcg_temp_free(t0);
23423 tcg_temp_free(t1);
23424 tcg_temp_free(v1_t);
23425 tcg_temp_free(v2_t);
23428 /* End MIPSDSP functions. */
23430 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23432 int rs, rt, rd, sa;
23433 uint32_t op1, op2;
23435 rs = (ctx->opcode >> 21) & 0x1f;
23436 rt = (ctx->opcode >> 16) & 0x1f;
23437 rd = (ctx->opcode >> 11) & 0x1f;
23438 sa = (ctx->opcode >> 6) & 0x1f;
23440 op1 = MASK_SPECIAL(ctx->opcode);
23441 switch (op1) {
23442 case OPC_LSA:
23443 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23444 break;
23445 case OPC_MULT:
23446 case OPC_MULTU:
23447 case OPC_DIV:
23448 case OPC_DIVU:
23449 op2 = MASK_R6_MULDIV(ctx->opcode);
23450 switch (op2) {
23451 case R6_OPC_MUL:
23452 case R6_OPC_MUH:
23453 case R6_OPC_MULU:
23454 case R6_OPC_MUHU:
23455 case R6_OPC_DIV:
23456 case R6_OPC_MOD:
23457 case R6_OPC_DIVU:
23458 case R6_OPC_MODU:
23459 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23460 break;
23461 default:
23462 MIPS_INVAL("special_r6 muldiv");
23463 generate_exception_end(ctx, EXCP_RI);
23464 break;
23466 break;
23467 case OPC_SELEQZ:
23468 case OPC_SELNEZ:
23469 gen_cond_move(ctx, op1, rd, rs, rt);
23470 break;
23471 case R6_OPC_CLO:
23472 case R6_OPC_CLZ:
23473 if (rt == 0 && sa == 1) {
23474 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23475 We need additionally to check other fields */
23476 gen_cl(ctx, op1, rd, rs);
23477 } else {
23478 generate_exception_end(ctx, EXCP_RI);
23480 break;
23481 case R6_OPC_SDBBP:
23482 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23483 gen_helper_do_semihosting(cpu_env);
23484 } else {
23485 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23486 generate_exception_end(ctx, EXCP_RI);
23487 } else {
23488 generate_exception_end(ctx, EXCP_DBp);
23491 break;
23492 #if defined(TARGET_MIPS64)
23493 case OPC_DLSA:
23494 check_mips_64(ctx);
23495 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23496 break;
23497 case R6_OPC_DCLO:
23498 case R6_OPC_DCLZ:
23499 if (rt == 0 && sa == 1) {
23500 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23501 We need additionally to check other fields */
23502 check_mips_64(ctx);
23503 gen_cl(ctx, op1, rd, rs);
23504 } else {
23505 generate_exception_end(ctx, EXCP_RI);
23507 break;
23508 case OPC_DMULT:
23509 case OPC_DMULTU:
23510 case OPC_DDIV:
23511 case OPC_DDIVU:
23513 op2 = MASK_R6_MULDIV(ctx->opcode);
23514 switch (op2) {
23515 case R6_OPC_DMUL:
23516 case R6_OPC_DMUH:
23517 case R6_OPC_DMULU:
23518 case R6_OPC_DMUHU:
23519 case R6_OPC_DDIV:
23520 case R6_OPC_DMOD:
23521 case R6_OPC_DDIVU:
23522 case R6_OPC_DMODU:
23523 check_mips_64(ctx);
23524 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23525 break;
23526 default:
23527 MIPS_INVAL("special_r6 muldiv");
23528 generate_exception_end(ctx, EXCP_RI);
23529 break;
23531 break;
23532 #endif
23533 default: /* Invalid */
23534 MIPS_INVAL("special_r6");
23535 generate_exception_end(ctx, EXCP_RI);
23536 break;
23540 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23542 int rs, rt, rd, sa;
23543 uint32_t op1;
23545 rs = (ctx->opcode >> 21) & 0x1f;
23546 rt = (ctx->opcode >> 16) & 0x1f;
23547 rd = (ctx->opcode >> 11) & 0x1f;
23548 sa = (ctx->opcode >> 6) & 0x1f;
23550 op1 = MASK_SPECIAL(ctx->opcode);
23551 switch (op1) {
23552 case OPC_MOVN: /* Conditional move */
23553 case OPC_MOVZ:
23554 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23555 INSN_LOONGSON2E | INSN_LOONGSON2F);
23556 gen_cond_move(ctx, op1, rd, rs, rt);
23557 break;
23558 case OPC_MFHI: /* Move from HI/LO */
23559 case OPC_MFLO:
23560 gen_HILO(ctx, op1, rs & 3, rd);
23561 break;
23562 case OPC_MTHI:
23563 case OPC_MTLO: /* Move to HI/LO */
23564 gen_HILO(ctx, op1, rd & 3, rs);
23565 break;
23566 case OPC_MOVCI:
23567 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23568 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23569 check_cp1_enabled(ctx);
23570 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23571 (ctx->opcode >> 16) & 1);
23572 } else {
23573 generate_exception_err(ctx, EXCP_CpU, 1);
23575 break;
23576 case OPC_MULT:
23577 case OPC_MULTU:
23578 if (sa) {
23579 check_insn(ctx, INSN_VR54XX);
23580 op1 = MASK_MUL_VR54XX(ctx->opcode);
23581 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23582 } else if (ctx->insn_flags & INSN_R5900) {
23583 gen_mul_txx9(ctx, op1, rd, rs, rt);
23584 } else {
23585 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23587 break;
23588 case OPC_DIV:
23589 case OPC_DIVU:
23590 gen_muldiv(ctx, op1, 0, rs, rt);
23591 break;
23592 #if defined(TARGET_MIPS64)
23593 case OPC_DMULT:
23594 case OPC_DMULTU:
23595 case OPC_DDIV:
23596 case OPC_DDIVU:
23597 check_insn(ctx, ISA_MIPS3);
23598 check_mips_64(ctx);
23599 gen_muldiv(ctx, op1, 0, rs, rt);
23600 break;
23601 #endif
23602 case OPC_JR:
23603 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23604 break;
23605 case OPC_SPIM:
23606 #ifdef MIPS_STRICT_STANDARD
23607 MIPS_INVAL("SPIM");
23608 generate_exception_end(ctx, EXCP_RI);
23609 #else
23610 /* Implemented as RI exception for now. */
23611 MIPS_INVAL("spim (unofficial)");
23612 generate_exception_end(ctx, EXCP_RI);
23613 #endif
23614 break;
23615 default: /* Invalid */
23616 MIPS_INVAL("special_legacy");
23617 generate_exception_end(ctx, EXCP_RI);
23618 break;
23622 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23624 int rs, rt, rd, sa;
23625 uint32_t op1;
23627 rs = (ctx->opcode >> 21) & 0x1f;
23628 rt = (ctx->opcode >> 16) & 0x1f;
23629 rd = (ctx->opcode >> 11) & 0x1f;
23630 sa = (ctx->opcode >> 6) & 0x1f;
23632 op1 = MASK_SPECIAL(ctx->opcode);
23633 switch (op1) {
23634 case OPC_SLL: /* Shift with immediate */
23635 if (sa == 5 && rd == 0 &&
23636 rs == 0 && rt == 0) { /* PAUSE */
23637 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23638 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23639 generate_exception_end(ctx, EXCP_RI);
23640 break;
23643 /* Fallthrough */
23644 case OPC_SRA:
23645 gen_shift_imm(ctx, op1, rd, rt, sa);
23646 break;
23647 case OPC_SRL:
23648 switch ((ctx->opcode >> 21) & 0x1f) {
23649 case 1:
23650 /* rotr is decoded as srl on non-R2 CPUs */
23651 if (ctx->insn_flags & ISA_MIPS32R2) {
23652 op1 = OPC_ROTR;
23654 /* Fallthrough */
23655 case 0:
23656 gen_shift_imm(ctx, op1, rd, rt, sa);
23657 break;
23658 default:
23659 generate_exception_end(ctx, EXCP_RI);
23660 break;
23662 break;
23663 case OPC_ADD:
23664 case OPC_ADDU:
23665 case OPC_SUB:
23666 case OPC_SUBU:
23667 gen_arith(ctx, op1, rd, rs, rt);
23668 break;
23669 case OPC_SLLV: /* Shifts */
23670 case OPC_SRAV:
23671 gen_shift(ctx, op1, rd, rs, rt);
23672 break;
23673 case OPC_SRLV:
23674 switch ((ctx->opcode >> 6) & 0x1f) {
23675 case 1:
23676 /* rotrv is decoded as srlv on non-R2 CPUs */
23677 if (ctx->insn_flags & ISA_MIPS32R2) {
23678 op1 = OPC_ROTRV;
23680 /* Fallthrough */
23681 case 0:
23682 gen_shift(ctx, op1, rd, rs, rt);
23683 break;
23684 default:
23685 generate_exception_end(ctx, EXCP_RI);
23686 break;
23688 break;
23689 case OPC_SLT: /* Set on less than */
23690 case OPC_SLTU:
23691 gen_slt(ctx, op1, rd, rs, rt);
23692 break;
23693 case OPC_AND: /* Logic*/
23694 case OPC_OR:
23695 case OPC_NOR:
23696 case OPC_XOR:
23697 gen_logic(ctx, op1, rd, rs, rt);
23698 break;
23699 case OPC_JALR:
23700 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23701 break;
23702 case OPC_TGE: /* Traps */
23703 case OPC_TGEU:
23704 case OPC_TLT:
23705 case OPC_TLTU:
23706 case OPC_TEQ:
23707 case OPC_TNE:
23708 check_insn(ctx, ISA_MIPS2);
23709 gen_trap(ctx, op1, rs, rt, -1);
23710 break;
23711 case OPC_LSA: /* OPC_PMON */
23712 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23713 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23714 decode_opc_special_r6(env, ctx);
23715 } else {
23716 /* Pmon entry point, also R4010 selsl */
23717 #ifdef MIPS_STRICT_STANDARD
23718 MIPS_INVAL("PMON / selsl");
23719 generate_exception_end(ctx, EXCP_RI);
23720 #else
23721 gen_helper_0e0i(pmon, sa);
23722 #endif
23724 break;
23725 case OPC_SYSCALL:
23726 generate_exception_end(ctx, EXCP_SYSCALL);
23727 break;
23728 case OPC_BREAK:
23729 generate_exception_end(ctx, EXCP_BREAK);
23730 break;
23731 case OPC_SYNC:
23732 check_insn(ctx, ISA_MIPS2);
23733 gen_sync(extract32(ctx->opcode, 6, 5));
23734 break;
23736 #if defined(TARGET_MIPS64)
23737 /* MIPS64 specific opcodes */
23738 case OPC_DSLL:
23739 case OPC_DSRA:
23740 case OPC_DSLL32:
23741 case OPC_DSRA32:
23742 check_insn(ctx, ISA_MIPS3);
23743 check_mips_64(ctx);
23744 gen_shift_imm(ctx, op1, rd, rt, sa);
23745 break;
23746 case OPC_DSRL:
23747 switch ((ctx->opcode >> 21) & 0x1f) {
23748 case 1:
23749 /* drotr is decoded as dsrl on non-R2 CPUs */
23750 if (ctx->insn_flags & ISA_MIPS32R2) {
23751 op1 = OPC_DROTR;
23753 /* Fallthrough */
23754 case 0:
23755 check_insn(ctx, ISA_MIPS3);
23756 check_mips_64(ctx);
23757 gen_shift_imm(ctx, op1, rd, rt, sa);
23758 break;
23759 default:
23760 generate_exception_end(ctx, EXCP_RI);
23761 break;
23763 break;
23764 case OPC_DSRL32:
23765 switch ((ctx->opcode >> 21) & 0x1f) {
23766 case 1:
23767 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23768 if (ctx->insn_flags & ISA_MIPS32R2) {
23769 op1 = OPC_DROTR32;
23771 /* Fallthrough */
23772 case 0:
23773 check_insn(ctx, ISA_MIPS3);
23774 check_mips_64(ctx);
23775 gen_shift_imm(ctx, op1, rd, rt, sa);
23776 break;
23777 default:
23778 generate_exception_end(ctx, EXCP_RI);
23779 break;
23781 break;
23782 case OPC_DADD:
23783 case OPC_DADDU:
23784 case OPC_DSUB:
23785 case OPC_DSUBU:
23786 check_insn(ctx, ISA_MIPS3);
23787 check_mips_64(ctx);
23788 gen_arith(ctx, op1, rd, rs, rt);
23789 break;
23790 case OPC_DSLLV:
23791 case OPC_DSRAV:
23792 check_insn(ctx, ISA_MIPS3);
23793 check_mips_64(ctx);
23794 gen_shift(ctx, op1, rd, rs, rt);
23795 break;
23796 case OPC_DSRLV:
23797 switch ((ctx->opcode >> 6) & 0x1f) {
23798 case 1:
23799 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23800 if (ctx->insn_flags & ISA_MIPS32R2) {
23801 op1 = OPC_DROTRV;
23803 /* Fallthrough */
23804 case 0:
23805 check_insn(ctx, ISA_MIPS3);
23806 check_mips_64(ctx);
23807 gen_shift(ctx, op1, rd, rs, rt);
23808 break;
23809 default:
23810 generate_exception_end(ctx, EXCP_RI);
23811 break;
23813 break;
23814 case OPC_DLSA:
23815 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23816 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23817 decode_opc_special_r6(env, ctx);
23819 break;
23820 #endif
23821 default:
23822 if (ctx->insn_flags & ISA_MIPS32R6) {
23823 decode_opc_special_r6(env, ctx);
23824 } else {
23825 decode_opc_special_legacy(env, ctx);
23830 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23832 int rs, rt, rd;
23833 uint32_t op1;
23835 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23837 rs = (ctx->opcode >> 21) & 0x1f;
23838 rt = (ctx->opcode >> 16) & 0x1f;
23839 rd = (ctx->opcode >> 11) & 0x1f;
23841 op1 = MASK_SPECIAL2(ctx->opcode);
23842 switch (op1) {
23843 case OPC_MADD: /* Multiply and add/sub */
23844 case OPC_MADDU:
23845 case OPC_MSUB:
23846 case OPC_MSUBU:
23847 check_insn(ctx, ISA_MIPS32);
23848 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23849 break;
23850 case OPC_MUL:
23851 gen_arith(ctx, op1, rd, rs, rt);
23852 break;
23853 case OPC_DIV_G_2F:
23854 case OPC_DIVU_G_2F:
23855 case OPC_MULT_G_2F:
23856 case OPC_MULTU_G_2F:
23857 case OPC_MOD_G_2F:
23858 case OPC_MODU_G_2F:
23859 check_insn(ctx, INSN_LOONGSON2F);
23860 gen_loongson_integer(ctx, op1, rd, rs, rt);
23861 break;
23862 case OPC_CLO:
23863 case OPC_CLZ:
23864 check_insn(ctx, ISA_MIPS32);
23865 gen_cl(ctx, op1, rd, rs);
23866 break;
23867 case OPC_SDBBP:
23868 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23869 gen_helper_do_semihosting(cpu_env);
23870 } else {
23871 /* XXX: not clear which exception should be raised
23872 * when in debug mode...
23874 check_insn(ctx, ISA_MIPS32);
23875 generate_exception_end(ctx, EXCP_DBp);
23877 break;
23878 #if defined(TARGET_MIPS64)
23879 case OPC_DCLO:
23880 case OPC_DCLZ:
23881 check_insn(ctx, ISA_MIPS64);
23882 check_mips_64(ctx);
23883 gen_cl(ctx, op1, rd, rs);
23884 break;
23885 case OPC_DMULT_G_2F:
23886 case OPC_DMULTU_G_2F:
23887 case OPC_DDIV_G_2F:
23888 case OPC_DDIVU_G_2F:
23889 case OPC_DMOD_G_2F:
23890 case OPC_DMODU_G_2F:
23891 check_insn(ctx, INSN_LOONGSON2F);
23892 gen_loongson_integer(ctx, op1, rd, rs, rt);
23893 break;
23894 #endif
23895 default: /* Invalid */
23896 MIPS_INVAL("special2_legacy");
23897 generate_exception_end(ctx, EXCP_RI);
23898 break;
23902 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23904 int rs, rt, rd, sa;
23905 uint32_t op1, op2;
23906 int16_t imm;
23908 rs = (ctx->opcode >> 21) & 0x1f;
23909 rt = (ctx->opcode >> 16) & 0x1f;
23910 rd = (ctx->opcode >> 11) & 0x1f;
23911 sa = (ctx->opcode >> 6) & 0x1f;
23912 imm = (int16_t)ctx->opcode >> 7;
23914 op1 = MASK_SPECIAL3(ctx->opcode);
23915 switch (op1) {
23916 case R6_OPC_PREF:
23917 if (rt >= 24) {
23918 /* hint codes 24-31 are reserved and signal RI */
23919 generate_exception_end(ctx, EXCP_RI);
23921 /* Treat as NOP. */
23922 break;
23923 case R6_OPC_CACHE:
23924 check_cp0_enabled(ctx);
23925 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23926 gen_cache_operation(ctx, rt, rs, imm);
23928 break;
23929 case R6_OPC_SC:
23930 gen_st_cond(ctx, op1, rt, rs, imm);
23931 break;
23932 case R6_OPC_LL:
23933 gen_ld(ctx, op1, rt, rs, imm);
23934 break;
23935 case OPC_BSHFL:
23937 if (rd == 0) {
23938 /* Treat as NOP. */
23939 break;
23941 op2 = MASK_BSHFL(ctx->opcode);
23942 switch (op2) {
23943 case OPC_ALIGN:
23944 case OPC_ALIGN_END:
23945 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23946 break;
23947 case OPC_BITSWAP:
23948 gen_bitswap(ctx, op2, rd, rt);
23949 break;
23952 break;
23953 #if defined(TARGET_MIPS64)
23954 case R6_OPC_SCD:
23955 gen_st_cond(ctx, op1, rt, rs, imm);
23956 break;
23957 case R6_OPC_LLD:
23958 gen_ld(ctx, op1, rt, rs, imm);
23959 break;
23960 case OPC_DBSHFL:
23961 check_mips_64(ctx);
23963 if (rd == 0) {
23964 /* Treat as NOP. */
23965 break;
23967 op2 = MASK_DBSHFL(ctx->opcode);
23968 switch (op2) {
23969 case OPC_DALIGN:
23970 case OPC_DALIGN_END:
23971 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23972 break;
23973 case OPC_DBITSWAP:
23974 gen_bitswap(ctx, op2, rd, rt);
23975 break;
23979 break;
23980 #endif
23981 default: /* Invalid */
23982 MIPS_INVAL("special3_r6");
23983 generate_exception_end(ctx, EXCP_RI);
23984 break;
23988 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23990 int rs, rt, rd;
23991 uint32_t op1, op2;
23993 rs = (ctx->opcode >> 21) & 0x1f;
23994 rt = (ctx->opcode >> 16) & 0x1f;
23995 rd = (ctx->opcode >> 11) & 0x1f;
23997 op1 = MASK_SPECIAL3(ctx->opcode);
23998 switch (op1) {
23999 case OPC_DIV_G_2E:
24000 case OPC_DIVU_G_2E:
24001 case OPC_MOD_G_2E:
24002 case OPC_MODU_G_2E:
24003 case OPC_MULT_G_2E:
24004 case OPC_MULTU_G_2E:
24005 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
24006 * the same mask and op1. */
24007 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
24008 op2 = MASK_ADDUH_QB(ctx->opcode);
24009 switch (op2) {
24010 case OPC_ADDUH_QB:
24011 case OPC_ADDUH_R_QB:
24012 case OPC_ADDQH_PH:
24013 case OPC_ADDQH_R_PH:
24014 case OPC_ADDQH_W:
24015 case OPC_ADDQH_R_W:
24016 case OPC_SUBUH_QB:
24017 case OPC_SUBUH_R_QB:
24018 case OPC_SUBQH_PH:
24019 case OPC_SUBQH_R_PH:
24020 case OPC_SUBQH_W:
24021 case OPC_SUBQH_R_W:
24022 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24023 break;
24024 case OPC_MUL_PH:
24025 case OPC_MUL_S_PH:
24026 case OPC_MULQ_S_W:
24027 case OPC_MULQ_RS_W:
24028 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24029 break;
24030 default:
24031 MIPS_INVAL("MASK ADDUH.QB");
24032 generate_exception_end(ctx, EXCP_RI);
24033 break;
24035 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
24036 gen_loongson_integer(ctx, op1, rd, rs, rt);
24037 } else {
24038 generate_exception_end(ctx, EXCP_RI);
24040 break;
24041 case OPC_LX_DSP:
24042 op2 = MASK_LX(ctx->opcode);
24043 switch (op2) {
24044 #if defined(TARGET_MIPS64)
24045 case OPC_LDX:
24046 #endif
24047 case OPC_LBUX:
24048 case OPC_LHX:
24049 case OPC_LWX:
24050 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
24051 break;
24052 default: /* Invalid */
24053 MIPS_INVAL("MASK LX");
24054 generate_exception_end(ctx, EXCP_RI);
24055 break;
24057 break;
24058 case OPC_ABSQ_S_PH_DSP:
24059 op2 = MASK_ABSQ_S_PH(ctx->opcode);
24060 switch (op2) {
24061 case OPC_ABSQ_S_QB:
24062 case OPC_ABSQ_S_PH:
24063 case OPC_ABSQ_S_W:
24064 case OPC_PRECEQ_W_PHL:
24065 case OPC_PRECEQ_W_PHR:
24066 case OPC_PRECEQU_PH_QBL:
24067 case OPC_PRECEQU_PH_QBR:
24068 case OPC_PRECEQU_PH_QBLA:
24069 case OPC_PRECEQU_PH_QBRA:
24070 case OPC_PRECEU_PH_QBL:
24071 case OPC_PRECEU_PH_QBR:
24072 case OPC_PRECEU_PH_QBLA:
24073 case OPC_PRECEU_PH_QBRA:
24074 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24075 break;
24076 case OPC_BITREV:
24077 case OPC_REPL_QB:
24078 case OPC_REPLV_QB:
24079 case OPC_REPL_PH:
24080 case OPC_REPLV_PH:
24081 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24082 break;
24083 default:
24084 MIPS_INVAL("MASK ABSQ_S.PH");
24085 generate_exception_end(ctx, EXCP_RI);
24086 break;
24088 break;
24089 case OPC_ADDU_QB_DSP:
24090 op2 = MASK_ADDU_QB(ctx->opcode);
24091 switch (op2) {
24092 case OPC_ADDQ_PH:
24093 case OPC_ADDQ_S_PH:
24094 case OPC_ADDQ_S_W:
24095 case OPC_ADDU_QB:
24096 case OPC_ADDU_S_QB:
24097 case OPC_ADDU_PH:
24098 case OPC_ADDU_S_PH:
24099 case OPC_SUBQ_PH:
24100 case OPC_SUBQ_S_PH:
24101 case OPC_SUBQ_S_W:
24102 case OPC_SUBU_QB:
24103 case OPC_SUBU_S_QB:
24104 case OPC_SUBU_PH:
24105 case OPC_SUBU_S_PH:
24106 case OPC_ADDSC:
24107 case OPC_ADDWC:
24108 case OPC_MODSUB:
24109 case OPC_RADDU_W_QB:
24110 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24111 break;
24112 case OPC_MULEU_S_PH_QBL:
24113 case OPC_MULEU_S_PH_QBR:
24114 case OPC_MULQ_RS_PH:
24115 case OPC_MULEQ_S_W_PHL:
24116 case OPC_MULEQ_S_W_PHR:
24117 case OPC_MULQ_S_PH:
24118 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24119 break;
24120 default: /* Invalid */
24121 MIPS_INVAL("MASK ADDU.QB");
24122 generate_exception_end(ctx, EXCP_RI);
24123 break;
24126 break;
24127 case OPC_CMPU_EQ_QB_DSP:
24128 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24129 switch (op2) {
24130 case OPC_PRECR_SRA_PH_W:
24131 case OPC_PRECR_SRA_R_PH_W:
24132 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24133 break;
24134 case OPC_PRECR_QB_PH:
24135 case OPC_PRECRQ_QB_PH:
24136 case OPC_PRECRQ_PH_W:
24137 case OPC_PRECRQ_RS_PH_W:
24138 case OPC_PRECRQU_S_QB_PH:
24139 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24140 break;
24141 case OPC_CMPU_EQ_QB:
24142 case OPC_CMPU_LT_QB:
24143 case OPC_CMPU_LE_QB:
24144 case OPC_CMP_EQ_PH:
24145 case OPC_CMP_LT_PH:
24146 case OPC_CMP_LE_PH:
24147 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24148 break;
24149 case OPC_CMPGU_EQ_QB:
24150 case OPC_CMPGU_LT_QB:
24151 case OPC_CMPGU_LE_QB:
24152 case OPC_CMPGDU_EQ_QB:
24153 case OPC_CMPGDU_LT_QB:
24154 case OPC_CMPGDU_LE_QB:
24155 case OPC_PICK_QB:
24156 case OPC_PICK_PH:
24157 case OPC_PACKRL_PH:
24158 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24159 break;
24160 default: /* Invalid */
24161 MIPS_INVAL("MASK CMPU.EQ.QB");
24162 generate_exception_end(ctx, EXCP_RI);
24163 break;
24165 break;
24166 case OPC_SHLL_QB_DSP:
24167 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24168 break;
24169 case OPC_DPA_W_PH_DSP:
24170 op2 = MASK_DPA_W_PH(ctx->opcode);
24171 switch (op2) {
24172 case OPC_DPAU_H_QBL:
24173 case OPC_DPAU_H_QBR:
24174 case OPC_DPSU_H_QBL:
24175 case OPC_DPSU_H_QBR:
24176 case OPC_DPA_W_PH:
24177 case OPC_DPAX_W_PH:
24178 case OPC_DPAQ_S_W_PH:
24179 case OPC_DPAQX_S_W_PH:
24180 case OPC_DPAQX_SA_W_PH:
24181 case OPC_DPS_W_PH:
24182 case OPC_DPSX_W_PH:
24183 case OPC_DPSQ_S_W_PH:
24184 case OPC_DPSQX_S_W_PH:
24185 case OPC_DPSQX_SA_W_PH:
24186 case OPC_MULSAQ_S_W_PH:
24187 case OPC_DPAQ_SA_L_W:
24188 case OPC_DPSQ_SA_L_W:
24189 case OPC_MAQ_S_W_PHL:
24190 case OPC_MAQ_S_W_PHR:
24191 case OPC_MAQ_SA_W_PHL:
24192 case OPC_MAQ_SA_W_PHR:
24193 case OPC_MULSA_W_PH:
24194 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24195 break;
24196 default: /* Invalid */
24197 MIPS_INVAL("MASK DPAW.PH");
24198 generate_exception_end(ctx, EXCP_RI);
24199 break;
24201 break;
24202 case OPC_INSV_DSP:
24203 op2 = MASK_INSV(ctx->opcode);
24204 switch (op2) {
24205 case OPC_INSV:
24206 check_dsp(ctx);
24208 TCGv t0, t1;
24210 if (rt == 0) {
24211 break;
24214 t0 = tcg_temp_new();
24215 t1 = tcg_temp_new();
24217 gen_load_gpr(t0, rt);
24218 gen_load_gpr(t1, rs);
24220 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24222 tcg_temp_free(t0);
24223 tcg_temp_free(t1);
24224 break;
24226 default: /* Invalid */
24227 MIPS_INVAL("MASK INSV");
24228 generate_exception_end(ctx, EXCP_RI);
24229 break;
24231 break;
24232 case OPC_APPEND_DSP:
24233 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24234 break;
24235 case OPC_EXTR_W_DSP:
24236 op2 = MASK_EXTR_W(ctx->opcode);
24237 switch (op2) {
24238 case OPC_EXTR_W:
24239 case OPC_EXTR_R_W:
24240 case OPC_EXTR_RS_W:
24241 case OPC_EXTR_S_H:
24242 case OPC_EXTRV_S_H:
24243 case OPC_EXTRV_W:
24244 case OPC_EXTRV_R_W:
24245 case OPC_EXTRV_RS_W:
24246 case OPC_EXTP:
24247 case OPC_EXTPV:
24248 case OPC_EXTPDP:
24249 case OPC_EXTPDPV:
24250 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24251 break;
24252 case OPC_RDDSP:
24253 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24254 break;
24255 case OPC_SHILO:
24256 case OPC_SHILOV:
24257 case OPC_MTHLIP:
24258 case OPC_WRDSP:
24259 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24260 break;
24261 default: /* Invalid */
24262 MIPS_INVAL("MASK EXTR.W");
24263 generate_exception_end(ctx, EXCP_RI);
24264 break;
24266 break;
24267 #if defined(TARGET_MIPS64)
24268 case OPC_DDIV_G_2E:
24269 case OPC_DDIVU_G_2E:
24270 case OPC_DMULT_G_2E:
24271 case OPC_DMULTU_G_2E:
24272 case OPC_DMOD_G_2E:
24273 case OPC_DMODU_G_2E:
24274 check_insn(ctx, INSN_LOONGSON2E);
24275 gen_loongson_integer(ctx, op1, rd, rs, rt);
24276 break;
24277 case OPC_ABSQ_S_QH_DSP:
24278 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24279 switch (op2) {
24280 case OPC_PRECEQ_L_PWL:
24281 case OPC_PRECEQ_L_PWR:
24282 case OPC_PRECEQ_PW_QHL:
24283 case OPC_PRECEQ_PW_QHR:
24284 case OPC_PRECEQ_PW_QHLA:
24285 case OPC_PRECEQ_PW_QHRA:
24286 case OPC_PRECEQU_QH_OBL:
24287 case OPC_PRECEQU_QH_OBR:
24288 case OPC_PRECEQU_QH_OBLA:
24289 case OPC_PRECEQU_QH_OBRA:
24290 case OPC_PRECEU_QH_OBL:
24291 case OPC_PRECEU_QH_OBR:
24292 case OPC_PRECEU_QH_OBLA:
24293 case OPC_PRECEU_QH_OBRA:
24294 case OPC_ABSQ_S_OB:
24295 case OPC_ABSQ_S_PW:
24296 case OPC_ABSQ_S_QH:
24297 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24298 break;
24299 case OPC_REPL_OB:
24300 case OPC_REPL_PW:
24301 case OPC_REPL_QH:
24302 case OPC_REPLV_OB:
24303 case OPC_REPLV_PW:
24304 case OPC_REPLV_QH:
24305 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24306 break;
24307 default: /* Invalid */
24308 MIPS_INVAL("MASK ABSQ_S.QH");
24309 generate_exception_end(ctx, EXCP_RI);
24310 break;
24312 break;
24313 case OPC_ADDU_OB_DSP:
24314 op2 = MASK_ADDU_OB(ctx->opcode);
24315 switch (op2) {
24316 case OPC_RADDU_L_OB:
24317 case OPC_SUBQ_PW:
24318 case OPC_SUBQ_S_PW:
24319 case OPC_SUBQ_QH:
24320 case OPC_SUBQ_S_QH:
24321 case OPC_SUBU_OB:
24322 case OPC_SUBU_S_OB:
24323 case OPC_SUBU_QH:
24324 case OPC_SUBU_S_QH:
24325 case OPC_SUBUH_OB:
24326 case OPC_SUBUH_R_OB:
24327 case OPC_ADDQ_PW:
24328 case OPC_ADDQ_S_PW:
24329 case OPC_ADDQ_QH:
24330 case OPC_ADDQ_S_QH:
24331 case OPC_ADDU_OB:
24332 case OPC_ADDU_S_OB:
24333 case OPC_ADDU_QH:
24334 case OPC_ADDU_S_QH:
24335 case OPC_ADDUH_OB:
24336 case OPC_ADDUH_R_OB:
24337 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24338 break;
24339 case OPC_MULEQ_S_PW_QHL:
24340 case OPC_MULEQ_S_PW_QHR:
24341 case OPC_MULEU_S_QH_OBL:
24342 case OPC_MULEU_S_QH_OBR:
24343 case OPC_MULQ_RS_QH:
24344 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24345 break;
24346 default: /* Invalid */
24347 MIPS_INVAL("MASK ADDU.OB");
24348 generate_exception_end(ctx, EXCP_RI);
24349 break;
24351 break;
24352 case OPC_CMPU_EQ_OB_DSP:
24353 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24354 switch (op2) {
24355 case OPC_PRECR_SRA_QH_PW:
24356 case OPC_PRECR_SRA_R_QH_PW:
24357 /* Return value is rt. */
24358 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24359 break;
24360 case OPC_PRECR_OB_QH:
24361 case OPC_PRECRQ_OB_QH:
24362 case OPC_PRECRQ_PW_L:
24363 case OPC_PRECRQ_QH_PW:
24364 case OPC_PRECRQ_RS_QH_PW:
24365 case OPC_PRECRQU_S_OB_QH:
24366 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24367 break;
24368 case OPC_CMPU_EQ_OB:
24369 case OPC_CMPU_LT_OB:
24370 case OPC_CMPU_LE_OB:
24371 case OPC_CMP_EQ_QH:
24372 case OPC_CMP_LT_QH:
24373 case OPC_CMP_LE_QH:
24374 case OPC_CMP_EQ_PW:
24375 case OPC_CMP_LT_PW:
24376 case OPC_CMP_LE_PW:
24377 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24378 break;
24379 case OPC_CMPGDU_EQ_OB:
24380 case OPC_CMPGDU_LT_OB:
24381 case OPC_CMPGDU_LE_OB:
24382 case OPC_CMPGU_EQ_OB:
24383 case OPC_CMPGU_LT_OB:
24384 case OPC_CMPGU_LE_OB:
24385 case OPC_PACKRL_PW:
24386 case OPC_PICK_OB:
24387 case OPC_PICK_PW:
24388 case OPC_PICK_QH:
24389 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24390 break;
24391 default: /* Invalid */
24392 MIPS_INVAL("MASK CMPU_EQ.OB");
24393 generate_exception_end(ctx, EXCP_RI);
24394 break;
24396 break;
24397 case OPC_DAPPEND_DSP:
24398 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24399 break;
24400 case OPC_DEXTR_W_DSP:
24401 op2 = MASK_DEXTR_W(ctx->opcode);
24402 switch (op2) {
24403 case OPC_DEXTP:
24404 case OPC_DEXTPDP:
24405 case OPC_DEXTPDPV:
24406 case OPC_DEXTPV:
24407 case OPC_DEXTR_L:
24408 case OPC_DEXTR_R_L:
24409 case OPC_DEXTR_RS_L:
24410 case OPC_DEXTR_W:
24411 case OPC_DEXTR_R_W:
24412 case OPC_DEXTR_RS_W:
24413 case OPC_DEXTR_S_H:
24414 case OPC_DEXTRV_L:
24415 case OPC_DEXTRV_R_L:
24416 case OPC_DEXTRV_RS_L:
24417 case OPC_DEXTRV_S_H:
24418 case OPC_DEXTRV_W:
24419 case OPC_DEXTRV_R_W:
24420 case OPC_DEXTRV_RS_W:
24421 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24422 break;
24423 case OPC_DMTHLIP:
24424 case OPC_DSHILO:
24425 case OPC_DSHILOV:
24426 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24427 break;
24428 default: /* Invalid */
24429 MIPS_INVAL("MASK EXTR.W");
24430 generate_exception_end(ctx, EXCP_RI);
24431 break;
24433 break;
24434 case OPC_DPAQ_W_QH_DSP:
24435 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24436 switch (op2) {
24437 case OPC_DPAU_H_OBL:
24438 case OPC_DPAU_H_OBR:
24439 case OPC_DPSU_H_OBL:
24440 case OPC_DPSU_H_OBR:
24441 case OPC_DPA_W_QH:
24442 case OPC_DPAQ_S_W_QH:
24443 case OPC_DPS_W_QH:
24444 case OPC_DPSQ_S_W_QH:
24445 case OPC_MULSAQ_S_W_QH:
24446 case OPC_DPAQ_SA_L_PW:
24447 case OPC_DPSQ_SA_L_PW:
24448 case OPC_MULSAQ_S_L_PW:
24449 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24450 break;
24451 case OPC_MAQ_S_W_QHLL:
24452 case OPC_MAQ_S_W_QHLR:
24453 case OPC_MAQ_S_W_QHRL:
24454 case OPC_MAQ_S_W_QHRR:
24455 case OPC_MAQ_SA_W_QHLL:
24456 case OPC_MAQ_SA_W_QHLR:
24457 case OPC_MAQ_SA_W_QHRL:
24458 case OPC_MAQ_SA_W_QHRR:
24459 case OPC_MAQ_S_L_PWL:
24460 case OPC_MAQ_S_L_PWR:
24461 case OPC_DMADD:
24462 case OPC_DMADDU:
24463 case OPC_DMSUB:
24464 case OPC_DMSUBU:
24465 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24466 break;
24467 default: /* Invalid */
24468 MIPS_INVAL("MASK DPAQ.W.QH");
24469 generate_exception_end(ctx, EXCP_RI);
24470 break;
24472 break;
24473 case OPC_DINSV_DSP:
24474 op2 = MASK_INSV(ctx->opcode);
24475 switch (op2) {
24476 case OPC_DINSV:
24478 TCGv t0, t1;
24480 if (rt == 0) {
24481 break;
24483 check_dsp(ctx);
24485 t0 = tcg_temp_new();
24486 t1 = tcg_temp_new();
24488 gen_load_gpr(t0, rt);
24489 gen_load_gpr(t1, rs);
24491 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24493 tcg_temp_free(t0);
24494 tcg_temp_free(t1);
24495 break;
24497 default: /* Invalid */
24498 MIPS_INVAL("MASK DINSV");
24499 generate_exception_end(ctx, EXCP_RI);
24500 break;
24502 break;
24503 case OPC_SHLL_OB_DSP:
24504 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24505 break;
24506 #endif
24507 default: /* Invalid */
24508 MIPS_INVAL("special3_legacy");
24509 generate_exception_end(ctx, EXCP_RI);
24510 break;
24514 static void decode_tx79_mmi0(CPUMIPSState *env, DisasContext *ctx)
24516 uint32_t opc = MASK_TX79_MMI0(ctx->opcode);
24518 switch (opc) {
24519 case TX79_MMI0_PADDW: /* TODO: TX79_MMI0_PADDW */
24520 case TX79_MMI0_PSUBW: /* TODO: TX79_MMI0_PSUBW */
24521 case TX79_MMI0_PCGTW: /* TODO: TX79_MMI0_PCGTW */
24522 case TX79_MMI0_PMAXW: /* TODO: TX79_MMI0_PMAXW */
24523 case TX79_MMI0_PADDH: /* TODO: TX79_MMI0_PADDH */
24524 case TX79_MMI0_PSUBH: /* TODO: TX79_MMI0_PSUBH */
24525 case TX79_MMI0_PCGTH: /* TODO: TX79_MMI0_PCGTH */
24526 case TX79_MMI0_PMAXH: /* TODO: TX79_MMI0_PMAXH */
24527 case TX79_MMI0_PADDB: /* TODO: TX79_MMI0_PADDB */
24528 case TX79_MMI0_PSUBB: /* TODO: TX79_MMI0_PSUBB */
24529 case TX79_MMI0_PCGTB: /* TODO: TX79_MMI0_PCGTB */
24530 case TX79_MMI0_PADDSW: /* TODO: TX79_MMI0_PADDSW */
24531 case TX79_MMI0_PSUBSW: /* TODO: TX79_MMI0_PSUBSW */
24532 case TX79_MMI0_PEXTLW: /* TODO: TX79_MMI0_PEXTLW */
24533 case TX79_MMI0_PPACW: /* TODO: TX79_MMI0_PPACW */
24534 case TX79_MMI0_PADDSH: /* TODO: TX79_MMI0_PADDSH */
24535 case TX79_MMI0_PSUBSH: /* TODO: TX79_MMI0_PSUBSH */
24536 case TX79_MMI0_PEXTLH: /* TODO: TX79_MMI0_PEXTLH */
24537 case TX79_MMI0_PPACH: /* TODO: TX79_MMI0_PPACH */
24538 case TX79_MMI0_PADDSB: /* TODO: TX79_MMI0_PADDSB */
24539 case TX79_MMI0_PSUBSB: /* TODO: TX79_MMI0_PSUBSB */
24540 case TX79_MMI0_PEXTLB: /* TODO: TX79_MMI0_PEXTLB */
24541 case TX79_MMI0_PPACB: /* TODO: TX79_MMI0_PPACB */
24542 case TX79_MMI0_PEXT5: /* TODO: TX79_MMI0_PEXT5 */
24543 case TX79_MMI0_PPAC5: /* TODO: TX79_MMI0_PPAC5 */
24544 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI0 */
24545 break;
24546 default:
24547 MIPS_INVAL("TX79 MMI class MMI0");
24548 generate_exception_end(ctx, EXCP_RI);
24549 break;
24553 static void decode_tx79_mmi1(CPUMIPSState *env, DisasContext *ctx)
24555 uint32_t opc = MASK_TX79_MMI1(ctx->opcode);
24557 switch (opc) {
24558 case TX79_MMI1_PABSW: /* TODO: TX79_MMI1_PABSW */
24559 case TX79_MMI1_PCEQW: /* TODO: TX79_MMI1_PCEQW */
24560 case TX79_MMI1_PMINW: /* TODO: TX79_MMI1_PMINW */
24561 case TX79_MMI1_PADSBH: /* TODO: TX79_MMI1_PADSBH */
24562 case TX79_MMI1_PABSH: /* TODO: TX79_MMI1_PABSH */
24563 case TX79_MMI1_PCEQH: /* TODO: TX79_MMI1_PCEQH */
24564 case TX79_MMI1_PMINH: /* TODO: TX79_MMI1_PMINH */
24565 case TX79_MMI1_PCEQB: /* TODO: TX79_MMI1_PCEQB */
24566 case TX79_MMI1_PADDUW: /* TODO: TX79_MMI1_PADDUW */
24567 case TX79_MMI1_PSUBUW: /* TODO: TX79_MMI1_PSUBUW */
24568 case TX79_MMI1_PEXTUW: /* TODO: TX79_MMI1_PEXTUW */
24569 case TX79_MMI1_PADDUH: /* TODO: TX79_MMI1_PADDUH */
24570 case TX79_MMI1_PSUBUH: /* TODO: TX79_MMI1_PSUBUH */
24571 case TX79_MMI1_PEXTUH: /* TODO: TX79_MMI1_PEXTUH */
24572 case TX79_MMI1_PADDUB: /* TODO: TX79_MMI1_PADDUB */
24573 case TX79_MMI1_PSUBUB: /* TODO: TX79_MMI1_PSUBUB */
24574 case TX79_MMI1_PEXTUB: /* TODO: TX79_MMI1_PEXTUB */
24575 case TX79_MMI1_QFSRV: /* TODO: TX79_MMI1_QFSRV */
24576 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI1 */
24577 break;
24578 default:
24579 MIPS_INVAL("TX79 MMI class MMI1");
24580 generate_exception_end(ctx, EXCP_RI);
24581 break;
24585 static void decode_tx79_mmi2(CPUMIPSState *env, DisasContext *ctx)
24587 uint32_t opc = MASK_TX79_MMI2(ctx->opcode);
24589 switch (opc) {
24590 case TX79_MMI2_PMADDW: /* TODO: TX79_MMI2_PMADDW */
24591 case TX79_MMI2_PSLLVW: /* TODO: TX79_MMI2_PSLLVW */
24592 case TX79_MMI2_PSRLVW: /* TODO: TX79_MMI2_PSRLVW */
24593 case TX79_MMI2_PMSUBW: /* TODO: TX79_MMI2_PMSUBW */
24594 case TX79_MMI2_PMFHI: /* TODO: TX79_MMI2_PMFHI */
24595 case TX79_MMI2_PMFLO: /* TODO: TX79_MMI2_PMFLO */
24596 case TX79_MMI2_PINTH: /* TODO: TX79_MMI2_PINTH */
24597 case TX79_MMI2_PMULTW: /* TODO: TX79_MMI2_PMULTW */
24598 case TX79_MMI2_PDIVW: /* TODO: TX79_MMI2_PDIVW */
24599 case TX79_MMI2_PCPYLD: /* TODO: TX79_MMI2_PCPYLD */
24600 case TX79_MMI2_PMADDH: /* TODO: TX79_MMI2_PMADDH */
24601 case TX79_MMI2_PHMADH: /* TODO: TX79_MMI2_PHMADH */
24602 case TX79_MMI2_PAND: /* TODO: TX79_MMI2_PAND */
24603 case TX79_MMI2_PXOR: /* TODO: TX79_MMI2_PXOR */
24604 case TX79_MMI2_PMSUBH: /* TODO: TX79_MMI2_PMSUBH */
24605 case TX79_MMI2_PHMSBH: /* TODO: TX79_MMI2_PHMSBH */
24606 case TX79_MMI2_PEXEH: /* TODO: TX79_MMI2_PEXEH */
24607 case TX79_MMI2_PREVH: /* TODO: TX79_MMI2_PREVH */
24608 case TX79_MMI2_PMULTH: /* TODO: TX79_MMI2_PMULTH */
24609 case TX79_MMI2_PDIVBW: /* TODO: TX79_MMI2_PDIVBW */
24610 case TX79_MMI2_PEXEW: /* TODO: TX79_MMI2_PEXEW */
24611 case TX79_MMI2_PROT3W: /* TODO: TX79_MMI2_PROT3W */
24612 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI2 */
24613 break;
24614 default:
24615 MIPS_INVAL("TX79 MMI class MMI2");
24616 generate_exception_end(ctx, EXCP_RI);
24617 break;
24621 static void decode_tx79_mmi3(CPUMIPSState *env, DisasContext *ctx)
24623 uint32_t opc = MASK_TX79_MMI3(ctx->opcode);
24625 switch (opc) {
24626 case TX79_MMI3_PMADDUW: /* TODO: TX79_MMI3_PMADDUW */
24627 case TX79_MMI3_PSRAVW: /* TODO: TX79_MMI3_PSRAVW */
24628 case TX79_MMI3_PMTHI: /* TODO: TX79_MMI3_PMTHI */
24629 case TX79_MMI3_PMTLO: /* TODO: TX79_MMI3_PMTLO */
24630 case TX79_MMI3_PINTEH: /* TODO: TX79_MMI3_PINTEH */
24631 case TX79_MMI3_PMULTUW: /* TODO: TX79_MMI3_PMULTUW */
24632 case TX79_MMI3_PDIVUW: /* TODO: TX79_MMI3_PDIVUW */
24633 case TX79_MMI3_PCPYUD: /* TODO: TX79_MMI3_PCPYUD */
24634 case TX79_MMI3_POR: /* TODO: TX79_MMI3_POR */
24635 case TX79_MMI3_PNOR: /* TODO: TX79_MMI3_PNOR */
24636 case TX79_MMI3_PEXCH: /* TODO: TX79_MMI3_PEXCH */
24637 case TX79_MMI3_PCPYH: /* TODO: TX79_MMI3_PCPYH */
24638 case TX79_MMI3_PEXCW: /* TODO: TX79_MMI3_PEXCW */
24639 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI3 */
24640 break;
24641 default:
24642 MIPS_INVAL("TX79 MMI class MMI3");
24643 generate_exception_end(ctx, EXCP_RI);
24644 break;
24648 static void decode_tx79_mmi(CPUMIPSState *env, DisasContext *ctx)
24650 uint32_t opc = MASK_TX79_MMI(ctx->opcode);
24651 int rs = extract32(ctx->opcode, 21, 5);
24652 int rt = extract32(ctx->opcode, 16, 5);
24653 int rd = extract32(ctx->opcode, 11, 5);
24655 switch (opc) {
24656 case TX79_MMI_CLASS_MMI0:
24657 decode_tx79_mmi0(env, ctx);
24658 break;
24659 case TX79_MMI_CLASS_MMI1:
24660 decode_tx79_mmi1(env, ctx);
24661 break;
24662 case TX79_MMI_CLASS_MMI2:
24663 decode_tx79_mmi2(env, ctx);
24664 break;
24665 case TX79_MMI_CLASS_MMI3:
24666 decode_tx79_mmi3(env, ctx);
24667 break;
24668 case TX79_MMI_MULT1:
24669 case TX79_MMI_MULTU1:
24670 gen_mul_txx9(ctx, opc, rd, rs, rt);
24671 break;
24672 case TX79_MMI_DIV1:
24673 case TX79_MMI_DIVU1:
24674 gen_muldiv(ctx, opc, 1, rs, rt);
24675 break;
24676 case TX79_MMI_MTLO1:
24677 case TX79_MMI_MTHI1:
24678 gen_HILO(ctx, opc, 1, rs);
24679 break;
24680 case TX79_MMI_MFLO1:
24681 case TX79_MMI_MFHI1:
24682 gen_HILO(ctx, opc, 1, rd);
24683 break;
24684 case TX79_MMI_MADD: /* TODO: TX79_MMI_MADD */
24685 case TX79_MMI_MADDU: /* TODO: TX79_MMI_MADDU */
24686 case TX79_MMI_PLZCW: /* TODO: TX79_MMI_PLZCW */
24687 case TX79_MMI_MADD1: /* TODO: TX79_MMI_MADD1 */
24688 case TX79_MMI_MADDU1: /* TODO: TX79_MMI_MADDU1 */
24689 case TX79_MMI_PMFHL: /* TODO: TX79_MMI_PMFHL */
24690 case TX79_MMI_PMTHL: /* TODO: TX79_MMI_PMTHL */
24691 case TX79_MMI_PSLLH: /* TODO: TX79_MMI_PSLLH */
24692 case TX79_MMI_PSRLH: /* TODO: TX79_MMI_PSRLH */
24693 case TX79_MMI_PSRAH: /* TODO: TX79_MMI_PSRAH */
24694 case TX79_MMI_PSLLW: /* TODO: TX79_MMI_PSLLW */
24695 case TX79_MMI_PSRLW: /* TODO: TX79_MMI_PSRLW */
24696 case TX79_MMI_PSRAW: /* TODO: TX79_MMI_PSRAW */
24697 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_CLASS_MMI */
24698 break;
24699 default:
24700 MIPS_INVAL("TX79 MMI class");
24701 generate_exception_end(ctx, EXCP_RI);
24702 break;
24706 static void decode_tx79_lq(CPUMIPSState *env, DisasContext *ctx)
24708 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_LQ */
24711 static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
24713 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
24717 * The TX79-specific instruction Store Quadword
24719 * +--------+-------+-------+------------------------+
24720 * | 011111 | base | rt | offset | SQ
24721 * +--------+-------+-------+------------------------+
24722 * 6 5 5 16
24724 * has the same opcode as the Read Hardware Register instruction
24726 * +--------+-------+-------+-------+-------+--------+
24727 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24728 * +--------+-------+-------+-------+-------+--------+
24729 * 6 5 5 5 5 6
24731 * that is required, trapped and emulated by the Linux kernel. However, all
24732 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24733 * offset is odd. Therefore all valid SQ instructions can execute normally.
24734 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24735 * between SQ and RDHWR, as the Linux kernel does.
24737 static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
24739 int base = extract32(ctx->opcode, 21, 5);
24740 int rt = extract32(ctx->opcode, 16, 5);
24741 int offset = extract32(ctx->opcode, 0, 16);
24743 #ifdef CONFIG_USER_ONLY
24744 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24745 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24747 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24748 int rd = extract32(ctx->opcode, 11, 5);
24750 gen_rdhwr(ctx, rt, rd, 0);
24751 return;
24753 #endif
24755 gen_tx79_sq(ctx, base, rt, offset);
24758 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24760 int rs, rt, rd, sa;
24761 uint32_t op1, op2;
24762 int16_t imm;
24764 rs = (ctx->opcode >> 21) & 0x1f;
24765 rt = (ctx->opcode >> 16) & 0x1f;
24766 rd = (ctx->opcode >> 11) & 0x1f;
24767 sa = (ctx->opcode >> 6) & 0x1f;
24768 imm = sextract32(ctx->opcode, 7, 9);
24770 op1 = MASK_SPECIAL3(ctx->opcode);
24773 * EVA loads and stores overlap Loongson 2E instructions decoded by
24774 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24775 * EVA is absent.
24777 if (ctx->eva) {
24778 switch (op1) {
24779 case OPC_LWLE:
24780 case OPC_LWRE:
24781 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24782 /* fall through */
24783 case OPC_LBUE:
24784 case OPC_LHUE:
24785 case OPC_LBE:
24786 case OPC_LHE:
24787 case OPC_LLE:
24788 case OPC_LWE:
24789 check_cp0_enabled(ctx);
24790 gen_ld(ctx, op1, rt, rs, imm);
24791 return;
24792 case OPC_SWLE:
24793 case OPC_SWRE:
24794 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24795 /* fall through */
24796 case OPC_SBE:
24797 case OPC_SHE:
24798 case OPC_SWE:
24799 check_cp0_enabled(ctx);
24800 gen_st(ctx, op1, rt, rs, imm);
24801 return;
24802 case OPC_SCE:
24803 check_cp0_enabled(ctx);
24804 gen_st_cond(ctx, op1, rt, rs, imm);
24805 return;
24806 case OPC_CACHEE:
24807 check_cp0_enabled(ctx);
24808 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24809 gen_cache_operation(ctx, rt, rs, imm);
24811 /* Treat as NOP. */
24812 return;
24813 case OPC_PREFE:
24814 check_cp0_enabled(ctx);
24815 /* Treat as NOP. */
24816 return;
24820 switch (op1) {
24821 case OPC_EXT:
24822 case OPC_INS:
24823 check_insn(ctx, ISA_MIPS32R2);
24824 gen_bitops(ctx, op1, rt, rs, sa, rd);
24825 break;
24826 case OPC_BSHFL:
24827 op2 = MASK_BSHFL(ctx->opcode);
24828 switch (op2) {
24829 case OPC_ALIGN:
24830 case OPC_ALIGN_END:
24831 case OPC_BITSWAP:
24832 check_insn(ctx, ISA_MIPS32R6);
24833 decode_opc_special3_r6(env, ctx);
24834 break;
24835 default:
24836 check_insn(ctx, ISA_MIPS32R2);
24837 gen_bshfl(ctx, op2, rt, rd);
24838 break;
24840 break;
24841 #if defined(TARGET_MIPS64)
24842 case OPC_DEXTM:
24843 case OPC_DEXTU:
24844 case OPC_DEXT:
24845 case OPC_DINSM:
24846 case OPC_DINSU:
24847 case OPC_DINS:
24848 check_insn(ctx, ISA_MIPS64R2);
24849 check_mips_64(ctx);
24850 gen_bitops(ctx, op1, rt, rs, sa, rd);
24851 break;
24852 case OPC_DBSHFL:
24853 op2 = MASK_DBSHFL(ctx->opcode);
24854 switch (op2) {
24855 case OPC_DALIGN:
24856 case OPC_DALIGN_END:
24857 case OPC_DBITSWAP:
24858 check_insn(ctx, ISA_MIPS32R6);
24859 decode_opc_special3_r6(env, ctx);
24860 break;
24861 default:
24862 check_insn(ctx, ISA_MIPS64R2);
24863 check_mips_64(ctx);
24864 op2 = MASK_DBSHFL(ctx->opcode);
24865 gen_bshfl(ctx, op2, rt, rd);
24866 break;
24868 break;
24869 #endif
24870 case OPC_RDHWR:
24871 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24872 break;
24873 case OPC_FORK:
24874 check_mt(ctx);
24876 TCGv t0 = tcg_temp_new();
24877 TCGv t1 = tcg_temp_new();
24879 gen_load_gpr(t0, rt);
24880 gen_load_gpr(t1, rs);
24881 gen_helper_fork(t0, t1);
24882 tcg_temp_free(t0);
24883 tcg_temp_free(t1);
24885 break;
24886 case OPC_YIELD:
24887 check_mt(ctx);
24889 TCGv t0 = tcg_temp_new();
24891 gen_load_gpr(t0, rs);
24892 gen_helper_yield(t0, cpu_env, t0);
24893 gen_store_gpr(t0, rd);
24894 tcg_temp_free(t0);
24896 break;
24897 default:
24898 if (ctx->insn_flags & ISA_MIPS32R6) {
24899 decode_opc_special3_r6(env, ctx);
24900 } else {
24901 decode_opc_special3_legacy(env, ctx);
24906 /* MIPS SIMD Architecture (MSA) */
24907 static inline int check_msa_access(DisasContext *ctx)
24909 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
24910 !(ctx->hflags & MIPS_HFLAG_F64))) {
24911 generate_exception_end(ctx, EXCP_RI);
24912 return 0;
24915 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
24916 if (ctx->insn_flags & ASE_MSA) {
24917 generate_exception_end(ctx, EXCP_MSADIS);
24918 return 0;
24919 } else {
24920 generate_exception_end(ctx, EXCP_RI);
24921 return 0;
24924 return 1;
24927 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
24929 /* generates tcg ops to check if any element is 0 */
24930 /* Note this function only works with MSA_WRLEN = 128 */
24931 uint64_t eval_zero_or_big = 0;
24932 uint64_t eval_big = 0;
24933 TCGv_i64 t0 = tcg_temp_new_i64();
24934 TCGv_i64 t1 = tcg_temp_new_i64();
24935 switch (df) {
24936 case DF_BYTE:
24937 eval_zero_or_big = 0x0101010101010101ULL;
24938 eval_big = 0x8080808080808080ULL;
24939 break;
24940 case DF_HALF:
24941 eval_zero_or_big = 0x0001000100010001ULL;
24942 eval_big = 0x8000800080008000ULL;
24943 break;
24944 case DF_WORD:
24945 eval_zero_or_big = 0x0000000100000001ULL;
24946 eval_big = 0x8000000080000000ULL;
24947 break;
24948 case DF_DOUBLE:
24949 eval_zero_or_big = 0x0000000000000001ULL;
24950 eval_big = 0x8000000000000000ULL;
24951 break;
24953 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
24954 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
24955 tcg_gen_andi_i64(t0, t0, eval_big);
24956 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
24957 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
24958 tcg_gen_andi_i64(t1, t1, eval_big);
24959 tcg_gen_or_i64(t0, t0, t1);
24960 /* if all bits are zero then all elements are not zero */
24961 /* if some bit is non-zero then some element is zero */
24962 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
24963 tcg_gen_trunc_i64_tl(tresult, t0);
24964 tcg_temp_free_i64(t0);
24965 tcg_temp_free_i64(t1);
24968 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
24970 uint8_t df = (ctx->opcode >> 21) & 0x3;
24971 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24972 int64_t s16 = (int16_t)ctx->opcode;
24974 check_msa_access(ctx);
24976 if (ctx->hflags & MIPS_HFLAG_BMASK) {
24977 generate_exception_end(ctx, EXCP_RI);
24978 return;
24980 switch (op1) {
24981 case OPC_BZ_V:
24982 case OPC_BNZ_V:
24984 TCGv_i64 t0 = tcg_temp_new_i64();
24985 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
24986 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
24987 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
24988 tcg_gen_trunc_i64_tl(bcond, t0);
24989 tcg_temp_free_i64(t0);
24991 break;
24992 case OPC_BZ_B:
24993 case OPC_BZ_H:
24994 case OPC_BZ_W:
24995 case OPC_BZ_D:
24996 gen_check_zero_element(bcond, df, wt);
24997 break;
24998 case OPC_BNZ_B:
24999 case OPC_BNZ_H:
25000 case OPC_BNZ_W:
25001 case OPC_BNZ_D:
25002 gen_check_zero_element(bcond, df, wt);
25003 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
25004 break;
25007 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
25009 ctx->hflags |= MIPS_HFLAG_BC;
25010 ctx->hflags |= MIPS_HFLAG_BDS32;
25013 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
25015 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
25016 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
25017 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25018 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25020 TCGv_i32 twd = tcg_const_i32(wd);
25021 TCGv_i32 tws = tcg_const_i32(ws);
25022 TCGv_i32 ti8 = tcg_const_i32(i8);
25024 switch (MASK_MSA_I8(ctx->opcode)) {
25025 case OPC_ANDI_B:
25026 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
25027 break;
25028 case OPC_ORI_B:
25029 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
25030 break;
25031 case OPC_NORI_B:
25032 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
25033 break;
25034 case OPC_XORI_B:
25035 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
25036 break;
25037 case OPC_BMNZI_B:
25038 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
25039 break;
25040 case OPC_BMZI_B:
25041 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
25042 break;
25043 case OPC_BSELI_B:
25044 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
25045 break;
25046 case OPC_SHF_B:
25047 case OPC_SHF_H:
25048 case OPC_SHF_W:
25050 uint8_t df = (ctx->opcode >> 24) & 0x3;
25051 if (df == DF_DOUBLE) {
25052 generate_exception_end(ctx, EXCP_RI);
25053 } else {
25054 TCGv_i32 tdf = tcg_const_i32(df);
25055 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
25056 tcg_temp_free_i32(tdf);
25059 break;
25060 default:
25061 MIPS_INVAL("MSA instruction");
25062 generate_exception_end(ctx, EXCP_RI);
25063 break;
25066 tcg_temp_free_i32(twd);
25067 tcg_temp_free_i32(tws);
25068 tcg_temp_free_i32(ti8);
25071 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
25073 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25074 uint8_t df = (ctx->opcode >> 21) & 0x3;
25075 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
25076 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
25077 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25078 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25080 TCGv_i32 tdf = tcg_const_i32(df);
25081 TCGv_i32 twd = tcg_const_i32(wd);
25082 TCGv_i32 tws = tcg_const_i32(ws);
25083 TCGv_i32 timm = tcg_temp_new_i32();
25084 tcg_gen_movi_i32(timm, u5);
25086 switch (MASK_MSA_I5(ctx->opcode)) {
25087 case OPC_ADDVI_df:
25088 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
25089 break;
25090 case OPC_SUBVI_df:
25091 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
25092 break;
25093 case OPC_MAXI_S_df:
25094 tcg_gen_movi_i32(timm, s5);
25095 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
25096 break;
25097 case OPC_MAXI_U_df:
25098 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
25099 break;
25100 case OPC_MINI_S_df:
25101 tcg_gen_movi_i32(timm, s5);
25102 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
25103 break;
25104 case OPC_MINI_U_df:
25105 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
25106 break;
25107 case OPC_CEQI_df:
25108 tcg_gen_movi_i32(timm, s5);
25109 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
25110 break;
25111 case OPC_CLTI_S_df:
25112 tcg_gen_movi_i32(timm, s5);
25113 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
25114 break;
25115 case OPC_CLTI_U_df:
25116 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
25117 break;
25118 case OPC_CLEI_S_df:
25119 tcg_gen_movi_i32(timm, s5);
25120 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
25121 break;
25122 case OPC_CLEI_U_df:
25123 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
25124 break;
25125 case OPC_LDI_df:
25127 int32_t s10 = sextract32(ctx->opcode, 11, 10);
25128 tcg_gen_movi_i32(timm, s10);
25129 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
25131 break;
25132 default:
25133 MIPS_INVAL("MSA instruction");
25134 generate_exception_end(ctx, EXCP_RI);
25135 break;
25138 tcg_temp_free_i32(tdf);
25139 tcg_temp_free_i32(twd);
25140 tcg_temp_free_i32(tws);
25141 tcg_temp_free_i32(timm);
25144 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
25146 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25147 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
25148 uint32_t df = 0, m = 0;
25149 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25150 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25152 TCGv_i32 tdf;
25153 TCGv_i32 tm;
25154 TCGv_i32 twd;
25155 TCGv_i32 tws;
25157 if ((dfm & 0x40) == 0x00) {
25158 m = dfm & 0x3f;
25159 df = DF_DOUBLE;
25160 } else if ((dfm & 0x60) == 0x40) {
25161 m = dfm & 0x1f;
25162 df = DF_WORD;
25163 } else if ((dfm & 0x70) == 0x60) {
25164 m = dfm & 0x0f;
25165 df = DF_HALF;
25166 } else if ((dfm & 0x78) == 0x70) {
25167 m = dfm & 0x7;
25168 df = DF_BYTE;
25169 } else {
25170 generate_exception_end(ctx, EXCP_RI);
25171 return;
25174 tdf = tcg_const_i32(df);
25175 tm = tcg_const_i32(m);
25176 twd = tcg_const_i32(wd);
25177 tws = tcg_const_i32(ws);
25179 switch (MASK_MSA_BIT(ctx->opcode)) {
25180 case OPC_SLLI_df:
25181 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
25182 break;
25183 case OPC_SRAI_df:
25184 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
25185 break;
25186 case OPC_SRLI_df:
25187 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
25188 break;
25189 case OPC_BCLRI_df:
25190 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
25191 break;
25192 case OPC_BSETI_df:
25193 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
25194 break;
25195 case OPC_BNEGI_df:
25196 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
25197 break;
25198 case OPC_BINSLI_df:
25199 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
25200 break;
25201 case OPC_BINSRI_df:
25202 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
25203 break;
25204 case OPC_SAT_S_df:
25205 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
25206 break;
25207 case OPC_SAT_U_df:
25208 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
25209 break;
25210 case OPC_SRARI_df:
25211 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
25212 break;
25213 case OPC_SRLRI_df:
25214 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
25215 break;
25216 default:
25217 MIPS_INVAL("MSA instruction");
25218 generate_exception_end(ctx, EXCP_RI);
25219 break;
25222 tcg_temp_free_i32(tdf);
25223 tcg_temp_free_i32(tm);
25224 tcg_temp_free_i32(twd);
25225 tcg_temp_free_i32(tws);
25228 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
25230 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25231 uint8_t df = (ctx->opcode >> 21) & 0x3;
25232 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25233 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25234 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25236 TCGv_i32 tdf = tcg_const_i32(df);
25237 TCGv_i32 twd = tcg_const_i32(wd);
25238 TCGv_i32 tws = tcg_const_i32(ws);
25239 TCGv_i32 twt = tcg_const_i32(wt);
25241 switch (MASK_MSA_3R(ctx->opcode)) {
25242 case OPC_SLL_df:
25243 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
25244 break;
25245 case OPC_ADDV_df:
25246 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
25247 break;
25248 case OPC_CEQ_df:
25249 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
25250 break;
25251 case OPC_ADD_A_df:
25252 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
25253 break;
25254 case OPC_SUBS_S_df:
25255 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
25256 break;
25257 case OPC_MULV_df:
25258 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
25259 break;
25260 case OPC_SLD_df:
25261 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
25262 break;
25263 case OPC_VSHF_df:
25264 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
25265 break;
25266 case OPC_SRA_df:
25267 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
25268 break;
25269 case OPC_SUBV_df:
25270 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
25271 break;
25272 case OPC_ADDS_A_df:
25273 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
25274 break;
25275 case OPC_SUBS_U_df:
25276 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
25277 break;
25278 case OPC_MADDV_df:
25279 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
25280 break;
25281 case OPC_SPLAT_df:
25282 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
25283 break;
25284 case OPC_SRAR_df:
25285 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
25286 break;
25287 case OPC_SRL_df:
25288 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
25289 break;
25290 case OPC_MAX_S_df:
25291 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
25292 break;
25293 case OPC_CLT_S_df:
25294 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
25295 break;
25296 case OPC_ADDS_S_df:
25297 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
25298 break;
25299 case OPC_SUBSUS_U_df:
25300 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
25301 break;
25302 case OPC_MSUBV_df:
25303 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
25304 break;
25305 case OPC_PCKEV_df:
25306 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
25307 break;
25308 case OPC_SRLR_df:
25309 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
25310 break;
25311 case OPC_BCLR_df:
25312 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
25313 break;
25314 case OPC_MAX_U_df:
25315 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
25316 break;
25317 case OPC_CLT_U_df:
25318 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
25319 break;
25320 case OPC_ADDS_U_df:
25321 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
25322 break;
25323 case OPC_SUBSUU_S_df:
25324 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
25325 break;
25326 case OPC_PCKOD_df:
25327 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
25328 break;
25329 case OPC_BSET_df:
25330 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
25331 break;
25332 case OPC_MIN_S_df:
25333 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
25334 break;
25335 case OPC_CLE_S_df:
25336 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
25337 break;
25338 case OPC_AVE_S_df:
25339 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
25340 break;
25341 case OPC_ASUB_S_df:
25342 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
25343 break;
25344 case OPC_DIV_S_df:
25345 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
25346 break;
25347 case OPC_ILVL_df:
25348 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
25349 break;
25350 case OPC_BNEG_df:
25351 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
25352 break;
25353 case OPC_MIN_U_df:
25354 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
25355 break;
25356 case OPC_CLE_U_df:
25357 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
25358 break;
25359 case OPC_AVE_U_df:
25360 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
25361 break;
25362 case OPC_ASUB_U_df:
25363 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
25364 break;
25365 case OPC_DIV_U_df:
25366 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
25367 break;
25368 case OPC_ILVR_df:
25369 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
25370 break;
25371 case OPC_BINSL_df:
25372 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
25373 break;
25374 case OPC_MAX_A_df:
25375 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
25376 break;
25377 case OPC_AVER_S_df:
25378 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
25379 break;
25380 case OPC_MOD_S_df:
25381 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
25382 break;
25383 case OPC_ILVEV_df:
25384 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
25385 break;
25386 case OPC_BINSR_df:
25387 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
25388 break;
25389 case OPC_MIN_A_df:
25390 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
25391 break;
25392 case OPC_AVER_U_df:
25393 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
25394 break;
25395 case OPC_MOD_U_df:
25396 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
25397 break;
25398 case OPC_ILVOD_df:
25399 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
25400 break;
25402 case OPC_DOTP_S_df:
25403 case OPC_DOTP_U_df:
25404 case OPC_DPADD_S_df:
25405 case OPC_DPADD_U_df:
25406 case OPC_DPSUB_S_df:
25407 case OPC_HADD_S_df:
25408 case OPC_DPSUB_U_df:
25409 case OPC_HADD_U_df:
25410 case OPC_HSUB_S_df:
25411 case OPC_HSUB_U_df:
25412 if (df == DF_BYTE) {
25413 generate_exception_end(ctx, EXCP_RI);
25414 break;
25416 switch (MASK_MSA_3R(ctx->opcode)) {
25417 case OPC_DOTP_S_df:
25418 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
25419 break;
25420 case OPC_DOTP_U_df:
25421 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
25422 break;
25423 case OPC_DPADD_S_df:
25424 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
25425 break;
25426 case OPC_DPADD_U_df:
25427 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
25428 break;
25429 case OPC_DPSUB_S_df:
25430 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
25431 break;
25432 case OPC_HADD_S_df:
25433 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
25434 break;
25435 case OPC_DPSUB_U_df:
25436 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
25437 break;
25438 case OPC_HADD_U_df:
25439 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
25440 break;
25441 case OPC_HSUB_S_df:
25442 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
25443 break;
25444 case OPC_HSUB_U_df:
25445 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
25446 break;
25448 break;
25449 default:
25450 MIPS_INVAL("MSA instruction");
25451 generate_exception_end(ctx, EXCP_RI);
25452 break;
25454 tcg_temp_free_i32(twd);
25455 tcg_temp_free_i32(tws);
25456 tcg_temp_free_i32(twt);
25457 tcg_temp_free_i32(tdf);
25460 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
25462 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
25463 uint8_t source = (ctx->opcode >> 11) & 0x1f;
25464 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
25465 TCGv telm = tcg_temp_new();
25466 TCGv_i32 tsr = tcg_const_i32(source);
25467 TCGv_i32 tdt = tcg_const_i32(dest);
25469 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
25470 case OPC_CTCMSA:
25471 gen_load_gpr(telm, source);
25472 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
25473 break;
25474 case OPC_CFCMSA:
25475 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
25476 gen_store_gpr(telm, dest);
25477 break;
25478 case OPC_MOVE_V:
25479 gen_helper_msa_move_v(cpu_env, tdt, tsr);
25480 break;
25481 default:
25482 MIPS_INVAL("MSA instruction");
25483 generate_exception_end(ctx, EXCP_RI);
25484 break;
25487 tcg_temp_free(telm);
25488 tcg_temp_free_i32(tdt);
25489 tcg_temp_free_i32(tsr);
25492 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
25493 uint32_t n)
25495 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25496 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25497 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25499 TCGv_i32 tws = tcg_const_i32(ws);
25500 TCGv_i32 twd = tcg_const_i32(wd);
25501 TCGv_i32 tn = tcg_const_i32(n);
25502 TCGv_i32 tdf = tcg_const_i32(df);
25504 switch (MASK_MSA_ELM(ctx->opcode)) {
25505 case OPC_SLDI_df:
25506 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
25507 break;
25508 case OPC_SPLATI_df:
25509 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
25510 break;
25511 case OPC_INSVE_df:
25512 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
25513 break;
25514 case OPC_COPY_S_df:
25515 case OPC_COPY_U_df:
25516 case OPC_INSERT_df:
25517 #if !defined(TARGET_MIPS64)
25518 /* Double format valid only for MIPS64 */
25519 if (df == DF_DOUBLE) {
25520 generate_exception_end(ctx, EXCP_RI);
25521 break;
25523 #endif
25524 switch (MASK_MSA_ELM(ctx->opcode)) {
25525 case OPC_COPY_S_df:
25526 if (likely(wd != 0)) {
25527 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
25529 break;
25530 case OPC_COPY_U_df:
25531 if (likely(wd != 0)) {
25532 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
25534 break;
25535 case OPC_INSERT_df:
25536 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
25537 break;
25539 break;
25540 default:
25541 MIPS_INVAL("MSA instruction");
25542 generate_exception_end(ctx, EXCP_RI);
25544 tcg_temp_free_i32(twd);
25545 tcg_temp_free_i32(tws);
25546 tcg_temp_free_i32(tn);
25547 tcg_temp_free_i32(tdf);
25550 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
25552 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
25553 uint32_t df = 0, n = 0;
25555 if ((dfn & 0x30) == 0x00) {
25556 n = dfn & 0x0f;
25557 df = DF_BYTE;
25558 } else if ((dfn & 0x38) == 0x20) {
25559 n = dfn & 0x07;
25560 df = DF_HALF;
25561 } else if ((dfn & 0x3c) == 0x30) {
25562 n = dfn & 0x03;
25563 df = DF_WORD;
25564 } else if ((dfn & 0x3e) == 0x38) {
25565 n = dfn & 0x01;
25566 df = DF_DOUBLE;
25567 } else if (dfn == 0x3E) {
25568 /* CTCMSA, CFCMSA, MOVE.V */
25569 gen_msa_elm_3e(env, ctx);
25570 return;
25571 } else {
25572 generate_exception_end(ctx, EXCP_RI);
25573 return;
25576 gen_msa_elm_df(env, ctx, df, n);
25579 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
25581 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25582 uint8_t df = (ctx->opcode >> 21) & 0x1;
25583 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25584 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25585 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25587 TCGv_i32 twd = tcg_const_i32(wd);
25588 TCGv_i32 tws = tcg_const_i32(ws);
25589 TCGv_i32 twt = tcg_const_i32(wt);
25590 TCGv_i32 tdf = tcg_temp_new_i32();
25592 /* adjust df value for floating-point instruction */
25593 tcg_gen_movi_i32(tdf, df + 2);
25595 switch (MASK_MSA_3RF(ctx->opcode)) {
25596 case OPC_FCAF_df:
25597 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
25598 break;
25599 case OPC_FADD_df:
25600 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
25601 break;
25602 case OPC_FCUN_df:
25603 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
25604 break;
25605 case OPC_FSUB_df:
25606 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
25607 break;
25608 case OPC_FCOR_df:
25609 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
25610 break;
25611 case OPC_FCEQ_df:
25612 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
25613 break;
25614 case OPC_FMUL_df:
25615 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
25616 break;
25617 case OPC_FCUNE_df:
25618 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
25619 break;
25620 case OPC_FCUEQ_df:
25621 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
25622 break;
25623 case OPC_FDIV_df:
25624 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
25625 break;
25626 case OPC_FCNE_df:
25627 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
25628 break;
25629 case OPC_FCLT_df:
25630 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
25631 break;
25632 case OPC_FMADD_df:
25633 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
25634 break;
25635 case OPC_MUL_Q_df:
25636 tcg_gen_movi_i32(tdf, df + 1);
25637 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
25638 break;
25639 case OPC_FCULT_df:
25640 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
25641 break;
25642 case OPC_FMSUB_df:
25643 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
25644 break;
25645 case OPC_MADD_Q_df:
25646 tcg_gen_movi_i32(tdf, df + 1);
25647 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
25648 break;
25649 case OPC_FCLE_df:
25650 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
25651 break;
25652 case OPC_MSUB_Q_df:
25653 tcg_gen_movi_i32(tdf, df + 1);
25654 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
25655 break;
25656 case OPC_FCULE_df:
25657 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
25658 break;
25659 case OPC_FEXP2_df:
25660 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
25661 break;
25662 case OPC_FSAF_df:
25663 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
25664 break;
25665 case OPC_FEXDO_df:
25666 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
25667 break;
25668 case OPC_FSUN_df:
25669 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
25670 break;
25671 case OPC_FSOR_df:
25672 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
25673 break;
25674 case OPC_FSEQ_df:
25675 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
25676 break;
25677 case OPC_FTQ_df:
25678 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
25679 break;
25680 case OPC_FSUNE_df:
25681 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
25682 break;
25683 case OPC_FSUEQ_df:
25684 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
25685 break;
25686 case OPC_FSNE_df:
25687 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
25688 break;
25689 case OPC_FSLT_df:
25690 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
25691 break;
25692 case OPC_FMIN_df:
25693 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
25694 break;
25695 case OPC_MULR_Q_df:
25696 tcg_gen_movi_i32(tdf, df + 1);
25697 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
25698 break;
25699 case OPC_FSULT_df:
25700 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
25701 break;
25702 case OPC_FMIN_A_df:
25703 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
25704 break;
25705 case OPC_MADDR_Q_df:
25706 tcg_gen_movi_i32(tdf, df + 1);
25707 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
25708 break;
25709 case OPC_FSLE_df:
25710 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
25711 break;
25712 case OPC_FMAX_df:
25713 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
25714 break;
25715 case OPC_MSUBR_Q_df:
25716 tcg_gen_movi_i32(tdf, df + 1);
25717 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
25718 break;
25719 case OPC_FSULE_df:
25720 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
25721 break;
25722 case OPC_FMAX_A_df:
25723 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
25724 break;
25725 default:
25726 MIPS_INVAL("MSA instruction");
25727 generate_exception_end(ctx, EXCP_RI);
25728 break;
25731 tcg_temp_free_i32(twd);
25732 tcg_temp_free_i32(tws);
25733 tcg_temp_free_i32(twt);
25734 tcg_temp_free_i32(tdf);
25737 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
25739 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25740 (op & (0x7 << 18)))
25741 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25742 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25743 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25744 uint8_t df = (ctx->opcode >> 16) & 0x3;
25745 TCGv_i32 twd = tcg_const_i32(wd);
25746 TCGv_i32 tws = tcg_const_i32(ws);
25747 TCGv_i32 twt = tcg_const_i32(wt);
25748 TCGv_i32 tdf = tcg_const_i32(df);
25750 switch (MASK_MSA_2R(ctx->opcode)) {
25751 case OPC_FILL_df:
25752 #if !defined(TARGET_MIPS64)
25753 /* Double format valid only for MIPS64 */
25754 if (df == DF_DOUBLE) {
25755 generate_exception_end(ctx, EXCP_RI);
25756 break;
25758 #endif
25759 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
25760 break;
25761 case OPC_PCNT_df:
25762 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
25763 break;
25764 case OPC_NLOC_df:
25765 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
25766 break;
25767 case OPC_NLZC_df:
25768 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25769 break;
25770 default:
25771 MIPS_INVAL("MSA instruction");
25772 generate_exception_end(ctx, EXCP_RI);
25773 break;
25776 tcg_temp_free_i32(twd);
25777 tcg_temp_free_i32(tws);
25778 tcg_temp_free_i32(twt);
25779 tcg_temp_free_i32(tdf);
25782 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25784 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25785 (op & (0xf << 17)))
25786 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25787 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25788 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25789 uint8_t df = (ctx->opcode >> 16) & 0x1;
25790 TCGv_i32 twd = tcg_const_i32(wd);
25791 TCGv_i32 tws = tcg_const_i32(ws);
25792 TCGv_i32 twt = tcg_const_i32(wt);
25793 /* adjust df value for floating-point instruction */
25794 TCGv_i32 tdf = tcg_const_i32(df + 2);
25796 switch (MASK_MSA_2RF(ctx->opcode)) {
25797 case OPC_FCLASS_df:
25798 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25799 break;
25800 case OPC_FTRUNC_S_df:
25801 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25802 break;
25803 case OPC_FTRUNC_U_df:
25804 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25805 break;
25806 case OPC_FSQRT_df:
25807 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25808 break;
25809 case OPC_FRSQRT_df:
25810 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25811 break;
25812 case OPC_FRCP_df:
25813 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25814 break;
25815 case OPC_FRINT_df:
25816 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25817 break;
25818 case OPC_FLOG2_df:
25819 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
25820 break;
25821 case OPC_FEXUPL_df:
25822 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
25823 break;
25824 case OPC_FEXUPR_df:
25825 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
25826 break;
25827 case OPC_FFQL_df:
25828 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
25829 break;
25830 case OPC_FFQR_df:
25831 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
25832 break;
25833 case OPC_FTINT_S_df:
25834 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
25835 break;
25836 case OPC_FTINT_U_df:
25837 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
25838 break;
25839 case OPC_FFINT_S_df:
25840 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
25841 break;
25842 case OPC_FFINT_U_df:
25843 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
25844 break;
25847 tcg_temp_free_i32(twd);
25848 tcg_temp_free_i32(tws);
25849 tcg_temp_free_i32(twt);
25850 tcg_temp_free_i32(tdf);
25853 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
25855 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
25856 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25857 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25858 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25859 TCGv_i32 twd = tcg_const_i32(wd);
25860 TCGv_i32 tws = tcg_const_i32(ws);
25861 TCGv_i32 twt = tcg_const_i32(wt);
25863 switch (MASK_MSA_VEC(ctx->opcode)) {
25864 case OPC_AND_V:
25865 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
25866 break;
25867 case OPC_OR_V:
25868 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
25869 break;
25870 case OPC_NOR_V:
25871 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
25872 break;
25873 case OPC_XOR_V:
25874 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
25875 break;
25876 case OPC_BMNZ_V:
25877 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
25878 break;
25879 case OPC_BMZ_V:
25880 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
25881 break;
25882 case OPC_BSEL_V:
25883 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
25884 break;
25885 default:
25886 MIPS_INVAL("MSA instruction");
25887 generate_exception_end(ctx, EXCP_RI);
25888 break;
25891 tcg_temp_free_i32(twd);
25892 tcg_temp_free_i32(tws);
25893 tcg_temp_free_i32(twt);
25896 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
25898 switch (MASK_MSA_VEC(ctx->opcode)) {
25899 case OPC_AND_V:
25900 case OPC_OR_V:
25901 case OPC_NOR_V:
25902 case OPC_XOR_V:
25903 case OPC_BMNZ_V:
25904 case OPC_BMZ_V:
25905 case OPC_BSEL_V:
25906 gen_msa_vec_v(env, ctx);
25907 break;
25908 case OPC_MSA_2R:
25909 gen_msa_2r(env, ctx);
25910 break;
25911 case OPC_MSA_2RF:
25912 gen_msa_2rf(env, ctx);
25913 break;
25914 default:
25915 MIPS_INVAL("MSA instruction");
25916 generate_exception_end(ctx, EXCP_RI);
25917 break;
25921 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
25923 uint32_t opcode = ctx->opcode;
25924 check_insn(ctx, ASE_MSA);
25925 check_msa_access(ctx);
25927 switch (MASK_MSA_MINOR(opcode)) {
25928 case OPC_MSA_I8_00:
25929 case OPC_MSA_I8_01:
25930 case OPC_MSA_I8_02:
25931 gen_msa_i8(env, ctx);
25932 break;
25933 case OPC_MSA_I5_06:
25934 case OPC_MSA_I5_07:
25935 gen_msa_i5(env, ctx);
25936 break;
25937 case OPC_MSA_BIT_09:
25938 case OPC_MSA_BIT_0A:
25939 gen_msa_bit(env, ctx);
25940 break;
25941 case OPC_MSA_3R_0D:
25942 case OPC_MSA_3R_0E:
25943 case OPC_MSA_3R_0F:
25944 case OPC_MSA_3R_10:
25945 case OPC_MSA_3R_11:
25946 case OPC_MSA_3R_12:
25947 case OPC_MSA_3R_13:
25948 case OPC_MSA_3R_14:
25949 case OPC_MSA_3R_15:
25950 gen_msa_3r(env, ctx);
25951 break;
25952 case OPC_MSA_ELM:
25953 gen_msa_elm(env, ctx);
25954 break;
25955 case OPC_MSA_3RF_1A:
25956 case OPC_MSA_3RF_1B:
25957 case OPC_MSA_3RF_1C:
25958 gen_msa_3rf(env, ctx);
25959 break;
25960 case OPC_MSA_VEC:
25961 gen_msa_vec(env, ctx);
25962 break;
25963 case OPC_LD_B:
25964 case OPC_LD_H:
25965 case OPC_LD_W:
25966 case OPC_LD_D:
25967 case OPC_ST_B:
25968 case OPC_ST_H:
25969 case OPC_ST_W:
25970 case OPC_ST_D:
25972 int32_t s10 = sextract32(ctx->opcode, 16, 10);
25973 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
25974 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25975 uint8_t df = (ctx->opcode >> 0) & 0x3;
25977 TCGv_i32 twd = tcg_const_i32(wd);
25978 TCGv taddr = tcg_temp_new();
25979 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
25981 switch (MASK_MSA_MINOR(opcode)) {
25982 case OPC_LD_B:
25983 gen_helper_msa_ld_b(cpu_env, twd, taddr);
25984 break;
25985 case OPC_LD_H:
25986 gen_helper_msa_ld_h(cpu_env, twd, taddr);
25987 break;
25988 case OPC_LD_W:
25989 gen_helper_msa_ld_w(cpu_env, twd, taddr);
25990 break;
25991 case OPC_LD_D:
25992 gen_helper_msa_ld_d(cpu_env, twd, taddr);
25993 break;
25994 case OPC_ST_B:
25995 gen_helper_msa_st_b(cpu_env, twd, taddr);
25996 break;
25997 case OPC_ST_H:
25998 gen_helper_msa_st_h(cpu_env, twd, taddr);
25999 break;
26000 case OPC_ST_W:
26001 gen_helper_msa_st_w(cpu_env, twd, taddr);
26002 break;
26003 case OPC_ST_D:
26004 gen_helper_msa_st_d(cpu_env, twd, taddr);
26005 break;
26008 tcg_temp_free_i32(twd);
26009 tcg_temp_free(taddr);
26011 break;
26012 default:
26013 MIPS_INVAL("MSA instruction");
26014 generate_exception_end(ctx, EXCP_RI);
26015 break;
26020 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
26022 int32_t offset;
26023 int rs, rt, rd, sa;
26024 uint32_t op, op1;
26025 int16_t imm;
26027 /* make sure instructions are on a word boundary */
26028 if (ctx->base.pc_next & 0x3) {
26029 env->CP0_BadVAddr = ctx->base.pc_next;
26030 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
26031 return;
26034 /* Handle blikely not taken case */
26035 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
26036 TCGLabel *l1 = gen_new_label();
26038 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
26039 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
26040 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
26041 gen_set_label(l1);
26044 op = MASK_OP_MAJOR(ctx->opcode);
26045 rs = (ctx->opcode >> 21) & 0x1f;
26046 rt = (ctx->opcode >> 16) & 0x1f;
26047 rd = (ctx->opcode >> 11) & 0x1f;
26048 sa = (ctx->opcode >> 6) & 0x1f;
26049 imm = (int16_t)ctx->opcode;
26050 switch (op) {
26051 case OPC_SPECIAL:
26052 decode_opc_special(env, ctx);
26053 break;
26054 case OPC_SPECIAL2:
26055 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
26056 decode_tx79_mmi(env, ctx);
26057 } else {
26058 decode_opc_special2_legacy(env, ctx);
26060 break;
26061 case OPC_SPECIAL3:
26062 if (ctx->insn_flags & INSN_R5900) {
26063 decode_tx79_sq(env, ctx); /* TX79_SQ */
26064 } else {
26065 decode_opc_special3(env, ctx);
26067 break;
26068 case OPC_REGIMM:
26069 op1 = MASK_REGIMM(ctx->opcode);
26070 switch (op1) {
26071 case OPC_BLTZL: /* REGIMM branches */
26072 case OPC_BGEZL:
26073 case OPC_BLTZALL:
26074 case OPC_BGEZALL:
26075 check_insn(ctx, ISA_MIPS2);
26076 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26077 /* Fallthrough */
26078 case OPC_BLTZ:
26079 case OPC_BGEZ:
26080 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26081 break;
26082 case OPC_BLTZAL:
26083 case OPC_BGEZAL:
26084 if (ctx->insn_flags & ISA_MIPS32R6) {
26085 if (rs == 0) {
26086 /* OPC_NAL, OPC_BAL */
26087 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
26088 } else {
26089 generate_exception_end(ctx, EXCP_RI);
26091 } else {
26092 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26094 break;
26095 case OPC_TGEI: /* REGIMM traps */
26096 case OPC_TGEIU:
26097 case OPC_TLTI:
26098 case OPC_TLTIU:
26099 case OPC_TEQI:
26101 case OPC_TNEI:
26102 check_insn(ctx, ISA_MIPS2);
26103 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26104 gen_trap(ctx, op1, rs, -1, imm);
26105 break;
26106 case OPC_SIGRIE:
26107 check_insn(ctx, ISA_MIPS32R6);
26108 generate_exception_end(ctx, EXCP_RI);
26109 break;
26110 case OPC_SYNCI:
26111 check_insn(ctx, ISA_MIPS32R2);
26112 /* Break the TB to be able to sync copied instructions
26113 immediately */
26114 ctx->base.is_jmp = DISAS_STOP;
26115 break;
26116 case OPC_BPOSGE32: /* MIPS DSP branch */
26117 #if defined(TARGET_MIPS64)
26118 case OPC_BPOSGE64:
26119 #endif
26120 check_dsp(ctx);
26121 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
26122 break;
26123 #if defined(TARGET_MIPS64)
26124 case OPC_DAHI:
26125 check_insn(ctx, ISA_MIPS32R6);
26126 check_mips_64(ctx);
26127 if (rs != 0) {
26128 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
26130 break;
26131 case OPC_DATI:
26132 check_insn(ctx, ISA_MIPS32R6);
26133 check_mips_64(ctx);
26134 if (rs != 0) {
26135 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
26137 break;
26138 #endif
26139 default: /* Invalid */
26140 MIPS_INVAL("regimm");
26141 generate_exception_end(ctx, EXCP_RI);
26142 break;
26144 break;
26145 case OPC_CP0:
26146 check_cp0_enabled(ctx);
26147 op1 = MASK_CP0(ctx->opcode);
26148 switch (op1) {
26149 case OPC_MFC0:
26150 case OPC_MTC0:
26151 case OPC_MFTR:
26152 case OPC_MTTR:
26153 case OPC_MFHC0:
26154 case OPC_MTHC0:
26155 #if defined(TARGET_MIPS64)
26156 case OPC_DMFC0:
26157 case OPC_DMTC0:
26158 #endif
26159 #ifndef CONFIG_USER_ONLY
26160 gen_cp0(env, ctx, op1, rt, rd);
26161 #endif /* !CONFIG_USER_ONLY */
26162 break;
26163 case OPC_C0:
26164 case OPC_C0_1:
26165 case OPC_C0_2:
26166 case OPC_C0_3:
26167 case OPC_C0_4:
26168 case OPC_C0_5:
26169 case OPC_C0_6:
26170 case OPC_C0_7:
26171 case OPC_C0_8:
26172 case OPC_C0_9:
26173 case OPC_C0_A:
26174 case OPC_C0_B:
26175 case OPC_C0_C:
26176 case OPC_C0_D:
26177 case OPC_C0_E:
26178 case OPC_C0_F:
26179 #ifndef CONFIG_USER_ONLY
26180 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
26181 #endif /* !CONFIG_USER_ONLY */
26182 break;
26183 case OPC_MFMC0:
26184 #ifndef CONFIG_USER_ONLY
26186 uint32_t op2;
26187 TCGv t0 = tcg_temp_new();
26189 op2 = MASK_MFMC0(ctx->opcode);
26190 switch (op2) {
26191 case OPC_DMT:
26192 check_cp0_mt(ctx);
26193 gen_helper_dmt(t0);
26194 gen_store_gpr(t0, rt);
26195 break;
26196 case OPC_EMT:
26197 check_cp0_mt(ctx);
26198 gen_helper_emt(t0);
26199 gen_store_gpr(t0, rt);
26200 break;
26201 case OPC_DVPE:
26202 check_cp0_mt(ctx);
26203 gen_helper_dvpe(t0, cpu_env);
26204 gen_store_gpr(t0, rt);
26205 break;
26206 case OPC_EVPE:
26207 check_cp0_mt(ctx);
26208 gen_helper_evpe(t0, cpu_env);
26209 gen_store_gpr(t0, rt);
26210 break;
26211 case OPC_DVP:
26212 check_insn(ctx, ISA_MIPS32R6);
26213 if (ctx->vp) {
26214 gen_helper_dvp(t0, cpu_env);
26215 gen_store_gpr(t0, rt);
26217 break;
26218 case OPC_EVP:
26219 check_insn(ctx, ISA_MIPS32R6);
26220 if (ctx->vp) {
26221 gen_helper_evp(t0, cpu_env);
26222 gen_store_gpr(t0, rt);
26224 break;
26225 case OPC_DI:
26226 check_insn(ctx, ISA_MIPS32R2);
26227 save_cpu_state(ctx, 1);
26228 gen_helper_di(t0, cpu_env);
26229 gen_store_gpr(t0, rt);
26230 /* Stop translation as we may have switched
26231 the execution mode. */
26232 ctx->base.is_jmp = DISAS_STOP;
26233 break;
26234 case OPC_EI:
26235 check_insn(ctx, ISA_MIPS32R2);
26236 save_cpu_state(ctx, 1);
26237 gen_helper_ei(t0, cpu_env);
26238 gen_store_gpr(t0, rt);
26239 /* DISAS_STOP isn't sufficient, we need to ensure we break
26240 out of translated code to check for pending interrupts */
26241 gen_save_pc(ctx->base.pc_next + 4);
26242 ctx->base.is_jmp = DISAS_EXIT;
26243 break;
26244 default: /* Invalid */
26245 MIPS_INVAL("mfmc0");
26246 generate_exception_end(ctx, EXCP_RI);
26247 break;
26249 tcg_temp_free(t0);
26251 #endif /* !CONFIG_USER_ONLY */
26252 break;
26253 case OPC_RDPGPR:
26254 check_insn(ctx, ISA_MIPS32R2);
26255 gen_load_srsgpr(rt, rd);
26256 break;
26257 case OPC_WRPGPR:
26258 check_insn(ctx, ISA_MIPS32R2);
26259 gen_store_srsgpr(rt, rd);
26260 break;
26261 default:
26262 MIPS_INVAL("cp0");
26263 generate_exception_end(ctx, EXCP_RI);
26264 break;
26266 break;
26267 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
26268 if (ctx->insn_flags & ISA_MIPS32R6) {
26269 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
26270 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26271 } else {
26272 /* OPC_ADDI */
26273 /* Arithmetic with immediate opcode */
26274 gen_arith_imm(ctx, op, rt, rs, imm);
26276 break;
26277 case OPC_ADDIU:
26278 gen_arith_imm(ctx, op, rt, rs, imm);
26279 break;
26280 case OPC_SLTI: /* Set on less than with immediate opcode */
26281 case OPC_SLTIU:
26282 gen_slt_imm(ctx, op, rt, rs, imm);
26283 break;
26284 case OPC_ANDI: /* Arithmetic with immediate opcode */
26285 case OPC_LUI: /* OPC_AUI */
26286 case OPC_ORI:
26287 case OPC_XORI:
26288 gen_logic_imm(ctx, op, rt, rs, imm);
26289 break;
26290 case OPC_J: /* Jump */
26291 case OPC_JAL:
26292 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26293 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26294 break;
26295 /* Branch */
26296 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
26297 if (ctx->insn_flags & ISA_MIPS32R6) {
26298 if (rt == 0) {
26299 generate_exception_end(ctx, EXCP_RI);
26300 break;
26302 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
26303 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26304 } else {
26305 /* OPC_BLEZL */
26306 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26308 break;
26309 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
26310 if (ctx->insn_flags & ISA_MIPS32R6) {
26311 if (rt == 0) {
26312 generate_exception_end(ctx, EXCP_RI);
26313 break;
26315 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
26316 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26317 } else {
26318 /* OPC_BGTZL */
26319 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26321 break;
26322 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
26323 if (rt == 0) {
26324 /* OPC_BLEZ */
26325 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26326 } else {
26327 check_insn(ctx, ISA_MIPS32R6);
26328 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
26329 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26331 break;
26332 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
26333 if (rt == 0) {
26334 /* OPC_BGTZ */
26335 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26336 } else {
26337 check_insn(ctx, ISA_MIPS32R6);
26338 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
26339 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26341 break;
26342 case OPC_BEQL:
26343 case OPC_BNEL:
26344 check_insn(ctx, ISA_MIPS2);
26345 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26346 /* Fallthrough */
26347 case OPC_BEQ:
26348 case OPC_BNE:
26349 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26350 break;
26351 case OPC_LL: /* Load and stores */
26352 check_insn(ctx, ISA_MIPS2);
26353 /* Fallthrough */
26354 case OPC_LWL:
26355 case OPC_LWR:
26356 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26357 /* Fallthrough */
26358 case OPC_LB:
26359 case OPC_LH:
26360 case OPC_LW:
26361 case OPC_LWPC:
26362 case OPC_LBU:
26363 case OPC_LHU:
26364 gen_ld(ctx, op, rt, rs, imm);
26365 break;
26366 case OPC_SWL:
26367 case OPC_SWR:
26368 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26369 /* fall through */
26370 case OPC_SB:
26371 case OPC_SH:
26372 case OPC_SW:
26373 gen_st(ctx, op, rt, rs, imm);
26374 break;
26375 case OPC_SC:
26376 check_insn(ctx, ISA_MIPS2);
26377 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26378 gen_st_cond(ctx, op, rt, rs, imm);
26379 break;
26380 case OPC_CACHE:
26381 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26382 check_cp0_enabled(ctx);
26383 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
26384 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26385 gen_cache_operation(ctx, rt, rs, imm);
26387 /* Treat as NOP. */
26388 break;
26389 case OPC_PREF:
26390 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26391 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
26392 /* Treat as NOP. */
26393 break;
26395 /* Floating point (COP1). */
26396 case OPC_LWC1:
26397 case OPC_LDC1:
26398 case OPC_SWC1:
26399 case OPC_SDC1:
26400 gen_cop1_ldst(ctx, op, rt, rs, imm);
26401 break;
26403 case OPC_CP1:
26404 op1 = MASK_CP1(ctx->opcode);
26406 switch (op1) {
26407 case OPC_MFHC1:
26408 case OPC_MTHC1:
26409 check_cp1_enabled(ctx);
26410 check_insn(ctx, ISA_MIPS32R2);
26411 /* fall through */
26412 case OPC_MFC1:
26413 case OPC_CFC1:
26414 case OPC_MTC1:
26415 case OPC_CTC1:
26416 check_cp1_enabled(ctx);
26417 gen_cp1(ctx, op1, rt, rd);
26418 break;
26419 #if defined(TARGET_MIPS64)
26420 case OPC_DMFC1:
26421 case OPC_DMTC1:
26422 check_cp1_enabled(ctx);
26423 check_insn(ctx, ISA_MIPS3);
26424 check_mips_64(ctx);
26425 gen_cp1(ctx, op1, rt, rd);
26426 break;
26427 #endif
26428 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
26429 check_cp1_enabled(ctx);
26430 if (ctx->insn_flags & ISA_MIPS32R6) {
26431 /* OPC_BC1EQZ */
26432 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26433 rt, imm << 2, 4);
26434 } else {
26435 /* OPC_BC1ANY2 */
26436 check_cop1x(ctx);
26437 check_insn(ctx, ASE_MIPS3D);
26438 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26439 (rt >> 2) & 0x7, imm << 2);
26441 break;
26442 case OPC_BC1NEZ:
26443 check_cp1_enabled(ctx);
26444 check_insn(ctx, ISA_MIPS32R6);
26445 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26446 rt, imm << 2, 4);
26447 break;
26448 case OPC_BC1ANY4:
26449 check_cp1_enabled(ctx);
26450 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26451 check_cop1x(ctx);
26452 check_insn(ctx, ASE_MIPS3D);
26453 /* fall through */
26454 case OPC_BC1:
26455 check_cp1_enabled(ctx);
26456 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26457 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26458 (rt >> 2) & 0x7, imm << 2);
26459 break;
26460 case OPC_PS_FMT:
26461 check_ps(ctx);
26462 /* fall through */
26463 case OPC_S_FMT:
26464 case OPC_D_FMT:
26465 check_cp1_enabled(ctx);
26466 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26467 (imm >> 8) & 0x7);
26468 break;
26469 case OPC_W_FMT:
26470 case OPC_L_FMT:
26472 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
26473 check_cp1_enabled(ctx);
26474 if (ctx->insn_flags & ISA_MIPS32R6) {
26475 switch (r6_op) {
26476 case R6_OPC_CMP_AF_S:
26477 case R6_OPC_CMP_UN_S:
26478 case R6_OPC_CMP_EQ_S:
26479 case R6_OPC_CMP_UEQ_S:
26480 case R6_OPC_CMP_LT_S:
26481 case R6_OPC_CMP_ULT_S:
26482 case R6_OPC_CMP_LE_S:
26483 case R6_OPC_CMP_ULE_S:
26484 case R6_OPC_CMP_SAF_S:
26485 case R6_OPC_CMP_SUN_S:
26486 case R6_OPC_CMP_SEQ_S:
26487 case R6_OPC_CMP_SEUQ_S:
26488 case R6_OPC_CMP_SLT_S:
26489 case R6_OPC_CMP_SULT_S:
26490 case R6_OPC_CMP_SLE_S:
26491 case R6_OPC_CMP_SULE_S:
26492 case R6_OPC_CMP_OR_S:
26493 case R6_OPC_CMP_UNE_S:
26494 case R6_OPC_CMP_NE_S:
26495 case R6_OPC_CMP_SOR_S:
26496 case R6_OPC_CMP_SUNE_S:
26497 case R6_OPC_CMP_SNE_S:
26498 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26499 break;
26500 case R6_OPC_CMP_AF_D:
26501 case R6_OPC_CMP_UN_D:
26502 case R6_OPC_CMP_EQ_D:
26503 case R6_OPC_CMP_UEQ_D:
26504 case R6_OPC_CMP_LT_D:
26505 case R6_OPC_CMP_ULT_D:
26506 case R6_OPC_CMP_LE_D:
26507 case R6_OPC_CMP_ULE_D:
26508 case R6_OPC_CMP_SAF_D:
26509 case R6_OPC_CMP_SUN_D:
26510 case R6_OPC_CMP_SEQ_D:
26511 case R6_OPC_CMP_SEUQ_D:
26512 case R6_OPC_CMP_SLT_D:
26513 case R6_OPC_CMP_SULT_D:
26514 case R6_OPC_CMP_SLE_D:
26515 case R6_OPC_CMP_SULE_D:
26516 case R6_OPC_CMP_OR_D:
26517 case R6_OPC_CMP_UNE_D:
26518 case R6_OPC_CMP_NE_D:
26519 case R6_OPC_CMP_SOR_D:
26520 case R6_OPC_CMP_SUNE_D:
26521 case R6_OPC_CMP_SNE_D:
26522 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26523 break;
26524 default:
26525 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
26526 rt, rd, sa, (imm >> 8) & 0x7);
26528 break;
26530 } else {
26531 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26532 (imm >> 8) & 0x7);
26534 break;
26536 case OPC_BZ_V:
26537 case OPC_BNZ_V:
26538 case OPC_BZ_B:
26539 case OPC_BZ_H:
26540 case OPC_BZ_W:
26541 case OPC_BZ_D:
26542 case OPC_BNZ_B:
26543 case OPC_BNZ_H:
26544 case OPC_BNZ_W:
26545 case OPC_BNZ_D:
26546 check_insn(ctx, ASE_MSA);
26547 gen_msa_branch(env, ctx, op1);
26548 break;
26549 default:
26550 MIPS_INVAL("cp1");
26551 generate_exception_end(ctx, EXCP_RI);
26552 break;
26554 break;
26556 /* Compact branches [R6] and COP2 [non-R6] */
26557 case OPC_BC: /* OPC_LWC2 */
26558 case OPC_BALC: /* OPC_SWC2 */
26559 if (ctx->insn_flags & ISA_MIPS32R6) {
26560 /* OPC_BC, OPC_BALC */
26561 gen_compute_compact_branch(ctx, op, 0, 0,
26562 sextract32(ctx->opcode << 2, 0, 28));
26563 } else {
26564 /* OPC_LWC2, OPC_SWC2 */
26565 /* COP2: Not implemented. */
26566 generate_exception_err(ctx, EXCP_CpU, 2);
26568 break;
26569 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
26570 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
26571 if (ctx->insn_flags & ISA_MIPS32R6) {
26572 if (rs != 0) {
26573 /* OPC_BEQZC, OPC_BNEZC */
26574 gen_compute_compact_branch(ctx, op, rs, 0,
26575 sextract32(ctx->opcode << 2, 0, 23));
26576 } else {
26577 /* OPC_JIC, OPC_JIALC */
26578 gen_compute_compact_branch(ctx, op, 0, rt, imm);
26580 } else {
26581 /* OPC_LWC2, OPC_SWC2 */
26582 /* COP2: Not implemented. */
26583 generate_exception_err(ctx, EXCP_CpU, 2);
26585 break;
26586 case OPC_CP2:
26587 check_insn(ctx, INSN_LOONGSON2F);
26588 /* Note that these instructions use different fields. */
26589 gen_loongson_multimedia(ctx, sa, rd, rt);
26590 break;
26592 case OPC_CP3:
26593 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26594 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26595 check_cp1_enabled(ctx);
26596 op1 = MASK_CP3(ctx->opcode);
26597 switch (op1) {
26598 case OPC_LUXC1:
26599 case OPC_SUXC1:
26600 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26601 /* Fallthrough */
26602 case OPC_LWXC1:
26603 case OPC_LDXC1:
26604 case OPC_SWXC1:
26605 case OPC_SDXC1:
26606 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26607 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
26608 break;
26609 case OPC_PREFX:
26610 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26611 /* Treat as NOP. */
26612 break;
26613 case OPC_ALNV_PS:
26614 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26615 /* Fallthrough */
26616 case OPC_MADD_S:
26617 case OPC_MADD_D:
26618 case OPC_MADD_PS:
26619 case OPC_MSUB_S:
26620 case OPC_MSUB_D:
26621 case OPC_MSUB_PS:
26622 case OPC_NMADD_S:
26623 case OPC_NMADD_D:
26624 case OPC_NMADD_PS:
26625 case OPC_NMSUB_S:
26626 case OPC_NMSUB_D:
26627 case OPC_NMSUB_PS:
26628 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26629 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
26630 break;
26631 default:
26632 MIPS_INVAL("cp3");
26633 generate_exception_end(ctx, EXCP_RI);
26634 break;
26636 } else {
26637 generate_exception_err(ctx, EXCP_CpU, 1);
26639 break;
26641 #if defined(TARGET_MIPS64)
26642 /* MIPS64 opcodes */
26643 case OPC_LDL:
26644 case OPC_LDR:
26645 case OPC_LLD:
26646 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26647 /* fall through */
26648 case OPC_LWU:
26649 case OPC_LD:
26650 check_insn(ctx, ISA_MIPS3);
26651 check_mips_64(ctx);
26652 gen_ld(ctx, op, rt, rs, imm);
26653 break;
26654 case OPC_SDL:
26655 case OPC_SDR:
26656 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26657 /* fall through */
26658 case OPC_SD:
26659 check_insn(ctx, ISA_MIPS3);
26660 check_mips_64(ctx);
26661 gen_st(ctx, op, rt, rs, imm);
26662 break;
26663 case OPC_SCD:
26664 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26665 check_insn(ctx, ISA_MIPS3);
26666 check_mips_64(ctx);
26667 gen_st_cond(ctx, op, rt, rs, imm);
26668 break;
26669 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
26670 if (ctx->insn_flags & ISA_MIPS32R6) {
26671 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
26672 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26673 } else {
26674 /* OPC_DADDI */
26675 check_insn(ctx, ISA_MIPS3);
26676 check_mips_64(ctx);
26677 gen_arith_imm(ctx, op, rt, rs, imm);
26679 break;
26680 case OPC_DADDIU:
26681 check_insn(ctx, ISA_MIPS3);
26682 check_mips_64(ctx);
26683 gen_arith_imm(ctx, op, rt, rs, imm);
26684 break;
26685 #else
26686 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
26687 if (ctx->insn_flags & ISA_MIPS32R6) {
26688 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26689 } else {
26690 MIPS_INVAL("major opcode");
26691 generate_exception_end(ctx, EXCP_RI);
26693 break;
26694 #endif
26695 case OPC_DAUI: /* OPC_JALX */
26696 if (ctx->insn_flags & ISA_MIPS32R6) {
26697 #if defined(TARGET_MIPS64)
26698 /* OPC_DAUI */
26699 check_mips_64(ctx);
26700 if (rs == 0) {
26701 generate_exception(ctx, EXCP_RI);
26702 } else if (rt != 0) {
26703 TCGv t0 = tcg_temp_new();
26704 gen_load_gpr(t0, rs);
26705 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
26706 tcg_temp_free(t0);
26708 #else
26709 generate_exception_end(ctx, EXCP_RI);
26710 MIPS_INVAL("major opcode");
26711 #endif
26712 } else {
26713 /* OPC_JALX */
26714 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26715 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26716 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26718 break;
26719 case OPC_MSA: /* OPC_MDMX */
26720 if (ctx->insn_flags & INSN_R5900) {
26721 decode_tx79_lq(env, ctx); /* TX79_LQ */
26722 } else {
26723 /* MDMX: Not implemented. */
26724 gen_msa(env, ctx);
26726 break;
26727 case OPC_PCREL:
26728 check_insn(ctx, ISA_MIPS32R6);
26729 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
26730 break;
26731 default: /* Invalid */
26732 MIPS_INVAL("major opcode");
26733 generate_exception_end(ctx, EXCP_RI);
26734 break;
26738 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
26740 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26741 CPUMIPSState *env = cs->env_ptr;
26743 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
26744 ctx->saved_pc = -1;
26745 ctx->insn_flags = env->insn_flags;
26746 ctx->CP0_Config1 = env->CP0_Config1;
26747 ctx->CP0_Config2 = env->CP0_Config2;
26748 ctx->CP0_Config3 = env->CP0_Config3;
26749 ctx->CP0_Config5 = env->CP0_Config5;
26750 ctx->btarget = 0;
26751 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26752 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26753 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26754 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26755 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26756 ctx->PAMask = env->PAMask;
26757 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26758 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26759 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26760 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26761 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
26762 /* Restore delay slot state from the tb context. */
26763 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26764 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26765 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
26766 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
26767 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26768 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26769 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26770 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26771 restore_cpu_state(env, ctx);
26772 #ifdef CONFIG_USER_ONLY
26773 ctx->mem_idx = MIPS_HFLAG_UM;
26774 #else
26775 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
26776 #endif
26777 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
26778 MO_UNALN : MO_ALIGN;
26780 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26781 ctx->hflags);
26784 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26788 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26790 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26792 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26793 ctx->btarget);
26796 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26797 const CPUBreakpoint *bp)
26799 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26801 save_cpu_state(ctx, 1);
26802 ctx->base.is_jmp = DISAS_NORETURN;
26803 gen_helper_raise_exception_debug(cpu_env);
26804 /* The address covered by the breakpoint must be included in
26805 [tb->pc, tb->pc + tb->size) in order to for it to be
26806 properly cleared -- thus we increment the PC here so that
26807 the logic setting tb->size below does the right thing. */
26808 ctx->base.pc_next += 4;
26809 return true;
26812 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26814 CPUMIPSState *env = cs->env_ptr;
26815 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26816 int insn_bytes;
26817 int is_slot;
26819 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26820 if (ctx->insn_flags & ISA_NANOMIPS32) {
26821 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26822 insn_bytes = decode_nanomips_opc(env, ctx);
26823 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26824 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
26825 insn_bytes = 4;
26826 decode_opc(env, ctx);
26827 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26828 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26829 insn_bytes = decode_micromips_opc(env, ctx);
26830 } else if (ctx->insn_flags & ASE_MIPS16) {
26831 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26832 insn_bytes = decode_mips16_opc(env, ctx);
26833 } else {
26834 generate_exception_end(ctx, EXCP_RI);
26835 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26836 return;
26839 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26840 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26841 MIPS_HFLAG_FBNSLOT))) {
26842 /* force to generate branch as there is neither delay nor
26843 forbidden slot */
26844 is_slot = 1;
26846 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26847 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26848 /* Force to generate branch as microMIPS R6 doesn't restrict
26849 branches in the forbidden slot. */
26850 is_slot = 1;
26853 if (is_slot) {
26854 gen_branch(ctx, insn_bytes);
26856 ctx->base.pc_next += insn_bytes;
26858 if (ctx->base.is_jmp != DISAS_NEXT) {
26859 return;
26861 /* Execute a branch and its delay slot as a single instruction.
26862 This is what GDB expects and is consistent with what the
26863 hardware does (e.g. if a delay slot instruction faults, the
26864 reported PC is the PC of the branch). */
26865 if (ctx->base.singlestep_enabled &&
26866 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26867 ctx->base.is_jmp = DISAS_TOO_MANY;
26869 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26870 ctx->base.is_jmp = DISAS_TOO_MANY;
26874 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26876 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26878 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26879 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26880 gen_helper_raise_exception_debug(cpu_env);
26881 } else {
26882 switch (ctx->base.is_jmp) {
26883 case DISAS_STOP:
26884 gen_save_pc(ctx->base.pc_next);
26885 tcg_gen_lookup_and_goto_ptr();
26886 break;
26887 case DISAS_NEXT:
26888 case DISAS_TOO_MANY:
26889 save_cpu_state(ctx, 0);
26890 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26891 break;
26892 case DISAS_EXIT:
26893 tcg_gen_exit_tb(NULL, 0);
26894 break;
26895 case DISAS_NORETURN:
26896 break;
26897 default:
26898 g_assert_not_reached();
26903 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26905 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26906 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26909 static const TranslatorOps mips_tr_ops = {
26910 .init_disas_context = mips_tr_init_disas_context,
26911 .tb_start = mips_tr_tb_start,
26912 .insn_start = mips_tr_insn_start,
26913 .breakpoint_check = mips_tr_breakpoint_check,
26914 .translate_insn = mips_tr_translate_insn,
26915 .tb_stop = mips_tr_tb_stop,
26916 .disas_log = mips_tr_disas_log,
26919 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
26921 DisasContext ctx;
26923 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
26926 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
26927 int flags)
26929 int i;
26930 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26932 #define printfpr(fp) \
26933 do { \
26934 if (is_fpu64) \
26935 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26936 " fd:%13g fs:%13g psu: %13g\n", \
26937 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26938 (double)(fp)->fd, \
26939 (double)(fp)->fs[FP_ENDIAN_IDX], \
26940 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26941 else { \
26942 fpr_t tmp; \
26943 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
26944 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
26945 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26946 " fd:%13g fs:%13g psu:%13g\n", \
26947 tmp.w[FP_ENDIAN_IDX], tmp.d, \
26948 (double)tmp.fd, \
26949 (double)tmp.fs[FP_ENDIAN_IDX], \
26950 (double)tmp.fs[!FP_ENDIAN_IDX]); \
26952 } while(0)
26955 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
26956 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
26957 get_float_exception_flags(&env->active_fpu.fp_status));
26958 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
26959 fpu_fprintf(f, "%3s: ", fregnames[i]);
26960 printfpr(&env->active_fpu.fpr[i]);
26963 #undef printfpr
26966 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
26967 int flags)
26969 MIPSCPU *cpu = MIPS_CPU(cs);
26970 CPUMIPSState *env = &cpu->env;
26971 int i;
26973 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
26974 " LO=0x" TARGET_FMT_lx " ds %04x "
26975 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
26976 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
26977 env->hflags, env->btarget, env->bcond);
26978 for (i = 0; i < 32; i++) {
26979 if ((i & 3) == 0)
26980 cpu_fprintf(f, "GPR%02d:", i);
26981 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
26982 if ((i & 3) == 3)
26983 cpu_fprintf(f, "\n");
26986 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
26987 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
26988 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
26989 PRIx64 "\n",
26990 env->CP0_Config0, env->CP0_Config1, env->lladdr);
26991 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
26992 env->CP0_Config2, env->CP0_Config3);
26993 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
26994 env->CP0_Config4, env->CP0_Config5);
26995 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
26996 fpu_dump_state(env, f, cpu_fprintf, flags);
27000 void mips_tcg_init(void)
27002 int i;
27004 cpu_gpr[0] = NULL;
27005 for (i = 1; i < 32; i++)
27006 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
27007 offsetof(CPUMIPSState, active_tc.gpr[i]),
27008 regnames[i]);
27010 for (i = 0; i < 32; i++) {
27011 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
27012 msa_wr_d[i * 2] =
27013 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
27014 /* The scalar floating-point unit (FPU) registers are mapped on
27015 * the MSA vector registers. */
27016 fpu_f64[i] = msa_wr_d[i * 2];
27017 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
27018 msa_wr_d[i * 2 + 1] =
27019 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
27022 cpu_PC = tcg_global_mem_new(cpu_env,
27023 offsetof(CPUMIPSState, active_tc.PC), "PC");
27024 for (i = 0; i < MIPS_DSP_ACC; i++) {
27025 cpu_HI[i] = tcg_global_mem_new(cpu_env,
27026 offsetof(CPUMIPSState, active_tc.HI[i]),
27027 regnames_HI[i]);
27028 cpu_LO[i] = tcg_global_mem_new(cpu_env,
27029 offsetof(CPUMIPSState, active_tc.LO[i]),
27030 regnames_LO[i]);
27032 cpu_dspctrl = tcg_global_mem_new(cpu_env,
27033 offsetof(CPUMIPSState, active_tc.DSPControl),
27034 "DSPControl");
27035 bcond = tcg_global_mem_new(cpu_env,
27036 offsetof(CPUMIPSState, bcond), "bcond");
27037 btarget = tcg_global_mem_new(cpu_env,
27038 offsetof(CPUMIPSState, btarget), "btarget");
27039 hflags = tcg_global_mem_new_i32(cpu_env,
27040 offsetof(CPUMIPSState, hflags), "hflags");
27042 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
27043 offsetof(CPUMIPSState, active_fpu.fcr0),
27044 "fcr0");
27045 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
27046 offsetof(CPUMIPSState, active_fpu.fcr31),
27047 "fcr31");
27050 #include "translate_init.inc.c"
27052 void cpu_mips_realize_env(CPUMIPSState *env)
27054 env->exception_base = (int32_t)0xBFC00000;
27056 #ifndef CONFIG_USER_ONLY
27057 mmu_init(env, env->cpu_model);
27058 #endif
27059 fpu_init(env, env->cpu_model);
27060 mvp_init(env, env->cpu_model);
27063 bool cpu_supports_cps_smp(const char *cpu_type)
27065 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27066 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
27069 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
27071 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27072 return (mcc->cpu_def->insn_flags & isa) != 0;
27075 void cpu_set_exception_base(int vp_index, target_ulong address)
27077 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
27078 vp->env.exception_base = address;
27081 void cpu_state_reset(CPUMIPSState *env)
27083 MIPSCPU *cpu = mips_env_get_cpu(env);
27084 CPUState *cs = CPU(cpu);
27086 /* Reset registers to their default values */
27087 env->CP0_PRid = env->cpu_model->CP0_PRid;
27088 env->CP0_Config0 = env->cpu_model->CP0_Config0;
27089 #ifdef TARGET_WORDS_BIGENDIAN
27090 env->CP0_Config0 |= (1 << CP0C0_BE);
27091 #endif
27092 env->CP0_Config1 = env->cpu_model->CP0_Config1;
27093 env->CP0_Config2 = env->cpu_model->CP0_Config2;
27094 env->CP0_Config3 = env->cpu_model->CP0_Config3;
27095 env->CP0_Config4 = env->cpu_model->CP0_Config4;
27096 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
27097 env->CP0_Config5 = env->cpu_model->CP0_Config5;
27098 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
27099 env->CP0_Config6 = env->cpu_model->CP0_Config6;
27100 env->CP0_Config7 = env->cpu_model->CP0_Config7;
27101 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
27102 << env->cpu_model->CP0_LLAddr_shift;
27103 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
27104 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
27105 env->CCRes = env->cpu_model->CCRes;
27106 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
27107 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
27108 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
27109 env->current_tc = 0;
27110 env->SEGBITS = env->cpu_model->SEGBITS;
27111 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
27112 #if defined(TARGET_MIPS64)
27113 if (env->cpu_model->insn_flags & ISA_MIPS3) {
27114 env->SEGMask |= 3ULL << 62;
27116 #endif
27117 env->PABITS = env->cpu_model->PABITS;
27118 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
27119 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
27120 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
27121 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
27122 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
27123 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
27124 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
27125 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
27126 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
27127 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
27128 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
27129 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
27130 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
27131 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
27132 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
27133 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
27134 env->msair = env->cpu_model->MSAIR;
27135 env->insn_flags = env->cpu_model->insn_flags;
27137 #if defined(CONFIG_USER_ONLY)
27138 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
27139 # ifdef TARGET_MIPS64
27140 /* Enable 64-bit register mode. */
27141 env->CP0_Status |= (1 << CP0St_PX);
27142 # endif
27143 # ifdef TARGET_ABI_MIPSN64
27144 /* Enable 64-bit address mode. */
27145 env->CP0_Status |= (1 << CP0St_UX);
27146 # endif
27147 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
27148 hardware registers. */
27149 env->CP0_HWREna |= 0x0000000F;
27150 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
27151 env->CP0_Status |= (1 << CP0St_CU1);
27153 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
27154 env->CP0_Status |= (1 << CP0St_MX);
27156 # if defined(TARGET_MIPS64)
27157 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
27158 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
27159 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
27160 env->CP0_Status |= (1 << CP0St_FR);
27162 # endif
27163 #else
27164 if (env->hflags & MIPS_HFLAG_BMASK) {
27165 /* If the exception was raised from a delay slot,
27166 come back to the jump. */
27167 env->CP0_ErrorEPC = (env->active_tc.PC
27168 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
27169 } else {
27170 env->CP0_ErrorEPC = env->active_tc.PC;
27172 env->active_tc.PC = env->exception_base;
27173 env->CP0_Random = env->tlb->nb_tlb - 1;
27174 env->tlb->tlb_in_use = env->tlb->nb_tlb;
27175 env->CP0_Wired = 0;
27176 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
27177 env->CP0_EBase = (cs->cpu_index & 0x3FF);
27178 if (mips_um_ksegs_enabled()) {
27179 env->CP0_EBase |= 0x40000000;
27180 } else {
27181 env->CP0_EBase |= (int32_t)0x80000000;
27183 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
27184 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
27186 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
27187 0x3ff : 0xff;
27188 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
27189 /* vectored interrupts not implemented, timer on int 7,
27190 no performance counters. */
27191 env->CP0_IntCtl = 0xe0000000;
27193 int i;
27195 for (i = 0; i < 7; i++) {
27196 env->CP0_WatchLo[i] = 0;
27197 env->CP0_WatchHi[i] = 0x80000000;
27199 env->CP0_WatchLo[7] = 0;
27200 env->CP0_WatchHi[7] = 0;
27202 /* Count register increments in debug mode, EJTAG version 1 */
27203 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
27205 cpu_mips_store_count(env, 1);
27207 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
27208 int i;
27210 /* Only TC0 on VPE 0 starts as active. */
27211 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
27212 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
27213 env->tcs[i].CP0_TCHalt = 1;
27215 env->active_tc.CP0_TCHalt = 1;
27216 cs->halted = 1;
27218 if (cs->cpu_index == 0) {
27219 /* VPE0 starts up enabled. */
27220 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
27221 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
27223 /* TC0 starts up unhalted. */
27224 cs->halted = 0;
27225 env->active_tc.CP0_TCHalt = 0;
27226 env->tcs[0].CP0_TCHalt = 0;
27227 /* With thread 0 active. */
27228 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
27229 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
27234 * Configure default legacy segmentation control. We use this regardless of
27235 * whether segmentation control is presented to the guest.
27237 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
27238 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
27239 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
27240 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
27241 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
27242 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27243 (2 << CP0SC_C);
27244 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
27245 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27246 (3 << CP0SC_C)) << 16;
27247 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
27248 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27249 (1 << CP0SC_EU) | (2 << CP0SC_C);
27250 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
27251 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27252 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
27253 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
27254 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
27255 #endif
27256 if ((env->insn_flags & ISA_MIPS32R6) &&
27257 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
27258 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
27259 env->CP0_Status |= (1 << CP0St_FR);
27262 if (env->insn_flags & ISA_MIPS32R6) {
27263 /* PTW = 1 */
27264 env->CP0_PWSize = 0x40;
27265 /* GDI = 12 */
27266 /* UDI = 12 */
27267 /* MDI = 12 */
27268 /* PRI = 12 */
27269 /* PTEI = 2 */
27270 env->CP0_PWField = 0x0C30C302;
27271 } else {
27272 /* GDI = 0 */
27273 /* UDI = 0 */
27274 /* MDI = 0 */
27275 /* PRI = 0 */
27276 /* PTEI = 2 */
27277 env->CP0_PWField = 0x02;
27280 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
27281 /* microMIPS on reset when Config3.ISA is 3 */
27282 env->hflags |= MIPS_HFLAG_M16;
27285 /* MSA */
27286 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
27287 msa_reset(env);
27290 compute_hflags(env);
27291 restore_fp_status(env);
27292 restore_pamask(env);
27293 cs->exception_index = EXCP_NONE;
27295 if (semihosting_get_argc()) {
27296 /* UHI interface can be used to obtain argc and argv */
27297 env->active_tc.gpr[4] = -1;
27301 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
27302 target_ulong *data)
27304 env->active_tc.PC = data[0];
27305 env->hflags &= ~MIPS_HFLAG_BMASK;
27306 env->hflags |= data[1];
27307 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
27308 case MIPS_HFLAG_BR:
27309 break;
27310 case MIPS_HFLAG_BC:
27311 case MIPS_HFLAG_BL:
27312 case MIPS_HFLAG_B:
27313 env->btarget = data[2];
27314 break;