target/mips: Support R5900 MFLO1, MTLO1, MFHI1 and MTHI1 instructions
[qemu/ar7.git] / target / mips / translate.c
blobd7d7145f84f8107acf598d4f0a1cd58a3d01d095
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 check_dsp(ctx);
4599 switch (opc) {
4600 case OPC_DIV:
4602 TCGv t2 = tcg_temp_new();
4603 TCGv t3 = tcg_temp_new();
4604 tcg_gen_ext32s_tl(t0, t0);
4605 tcg_gen_ext32s_tl(t1, t1);
4606 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4607 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4608 tcg_gen_and_tl(t2, t2, t3);
4609 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4610 tcg_gen_or_tl(t2, t2, t3);
4611 tcg_gen_movi_tl(t3, 0);
4612 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4613 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4614 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4615 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4616 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4617 tcg_temp_free(t3);
4618 tcg_temp_free(t2);
4620 break;
4621 case OPC_DIVU:
4623 TCGv t2 = tcg_const_tl(0);
4624 TCGv t3 = tcg_const_tl(1);
4625 tcg_gen_ext32u_tl(t0, t0);
4626 tcg_gen_ext32u_tl(t1, t1);
4627 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4628 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4629 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4630 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4631 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4632 tcg_temp_free(t3);
4633 tcg_temp_free(t2);
4635 break;
4636 case OPC_MULT:
4638 TCGv_i32 t2 = tcg_temp_new_i32();
4639 TCGv_i32 t3 = tcg_temp_new_i32();
4640 tcg_gen_trunc_tl_i32(t2, t0);
4641 tcg_gen_trunc_tl_i32(t3, t1);
4642 tcg_gen_muls2_i32(t2, t3, t2, t3);
4643 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4644 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4645 tcg_temp_free_i32(t2);
4646 tcg_temp_free_i32(t3);
4648 break;
4649 case OPC_MULTU:
4651 TCGv_i32 t2 = tcg_temp_new_i32();
4652 TCGv_i32 t3 = tcg_temp_new_i32();
4653 tcg_gen_trunc_tl_i32(t2, t0);
4654 tcg_gen_trunc_tl_i32(t3, t1);
4655 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4656 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4657 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4658 tcg_temp_free_i32(t2);
4659 tcg_temp_free_i32(t3);
4661 break;
4662 #if defined(TARGET_MIPS64)
4663 case OPC_DDIV:
4665 TCGv t2 = tcg_temp_new();
4666 TCGv t3 = tcg_temp_new();
4667 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4668 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4669 tcg_gen_and_tl(t2, t2, t3);
4670 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4671 tcg_gen_or_tl(t2, t2, t3);
4672 tcg_gen_movi_tl(t3, 0);
4673 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4674 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4675 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4676 tcg_temp_free(t3);
4677 tcg_temp_free(t2);
4679 break;
4680 case OPC_DDIVU:
4682 TCGv t2 = tcg_const_tl(0);
4683 TCGv t3 = tcg_const_tl(1);
4684 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4685 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4686 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4687 tcg_temp_free(t3);
4688 tcg_temp_free(t2);
4690 break;
4691 case OPC_DMULT:
4692 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4693 break;
4694 case OPC_DMULTU:
4695 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4696 break;
4697 #endif
4698 case OPC_MADD:
4700 TCGv_i64 t2 = tcg_temp_new_i64();
4701 TCGv_i64 t3 = tcg_temp_new_i64();
4703 tcg_gen_ext_tl_i64(t2, t0);
4704 tcg_gen_ext_tl_i64(t3, t1);
4705 tcg_gen_mul_i64(t2, t2, t3);
4706 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4707 tcg_gen_add_i64(t2, t2, t3);
4708 tcg_temp_free_i64(t3);
4709 gen_move_low32(cpu_LO[acc], t2);
4710 gen_move_high32(cpu_HI[acc], t2);
4711 tcg_temp_free_i64(t2);
4713 break;
4714 case OPC_MADDU:
4716 TCGv_i64 t2 = tcg_temp_new_i64();
4717 TCGv_i64 t3 = tcg_temp_new_i64();
4719 tcg_gen_ext32u_tl(t0, t0);
4720 tcg_gen_ext32u_tl(t1, t1);
4721 tcg_gen_extu_tl_i64(t2, t0);
4722 tcg_gen_extu_tl_i64(t3, t1);
4723 tcg_gen_mul_i64(t2, t2, t3);
4724 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4725 tcg_gen_add_i64(t2, t2, t3);
4726 tcg_temp_free_i64(t3);
4727 gen_move_low32(cpu_LO[acc], t2);
4728 gen_move_high32(cpu_HI[acc], t2);
4729 tcg_temp_free_i64(t2);
4731 break;
4732 case OPC_MSUB:
4734 TCGv_i64 t2 = tcg_temp_new_i64();
4735 TCGv_i64 t3 = tcg_temp_new_i64();
4737 tcg_gen_ext_tl_i64(t2, t0);
4738 tcg_gen_ext_tl_i64(t3, t1);
4739 tcg_gen_mul_i64(t2, t2, t3);
4740 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4741 tcg_gen_sub_i64(t2, t3, t2);
4742 tcg_temp_free_i64(t3);
4743 gen_move_low32(cpu_LO[acc], t2);
4744 gen_move_high32(cpu_HI[acc], t2);
4745 tcg_temp_free_i64(t2);
4747 break;
4748 case OPC_MSUBU:
4750 TCGv_i64 t2 = tcg_temp_new_i64();
4751 TCGv_i64 t3 = tcg_temp_new_i64();
4753 tcg_gen_ext32u_tl(t0, t0);
4754 tcg_gen_ext32u_tl(t1, t1);
4755 tcg_gen_extu_tl_i64(t2, t0);
4756 tcg_gen_extu_tl_i64(t3, t1);
4757 tcg_gen_mul_i64(t2, t2, t3);
4758 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4759 tcg_gen_sub_i64(t2, t3, t2);
4760 tcg_temp_free_i64(t3);
4761 gen_move_low32(cpu_LO[acc], t2);
4762 gen_move_high32(cpu_HI[acc], t2);
4763 tcg_temp_free_i64(t2);
4765 break;
4766 default:
4767 MIPS_INVAL("mul/div");
4768 generate_exception_end(ctx, EXCP_RI);
4769 goto out;
4771 out:
4772 tcg_temp_free(t0);
4773 tcg_temp_free(t1);
4777 * These MULT and MULTU instructions implemented in for example the
4778 * Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
4779 * architectures are special three-operand variants with the syntax
4781 * MULT[U][1] rd, rs, rt
4783 * such that
4785 * (rd, LO, HI) <- rs * rt
4787 * where the low-order 32-bits of the result is placed into both the
4788 * GPR rd and the special register LO. The high-order 32-bits of the
4789 * result is placed into the special register HI.
4791 * If the GPR rd is omitted in assembly language, it is taken to be 0,
4792 * which is the zero register that always reads as 0.
4794 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
4795 int rd, int rs, int rt)
4797 TCGv t0 = tcg_temp_new();
4798 TCGv t1 = tcg_temp_new();
4799 int acc = 0;
4801 gen_load_gpr(t0, rs);
4802 gen_load_gpr(t1, rt);
4804 switch (opc) {
4805 case TX79_MMI_MULT1:
4806 acc = 1;
4807 /* Fall through */
4808 case OPC_MULT:
4810 TCGv_i32 t2 = tcg_temp_new_i32();
4811 TCGv_i32 t3 = tcg_temp_new_i32();
4812 tcg_gen_trunc_tl_i32(t2, t0);
4813 tcg_gen_trunc_tl_i32(t3, t1);
4814 tcg_gen_muls2_i32(t2, t3, t2, t3);
4815 if (rd) {
4816 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4818 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4819 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4820 tcg_temp_free_i32(t2);
4821 tcg_temp_free_i32(t3);
4823 break;
4824 case TX79_MMI_MULTU1:
4825 acc = 1;
4826 /* Fall through */
4827 case OPC_MULTU:
4829 TCGv_i32 t2 = tcg_temp_new_i32();
4830 TCGv_i32 t3 = tcg_temp_new_i32();
4831 tcg_gen_trunc_tl_i32(t2, t0);
4832 tcg_gen_trunc_tl_i32(t3, t1);
4833 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4834 if (rd) {
4835 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4837 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4838 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4839 tcg_temp_free_i32(t2);
4840 tcg_temp_free_i32(t3);
4842 break;
4843 default:
4844 MIPS_INVAL("mul TXx9");
4845 generate_exception_end(ctx, EXCP_RI);
4846 goto out;
4849 out:
4850 tcg_temp_free(t0);
4851 tcg_temp_free(t1);
4854 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4855 int rd, int rs, int rt)
4857 TCGv t0 = tcg_temp_new();
4858 TCGv t1 = tcg_temp_new();
4860 gen_load_gpr(t0, rs);
4861 gen_load_gpr(t1, rt);
4863 switch (opc) {
4864 case OPC_VR54XX_MULS:
4865 gen_helper_muls(t0, cpu_env, t0, t1);
4866 break;
4867 case OPC_VR54XX_MULSU:
4868 gen_helper_mulsu(t0, cpu_env, t0, t1);
4869 break;
4870 case OPC_VR54XX_MACC:
4871 gen_helper_macc(t0, cpu_env, t0, t1);
4872 break;
4873 case OPC_VR54XX_MACCU:
4874 gen_helper_maccu(t0, cpu_env, t0, t1);
4875 break;
4876 case OPC_VR54XX_MSAC:
4877 gen_helper_msac(t0, cpu_env, t0, t1);
4878 break;
4879 case OPC_VR54XX_MSACU:
4880 gen_helper_msacu(t0, cpu_env, t0, t1);
4881 break;
4882 case OPC_VR54XX_MULHI:
4883 gen_helper_mulhi(t0, cpu_env, t0, t1);
4884 break;
4885 case OPC_VR54XX_MULHIU:
4886 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4887 break;
4888 case OPC_VR54XX_MULSHI:
4889 gen_helper_mulshi(t0, cpu_env, t0, t1);
4890 break;
4891 case OPC_VR54XX_MULSHIU:
4892 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4893 break;
4894 case OPC_VR54XX_MACCHI:
4895 gen_helper_macchi(t0, cpu_env, t0, t1);
4896 break;
4897 case OPC_VR54XX_MACCHIU:
4898 gen_helper_macchiu(t0, cpu_env, t0, t1);
4899 break;
4900 case OPC_VR54XX_MSACHI:
4901 gen_helper_msachi(t0, cpu_env, t0, t1);
4902 break;
4903 case OPC_VR54XX_MSACHIU:
4904 gen_helper_msachiu(t0, cpu_env, t0, t1);
4905 break;
4906 default:
4907 MIPS_INVAL("mul vr54xx");
4908 generate_exception_end(ctx, EXCP_RI);
4909 goto out;
4911 gen_store_gpr(t0, rd);
4913 out:
4914 tcg_temp_free(t0);
4915 tcg_temp_free(t1);
4918 static void gen_cl (DisasContext *ctx, uint32_t opc,
4919 int rd, int rs)
4921 TCGv t0;
4923 if (rd == 0) {
4924 /* Treat as NOP. */
4925 return;
4927 t0 = cpu_gpr[rd];
4928 gen_load_gpr(t0, rs);
4930 switch (opc) {
4931 case OPC_CLO:
4932 case R6_OPC_CLO:
4933 #if defined(TARGET_MIPS64)
4934 case OPC_DCLO:
4935 case R6_OPC_DCLO:
4936 #endif
4937 tcg_gen_not_tl(t0, t0);
4938 break;
4941 switch (opc) {
4942 case OPC_CLO:
4943 case R6_OPC_CLO:
4944 case OPC_CLZ:
4945 case R6_OPC_CLZ:
4946 tcg_gen_ext32u_tl(t0, t0);
4947 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4948 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4949 break;
4950 #if defined(TARGET_MIPS64)
4951 case OPC_DCLO:
4952 case R6_OPC_DCLO:
4953 case OPC_DCLZ:
4954 case R6_OPC_DCLZ:
4955 tcg_gen_clzi_i64(t0, t0, 64);
4956 break;
4957 #endif
4961 /* Godson integer instructions */
4962 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4963 int rd, int rs, int rt)
4965 TCGv t0, t1;
4967 if (rd == 0) {
4968 /* Treat as NOP. */
4969 return;
4972 switch (opc) {
4973 case OPC_MULT_G_2E:
4974 case OPC_MULT_G_2F:
4975 case OPC_MULTU_G_2E:
4976 case OPC_MULTU_G_2F:
4977 #if defined(TARGET_MIPS64)
4978 case OPC_DMULT_G_2E:
4979 case OPC_DMULT_G_2F:
4980 case OPC_DMULTU_G_2E:
4981 case OPC_DMULTU_G_2F:
4982 #endif
4983 t0 = tcg_temp_new();
4984 t1 = tcg_temp_new();
4985 break;
4986 default:
4987 t0 = tcg_temp_local_new();
4988 t1 = tcg_temp_local_new();
4989 break;
4992 gen_load_gpr(t0, rs);
4993 gen_load_gpr(t1, rt);
4995 switch (opc) {
4996 case OPC_MULT_G_2E:
4997 case OPC_MULT_G_2F:
4998 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4999 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5000 break;
5001 case OPC_MULTU_G_2E:
5002 case OPC_MULTU_G_2F:
5003 tcg_gen_ext32u_tl(t0, t0);
5004 tcg_gen_ext32u_tl(t1, t1);
5005 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5006 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5007 break;
5008 case OPC_DIV_G_2E:
5009 case OPC_DIV_G_2F:
5011 TCGLabel *l1 = gen_new_label();
5012 TCGLabel *l2 = gen_new_label();
5013 TCGLabel *l3 = gen_new_label();
5014 tcg_gen_ext32s_tl(t0, t0);
5015 tcg_gen_ext32s_tl(t1, t1);
5016 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5017 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5018 tcg_gen_br(l3);
5019 gen_set_label(l1);
5020 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5021 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5022 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5023 tcg_gen_br(l3);
5024 gen_set_label(l2);
5025 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5026 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5027 gen_set_label(l3);
5029 break;
5030 case OPC_DIVU_G_2E:
5031 case OPC_DIVU_G_2F:
5033 TCGLabel *l1 = gen_new_label();
5034 TCGLabel *l2 = gen_new_label();
5035 tcg_gen_ext32u_tl(t0, t0);
5036 tcg_gen_ext32u_tl(t1, t1);
5037 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5038 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5039 tcg_gen_br(l2);
5040 gen_set_label(l1);
5041 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5042 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5043 gen_set_label(l2);
5045 break;
5046 case OPC_MOD_G_2E:
5047 case OPC_MOD_G_2F:
5049 TCGLabel *l1 = gen_new_label();
5050 TCGLabel *l2 = gen_new_label();
5051 TCGLabel *l3 = gen_new_label();
5052 tcg_gen_ext32u_tl(t0, t0);
5053 tcg_gen_ext32u_tl(t1, t1);
5054 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5055 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5056 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5057 gen_set_label(l1);
5058 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5059 tcg_gen_br(l3);
5060 gen_set_label(l2);
5061 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5062 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5063 gen_set_label(l3);
5065 break;
5066 case OPC_MODU_G_2E:
5067 case OPC_MODU_G_2F:
5069 TCGLabel *l1 = gen_new_label();
5070 TCGLabel *l2 = gen_new_label();
5071 tcg_gen_ext32u_tl(t0, t0);
5072 tcg_gen_ext32u_tl(t1, t1);
5073 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5074 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5075 tcg_gen_br(l2);
5076 gen_set_label(l1);
5077 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5078 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5079 gen_set_label(l2);
5081 break;
5082 #if defined(TARGET_MIPS64)
5083 case OPC_DMULT_G_2E:
5084 case OPC_DMULT_G_2F:
5085 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5086 break;
5087 case OPC_DMULTU_G_2E:
5088 case OPC_DMULTU_G_2F:
5089 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5090 break;
5091 case OPC_DDIV_G_2E:
5092 case OPC_DDIV_G_2F:
5094 TCGLabel *l1 = gen_new_label();
5095 TCGLabel *l2 = gen_new_label();
5096 TCGLabel *l3 = gen_new_label();
5097 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5098 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5099 tcg_gen_br(l3);
5100 gen_set_label(l1);
5101 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5102 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5103 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5104 tcg_gen_br(l3);
5105 gen_set_label(l2);
5106 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5107 gen_set_label(l3);
5109 break;
5110 case OPC_DDIVU_G_2E:
5111 case OPC_DDIVU_G_2F:
5113 TCGLabel *l1 = gen_new_label();
5114 TCGLabel *l2 = gen_new_label();
5115 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5116 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5117 tcg_gen_br(l2);
5118 gen_set_label(l1);
5119 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5120 gen_set_label(l2);
5122 break;
5123 case OPC_DMOD_G_2E:
5124 case OPC_DMOD_G_2F:
5126 TCGLabel *l1 = gen_new_label();
5127 TCGLabel *l2 = gen_new_label();
5128 TCGLabel *l3 = gen_new_label();
5129 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5130 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5131 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5132 gen_set_label(l1);
5133 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5134 tcg_gen_br(l3);
5135 gen_set_label(l2);
5136 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5137 gen_set_label(l3);
5139 break;
5140 case OPC_DMODU_G_2E:
5141 case OPC_DMODU_G_2F:
5143 TCGLabel *l1 = gen_new_label();
5144 TCGLabel *l2 = gen_new_label();
5145 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5146 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5147 tcg_gen_br(l2);
5148 gen_set_label(l1);
5149 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5150 gen_set_label(l2);
5152 break;
5153 #endif
5156 tcg_temp_free(t0);
5157 tcg_temp_free(t1);
5160 /* Loongson multimedia instructions */
5161 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5163 uint32_t opc, shift_max;
5164 TCGv_i64 t0, t1;
5166 opc = MASK_LMI(ctx->opcode);
5167 switch (opc) {
5168 case OPC_ADD_CP2:
5169 case OPC_SUB_CP2:
5170 case OPC_DADD_CP2:
5171 case OPC_DSUB_CP2:
5172 t0 = tcg_temp_local_new_i64();
5173 t1 = tcg_temp_local_new_i64();
5174 break;
5175 default:
5176 t0 = tcg_temp_new_i64();
5177 t1 = tcg_temp_new_i64();
5178 break;
5181 check_cp1_enabled(ctx);
5182 gen_load_fpr64(ctx, t0, rs);
5183 gen_load_fpr64(ctx, t1, rt);
5185 #define LMI_HELPER(UP, LO) \
5186 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
5187 #define LMI_HELPER_1(UP, LO) \
5188 case OPC_##UP: gen_helper_##LO(t0, t0); break
5189 #define LMI_DIRECT(UP, LO, OP) \
5190 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
5192 switch (opc) {
5193 LMI_HELPER(PADDSH, paddsh);
5194 LMI_HELPER(PADDUSH, paddush);
5195 LMI_HELPER(PADDH, paddh);
5196 LMI_HELPER(PADDW, paddw);
5197 LMI_HELPER(PADDSB, paddsb);
5198 LMI_HELPER(PADDUSB, paddusb);
5199 LMI_HELPER(PADDB, paddb);
5201 LMI_HELPER(PSUBSH, psubsh);
5202 LMI_HELPER(PSUBUSH, psubush);
5203 LMI_HELPER(PSUBH, psubh);
5204 LMI_HELPER(PSUBW, psubw);
5205 LMI_HELPER(PSUBSB, psubsb);
5206 LMI_HELPER(PSUBUSB, psubusb);
5207 LMI_HELPER(PSUBB, psubb);
5209 LMI_HELPER(PSHUFH, pshufh);
5210 LMI_HELPER(PACKSSWH, packsswh);
5211 LMI_HELPER(PACKSSHB, packsshb);
5212 LMI_HELPER(PACKUSHB, packushb);
5214 LMI_HELPER(PUNPCKLHW, punpcklhw);
5215 LMI_HELPER(PUNPCKHHW, punpckhhw);
5216 LMI_HELPER(PUNPCKLBH, punpcklbh);
5217 LMI_HELPER(PUNPCKHBH, punpckhbh);
5218 LMI_HELPER(PUNPCKLWD, punpcklwd);
5219 LMI_HELPER(PUNPCKHWD, punpckhwd);
5221 LMI_HELPER(PAVGH, pavgh);
5222 LMI_HELPER(PAVGB, pavgb);
5223 LMI_HELPER(PMAXSH, pmaxsh);
5224 LMI_HELPER(PMINSH, pminsh);
5225 LMI_HELPER(PMAXUB, pmaxub);
5226 LMI_HELPER(PMINUB, pminub);
5228 LMI_HELPER(PCMPEQW, pcmpeqw);
5229 LMI_HELPER(PCMPGTW, pcmpgtw);
5230 LMI_HELPER(PCMPEQH, pcmpeqh);
5231 LMI_HELPER(PCMPGTH, pcmpgth);
5232 LMI_HELPER(PCMPEQB, pcmpeqb);
5233 LMI_HELPER(PCMPGTB, pcmpgtb);
5235 LMI_HELPER(PSLLW, psllw);
5236 LMI_HELPER(PSLLH, psllh);
5237 LMI_HELPER(PSRLW, psrlw);
5238 LMI_HELPER(PSRLH, psrlh);
5239 LMI_HELPER(PSRAW, psraw);
5240 LMI_HELPER(PSRAH, psrah);
5242 LMI_HELPER(PMULLH, pmullh);
5243 LMI_HELPER(PMULHH, pmulhh);
5244 LMI_HELPER(PMULHUH, pmulhuh);
5245 LMI_HELPER(PMADDHW, pmaddhw);
5247 LMI_HELPER(PASUBUB, pasubub);
5248 LMI_HELPER_1(BIADD, biadd);
5249 LMI_HELPER_1(PMOVMSKB, pmovmskb);
5251 LMI_DIRECT(PADDD, paddd, add);
5252 LMI_DIRECT(PSUBD, psubd, sub);
5253 LMI_DIRECT(XOR_CP2, xor, xor);
5254 LMI_DIRECT(NOR_CP2, nor, nor);
5255 LMI_DIRECT(AND_CP2, and, and);
5256 LMI_DIRECT(OR_CP2, or, or);
5258 case OPC_PANDN:
5259 tcg_gen_andc_i64(t0, t1, t0);
5260 break;
5262 case OPC_PINSRH_0:
5263 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5264 break;
5265 case OPC_PINSRH_1:
5266 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5267 break;
5268 case OPC_PINSRH_2:
5269 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5270 break;
5271 case OPC_PINSRH_3:
5272 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5273 break;
5275 case OPC_PEXTRH:
5276 tcg_gen_andi_i64(t1, t1, 3);
5277 tcg_gen_shli_i64(t1, t1, 4);
5278 tcg_gen_shr_i64(t0, t0, t1);
5279 tcg_gen_ext16u_i64(t0, t0);
5280 break;
5282 case OPC_ADDU_CP2:
5283 tcg_gen_add_i64(t0, t0, t1);
5284 tcg_gen_ext32s_i64(t0, t0);
5285 break;
5286 case OPC_SUBU_CP2:
5287 tcg_gen_sub_i64(t0, t0, t1);
5288 tcg_gen_ext32s_i64(t0, t0);
5289 break;
5291 case OPC_SLL_CP2:
5292 shift_max = 32;
5293 goto do_shift;
5294 case OPC_SRL_CP2:
5295 shift_max = 32;
5296 goto do_shift;
5297 case OPC_SRA_CP2:
5298 shift_max = 32;
5299 goto do_shift;
5300 case OPC_DSLL_CP2:
5301 shift_max = 64;
5302 goto do_shift;
5303 case OPC_DSRL_CP2:
5304 shift_max = 64;
5305 goto do_shift;
5306 case OPC_DSRA_CP2:
5307 shift_max = 64;
5308 goto do_shift;
5309 do_shift:
5310 /* Make sure shift count isn't TCG undefined behaviour. */
5311 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5313 switch (opc) {
5314 case OPC_SLL_CP2:
5315 case OPC_DSLL_CP2:
5316 tcg_gen_shl_i64(t0, t0, t1);
5317 break;
5318 case OPC_SRA_CP2:
5319 case OPC_DSRA_CP2:
5320 /* Since SRA is UndefinedResult without sign-extended inputs,
5321 we can treat SRA and DSRA the same. */
5322 tcg_gen_sar_i64(t0, t0, t1);
5323 break;
5324 case OPC_SRL_CP2:
5325 /* We want to shift in zeros for SRL; zero-extend first. */
5326 tcg_gen_ext32u_i64(t0, t0);
5327 /* FALLTHRU */
5328 case OPC_DSRL_CP2:
5329 tcg_gen_shr_i64(t0, t0, t1);
5330 break;
5333 if (shift_max == 32) {
5334 tcg_gen_ext32s_i64(t0, t0);
5337 /* Shifts larger than MAX produce zero. */
5338 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5339 tcg_gen_neg_i64(t1, t1);
5340 tcg_gen_and_i64(t0, t0, t1);
5341 break;
5343 case OPC_ADD_CP2:
5344 case OPC_DADD_CP2:
5346 TCGv_i64 t2 = tcg_temp_new_i64();
5347 TCGLabel *lab = gen_new_label();
5349 tcg_gen_mov_i64(t2, t0);
5350 tcg_gen_add_i64(t0, t1, t2);
5351 if (opc == OPC_ADD_CP2) {
5352 tcg_gen_ext32s_i64(t0, t0);
5354 tcg_gen_xor_i64(t1, t1, t2);
5355 tcg_gen_xor_i64(t2, t2, t0);
5356 tcg_gen_andc_i64(t1, t2, t1);
5357 tcg_temp_free_i64(t2);
5358 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5359 generate_exception(ctx, EXCP_OVERFLOW);
5360 gen_set_label(lab);
5361 break;
5364 case OPC_SUB_CP2:
5365 case OPC_DSUB_CP2:
5367 TCGv_i64 t2 = tcg_temp_new_i64();
5368 TCGLabel *lab = gen_new_label();
5370 tcg_gen_mov_i64(t2, t0);
5371 tcg_gen_sub_i64(t0, t1, t2);
5372 if (opc == OPC_SUB_CP2) {
5373 tcg_gen_ext32s_i64(t0, t0);
5375 tcg_gen_xor_i64(t1, t1, t2);
5376 tcg_gen_xor_i64(t2, t2, t0);
5377 tcg_gen_and_i64(t1, t1, t2);
5378 tcg_temp_free_i64(t2);
5379 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5380 generate_exception(ctx, EXCP_OVERFLOW);
5381 gen_set_label(lab);
5382 break;
5385 case OPC_PMULUW:
5386 tcg_gen_ext32u_i64(t0, t0);
5387 tcg_gen_ext32u_i64(t1, t1);
5388 tcg_gen_mul_i64(t0, t0, t1);
5389 break;
5391 case OPC_SEQU_CP2:
5392 case OPC_SEQ_CP2:
5393 case OPC_SLTU_CP2:
5394 case OPC_SLT_CP2:
5395 case OPC_SLEU_CP2:
5396 case OPC_SLE_CP2:
5397 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5398 FD field is the CC field? */
5399 default:
5400 MIPS_INVAL("loongson_cp2");
5401 generate_exception_end(ctx, EXCP_RI);
5402 return;
5405 #undef LMI_HELPER
5406 #undef LMI_DIRECT
5408 gen_store_fpr64(ctx, t0, rd);
5410 tcg_temp_free_i64(t0);
5411 tcg_temp_free_i64(t1);
5414 /* Traps */
5415 static void gen_trap (DisasContext *ctx, uint32_t opc,
5416 int rs, int rt, int16_t imm)
5418 int cond;
5419 TCGv t0 = tcg_temp_new();
5420 TCGv t1 = tcg_temp_new();
5422 cond = 0;
5423 /* Load needed operands */
5424 switch (opc) {
5425 case OPC_TEQ:
5426 case OPC_TGE:
5427 case OPC_TGEU:
5428 case OPC_TLT:
5429 case OPC_TLTU:
5430 case OPC_TNE:
5431 /* Compare two registers */
5432 if (rs != rt) {
5433 gen_load_gpr(t0, rs);
5434 gen_load_gpr(t1, rt);
5435 cond = 1;
5437 break;
5438 case OPC_TEQI:
5439 case OPC_TGEI:
5440 case OPC_TGEIU:
5441 case OPC_TLTI:
5442 case OPC_TLTIU:
5443 case OPC_TNEI:
5444 /* Compare register to immediate */
5445 if (rs != 0 || imm != 0) {
5446 gen_load_gpr(t0, rs);
5447 tcg_gen_movi_tl(t1, (int32_t)imm);
5448 cond = 1;
5450 break;
5452 if (cond == 0) {
5453 switch (opc) {
5454 case OPC_TEQ: /* rs == rs */
5455 case OPC_TEQI: /* r0 == 0 */
5456 case OPC_TGE: /* rs >= rs */
5457 case OPC_TGEI: /* r0 >= 0 */
5458 case OPC_TGEU: /* rs >= rs unsigned */
5459 case OPC_TGEIU: /* r0 >= 0 unsigned */
5460 /* Always trap */
5461 generate_exception_end(ctx, EXCP_TRAP);
5462 break;
5463 case OPC_TLT: /* rs < rs */
5464 case OPC_TLTI: /* r0 < 0 */
5465 case OPC_TLTU: /* rs < rs unsigned */
5466 case OPC_TLTIU: /* r0 < 0 unsigned */
5467 case OPC_TNE: /* rs != rs */
5468 case OPC_TNEI: /* r0 != 0 */
5469 /* Never trap: treat as NOP. */
5470 break;
5472 } else {
5473 TCGLabel *l1 = gen_new_label();
5475 switch (opc) {
5476 case OPC_TEQ:
5477 case OPC_TEQI:
5478 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5479 break;
5480 case OPC_TGE:
5481 case OPC_TGEI:
5482 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5483 break;
5484 case OPC_TGEU:
5485 case OPC_TGEIU:
5486 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5487 break;
5488 case OPC_TLT:
5489 case OPC_TLTI:
5490 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5491 break;
5492 case OPC_TLTU:
5493 case OPC_TLTIU:
5494 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5495 break;
5496 case OPC_TNE:
5497 case OPC_TNEI:
5498 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5499 break;
5501 generate_exception(ctx, EXCP_TRAP);
5502 gen_set_label(l1);
5504 tcg_temp_free(t0);
5505 tcg_temp_free(t1);
5508 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5510 if (unlikely(ctx->base.singlestep_enabled)) {
5511 return false;
5514 #ifndef CONFIG_USER_ONLY
5515 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5516 #else
5517 return true;
5518 #endif
5521 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5523 if (use_goto_tb(ctx, dest)) {
5524 tcg_gen_goto_tb(n);
5525 gen_save_pc(dest);
5526 tcg_gen_exit_tb(ctx->base.tb, n);
5527 } else {
5528 gen_save_pc(dest);
5529 if (ctx->base.singlestep_enabled) {
5530 save_cpu_state(ctx, 0);
5531 gen_helper_raise_exception_debug(cpu_env);
5533 tcg_gen_lookup_and_goto_ptr();
5537 /* Branches (before delay slot) */
5538 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5539 int insn_bytes,
5540 int rs, int rt, int32_t offset,
5541 int delayslot_size)
5543 target_ulong btgt = -1;
5544 int blink = 0;
5545 int bcond_compute = 0;
5546 TCGv t0 = tcg_temp_new();
5547 TCGv t1 = tcg_temp_new();
5549 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5550 #ifdef MIPS_DEBUG_DISAS
5551 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5552 TARGET_FMT_lx "\n", ctx->base.pc_next);
5553 #endif
5554 generate_exception_end(ctx, EXCP_RI);
5555 goto out;
5558 /* Load needed operands */
5559 switch (opc) {
5560 case OPC_BEQ:
5561 case OPC_BEQL:
5562 case OPC_BNE:
5563 case OPC_BNEL:
5564 /* Compare two registers */
5565 if (rs != rt) {
5566 gen_load_gpr(t0, rs);
5567 gen_load_gpr(t1, rt);
5568 bcond_compute = 1;
5570 btgt = ctx->base.pc_next + insn_bytes + offset;
5571 break;
5572 case OPC_BGEZ:
5573 case OPC_BGEZAL:
5574 case OPC_BGEZALL:
5575 case OPC_BGEZL:
5576 case OPC_BGTZ:
5577 case OPC_BGTZL:
5578 case OPC_BLEZ:
5579 case OPC_BLEZL:
5580 case OPC_BLTZ:
5581 case OPC_BLTZAL:
5582 case OPC_BLTZALL:
5583 case OPC_BLTZL:
5584 /* Compare to zero */
5585 if (rs != 0) {
5586 gen_load_gpr(t0, rs);
5587 bcond_compute = 1;
5589 btgt = ctx->base.pc_next + insn_bytes + offset;
5590 break;
5591 case OPC_BPOSGE32:
5592 #if defined(TARGET_MIPS64)
5593 case OPC_BPOSGE64:
5594 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5595 #else
5596 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5597 #endif
5598 bcond_compute = 1;
5599 btgt = ctx->base.pc_next + insn_bytes + offset;
5600 break;
5601 case OPC_J:
5602 case OPC_JAL:
5603 case OPC_JALX:
5604 /* Jump to immediate */
5605 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5606 (uint32_t)offset;
5607 break;
5608 case OPC_JR:
5609 case OPC_JALR:
5610 /* Jump to register */
5611 if (offset != 0 && offset != 16) {
5612 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5613 others are reserved. */
5614 MIPS_INVAL("jump hint");
5615 generate_exception_end(ctx, EXCP_RI);
5616 goto out;
5618 gen_load_gpr(btarget, rs);
5619 break;
5620 default:
5621 MIPS_INVAL("branch/jump");
5622 generate_exception_end(ctx, EXCP_RI);
5623 goto out;
5625 if (bcond_compute == 0) {
5626 /* No condition to be computed */
5627 switch (opc) {
5628 case OPC_BEQ: /* rx == rx */
5629 case OPC_BEQL: /* rx == rx likely */
5630 case OPC_BGEZ: /* 0 >= 0 */
5631 case OPC_BGEZL: /* 0 >= 0 likely */
5632 case OPC_BLEZ: /* 0 <= 0 */
5633 case OPC_BLEZL: /* 0 <= 0 likely */
5634 /* Always take */
5635 ctx->hflags |= MIPS_HFLAG_B;
5636 break;
5637 case OPC_BGEZAL: /* 0 >= 0 */
5638 case OPC_BGEZALL: /* 0 >= 0 likely */
5639 /* Always take and link */
5640 blink = 31;
5641 ctx->hflags |= MIPS_HFLAG_B;
5642 break;
5643 case OPC_BNE: /* rx != rx */
5644 case OPC_BGTZ: /* 0 > 0 */
5645 case OPC_BLTZ: /* 0 < 0 */
5646 /* Treat as NOP. */
5647 goto out;
5648 case OPC_BLTZAL: /* 0 < 0 */
5649 /* Handle as an unconditional branch to get correct delay
5650 slot checking. */
5651 blink = 31;
5652 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5653 ctx->hflags |= MIPS_HFLAG_B;
5654 break;
5655 case OPC_BLTZALL: /* 0 < 0 likely */
5656 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5657 /* Skip the instruction in the delay slot */
5658 ctx->base.pc_next += 4;
5659 goto out;
5660 case OPC_BNEL: /* rx != rx likely */
5661 case OPC_BGTZL: /* 0 > 0 likely */
5662 case OPC_BLTZL: /* 0 < 0 likely */
5663 /* Skip the instruction in the delay slot */
5664 ctx->base.pc_next += 4;
5665 goto out;
5666 case OPC_J:
5667 ctx->hflags |= MIPS_HFLAG_B;
5668 break;
5669 case OPC_JALX:
5670 ctx->hflags |= MIPS_HFLAG_BX;
5671 /* Fallthrough */
5672 case OPC_JAL:
5673 blink = 31;
5674 ctx->hflags |= MIPS_HFLAG_B;
5675 break;
5676 case OPC_JR:
5677 ctx->hflags |= MIPS_HFLAG_BR;
5678 break;
5679 case OPC_JALR:
5680 blink = rt;
5681 ctx->hflags |= MIPS_HFLAG_BR;
5682 break;
5683 default:
5684 MIPS_INVAL("branch/jump");
5685 generate_exception_end(ctx, EXCP_RI);
5686 goto out;
5688 } else {
5689 switch (opc) {
5690 case OPC_BEQ:
5691 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5692 goto not_likely;
5693 case OPC_BEQL:
5694 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5695 goto likely;
5696 case OPC_BNE:
5697 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5698 goto not_likely;
5699 case OPC_BNEL:
5700 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5701 goto likely;
5702 case OPC_BGEZ:
5703 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5704 goto not_likely;
5705 case OPC_BGEZL:
5706 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5707 goto likely;
5708 case OPC_BGEZAL:
5709 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5710 blink = 31;
5711 goto not_likely;
5712 case OPC_BGEZALL:
5713 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5714 blink = 31;
5715 goto likely;
5716 case OPC_BGTZ:
5717 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5718 goto not_likely;
5719 case OPC_BGTZL:
5720 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5721 goto likely;
5722 case OPC_BLEZ:
5723 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5724 goto not_likely;
5725 case OPC_BLEZL:
5726 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5727 goto likely;
5728 case OPC_BLTZ:
5729 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5730 goto not_likely;
5731 case OPC_BLTZL:
5732 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5733 goto likely;
5734 case OPC_BPOSGE32:
5735 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5736 goto not_likely;
5737 #if defined(TARGET_MIPS64)
5738 case OPC_BPOSGE64:
5739 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5740 goto not_likely;
5741 #endif
5742 case OPC_BLTZAL:
5743 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5744 blink = 31;
5745 not_likely:
5746 ctx->hflags |= MIPS_HFLAG_BC;
5747 break;
5748 case OPC_BLTZALL:
5749 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5750 blink = 31;
5751 likely:
5752 ctx->hflags |= MIPS_HFLAG_BL;
5753 break;
5754 default:
5755 MIPS_INVAL("conditional branch/jump");
5756 generate_exception_end(ctx, EXCP_RI);
5757 goto out;
5761 ctx->btarget = btgt;
5763 switch (delayslot_size) {
5764 case 2:
5765 ctx->hflags |= MIPS_HFLAG_BDS16;
5766 break;
5767 case 4:
5768 ctx->hflags |= MIPS_HFLAG_BDS32;
5769 break;
5772 if (blink > 0) {
5773 int post_delay = insn_bytes + delayslot_size;
5774 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5776 tcg_gen_movi_tl(cpu_gpr[blink],
5777 ctx->base.pc_next + post_delay + lowbit);
5780 out:
5781 if (insn_bytes == 2)
5782 ctx->hflags |= MIPS_HFLAG_B16;
5783 tcg_temp_free(t0);
5784 tcg_temp_free(t1);
5788 /* nanoMIPS Branches */
5789 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5790 int insn_bytes,
5791 int rs, int rt, int32_t offset)
5793 target_ulong btgt = -1;
5794 int bcond_compute = 0;
5795 TCGv t0 = tcg_temp_new();
5796 TCGv t1 = tcg_temp_new();
5798 /* Load needed operands */
5799 switch (opc) {
5800 case OPC_BEQ:
5801 case OPC_BNE:
5802 /* Compare two registers */
5803 if (rs != rt) {
5804 gen_load_gpr(t0, rs);
5805 gen_load_gpr(t1, rt);
5806 bcond_compute = 1;
5808 btgt = ctx->base.pc_next + insn_bytes + offset;
5809 break;
5810 case OPC_BGEZAL:
5811 /* Compare to zero */
5812 if (rs != 0) {
5813 gen_load_gpr(t0, rs);
5814 bcond_compute = 1;
5816 btgt = ctx->base.pc_next + insn_bytes + offset;
5817 break;
5818 case OPC_BPOSGE32:
5819 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5820 bcond_compute = 1;
5821 btgt = ctx->base.pc_next + insn_bytes + offset;
5822 break;
5823 case OPC_JR:
5824 case OPC_JALR:
5825 /* Jump to register */
5826 if (offset != 0 && offset != 16) {
5827 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5828 others are reserved. */
5829 MIPS_INVAL("jump hint");
5830 generate_exception_end(ctx, EXCP_RI);
5831 goto out;
5833 gen_load_gpr(btarget, rs);
5834 break;
5835 default:
5836 MIPS_INVAL("branch/jump");
5837 generate_exception_end(ctx, EXCP_RI);
5838 goto out;
5840 if (bcond_compute == 0) {
5841 /* No condition to be computed */
5842 switch (opc) {
5843 case OPC_BEQ: /* rx == rx */
5844 /* Always take */
5845 ctx->hflags |= MIPS_HFLAG_B;
5846 break;
5847 case OPC_BGEZAL: /* 0 >= 0 */
5848 /* Always take and link */
5849 tcg_gen_movi_tl(cpu_gpr[31],
5850 ctx->base.pc_next + insn_bytes);
5851 ctx->hflags |= MIPS_HFLAG_B;
5852 break;
5853 case OPC_BNE: /* rx != rx */
5854 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5855 /* Skip the instruction in the delay slot */
5856 ctx->base.pc_next += 4;
5857 goto out;
5858 case OPC_JR:
5859 ctx->hflags |= MIPS_HFLAG_BR;
5860 break;
5861 case OPC_JALR:
5862 if (rt > 0) {
5863 tcg_gen_movi_tl(cpu_gpr[rt],
5864 ctx->base.pc_next + insn_bytes);
5866 ctx->hflags |= MIPS_HFLAG_BR;
5867 break;
5868 default:
5869 MIPS_INVAL("branch/jump");
5870 generate_exception_end(ctx, EXCP_RI);
5871 goto out;
5873 } else {
5874 switch (opc) {
5875 case OPC_BEQ:
5876 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5877 goto not_likely;
5878 case OPC_BNE:
5879 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5880 goto not_likely;
5881 case OPC_BGEZAL:
5882 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5883 tcg_gen_movi_tl(cpu_gpr[31],
5884 ctx->base.pc_next + insn_bytes);
5885 goto not_likely;
5886 case OPC_BPOSGE32:
5887 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5888 not_likely:
5889 ctx->hflags |= MIPS_HFLAG_BC;
5890 break;
5891 default:
5892 MIPS_INVAL("conditional branch/jump");
5893 generate_exception_end(ctx, EXCP_RI);
5894 goto out;
5898 ctx->btarget = btgt;
5900 out:
5901 if (insn_bytes == 2) {
5902 ctx->hflags |= MIPS_HFLAG_B16;
5904 tcg_temp_free(t0);
5905 tcg_temp_free(t1);
5909 /* special3 bitfield operations */
5910 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5911 int rs, int lsb, int msb)
5913 TCGv t0 = tcg_temp_new();
5914 TCGv t1 = tcg_temp_new();
5916 gen_load_gpr(t1, rs);
5917 switch (opc) {
5918 case OPC_EXT:
5919 if (lsb + msb > 31) {
5920 goto fail;
5922 if (msb != 31) {
5923 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5924 } else {
5925 /* The two checks together imply that lsb == 0,
5926 so this is a simple sign-extension. */
5927 tcg_gen_ext32s_tl(t0, t1);
5929 break;
5930 #if defined(TARGET_MIPS64)
5931 case OPC_DEXTU:
5932 lsb += 32;
5933 goto do_dext;
5934 case OPC_DEXTM:
5935 msb += 32;
5936 goto do_dext;
5937 case OPC_DEXT:
5938 do_dext:
5939 if (lsb + msb > 63) {
5940 goto fail;
5942 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5943 break;
5944 #endif
5945 case OPC_INS:
5946 if (lsb > msb) {
5947 goto fail;
5949 gen_load_gpr(t0, rt);
5950 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5951 tcg_gen_ext32s_tl(t0, t0);
5952 break;
5953 #if defined(TARGET_MIPS64)
5954 case OPC_DINSU:
5955 lsb += 32;
5956 /* FALLTHRU */
5957 case OPC_DINSM:
5958 msb += 32;
5959 /* FALLTHRU */
5960 case OPC_DINS:
5961 if (lsb > msb) {
5962 goto fail;
5964 gen_load_gpr(t0, rt);
5965 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5966 break;
5967 #endif
5968 default:
5969 fail:
5970 MIPS_INVAL("bitops");
5971 generate_exception_end(ctx, EXCP_RI);
5972 tcg_temp_free(t0);
5973 tcg_temp_free(t1);
5974 return;
5976 gen_store_gpr(t0, rt);
5977 tcg_temp_free(t0);
5978 tcg_temp_free(t1);
5981 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
5983 TCGv t0;
5985 if (rd == 0) {
5986 /* If no destination, treat it as a NOP. */
5987 return;
5990 t0 = tcg_temp_new();
5991 gen_load_gpr(t0, rt);
5992 switch (op2) {
5993 case OPC_WSBH:
5995 TCGv t1 = tcg_temp_new();
5996 TCGv t2 = tcg_const_tl(0x00FF00FF);
5998 tcg_gen_shri_tl(t1, t0, 8);
5999 tcg_gen_and_tl(t1, t1, t2);
6000 tcg_gen_and_tl(t0, t0, t2);
6001 tcg_gen_shli_tl(t0, t0, 8);
6002 tcg_gen_or_tl(t0, t0, t1);
6003 tcg_temp_free(t2);
6004 tcg_temp_free(t1);
6005 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6007 break;
6008 case OPC_SEB:
6009 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6010 break;
6011 case OPC_SEH:
6012 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6013 break;
6014 #if defined(TARGET_MIPS64)
6015 case OPC_DSBH:
6017 TCGv t1 = tcg_temp_new();
6018 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6020 tcg_gen_shri_tl(t1, t0, 8);
6021 tcg_gen_and_tl(t1, t1, t2);
6022 tcg_gen_and_tl(t0, t0, t2);
6023 tcg_gen_shli_tl(t0, t0, 8);
6024 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6025 tcg_temp_free(t2);
6026 tcg_temp_free(t1);
6028 break;
6029 case OPC_DSHD:
6031 TCGv t1 = tcg_temp_new();
6032 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6034 tcg_gen_shri_tl(t1, t0, 16);
6035 tcg_gen_and_tl(t1, t1, t2);
6036 tcg_gen_and_tl(t0, t0, t2);
6037 tcg_gen_shli_tl(t0, t0, 16);
6038 tcg_gen_or_tl(t0, t0, t1);
6039 tcg_gen_shri_tl(t1, t0, 32);
6040 tcg_gen_shli_tl(t0, t0, 32);
6041 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6042 tcg_temp_free(t2);
6043 tcg_temp_free(t1);
6045 break;
6046 #endif
6047 default:
6048 MIPS_INVAL("bsfhl");
6049 generate_exception_end(ctx, EXCP_RI);
6050 tcg_temp_free(t0);
6051 return;
6053 tcg_temp_free(t0);
6056 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6057 int imm2)
6059 TCGv t0;
6060 TCGv t1;
6061 if (rd == 0) {
6062 /* Treat as NOP. */
6063 return;
6065 t0 = tcg_temp_new();
6066 t1 = tcg_temp_new();
6067 gen_load_gpr(t0, rs);
6068 gen_load_gpr(t1, rt);
6069 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6070 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6071 if (opc == OPC_LSA) {
6072 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6075 tcg_temp_free(t1);
6076 tcg_temp_free(t0);
6078 return;
6081 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6082 int rt, int bits)
6084 TCGv t0;
6085 if (rd == 0) {
6086 /* Treat as NOP. */
6087 return;
6089 t0 = tcg_temp_new();
6090 if (bits == 0 || bits == wordsz) {
6091 if (bits == 0) {
6092 gen_load_gpr(t0, rt);
6093 } else {
6094 gen_load_gpr(t0, rs);
6096 switch (wordsz) {
6097 case 32:
6098 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6099 break;
6100 #if defined(TARGET_MIPS64)
6101 case 64:
6102 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6103 break;
6104 #endif
6106 } else {
6107 TCGv t1 = tcg_temp_new();
6108 gen_load_gpr(t0, rt);
6109 gen_load_gpr(t1, rs);
6110 switch (wordsz) {
6111 case 32:
6113 TCGv_i64 t2 = tcg_temp_new_i64();
6114 tcg_gen_concat_tl_i64(t2, t1, t0);
6115 tcg_gen_shri_i64(t2, t2, 32 - bits);
6116 gen_move_low32(cpu_gpr[rd], t2);
6117 tcg_temp_free_i64(t2);
6119 break;
6120 #if defined(TARGET_MIPS64)
6121 case 64:
6122 tcg_gen_shli_tl(t0, t0, bits);
6123 tcg_gen_shri_tl(t1, t1, 64 - bits);
6124 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6125 break;
6126 #endif
6128 tcg_temp_free(t1);
6131 tcg_temp_free(t0);
6134 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6135 int bp)
6137 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6140 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6141 int shift)
6143 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6146 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6148 TCGv t0;
6149 if (rd == 0) {
6150 /* Treat as NOP. */
6151 return;
6153 t0 = tcg_temp_new();
6154 gen_load_gpr(t0, rt);
6155 switch (opc) {
6156 case OPC_BITSWAP:
6157 gen_helper_bitswap(cpu_gpr[rd], t0);
6158 break;
6159 #if defined(TARGET_MIPS64)
6160 case OPC_DBITSWAP:
6161 gen_helper_dbitswap(cpu_gpr[rd], t0);
6162 break;
6163 #endif
6165 tcg_temp_free(t0);
6168 #ifndef CONFIG_USER_ONLY
6169 /* CP0 (MMU and control) */
6170 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6172 TCGv_i64 t0 = tcg_temp_new_i64();
6173 TCGv_i64 t1 = tcg_temp_new_i64();
6175 tcg_gen_ext_tl_i64(t0, arg);
6176 tcg_gen_ld_i64(t1, cpu_env, off);
6177 #if defined(TARGET_MIPS64)
6178 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6179 #else
6180 tcg_gen_concat32_i64(t1, t1, t0);
6181 #endif
6182 tcg_gen_st_i64(t1, cpu_env, off);
6183 tcg_temp_free_i64(t1);
6184 tcg_temp_free_i64(t0);
6187 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
6189 TCGv_i64 t0 = tcg_temp_new_i64();
6190 TCGv_i64 t1 = tcg_temp_new_i64();
6192 tcg_gen_ext_tl_i64(t0, arg);
6193 tcg_gen_ld_i64(t1, cpu_env, off);
6194 tcg_gen_concat32_i64(t1, t1, t0);
6195 tcg_gen_st_i64(t1, cpu_env, off);
6196 tcg_temp_free_i64(t1);
6197 tcg_temp_free_i64(t0);
6200 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
6202 TCGv_i64 t0 = tcg_temp_new_i64();
6204 tcg_gen_ld_i64(t0, cpu_env, off);
6205 #if defined(TARGET_MIPS64)
6206 tcg_gen_shri_i64(t0, t0, 30);
6207 #else
6208 tcg_gen_shri_i64(t0, t0, 32);
6209 #endif
6210 gen_move_low32(arg, t0);
6211 tcg_temp_free_i64(t0);
6214 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
6216 TCGv_i64 t0 = tcg_temp_new_i64();
6218 tcg_gen_ld_i64(t0, cpu_env, off);
6219 tcg_gen_shri_i64(t0, t0, 32 + shift);
6220 gen_move_low32(arg, t0);
6221 tcg_temp_free_i64(t0);
6224 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
6226 TCGv_i32 t0 = tcg_temp_new_i32();
6228 tcg_gen_ld_i32(t0, cpu_env, off);
6229 tcg_gen_ext_i32_tl(arg, t0);
6230 tcg_temp_free_i32(t0);
6233 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
6235 tcg_gen_ld_tl(arg, cpu_env, off);
6236 tcg_gen_ext32s_tl(arg, arg);
6239 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
6241 TCGv_i32 t0 = tcg_temp_new_i32();
6243 tcg_gen_trunc_tl_i32(t0, arg);
6244 tcg_gen_st_i32(t0, cpu_env, off);
6245 tcg_temp_free_i32(t0);
6248 #define CP0_CHECK(c) \
6249 do { \
6250 if (!(c)) { \
6251 goto cp0_unimplemented; \
6253 } while (0)
6255 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6257 const char *rn = "invalid";
6259 switch (reg) {
6260 case 2:
6261 switch (sel) {
6262 case 0:
6263 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6264 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6265 rn = "EntryLo0";
6266 break;
6267 default:
6268 goto cp0_unimplemented;
6270 break;
6271 case 3:
6272 switch (sel) {
6273 case 0:
6274 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6275 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6276 rn = "EntryLo1";
6277 break;
6278 default:
6279 goto cp0_unimplemented;
6281 break;
6282 case 17:
6283 switch (sel) {
6284 case 0:
6285 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6286 ctx->CP0_LLAddr_shift);
6287 rn = "LLAddr";
6288 break;
6289 case 1:
6290 CP0_CHECK(ctx->mrp);
6291 gen_helper_mfhc0_maar(arg, cpu_env);
6292 rn = "MAAR";
6293 break;
6294 default:
6295 goto cp0_unimplemented;
6297 break;
6298 case 28:
6299 switch (sel) {
6300 case 0:
6301 case 2:
6302 case 4:
6303 case 6:
6304 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6305 rn = "TagLo";
6306 break;
6307 default:
6308 goto cp0_unimplemented;
6310 break;
6311 default:
6312 goto cp0_unimplemented;
6314 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6315 return;
6317 cp0_unimplemented:
6318 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6319 tcg_gen_movi_tl(arg, 0);
6322 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6324 const char *rn = "invalid";
6325 uint64_t mask = ctx->PAMask >> 36;
6327 switch (reg) {
6328 case 2:
6329 switch (sel) {
6330 case 0:
6331 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6332 tcg_gen_andi_tl(arg, arg, mask);
6333 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6334 rn = "EntryLo0";
6335 break;
6336 default:
6337 goto cp0_unimplemented;
6339 break;
6340 case 3:
6341 switch (sel) {
6342 case 0:
6343 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6344 tcg_gen_andi_tl(arg, arg, mask);
6345 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6346 rn = "EntryLo1";
6347 break;
6348 default:
6349 goto cp0_unimplemented;
6351 break;
6352 case 17:
6353 switch (sel) {
6354 case 0:
6355 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6356 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6357 relevant for modern MIPS cores supporting MTHC0, therefore
6358 treating MTHC0 to LLAddr as NOP. */
6359 rn = "LLAddr";
6360 break;
6361 case 1:
6362 CP0_CHECK(ctx->mrp);
6363 gen_helper_mthc0_maar(cpu_env, arg);
6364 rn = "MAAR";
6365 break;
6366 default:
6367 goto cp0_unimplemented;
6369 break;
6370 case 28:
6371 switch (sel) {
6372 case 0:
6373 case 2:
6374 case 4:
6375 case 6:
6376 tcg_gen_andi_tl(arg, arg, mask);
6377 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6378 rn = "TagLo";
6379 break;
6380 default:
6381 goto cp0_unimplemented;
6383 break;
6384 default:
6385 goto cp0_unimplemented;
6387 trace_mips_translate_c0("mthc0", rn, reg, sel);
6389 cp0_unimplemented:
6390 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6393 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6395 if (ctx->insn_flags & ISA_MIPS32R6) {
6396 tcg_gen_movi_tl(arg, 0);
6397 } else {
6398 tcg_gen_movi_tl(arg, ~0);
6402 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6404 const char *rn = "invalid";
6406 if (sel != 0)
6407 check_insn(ctx, ISA_MIPS32);
6409 switch (reg) {
6410 case 0:
6411 switch (sel) {
6412 case 0:
6413 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6414 rn = "Index";
6415 break;
6416 case 1:
6417 CP0_CHECK(ctx->insn_flags & ASE_MT);
6418 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6419 rn = "MVPControl";
6420 break;
6421 case 2:
6422 CP0_CHECK(ctx->insn_flags & ASE_MT);
6423 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6424 rn = "MVPConf0";
6425 break;
6426 case 3:
6427 CP0_CHECK(ctx->insn_flags & ASE_MT);
6428 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6429 rn = "MVPConf1";
6430 break;
6431 case 4:
6432 CP0_CHECK(ctx->vp);
6433 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6434 rn = "VPControl";
6435 break;
6436 default:
6437 goto cp0_unimplemented;
6439 break;
6440 case 1:
6441 switch (sel) {
6442 case 0:
6443 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6444 gen_helper_mfc0_random(arg, cpu_env);
6445 rn = "Random";
6446 break;
6447 case 1:
6448 CP0_CHECK(ctx->insn_flags & ASE_MT);
6449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6450 rn = "VPEControl";
6451 break;
6452 case 2:
6453 CP0_CHECK(ctx->insn_flags & ASE_MT);
6454 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6455 rn = "VPEConf0";
6456 break;
6457 case 3:
6458 CP0_CHECK(ctx->insn_flags & ASE_MT);
6459 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6460 rn = "VPEConf1";
6461 break;
6462 case 4:
6463 CP0_CHECK(ctx->insn_flags & ASE_MT);
6464 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6465 rn = "YQMask";
6466 break;
6467 case 5:
6468 CP0_CHECK(ctx->insn_flags & ASE_MT);
6469 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6470 rn = "VPESchedule";
6471 break;
6472 case 6:
6473 CP0_CHECK(ctx->insn_flags & ASE_MT);
6474 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6475 rn = "VPEScheFBack";
6476 break;
6477 case 7:
6478 CP0_CHECK(ctx->insn_flags & ASE_MT);
6479 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6480 rn = "VPEOpt";
6481 break;
6482 default:
6483 goto cp0_unimplemented;
6485 break;
6486 case 2:
6487 switch (sel) {
6488 case 0:
6490 TCGv_i64 tmp = tcg_temp_new_i64();
6491 tcg_gen_ld_i64(tmp, cpu_env,
6492 offsetof(CPUMIPSState, CP0_EntryLo0));
6493 #if defined(TARGET_MIPS64)
6494 if (ctx->rxi) {
6495 /* Move RI/XI fields to bits 31:30 */
6496 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6497 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6499 #endif
6500 gen_move_low32(arg, tmp);
6501 tcg_temp_free_i64(tmp);
6503 rn = "EntryLo0";
6504 break;
6505 case 1:
6506 CP0_CHECK(ctx->insn_flags & ASE_MT);
6507 gen_helper_mfc0_tcstatus(arg, cpu_env);
6508 rn = "TCStatus";
6509 break;
6510 case 2:
6511 CP0_CHECK(ctx->insn_flags & ASE_MT);
6512 gen_helper_mfc0_tcbind(arg, cpu_env);
6513 rn = "TCBind";
6514 break;
6515 case 3:
6516 CP0_CHECK(ctx->insn_flags & ASE_MT);
6517 gen_helper_mfc0_tcrestart(arg, cpu_env);
6518 rn = "TCRestart";
6519 break;
6520 case 4:
6521 CP0_CHECK(ctx->insn_flags & ASE_MT);
6522 gen_helper_mfc0_tchalt(arg, cpu_env);
6523 rn = "TCHalt";
6524 break;
6525 case 5:
6526 CP0_CHECK(ctx->insn_flags & ASE_MT);
6527 gen_helper_mfc0_tccontext(arg, cpu_env);
6528 rn = "TCContext";
6529 break;
6530 case 6:
6531 CP0_CHECK(ctx->insn_flags & ASE_MT);
6532 gen_helper_mfc0_tcschedule(arg, cpu_env);
6533 rn = "TCSchedule";
6534 break;
6535 case 7:
6536 CP0_CHECK(ctx->insn_flags & ASE_MT);
6537 gen_helper_mfc0_tcschefback(arg, cpu_env);
6538 rn = "TCScheFBack";
6539 break;
6540 default:
6541 goto cp0_unimplemented;
6543 break;
6544 case 3:
6545 switch (sel) {
6546 case 0:
6548 TCGv_i64 tmp = tcg_temp_new_i64();
6549 tcg_gen_ld_i64(tmp, cpu_env,
6550 offsetof(CPUMIPSState, CP0_EntryLo1));
6551 #if defined(TARGET_MIPS64)
6552 if (ctx->rxi) {
6553 /* Move RI/XI fields to bits 31:30 */
6554 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6555 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6557 #endif
6558 gen_move_low32(arg, tmp);
6559 tcg_temp_free_i64(tmp);
6561 rn = "EntryLo1";
6562 break;
6563 case 1:
6564 CP0_CHECK(ctx->vp);
6565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6566 rn = "GlobalNumber";
6567 break;
6568 default:
6569 goto cp0_unimplemented;
6571 break;
6572 case 4:
6573 switch (sel) {
6574 case 0:
6575 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6576 tcg_gen_ext32s_tl(arg, arg);
6577 rn = "Context";
6578 break;
6579 case 1:
6580 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6581 rn = "ContextConfig";
6582 goto cp0_unimplemented;
6583 case 2:
6584 CP0_CHECK(ctx->ulri);
6585 tcg_gen_ld_tl(arg, cpu_env,
6586 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6587 tcg_gen_ext32s_tl(arg, arg);
6588 rn = "UserLocal";
6589 break;
6590 default:
6591 goto cp0_unimplemented;
6593 break;
6594 case 5:
6595 switch (sel) {
6596 case 0:
6597 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6598 rn = "PageMask";
6599 break;
6600 case 1:
6601 check_insn(ctx, ISA_MIPS32R2);
6602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6603 rn = "PageGrain";
6604 break;
6605 case 2:
6606 CP0_CHECK(ctx->sc);
6607 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6608 tcg_gen_ext32s_tl(arg, arg);
6609 rn = "SegCtl0";
6610 break;
6611 case 3:
6612 CP0_CHECK(ctx->sc);
6613 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6614 tcg_gen_ext32s_tl(arg, arg);
6615 rn = "SegCtl1";
6616 break;
6617 case 4:
6618 CP0_CHECK(ctx->sc);
6619 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6620 tcg_gen_ext32s_tl(arg, arg);
6621 rn = "SegCtl2";
6622 break;
6623 case 5:
6624 check_pw(ctx);
6625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6626 rn = "PWBase";
6627 break;
6628 case 6:
6629 check_pw(ctx);
6630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6631 rn = "PWField";
6632 break;
6633 case 7:
6634 check_pw(ctx);
6635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6636 rn = "PWSize";
6637 break;
6638 default:
6639 goto cp0_unimplemented;
6641 break;
6642 case 6:
6643 switch (sel) {
6644 case 0:
6645 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6646 rn = "Wired";
6647 break;
6648 case 1:
6649 check_insn(ctx, ISA_MIPS32R2);
6650 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6651 rn = "SRSConf0";
6652 break;
6653 case 2:
6654 check_insn(ctx, ISA_MIPS32R2);
6655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6656 rn = "SRSConf1";
6657 break;
6658 case 3:
6659 check_insn(ctx, ISA_MIPS32R2);
6660 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6661 rn = "SRSConf2";
6662 break;
6663 case 4:
6664 check_insn(ctx, ISA_MIPS32R2);
6665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6666 rn = "SRSConf3";
6667 break;
6668 case 5:
6669 check_insn(ctx, ISA_MIPS32R2);
6670 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6671 rn = "SRSConf4";
6672 break;
6673 case 6:
6674 check_pw(ctx);
6675 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6676 rn = "PWCtl";
6677 break;
6678 default:
6679 goto cp0_unimplemented;
6681 break;
6682 case 7:
6683 switch (sel) {
6684 case 0:
6685 check_insn(ctx, ISA_MIPS32R2);
6686 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6687 rn = "HWREna";
6688 break;
6689 default:
6690 goto cp0_unimplemented;
6692 break;
6693 case 8:
6694 switch (sel) {
6695 case 0:
6696 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6697 tcg_gen_ext32s_tl(arg, arg);
6698 rn = "BadVAddr";
6699 break;
6700 case 1:
6701 CP0_CHECK(ctx->bi);
6702 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6703 rn = "BadInstr";
6704 break;
6705 case 2:
6706 CP0_CHECK(ctx->bp);
6707 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6708 rn = "BadInstrP";
6709 break;
6710 case 3:
6711 CP0_CHECK(ctx->bi);
6712 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6713 tcg_gen_andi_tl(arg, arg, ~0xffff);
6714 rn = "BadInstrX";
6715 break;
6716 default:
6717 goto cp0_unimplemented;
6719 break;
6720 case 9:
6721 switch (sel) {
6722 case 0:
6723 /* Mark as an IO operation because we read the time. */
6724 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6725 gen_io_start();
6727 gen_helper_mfc0_count(arg, cpu_env);
6728 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6729 gen_io_end();
6731 /* Break the TB to be able to take timer interrupts immediately
6732 after reading count. DISAS_STOP isn't sufficient, we need to
6733 ensure we break completely out of translated code. */
6734 gen_save_pc(ctx->base.pc_next + 4);
6735 ctx->base.is_jmp = DISAS_EXIT;
6736 rn = "Count";
6737 break;
6738 /* 6,7 are implementation dependent */
6739 default:
6740 goto cp0_unimplemented;
6742 break;
6743 case 10:
6744 switch (sel) {
6745 case 0:
6746 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6747 tcg_gen_ext32s_tl(arg, arg);
6748 rn = "EntryHi";
6749 break;
6750 default:
6751 goto cp0_unimplemented;
6753 break;
6754 case 11:
6755 switch (sel) {
6756 case 0:
6757 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6758 rn = "Compare";
6759 break;
6760 /* 6,7 are implementation dependent */
6761 default:
6762 goto cp0_unimplemented;
6764 break;
6765 case 12:
6766 switch (sel) {
6767 case 0:
6768 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6769 rn = "Status";
6770 break;
6771 case 1:
6772 check_insn(ctx, ISA_MIPS32R2);
6773 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6774 rn = "IntCtl";
6775 break;
6776 case 2:
6777 check_insn(ctx, ISA_MIPS32R2);
6778 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6779 rn = "SRSCtl";
6780 break;
6781 case 3:
6782 check_insn(ctx, ISA_MIPS32R2);
6783 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6784 rn = "SRSMap";
6785 break;
6786 default:
6787 goto cp0_unimplemented;
6789 break;
6790 case 13:
6791 switch (sel) {
6792 case 0:
6793 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6794 rn = "Cause";
6795 break;
6796 default:
6797 goto cp0_unimplemented;
6799 break;
6800 case 14:
6801 switch (sel) {
6802 case 0:
6803 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6804 tcg_gen_ext32s_tl(arg, arg);
6805 rn = "EPC";
6806 break;
6807 default:
6808 goto cp0_unimplemented;
6810 break;
6811 case 15:
6812 switch (sel) {
6813 case 0:
6814 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6815 rn = "PRid";
6816 break;
6817 case 1:
6818 check_insn(ctx, ISA_MIPS32R2);
6819 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6820 tcg_gen_ext32s_tl(arg, arg);
6821 rn = "EBase";
6822 break;
6823 case 3:
6824 check_insn(ctx, ISA_MIPS32R2);
6825 CP0_CHECK(ctx->cmgcr);
6826 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6827 tcg_gen_ext32s_tl(arg, arg);
6828 rn = "CMGCRBase";
6829 break;
6830 default:
6831 goto cp0_unimplemented;
6833 break;
6834 case 16:
6835 switch (sel) {
6836 case 0:
6837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6838 rn = "Config";
6839 break;
6840 case 1:
6841 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6842 rn = "Config1";
6843 break;
6844 case 2:
6845 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6846 rn = "Config2";
6847 break;
6848 case 3:
6849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6850 rn = "Config3";
6851 break;
6852 case 4:
6853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6854 rn = "Config4";
6855 break;
6856 case 5:
6857 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6858 rn = "Config5";
6859 break;
6860 /* 6,7 are implementation dependent */
6861 case 6:
6862 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6863 rn = "Config6";
6864 break;
6865 case 7:
6866 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6867 rn = "Config7";
6868 break;
6869 default:
6870 goto cp0_unimplemented;
6872 break;
6873 case 17:
6874 switch (sel) {
6875 case 0:
6876 gen_helper_mfc0_lladdr(arg, cpu_env);
6877 rn = "LLAddr";
6878 break;
6879 case 1:
6880 CP0_CHECK(ctx->mrp);
6881 gen_helper_mfc0_maar(arg, cpu_env);
6882 rn = "MAAR";
6883 break;
6884 case 2:
6885 CP0_CHECK(ctx->mrp);
6886 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6887 rn = "MAARI";
6888 break;
6889 default:
6890 goto cp0_unimplemented;
6892 break;
6893 case 18:
6894 switch (sel) {
6895 case 0:
6896 case 1:
6897 case 2:
6898 case 3:
6899 case 4:
6900 case 5:
6901 case 6:
6902 case 7:
6903 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6904 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6905 rn = "WatchLo";
6906 break;
6907 default:
6908 goto cp0_unimplemented;
6910 break;
6911 case 19:
6912 switch (sel) {
6913 case 0:
6914 case 1:
6915 case 2:
6916 case 3:
6917 case 4:
6918 case 5:
6919 case 6:
6920 case 7:
6921 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6922 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6923 rn = "WatchHi";
6924 break;
6925 default:
6926 goto cp0_unimplemented;
6928 break;
6929 case 20:
6930 switch (sel) {
6931 case 0:
6932 #if defined(TARGET_MIPS64)
6933 check_insn(ctx, ISA_MIPS3);
6934 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6935 tcg_gen_ext32s_tl(arg, arg);
6936 rn = "XContext";
6937 break;
6938 #endif
6939 default:
6940 goto cp0_unimplemented;
6942 break;
6943 case 21:
6944 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6945 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6946 switch (sel) {
6947 case 0:
6948 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6949 rn = "Framemask";
6950 break;
6951 default:
6952 goto cp0_unimplemented;
6954 break;
6955 case 22:
6956 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6957 rn = "'Diagnostic"; /* implementation dependent */
6958 break;
6959 case 23:
6960 switch (sel) {
6961 case 0:
6962 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6963 rn = "Debug";
6964 break;
6965 case 1:
6966 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
6967 rn = "TraceControl";
6968 goto cp0_unimplemented;
6969 case 2:
6970 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
6971 rn = "TraceControl2";
6972 goto cp0_unimplemented;
6973 case 3:
6974 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
6975 rn = "UserTraceData";
6976 goto cp0_unimplemented;
6977 case 4:
6978 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
6979 rn = "TraceBPC";
6980 goto cp0_unimplemented;
6981 default:
6982 goto cp0_unimplemented;
6984 break;
6985 case 24:
6986 switch (sel) {
6987 case 0:
6988 /* EJTAG support */
6989 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6990 tcg_gen_ext32s_tl(arg, arg);
6991 rn = "DEPC";
6992 break;
6993 default:
6994 goto cp0_unimplemented;
6996 break;
6997 case 25:
6998 switch (sel) {
6999 case 0:
7000 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7001 rn = "Performance0";
7002 break;
7003 case 1:
7004 // gen_helper_mfc0_performance1(arg);
7005 rn = "Performance1";
7006 goto cp0_unimplemented;
7007 case 2:
7008 // gen_helper_mfc0_performance2(arg);
7009 rn = "Performance2";
7010 goto cp0_unimplemented;
7011 case 3:
7012 // gen_helper_mfc0_performance3(arg);
7013 rn = "Performance3";
7014 goto cp0_unimplemented;
7015 case 4:
7016 // gen_helper_mfc0_performance4(arg);
7017 rn = "Performance4";
7018 goto cp0_unimplemented;
7019 case 5:
7020 // gen_helper_mfc0_performance5(arg);
7021 rn = "Performance5";
7022 goto cp0_unimplemented;
7023 case 6:
7024 // gen_helper_mfc0_performance6(arg);
7025 rn = "Performance6";
7026 goto cp0_unimplemented;
7027 case 7:
7028 // gen_helper_mfc0_performance7(arg);
7029 rn = "Performance7";
7030 goto cp0_unimplemented;
7031 default:
7032 goto cp0_unimplemented;
7034 break;
7035 case 26:
7036 switch (sel) {
7037 case 0:
7038 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7039 rn = "ErrCtl";
7040 break;
7041 default:
7042 goto cp0_unimplemented;
7044 break;
7045 case 27:
7046 switch (sel) {
7047 case 0:
7048 case 1:
7049 case 2:
7050 case 3:
7051 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7052 rn = "CacheErr";
7053 break;
7054 default:
7055 goto cp0_unimplemented;
7057 break;
7058 case 28:
7059 switch (sel) {
7060 case 0:
7061 case 2:
7062 case 4:
7063 case 6:
7065 TCGv_i64 tmp = tcg_temp_new_i64();
7066 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7067 gen_move_low32(arg, tmp);
7068 tcg_temp_free_i64(tmp);
7070 rn = "TagLo";
7071 break;
7072 case 1:
7073 case 3:
7074 case 5:
7075 case 7:
7076 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7077 rn = "DataLo";
7078 break;
7079 default:
7080 goto cp0_unimplemented;
7082 break;
7083 case 29:
7084 switch (sel) {
7085 case 0:
7086 case 2:
7087 case 4:
7088 case 6:
7089 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7090 rn = "TagHi";
7091 break;
7092 case 1:
7093 case 3:
7094 case 5:
7095 case 7:
7096 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7097 rn = "DataHi";
7098 break;
7099 default:
7100 goto cp0_unimplemented;
7102 break;
7103 case 30:
7104 switch (sel) {
7105 case 0:
7106 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7107 tcg_gen_ext32s_tl(arg, arg);
7108 rn = "ErrorEPC";
7109 break;
7110 default:
7111 goto cp0_unimplemented;
7113 break;
7114 case 31:
7115 switch (sel) {
7116 case 0:
7117 /* EJTAG support */
7118 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7119 rn = "DESAVE";
7120 break;
7121 case 2:
7122 case 3:
7123 case 4:
7124 case 5:
7125 case 6:
7126 case 7:
7127 CP0_CHECK(ctx->kscrexist & (1 << sel));
7128 tcg_gen_ld_tl(arg, cpu_env,
7129 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7130 tcg_gen_ext32s_tl(arg, arg);
7131 rn = "KScratch";
7132 break;
7133 default:
7134 goto cp0_unimplemented;
7136 break;
7137 default:
7138 goto cp0_unimplemented;
7140 trace_mips_translate_c0("mfc0", rn, reg, sel);
7141 return;
7143 cp0_unimplemented:
7144 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7145 gen_mfc0_unimplemented(ctx, arg);
7148 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7150 const char *rn = "invalid";
7152 if (sel != 0)
7153 check_insn(ctx, ISA_MIPS32);
7155 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7156 gen_io_start();
7159 switch (reg) {
7160 case 0:
7161 switch (sel) {
7162 case 0:
7163 gen_helper_mtc0_index(cpu_env, arg);
7164 rn = "Index";
7165 break;
7166 case 1:
7167 CP0_CHECK(ctx->insn_flags & ASE_MT);
7168 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7169 rn = "MVPControl";
7170 break;
7171 case 2:
7172 CP0_CHECK(ctx->insn_flags & ASE_MT);
7173 /* ignored */
7174 rn = "MVPConf0";
7175 break;
7176 case 3:
7177 CP0_CHECK(ctx->insn_flags & ASE_MT);
7178 /* ignored */
7179 rn = "MVPConf1";
7180 break;
7181 case 4:
7182 CP0_CHECK(ctx->vp);
7183 /* ignored */
7184 rn = "VPControl";
7185 break;
7186 default:
7187 goto cp0_unimplemented;
7189 break;
7190 case 1:
7191 switch (sel) {
7192 case 0:
7193 /* ignored */
7194 rn = "Random";
7195 break;
7196 case 1:
7197 CP0_CHECK(ctx->insn_flags & ASE_MT);
7198 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7199 rn = "VPEControl";
7200 break;
7201 case 2:
7202 CP0_CHECK(ctx->insn_flags & ASE_MT);
7203 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7204 rn = "VPEConf0";
7205 break;
7206 case 3:
7207 CP0_CHECK(ctx->insn_flags & ASE_MT);
7208 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7209 rn = "VPEConf1";
7210 break;
7211 case 4:
7212 CP0_CHECK(ctx->insn_flags & ASE_MT);
7213 gen_helper_mtc0_yqmask(cpu_env, arg);
7214 rn = "YQMask";
7215 break;
7216 case 5:
7217 CP0_CHECK(ctx->insn_flags & ASE_MT);
7218 tcg_gen_st_tl(arg, cpu_env,
7219 offsetof(CPUMIPSState, CP0_VPESchedule));
7220 rn = "VPESchedule";
7221 break;
7222 case 6:
7223 CP0_CHECK(ctx->insn_flags & ASE_MT);
7224 tcg_gen_st_tl(arg, cpu_env,
7225 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7226 rn = "VPEScheFBack";
7227 break;
7228 case 7:
7229 CP0_CHECK(ctx->insn_flags & ASE_MT);
7230 gen_helper_mtc0_vpeopt(cpu_env, arg);
7231 rn = "VPEOpt";
7232 break;
7233 default:
7234 goto cp0_unimplemented;
7236 break;
7237 case 2:
7238 switch (sel) {
7239 case 0:
7240 gen_helper_mtc0_entrylo0(cpu_env, arg);
7241 rn = "EntryLo0";
7242 break;
7243 case 1:
7244 CP0_CHECK(ctx->insn_flags & ASE_MT);
7245 gen_helper_mtc0_tcstatus(cpu_env, arg);
7246 rn = "TCStatus";
7247 break;
7248 case 2:
7249 CP0_CHECK(ctx->insn_flags & ASE_MT);
7250 gen_helper_mtc0_tcbind(cpu_env, arg);
7251 rn = "TCBind";
7252 break;
7253 case 3:
7254 CP0_CHECK(ctx->insn_flags & ASE_MT);
7255 gen_helper_mtc0_tcrestart(cpu_env, arg);
7256 rn = "TCRestart";
7257 break;
7258 case 4:
7259 CP0_CHECK(ctx->insn_flags & ASE_MT);
7260 gen_helper_mtc0_tchalt(cpu_env, arg);
7261 rn = "TCHalt";
7262 break;
7263 case 5:
7264 CP0_CHECK(ctx->insn_flags & ASE_MT);
7265 gen_helper_mtc0_tccontext(cpu_env, arg);
7266 rn = "TCContext";
7267 break;
7268 case 6:
7269 CP0_CHECK(ctx->insn_flags & ASE_MT);
7270 gen_helper_mtc0_tcschedule(cpu_env, arg);
7271 rn = "TCSchedule";
7272 break;
7273 case 7:
7274 CP0_CHECK(ctx->insn_flags & ASE_MT);
7275 gen_helper_mtc0_tcschefback(cpu_env, arg);
7276 rn = "TCScheFBack";
7277 break;
7278 default:
7279 goto cp0_unimplemented;
7281 break;
7282 case 3:
7283 switch (sel) {
7284 case 0:
7285 gen_helper_mtc0_entrylo1(cpu_env, arg);
7286 rn = "EntryLo1";
7287 break;
7288 case 1:
7289 CP0_CHECK(ctx->vp);
7290 /* ignored */
7291 rn = "GlobalNumber";
7292 break;
7293 default:
7294 goto cp0_unimplemented;
7296 break;
7297 case 4:
7298 switch (sel) {
7299 case 0:
7300 gen_helper_mtc0_context(cpu_env, arg);
7301 rn = "Context";
7302 break;
7303 case 1:
7304 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7305 rn = "ContextConfig";
7306 goto cp0_unimplemented;
7307 case 2:
7308 CP0_CHECK(ctx->ulri);
7309 tcg_gen_st_tl(arg, cpu_env,
7310 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7311 rn = "UserLocal";
7312 break;
7313 default:
7314 goto cp0_unimplemented;
7316 break;
7317 case 5:
7318 switch (sel) {
7319 case 0:
7320 gen_helper_mtc0_pagemask(cpu_env, arg);
7321 rn = "PageMask";
7322 break;
7323 case 1:
7324 check_insn(ctx, ISA_MIPS32R2);
7325 gen_helper_mtc0_pagegrain(cpu_env, arg);
7326 rn = "PageGrain";
7327 ctx->base.is_jmp = DISAS_STOP;
7328 break;
7329 case 2:
7330 CP0_CHECK(ctx->sc);
7331 gen_helper_mtc0_segctl0(cpu_env, arg);
7332 rn = "SegCtl0";
7333 break;
7334 case 3:
7335 CP0_CHECK(ctx->sc);
7336 gen_helper_mtc0_segctl1(cpu_env, arg);
7337 rn = "SegCtl1";
7338 break;
7339 case 4:
7340 CP0_CHECK(ctx->sc);
7341 gen_helper_mtc0_segctl2(cpu_env, arg);
7342 rn = "SegCtl2";
7343 break;
7344 case 5:
7345 check_pw(ctx);
7346 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7347 rn = "PWBase";
7348 break;
7349 case 6:
7350 check_pw(ctx);
7351 gen_helper_mtc0_pwfield(cpu_env, arg);
7352 rn = "PWField";
7353 break;
7354 case 7:
7355 check_pw(ctx);
7356 gen_helper_mtc0_pwsize(cpu_env, arg);
7357 rn = "PWSize";
7358 break;
7359 default:
7360 goto cp0_unimplemented;
7362 break;
7363 case 6:
7364 switch (sel) {
7365 case 0:
7366 gen_helper_mtc0_wired(cpu_env, arg);
7367 rn = "Wired";
7368 break;
7369 case 1:
7370 check_insn(ctx, ISA_MIPS32R2);
7371 gen_helper_mtc0_srsconf0(cpu_env, arg);
7372 rn = "SRSConf0";
7373 break;
7374 case 2:
7375 check_insn(ctx, ISA_MIPS32R2);
7376 gen_helper_mtc0_srsconf1(cpu_env, arg);
7377 rn = "SRSConf1";
7378 break;
7379 case 3:
7380 check_insn(ctx, ISA_MIPS32R2);
7381 gen_helper_mtc0_srsconf2(cpu_env, arg);
7382 rn = "SRSConf2";
7383 break;
7384 case 4:
7385 check_insn(ctx, ISA_MIPS32R2);
7386 gen_helper_mtc0_srsconf3(cpu_env, arg);
7387 rn = "SRSConf3";
7388 break;
7389 case 5:
7390 check_insn(ctx, ISA_MIPS32R2);
7391 gen_helper_mtc0_srsconf4(cpu_env, arg);
7392 rn = "SRSConf4";
7393 break;
7394 case 6:
7395 check_pw(ctx);
7396 gen_helper_mtc0_pwctl(cpu_env, arg);
7397 rn = "PWCtl";
7398 break;
7399 default:
7400 goto cp0_unimplemented;
7402 break;
7403 case 7:
7404 switch (sel) {
7405 case 0:
7406 check_insn(ctx, ISA_MIPS32R2);
7407 gen_helper_mtc0_hwrena(cpu_env, arg);
7408 ctx->base.is_jmp = DISAS_STOP;
7409 rn = "HWREna";
7410 break;
7411 default:
7412 goto cp0_unimplemented;
7414 break;
7415 case 8:
7416 switch (sel) {
7417 case 0:
7418 /* ignored */
7419 rn = "BadVAddr";
7420 break;
7421 case 1:
7422 /* ignored */
7423 rn = "BadInstr";
7424 break;
7425 case 2:
7426 /* ignored */
7427 rn = "BadInstrP";
7428 break;
7429 case 3:
7430 /* ignored */
7431 rn = "BadInstrX";
7432 break;
7433 default:
7434 goto cp0_unimplemented;
7436 break;
7437 case 9:
7438 switch (sel) {
7439 case 0:
7440 gen_helper_mtc0_count(cpu_env, arg);
7441 rn = "Count";
7442 break;
7443 /* 6,7 are implementation dependent */
7444 default:
7445 goto cp0_unimplemented;
7447 break;
7448 case 10:
7449 switch (sel) {
7450 case 0:
7451 gen_helper_mtc0_entryhi(cpu_env, arg);
7452 rn = "EntryHi";
7453 break;
7454 default:
7455 goto cp0_unimplemented;
7457 break;
7458 case 11:
7459 switch (sel) {
7460 case 0:
7461 gen_helper_mtc0_compare(cpu_env, arg);
7462 rn = "Compare";
7463 break;
7464 /* 6,7 are implementation dependent */
7465 default:
7466 goto cp0_unimplemented;
7468 break;
7469 case 12:
7470 switch (sel) {
7471 case 0:
7472 save_cpu_state(ctx, 1);
7473 gen_helper_mtc0_status(cpu_env, arg);
7474 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7475 gen_save_pc(ctx->base.pc_next + 4);
7476 ctx->base.is_jmp = DISAS_EXIT;
7477 rn = "Status";
7478 break;
7479 case 1:
7480 check_insn(ctx, ISA_MIPS32R2);
7481 gen_helper_mtc0_intctl(cpu_env, arg);
7482 /* Stop translation as we may have switched the execution mode */
7483 ctx->base.is_jmp = DISAS_STOP;
7484 rn = "IntCtl";
7485 break;
7486 case 2:
7487 check_insn(ctx, ISA_MIPS32R2);
7488 gen_helper_mtc0_srsctl(cpu_env, arg);
7489 /* Stop translation as we may have switched the execution mode */
7490 ctx->base.is_jmp = DISAS_STOP;
7491 rn = "SRSCtl";
7492 break;
7493 case 3:
7494 check_insn(ctx, ISA_MIPS32R2);
7495 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7496 /* Stop translation as we may have switched the execution mode */
7497 ctx->base.is_jmp = DISAS_STOP;
7498 rn = "SRSMap";
7499 break;
7500 default:
7501 goto cp0_unimplemented;
7503 break;
7504 case 13:
7505 switch (sel) {
7506 case 0:
7507 save_cpu_state(ctx, 1);
7508 gen_helper_mtc0_cause(cpu_env, arg);
7509 /* Stop translation as we may have triggered an interrupt.
7510 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7511 * translated code to check for pending interrupts. */
7512 gen_save_pc(ctx->base.pc_next + 4);
7513 ctx->base.is_jmp = DISAS_EXIT;
7514 rn = "Cause";
7515 break;
7516 default:
7517 goto cp0_unimplemented;
7519 break;
7520 case 14:
7521 switch (sel) {
7522 case 0:
7523 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7524 rn = "EPC";
7525 break;
7526 default:
7527 goto cp0_unimplemented;
7529 break;
7530 case 15:
7531 switch (sel) {
7532 case 0:
7533 /* ignored */
7534 rn = "PRid";
7535 break;
7536 case 1:
7537 check_insn(ctx, ISA_MIPS32R2);
7538 gen_helper_mtc0_ebase(cpu_env, arg);
7539 rn = "EBase";
7540 break;
7541 default:
7542 goto cp0_unimplemented;
7544 break;
7545 case 16:
7546 switch (sel) {
7547 case 0:
7548 gen_helper_mtc0_config0(cpu_env, arg);
7549 rn = "Config";
7550 /* Stop translation as we may have switched the execution mode */
7551 ctx->base.is_jmp = DISAS_STOP;
7552 break;
7553 case 1:
7554 /* ignored, read only */
7555 rn = "Config1";
7556 break;
7557 case 2:
7558 gen_helper_mtc0_config2(cpu_env, arg);
7559 rn = "Config2";
7560 /* Stop translation as we may have switched the execution mode */
7561 ctx->base.is_jmp = DISAS_STOP;
7562 break;
7563 case 3:
7564 gen_helper_mtc0_config3(cpu_env, arg);
7565 rn = "Config3";
7566 /* Stop translation as we may have switched the execution mode */
7567 ctx->base.is_jmp = DISAS_STOP;
7568 break;
7569 case 4:
7570 gen_helper_mtc0_config4(cpu_env, arg);
7571 rn = "Config4";
7572 ctx->base.is_jmp = DISAS_STOP;
7573 break;
7574 case 5:
7575 gen_helper_mtc0_config5(cpu_env, arg);
7576 rn = "Config5";
7577 /* Stop translation as we may have switched the execution mode */
7578 ctx->base.is_jmp = DISAS_STOP;
7579 break;
7580 /* 6,7 are implementation dependent */
7581 case 6:
7582 /* ignored */
7583 rn = "Config6";
7584 break;
7585 case 7:
7586 /* ignored */
7587 rn = "Config7";
7588 break;
7589 default:
7590 rn = "Invalid config selector";
7591 goto cp0_unimplemented;
7593 break;
7594 case 17:
7595 switch (sel) {
7596 case 0:
7597 gen_helper_mtc0_lladdr(cpu_env, arg);
7598 rn = "LLAddr";
7599 break;
7600 case 1:
7601 CP0_CHECK(ctx->mrp);
7602 gen_helper_mtc0_maar(cpu_env, arg);
7603 rn = "MAAR";
7604 break;
7605 case 2:
7606 CP0_CHECK(ctx->mrp);
7607 gen_helper_mtc0_maari(cpu_env, arg);
7608 rn = "MAARI";
7609 break;
7610 default:
7611 goto cp0_unimplemented;
7613 break;
7614 case 18:
7615 switch (sel) {
7616 case 0:
7617 case 1:
7618 case 2:
7619 case 3:
7620 case 4:
7621 case 5:
7622 case 6:
7623 case 7:
7624 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7625 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7626 rn = "WatchLo";
7627 break;
7628 default:
7629 goto cp0_unimplemented;
7631 break;
7632 case 19:
7633 switch (sel) {
7634 case 0:
7635 case 1:
7636 case 2:
7637 case 3:
7638 case 4:
7639 case 5:
7640 case 6:
7641 case 7:
7642 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7643 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7644 rn = "WatchHi";
7645 break;
7646 default:
7647 goto cp0_unimplemented;
7649 break;
7650 case 20:
7651 switch (sel) {
7652 case 0:
7653 #if defined(TARGET_MIPS64)
7654 check_insn(ctx, ISA_MIPS3);
7655 gen_helper_mtc0_xcontext(cpu_env, arg);
7656 rn = "XContext";
7657 break;
7658 #endif
7659 default:
7660 goto cp0_unimplemented;
7662 break;
7663 case 21:
7664 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7665 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7666 switch (sel) {
7667 case 0:
7668 gen_helper_mtc0_framemask(cpu_env, arg);
7669 rn = "Framemask";
7670 break;
7671 default:
7672 goto cp0_unimplemented;
7674 break;
7675 case 22:
7676 /* ignored */
7677 rn = "Diagnostic"; /* implementation dependent */
7678 break;
7679 case 23:
7680 switch (sel) {
7681 case 0:
7682 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7683 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7684 gen_save_pc(ctx->base.pc_next + 4);
7685 ctx->base.is_jmp = DISAS_EXIT;
7686 rn = "Debug";
7687 break;
7688 case 1:
7689 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7690 rn = "TraceControl";
7691 /* Stop translation as we may have switched the execution mode */
7692 ctx->base.is_jmp = DISAS_STOP;
7693 goto cp0_unimplemented;
7694 case 2:
7695 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7696 rn = "TraceControl2";
7697 /* Stop translation as we may have switched the execution mode */
7698 ctx->base.is_jmp = DISAS_STOP;
7699 goto cp0_unimplemented;
7700 case 3:
7701 /* Stop translation as we may have switched the execution mode */
7702 ctx->base.is_jmp = DISAS_STOP;
7703 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7704 rn = "UserTraceData";
7705 /* Stop translation as we may have switched the execution mode */
7706 ctx->base.is_jmp = DISAS_STOP;
7707 goto cp0_unimplemented;
7708 case 4:
7709 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7710 /* Stop translation as we may have switched the execution mode */
7711 ctx->base.is_jmp = DISAS_STOP;
7712 rn = "TraceBPC";
7713 goto cp0_unimplemented;
7714 default:
7715 goto cp0_unimplemented;
7717 break;
7718 case 24:
7719 switch (sel) {
7720 case 0:
7721 /* EJTAG support */
7722 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7723 rn = "DEPC";
7724 break;
7725 default:
7726 goto cp0_unimplemented;
7728 break;
7729 case 25:
7730 switch (sel) {
7731 case 0:
7732 gen_helper_mtc0_performance0(cpu_env, arg);
7733 rn = "Performance0";
7734 break;
7735 case 1:
7736 // gen_helper_mtc0_performance1(arg);
7737 rn = "Performance1";
7738 goto cp0_unimplemented;
7739 case 2:
7740 // gen_helper_mtc0_performance2(arg);
7741 rn = "Performance2";
7742 goto cp0_unimplemented;
7743 case 3:
7744 // gen_helper_mtc0_performance3(arg);
7745 rn = "Performance3";
7746 goto cp0_unimplemented;
7747 case 4:
7748 // gen_helper_mtc0_performance4(arg);
7749 rn = "Performance4";
7750 goto cp0_unimplemented;
7751 case 5:
7752 // gen_helper_mtc0_performance5(arg);
7753 rn = "Performance5";
7754 goto cp0_unimplemented;
7755 case 6:
7756 // gen_helper_mtc0_performance6(arg);
7757 rn = "Performance6";
7758 goto cp0_unimplemented;
7759 case 7:
7760 // gen_helper_mtc0_performance7(arg);
7761 rn = "Performance7";
7762 goto cp0_unimplemented;
7763 default:
7764 goto cp0_unimplemented;
7766 break;
7767 case 26:
7768 switch (sel) {
7769 case 0:
7770 gen_helper_mtc0_errctl(cpu_env, arg);
7771 ctx->base.is_jmp = DISAS_STOP;
7772 rn = "ErrCtl";
7773 break;
7774 default:
7775 goto cp0_unimplemented;
7777 break;
7778 case 27:
7779 switch (sel) {
7780 case 0:
7781 case 1:
7782 case 2:
7783 case 3:
7784 /* ignored */
7785 rn = "CacheErr";
7786 break;
7787 default:
7788 goto cp0_unimplemented;
7790 break;
7791 case 28:
7792 switch (sel) {
7793 case 0:
7794 case 2:
7795 case 4:
7796 case 6:
7797 gen_helper_mtc0_taglo(cpu_env, arg);
7798 rn = "TagLo";
7799 break;
7800 case 1:
7801 case 3:
7802 case 5:
7803 case 7:
7804 gen_helper_mtc0_datalo(cpu_env, arg);
7805 rn = "DataLo";
7806 break;
7807 default:
7808 goto cp0_unimplemented;
7810 break;
7811 case 29:
7812 switch (sel) {
7813 case 0:
7814 case 2:
7815 case 4:
7816 case 6:
7817 gen_helper_mtc0_taghi(cpu_env, arg);
7818 rn = "TagHi";
7819 break;
7820 case 1:
7821 case 3:
7822 case 5:
7823 case 7:
7824 gen_helper_mtc0_datahi(cpu_env, arg);
7825 rn = "DataHi";
7826 break;
7827 default:
7828 rn = "invalid sel";
7829 goto cp0_unimplemented;
7831 break;
7832 case 30:
7833 switch (sel) {
7834 case 0:
7835 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7836 rn = "ErrorEPC";
7837 break;
7838 default:
7839 goto cp0_unimplemented;
7841 break;
7842 case 31:
7843 switch (sel) {
7844 case 0:
7845 /* EJTAG support */
7846 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7847 rn = "DESAVE";
7848 break;
7849 case 2:
7850 case 3:
7851 case 4:
7852 case 5:
7853 case 6:
7854 case 7:
7855 CP0_CHECK(ctx->kscrexist & (1 << sel));
7856 tcg_gen_st_tl(arg, cpu_env,
7857 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7858 rn = "KScratch";
7859 break;
7860 default:
7861 goto cp0_unimplemented;
7863 break;
7864 default:
7865 goto cp0_unimplemented;
7867 trace_mips_translate_c0("mtc0", rn, reg, sel);
7869 /* For simplicity assume that all writes can cause interrupts. */
7870 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7871 gen_io_end();
7872 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7873 * translated code to check for pending interrupts. */
7874 gen_save_pc(ctx->base.pc_next + 4);
7875 ctx->base.is_jmp = DISAS_EXIT;
7877 return;
7879 cp0_unimplemented:
7880 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7883 #if defined(TARGET_MIPS64)
7884 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7886 const char *rn = "invalid";
7888 if (sel != 0)
7889 check_insn(ctx, ISA_MIPS64);
7891 switch (reg) {
7892 case 0:
7893 switch (sel) {
7894 case 0:
7895 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7896 rn = "Index";
7897 break;
7898 case 1:
7899 CP0_CHECK(ctx->insn_flags & ASE_MT);
7900 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7901 rn = "MVPControl";
7902 break;
7903 case 2:
7904 CP0_CHECK(ctx->insn_flags & ASE_MT);
7905 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7906 rn = "MVPConf0";
7907 break;
7908 case 3:
7909 CP0_CHECK(ctx->insn_flags & ASE_MT);
7910 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7911 rn = "MVPConf1";
7912 break;
7913 case 4:
7914 CP0_CHECK(ctx->vp);
7915 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7916 rn = "VPControl";
7917 break;
7918 default:
7919 goto cp0_unimplemented;
7921 break;
7922 case 1:
7923 switch (sel) {
7924 case 0:
7925 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7926 gen_helper_mfc0_random(arg, cpu_env);
7927 rn = "Random";
7928 break;
7929 case 1:
7930 CP0_CHECK(ctx->insn_flags & ASE_MT);
7931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7932 rn = "VPEControl";
7933 break;
7934 case 2:
7935 CP0_CHECK(ctx->insn_flags & ASE_MT);
7936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7937 rn = "VPEConf0";
7938 break;
7939 case 3:
7940 CP0_CHECK(ctx->insn_flags & ASE_MT);
7941 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7942 rn = "VPEConf1";
7943 break;
7944 case 4:
7945 CP0_CHECK(ctx->insn_flags & ASE_MT);
7946 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7947 rn = "YQMask";
7948 break;
7949 case 5:
7950 CP0_CHECK(ctx->insn_flags & ASE_MT);
7951 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7952 rn = "VPESchedule";
7953 break;
7954 case 6:
7955 CP0_CHECK(ctx->insn_flags & ASE_MT);
7956 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7957 rn = "VPEScheFBack";
7958 break;
7959 case 7:
7960 CP0_CHECK(ctx->insn_flags & ASE_MT);
7961 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7962 rn = "VPEOpt";
7963 break;
7964 default:
7965 goto cp0_unimplemented;
7967 break;
7968 case 2:
7969 switch (sel) {
7970 case 0:
7971 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7972 rn = "EntryLo0";
7973 break;
7974 case 1:
7975 CP0_CHECK(ctx->insn_flags & ASE_MT);
7976 gen_helper_mfc0_tcstatus(arg, cpu_env);
7977 rn = "TCStatus";
7978 break;
7979 case 2:
7980 CP0_CHECK(ctx->insn_flags & ASE_MT);
7981 gen_helper_mfc0_tcbind(arg, cpu_env);
7982 rn = "TCBind";
7983 break;
7984 case 3:
7985 CP0_CHECK(ctx->insn_flags & ASE_MT);
7986 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7987 rn = "TCRestart";
7988 break;
7989 case 4:
7990 CP0_CHECK(ctx->insn_flags & ASE_MT);
7991 gen_helper_dmfc0_tchalt(arg, cpu_env);
7992 rn = "TCHalt";
7993 break;
7994 case 5:
7995 CP0_CHECK(ctx->insn_flags & ASE_MT);
7996 gen_helper_dmfc0_tccontext(arg, cpu_env);
7997 rn = "TCContext";
7998 break;
7999 case 6:
8000 CP0_CHECK(ctx->insn_flags & ASE_MT);
8001 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8002 rn = "TCSchedule";
8003 break;
8004 case 7:
8005 CP0_CHECK(ctx->insn_flags & ASE_MT);
8006 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8007 rn = "TCScheFBack";
8008 break;
8009 default:
8010 goto cp0_unimplemented;
8012 break;
8013 case 3:
8014 switch (sel) {
8015 case 0:
8016 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8017 rn = "EntryLo1";
8018 break;
8019 case 1:
8020 CP0_CHECK(ctx->vp);
8021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8022 rn = "GlobalNumber";
8023 break;
8024 default:
8025 goto cp0_unimplemented;
8027 break;
8028 case 4:
8029 switch (sel) {
8030 case 0:
8031 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8032 rn = "Context";
8033 break;
8034 case 1:
8035 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
8036 rn = "ContextConfig";
8037 goto cp0_unimplemented;
8038 case 2:
8039 CP0_CHECK(ctx->ulri);
8040 tcg_gen_ld_tl(arg, cpu_env,
8041 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8042 rn = "UserLocal";
8043 break;
8044 default:
8045 goto cp0_unimplemented;
8047 break;
8048 case 5:
8049 switch (sel) {
8050 case 0:
8051 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8052 rn = "PageMask";
8053 break;
8054 case 1:
8055 check_insn(ctx, ISA_MIPS32R2);
8056 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8057 rn = "PageGrain";
8058 break;
8059 case 2:
8060 CP0_CHECK(ctx->sc);
8061 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
8062 rn = "SegCtl0";
8063 break;
8064 case 3:
8065 CP0_CHECK(ctx->sc);
8066 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
8067 rn = "SegCtl1";
8068 break;
8069 case 4:
8070 CP0_CHECK(ctx->sc);
8071 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
8072 rn = "SegCtl2";
8073 break;
8074 case 5:
8075 check_pw(ctx);
8076 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8077 rn = "PWBase";
8078 break;
8079 case 6:
8080 check_pw(ctx);
8081 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
8082 rn = "PWField";
8083 break;
8084 case 7:
8085 check_pw(ctx);
8086 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
8087 rn = "PWSize";
8088 break;
8089 default:
8090 goto cp0_unimplemented;
8092 break;
8093 case 6:
8094 switch (sel) {
8095 case 0:
8096 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
8097 rn = "Wired";
8098 break;
8099 case 1:
8100 check_insn(ctx, ISA_MIPS32R2);
8101 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
8102 rn = "SRSConf0";
8103 break;
8104 case 2:
8105 check_insn(ctx, ISA_MIPS32R2);
8106 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
8107 rn = "SRSConf1";
8108 break;
8109 case 3:
8110 check_insn(ctx, ISA_MIPS32R2);
8111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
8112 rn = "SRSConf2";
8113 break;
8114 case 4:
8115 check_insn(ctx, ISA_MIPS32R2);
8116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
8117 rn = "SRSConf3";
8118 break;
8119 case 5:
8120 check_insn(ctx, ISA_MIPS32R2);
8121 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
8122 rn = "SRSConf4";
8123 break;
8124 case 6:
8125 check_pw(ctx);
8126 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
8127 rn = "PWCtl";
8128 break;
8129 default:
8130 goto cp0_unimplemented;
8132 break;
8133 case 7:
8134 switch (sel) {
8135 case 0:
8136 check_insn(ctx, ISA_MIPS32R2);
8137 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
8138 rn = "HWREna";
8139 break;
8140 default:
8141 goto cp0_unimplemented;
8143 break;
8144 case 8:
8145 switch (sel) {
8146 case 0:
8147 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
8148 rn = "BadVAddr";
8149 break;
8150 case 1:
8151 CP0_CHECK(ctx->bi);
8152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
8153 rn = "BadInstr";
8154 break;
8155 case 2:
8156 CP0_CHECK(ctx->bp);
8157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
8158 rn = "BadInstrP";
8159 break;
8160 case 3:
8161 CP0_CHECK(ctx->bi);
8162 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
8163 tcg_gen_andi_tl(arg, arg, ~0xffff);
8164 rn = "BadInstrX";
8165 break;
8166 default:
8167 goto cp0_unimplemented;
8169 break;
8170 case 9:
8171 switch (sel) {
8172 case 0:
8173 /* Mark as an IO operation because we read the time. */
8174 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8175 gen_io_start();
8177 gen_helper_mfc0_count(arg, cpu_env);
8178 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8179 gen_io_end();
8181 /* Break the TB to be able to take timer interrupts immediately
8182 after reading count. DISAS_STOP isn't sufficient, we need to
8183 ensure we break completely out of translated code. */
8184 gen_save_pc(ctx->base.pc_next + 4);
8185 ctx->base.is_jmp = DISAS_EXIT;
8186 rn = "Count";
8187 break;
8188 /* 6,7 are implementation dependent */
8189 default:
8190 goto cp0_unimplemented;
8192 break;
8193 case 10:
8194 switch (sel) {
8195 case 0:
8196 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
8197 rn = "EntryHi";
8198 break;
8199 default:
8200 goto cp0_unimplemented;
8202 break;
8203 case 11:
8204 switch (sel) {
8205 case 0:
8206 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
8207 rn = "Compare";
8208 break;
8209 /* 6,7 are implementation dependent */
8210 default:
8211 goto cp0_unimplemented;
8213 break;
8214 case 12:
8215 switch (sel) {
8216 case 0:
8217 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
8218 rn = "Status";
8219 break;
8220 case 1:
8221 check_insn(ctx, ISA_MIPS32R2);
8222 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
8223 rn = "IntCtl";
8224 break;
8225 case 2:
8226 check_insn(ctx, ISA_MIPS32R2);
8227 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
8228 rn = "SRSCtl";
8229 break;
8230 case 3:
8231 check_insn(ctx, ISA_MIPS32R2);
8232 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8233 rn = "SRSMap";
8234 break;
8235 default:
8236 goto cp0_unimplemented;
8238 break;
8239 case 13:
8240 switch (sel) {
8241 case 0:
8242 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
8243 rn = "Cause";
8244 break;
8245 default:
8246 goto cp0_unimplemented;
8248 break;
8249 case 14:
8250 switch (sel) {
8251 case 0:
8252 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8253 rn = "EPC";
8254 break;
8255 default:
8256 goto cp0_unimplemented;
8258 break;
8259 case 15:
8260 switch (sel) {
8261 case 0:
8262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
8263 rn = "PRid";
8264 break;
8265 case 1:
8266 check_insn(ctx, ISA_MIPS32R2);
8267 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8268 rn = "EBase";
8269 break;
8270 case 3:
8271 check_insn(ctx, ISA_MIPS32R2);
8272 CP0_CHECK(ctx->cmgcr);
8273 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8274 rn = "CMGCRBase";
8275 break;
8276 default:
8277 goto cp0_unimplemented;
8279 break;
8280 case 16:
8281 switch (sel) {
8282 case 0:
8283 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8284 rn = "Config";
8285 break;
8286 case 1:
8287 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8288 rn = "Config1";
8289 break;
8290 case 2:
8291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8292 rn = "Config2";
8293 break;
8294 case 3:
8295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8296 rn = "Config3";
8297 break;
8298 case 4:
8299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8300 rn = "Config4";
8301 break;
8302 case 5:
8303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8304 rn = "Config5";
8305 break;
8306 /* 6,7 are implementation dependent */
8307 case 6:
8308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8309 rn = "Config6";
8310 break;
8311 case 7:
8312 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8313 rn = "Config7";
8314 break;
8315 default:
8316 goto cp0_unimplemented;
8318 break;
8319 case 17:
8320 switch (sel) {
8321 case 0:
8322 gen_helper_dmfc0_lladdr(arg, cpu_env);
8323 rn = "LLAddr";
8324 break;
8325 case 1:
8326 CP0_CHECK(ctx->mrp);
8327 gen_helper_dmfc0_maar(arg, cpu_env);
8328 rn = "MAAR";
8329 break;
8330 case 2:
8331 CP0_CHECK(ctx->mrp);
8332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8333 rn = "MAARI";
8334 break;
8335 default:
8336 goto cp0_unimplemented;
8338 break;
8339 case 18:
8340 switch (sel) {
8341 case 0:
8342 case 1:
8343 case 2:
8344 case 3:
8345 case 4:
8346 case 5:
8347 case 6:
8348 case 7:
8349 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8350 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8351 rn = "WatchLo";
8352 break;
8353 default:
8354 goto cp0_unimplemented;
8356 break;
8357 case 19:
8358 switch (sel) {
8359 case 0:
8360 case 1:
8361 case 2:
8362 case 3:
8363 case 4:
8364 case 5:
8365 case 6:
8366 case 7:
8367 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8368 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8369 rn = "WatchHi";
8370 break;
8371 default:
8372 goto cp0_unimplemented;
8374 break;
8375 case 20:
8376 switch (sel) {
8377 case 0:
8378 check_insn(ctx, ISA_MIPS3);
8379 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8380 rn = "XContext";
8381 break;
8382 default:
8383 goto cp0_unimplemented;
8385 break;
8386 case 21:
8387 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8388 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8389 switch (sel) {
8390 case 0:
8391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8392 rn = "Framemask";
8393 break;
8394 default:
8395 goto cp0_unimplemented;
8397 break;
8398 case 22:
8399 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8400 rn = "'Diagnostic"; /* implementation dependent */
8401 break;
8402 case 23:
8403 switch (sel) {
8404 case 0:
8405 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8406 rn = "Debug";
8407 break;
8408 case 1:
8409 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8410 rn = "TraceControl";
8411 goto cp0_unimplemented;
8412 case 2:
8413 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8414 rn = "TraceControl2";
8415 goto cp0_unimplemented;
8416 case 3:
8417 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8418 rn = "UserTraceData";
8419 goto cp0_unimplemented;
8420 case 4:
8421 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8422 rn = "TraceBPC";
8423 goto cp0_unimplemented;
8424 default:
8425 goto cp0_unimplemented;
8427 break;
8428 case 24:
8429 switch (sel) {
8430 case 0:
8431 /* EJTAG support */
8432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8433 rn = "DEPC";
8434 break;
8435 default:
8436 goto cp0_unimplemented;
8438 break;
8439 case 25:
8440 switch (sel) {
8441 case 0:
8442 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8443 rn = "Performance0";
8444 break;
8445 case 1:
8446 // gen_helper_dmfc0_performance1(arg);
8447 rn = "Performance1";
8448 goto cp0_unimplemented;
8449 case 2:
8450 // gen_helper_dmfc0_performance2(arg);
8451 rn = "Performance2";
8452 goto cp0_unimplemented;
8453 case 3:
8454 // gen_helper_dmfc0_performance3(arg);
8455 rn = "Performance3";
8456 goto cp0_unimplemented;
8457 case 4:
8458 // gen_helper_dmfc0_performance4(arg);
8459 rn = "Performance4";
8460 goto cp0_unimplemented;
8461 case 5:
8462 // gen_helper_dmfc0_performance5(arg);
8463 rn = "Performance5";
8464 goto cp0_unimplemented;
8465 case 6:
8466 // gen_helper_dmfc0_performance6(arg);
8467 rn = "Performance6";
8468 goto cp0_unimplemented;
8469 case 7:
8470 // gen_helper_dmfc0_performance7(arg);
8471 rn = "Performance7";
8472 goto cp0_unimplemented;
8473 default:
8474 goto cp0_unimplemented;
8476 break;
8477 case 26:
8478 switch (sel) {
8479 case 0:
8480 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8481 rn = "ErrCtl";
8482 break;
8483 default:
8484 goto cp0_unimplemented;
8486 break;
8487 case 27:
8488 switch (sel) {
8489 /* ignored */
8490 case 0:
8491 case 1:
8492 case 2:
8493 case 3:
8494 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8495 rn = "CacheErr";
8496 break;
8497 default:
8498 goto cp0_unimplemented;
8500 break;
8501 case 28:
8502 switch (sel) {
8503 case 0:
8504 case 2:
8505 case 4:
8506 case 6:
8507 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8508 rn = "TagLo";
8509 break;
8510 case 1:
8511 case 3:
8512 case 5:
8513 case 7:
8514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8515 rn = "DataLo";
8516 break;
8517 default:
8518 goto cp0_unimplemented;
8520 break;
8521 case 29:
8522 switch (sel) {
8523 case 0:
8524 case 2:
8525 case 4:
8526 case 6:
8527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8528 rn = "TagHi";
8529 break;
8530 case 1:
8531 case 3:
8532 case 5:
8533 case 7:
8534 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8535 rn = "DataHi";
8536 break;
8537 default:
8538 goto cp0_unimplemented;
8540 break;
8541 case 30:
8542 switch (sel) {
8543 case 0:
8544 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8545 rn = "ErrorEPC";
8546 break;
8547 default:
8548 goto cp0_unimplemented;
8550 break;
8551 case 31:
8552 switch (sel) {
8553 case 0:
8554 /* EJTAG support */
8555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8556 rn = "DESAVE";
8557 break;
8558 case 2:
8559 case 3:
8560 case 4:
8561 case 5:
8562 case 6:
8563 case 7:
8564 CP0_CHECK(ctx->kscrexist & (1 << sel));
8565 tcg_gen_ld_tl(arg, cpu_env,
8566 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8567 rn = "KScratch";
8568 break;
8569 default:
8570 goto cp0_unimplemented;
8572 break;
8573 default:
8574 goto cp0_unimplemented;
8576 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8577 return;
8579 cp0_unimplemented:
8580 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8581 gen_mfc0_unimplemented(ctx, arg);
8584 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8586 const char *rn = "invalid";
8588 if (sel != 0)
8589 check_insn(ctx, ISA_MIPS64);
8591 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8592 gen_io_start();
8595 switch (reg) {
8596 case 0:
8597 switch (sel) {
8598 case 0:
8599 gen_helper_mtc0_index(cpu_env, arg);
8600 rn = "Index";
8601 break;
8602 case 1:
8603 CP0_CHECK(ctx->insn_flags & ASE_MT);
8604 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8605 rn = "MVPControl";
8606 break;
8607 case 2:
8608 CP0_CHECK(ctx->insn_flags & ASE_MT);
8609 /* ignored */
8610 rn = "MVPConf0";
8611 break;
8612 case 3:
8613 CP0_CHECK(ctx->insn_flags & ASE_MT);
8614 /* ignored */
8615 rn = "MVPConf1";
8616 break;
8617 case 4:
8618 CP0_CHECK(ctx->vp);
8619 /* ignored */
8620 rn = "VPControl";
8621 break;
8622 default:
8623 goto cp0_unimplemented;
8625 break;
8626 case 1:
8627 switch (sel) {
8628 case 0:
8629 /* ignored */
8630 rn = "Random";
8631 break;
8632 case 1:
8633 CP0_CHECK(ctx->insn_flags & ASE_MT);
8634 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8635 rn = "VPEControl";
8636 break;
8637 case 2:
8638 CP0_CHECK(ctx->insn_flags & ASE_MT);
8639 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8640 rn = "VPEConf0";
8641 break;
8642 case 3:
8643 CP0_CHECK(ctx->insn_flags & ASE_MT);
8644 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8645 rn = "VPEConf1";
8646 break;
8647 case 4:
8648 CP0_CHECK(ctx->insn_flags & ASE_MT);
8649 gen_helper_mtc0_yqmask(cpu_env, arg);
8650 rn = "YQMask";
8651 break;
8652 case 5:
8653 CP0_CHECK(ctx->insn_flags & ASE_MT);
8654 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8655 rn = "VPESchedule";
8656 break;
8657 case 6:
8658 CP0_CHECK(ctx->insn_flags & ASE_MT);
8659 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8660 rn = "VPEScheFBack";
8661 break;
8662 case 7:
8663 CP0_CHECK(ctx->insn_flags & ASE_MT);
8664 gen_helper_mtc0_vpeopt(cpu_env, arg);
8665 rn = "VPEOpt";
8666 break;
8667 default:
8668 goto cp0_unimplemented;
8670 break;
8671 case 2:
8672 switch (sel) {
8673 case 0:
8674 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8675 rn = "EntryLo0";
8676 break;
8677 case 1:
8678 CP0_CHECK(ctx->insn_flags & ASE_MT);
8679 gen_helper_mtc0_tcstatus(cpu_env, arg);
8680 rn = "TCStatus";
8681 break;
8682 case 2:
8683 CP0_CHECK(ctx->insn_flags & ASE_MT);
8684 gen_helper_mtc0_tcbind(cpu_env, arg);
8685 rn = "TCBind";
8686 break;
8687 case 3:
8688 CP0_CHECK(ctx->insn_flags & ASE_MT);
8689 gen_helper_mtc0_tcrestart(cpu_env, arg);
8690 rn = "TCRestart";
8691 break;
8692 case 4:
8693 CP0_CHECK(ctx->insn_flags & ASE_MT);
8694 gen_helper_mtc0_tchalt(cpu_env, arg);
8695 rn = "TCHalt";
8696 break;
8697 case 5:
8698 CP0_CHECK(ctx->insn_flags & ASE_MT);
8699 gen_helper_mtc0_tccontext(cpu_env, arg);
8700 rn = "TCContext";
8701 break;
8702 case 6:
8703 CP0_CHECK(ctx->insn_flags & ASE_MT);
8704 gen_helper_mtc0_tcschedule(cpu_env, arg);
8705 rn = "TCSchedule";
8706 break;
8707 case 7:
8708 CP0_CHECK(ctx->insn_flags & ASE_MT);
8709 gen_helper_mtc0_tcschefback(cpu_env, arg);
8710 rn = "TCScheFBack";
8711 break;
8712 default:
8713 goto cp0_unimplemented;
8715 break;
8716 case 3:
8717 switch (sel) {
8718 case 0:
8719 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8720 rn = "EntryLo1";
8721 break;
8722 case 1:
8723 CP0_CHECK(ctx->vp);
8724 /* ignored */
8725 rn = "GlobalNumber";
8726 break;
8727 default:
8728 goto cp0_unimplemented;
8730 break;
8731 case 4:
8732 switch (sel) {
8733 case 0:
8734 gen_helper_mtc0_context(cpu_env, arg);
8735 rn = "Context";
8736 break;
8737 case 1:
8738 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8739 rn = "ContextConfig";
8740 goto cp0_unimplemented;
8741 case 2:
8742 CP0_CHECK(ctx->ulri);
8743 tcg_gen_st_tl(arg, cpu_env,
8744 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8745 rn = "UserLocal";
8746 break;
8747 default:
8748 goto cp0_unimplemented;
8750 break;
8751 case 5:
8752 switch (sel) {
8753 case 0:
8754 gen_helper_mtc0_pagemask(cpu_env, arg);
8755 rn = "PageMask";
8756 break;
8757 case 1:
8758 check_insn(ctx, ISA_MIPS32R2);
8759 gen_helper_mtc0_pagegrain(cpu_env, arg);
8760 rn = "PageGrain";
8761 break;
8762 case 2:
8763 CP0_CHECK(ctx->sc);
8764 gen_helper_mtc0_segctl0(cpu_env, arg);
8765 rn = "SegCtl0";
8766 break;
8767 case 3:
8768 CP0_CHECK(ctx->sc);
8769 gen_helper_mtc0_segctl1(cpu_env, arg);
8770 rn = "SegCtl1";
8771 break;
8772 case 4:
8773 CP0_CHECK(ctx->sc);
8774 gen_helper_mtc0_segctl2(cpu_env, arg);
8775 rn = "SegCtl2";
8776 break;
8777 case 5:
8778 check_pw(ctx);
8779 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8780 rn = "PWBase";
8781 break;
8782 case 6:
8783 check_pw(ctx);
8784 gen_helper_mtc0_pwfield(cpu_env, arg);
8785 rn = "PWField";
8786 break;
8787 case 7:
8788 check_pw(ctx);
8789 gen_helper_mtc0_pwsize(cpu_env, arg);
8790 rn = "PWSize";
8791 break;
8792 default:
8793 goto cp0_unimplemented;
8795 break;
8796 case 6:
8797 switch (sel) {
8798 case 0:
8799 gen_helper_mtc0_wired(cpu_env, arg);
8800 rn = "Wired";
8801 break;
8802 case 1:
8803 check_insn(ctx, ISA_MIPS32R2);
8804 gen_helper_mtc0_srsconf0(cpu_env, arg);
8805 rn = "SRSConf0";
8806 break;
8807 case 2:
8808 check_insn(ctx, ISA_MIPS32R2);
8809 gen_helper_mtc0_srsconf1(cpu_env, arg);
8810 rn = "SRSConf1";
8811 break;
8812 case 3:
8813 check_insn(ctx, ISA_MIPS32R2);
8814 gen_helper_mtc0_srsconf2(cpu_env, arg);
8815 rn = "SRSConf2";
8816 break;
8817 case 4:
8818 check_insn(ctx, ISA_MIPS32R2);
8819 gen_helper_mtc0_srsconf3(cpu_env, arg);
8820 rn = "SRSConf3";
8821 break;
8822 case 5:
8823 check_insn(ctx, ISA_MIPS32R2);
8824 gen_helper_mtc0_srsconf4(cpu_env, arg);
8825 rn = "SRSConf4";
8826 break;
8827 case 6:
8828 check_pw(ctx);
8829 gen_helper_mtc0_pwctl(cpu_env, arg);
8830 rn = "PWCtl";
8831 break;
8832 default:
8833 goto cp0_unimplemented;
8835 break;
8836 case 7:
8837 switch (sel) {
8838 case 0:
8839 check_insn(ctx, ISA_MIPS32R2);
8840 gen_helper_mtc0_hwrena(cpu_env, arg);
8841 ctx->base.is_jmp = DISAS_STOP;
8842 rn = "HWREna";
8843 break;
8844 default:
8845 goto cp0_unimplemented;
8847 break;
8848 case 8:
8849 switch (sel) {
8850 case 0:
8851 /* ignored */
8852 rn = "BadVAddr";
8853 break;
8854 case 1:
8855 /* ignored */
8856 rn = "BadInstr";
8857 break;
8858 case 2:
8859 /* ignored */
8860 rn = "BadInstrP";
8861 break;
8862 case 3:
8863 /* ignored */
8864 rn = "BadInstrX";
8865 break;
8866 default:
8867 goto cp0_unimplemented;
8869 break;
8870 case 9:
8871 switch (sel) {
8872 case 0:
8873 gen_helper_mtc0_count(cpu_env, arg);
8874 rn = "Count";
8875 break;
8876 /* 6,7 are implementation dependent */
8877 default:
8878 goto cp0_unimplemented;
8880 /* Stop translation as we may have switched the execution mode */
8881 ctx->base.is_jmp = DISAS_STOP;
8882 break;
8883 case 10:
8884 switch (sel) {
8885 case 0:
8886 gen_helper_mtc0_entryhi(cpu_env, arg);
8887 rn = "EntryHi";
8888 break;
8889 default:
8890 goto cp0_unimplemented;
8892 break;
8893 case 11:
8894 switch (sel) {
8895 case 0:
8896 gen_helper_mtc0_compare(cpu_env, arg);
8897 rn = "Compare";
8898 break;
8899 /* 6,7 are implementation dependent */
8900 default:
8901 goto cp0_unimplemented;
8903 /* Stop translation as we may have switched the execution mode */
8904 ctx->base.is_jmp = DISAS_STOP;
8905 break;
8906 case 12:
8907 switch (sel) {
8908 case 0:
8909 save_cpu_state(ctx, 1);
8910 gen_helper_mtc0_status(cpu_env, arg);
8911 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8912 gen_save_pc(ctx->base.pc_next + 4);
8913 ctx->base.is_jmp = DISAS_EXIT;
8914 rn = "Status";
8915 break;
8916 case 1:
8917 check_insn(ctx, ISA_MIPS32R2);
8918 gen_helper_mtc0_intctl(cpu_env, arg);
8919 /* Stop translation as we may have switched the execution mode */
8920 ctx->base.is_jmp = DISAS_STOP;
8921 rn = "IntCtl";
8922 break;
8923 case 2:
8924 check_insn(ctx, ISA_MIPS32R2);
8925 gen_helper_mtc0_srsctl(cpu_env, arg);
8926 /* Stop translation as we may have switched the execution mode */
8927 ctx->base.is_jmp = DISAS_STOP;
8928 rn = "SRSCtl";
8929 break;
8930 case 3:
8931 check_insn(ctx, ISA_MIPS32R2);
8932 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8933 /* Stop translation as we may have switched the execution mode */
8934 ctx->base.is_jmp = DISAS_STOP;
8935 rn = "SRSMap";
8936 break;
8937 default:
8938 goto cp0_unimplemented;
8940 break;
8941 case 13:
8942 switch (sel) {
8943 case 0:
8944 save_cpu_state(ctx, 1);
8945 gen_helper_mtc0_cause(cpu_env, arg);
8946 /* Stop translation as we may have triggered an interrupt.
8947 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8948 * translated code to check for pending interrupts. */
8949 gen_save_pc(ctx->base.pc_next + 4);
8950 ctx->base.is_jmp = DISAS_EXIT;
8951 rn = "Cause";
8952 break;
8953 default:
8954 goto cp0_unimplemented;
8956 break;
8957 case 14:
8958 switch (sel) {
8959 case 0:
8960 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8961 rn = "EPC";
8962 break;
8963 default:
8964 goto cp0_unimplemented;
8966 break;
8967 case 15:
8968 switch (sel) {
8969 case 0:
8970 /* ignored */
8971 rn = "PRid";
8972 break;
8973 case 1:
8974 check_insn(ctx, ISA_MIPS32R2);
8975 gen_helper_mtc0_ebase(cpu_env, arg);
8976 rn = "EBase";
8977 break;
8978 default:
8979 goto cp0_unimplemented;
8981 break;
8982 case 16:
8983 switch (sel) {
8984 case 0:
8985 gen_helper_mtc0_config0(cpu_env, arg);
8986 rn = "Config";
8987 /* Stop translation as we may have switched the execution mode */
8988 ctx->base.is_jmp = DISAS_STOP;
8989 break;
8990 case 1:
8991 /* ignored, read only */
8992 rn = "Config1";
8993 break;
8994 case 2:
8995 gen_helper_mtc0_config2(cpu_env, arg);
8996 rn = "Config2";
8997 /* Stop translation as we may have switched the execution mode */
8998 ctx->base.is_jmp = DISAS_STOP;
8999 break;
9000 case 3:
9001 gen_helper_mtc0_config3(cpu_env, arg);
9002 rn = "Config3";
9003 /* Stop translation as we may have switched the execution mode */
9004 ctx->base.is_jmp = DISAS_STOP;
9005 break;
9006 case 4:
9007 /* currently ignored */
9008 rn = "Config4";
9009 break;
9010 case 5:
9011 gen_helper_mtc0_config5(cpu_env, arg);
9012 rn = "Config5";
9013 /* Stop translation as we may have switched the execution mode */
9014 ctx->base.is_jmp = DISAS_STOP;
9015 break;
9016 /* 6,7 are implementation dependent */
9017 default:
9018 rn = "Invalid config selector";
9019 goto cp0_unimplemented;
9021 break;
9022 case 17:
9023 switch (sel) {
9024 case 0:
9025 gen_helper_mtc0_lladdr(cpu_env, arg);
9026 rn = "LLAddr";
9027 break;
9028 case 1:
9029 CP0_CHECK(ctx->mrp);
9030 gen_helper_mtc0_maar(cpu_env, arg);
9031 rn = "MAAR";
9032 break;
9033 case 2:
9034 CP0_CHECK(ctx->mrp);
9035 gen_helper_mtc0_maari(cpu_env, arg);
9036 rn = "MAARI";
9037 break;
9038 default:
9039 goto cp0_unimplemented;
9041 break;
9042 case 18:
9043 switch (sel) {
9044 case 0:
9045 case 1:
9046 case 2:
9047 case 3:
9048 case 4:
9049 case 5:
9050 case 6:
9051 case 7:
9052 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9053 gen_helper_0e1i(mtc0_watchlo, arg, sel);
9054 rn = "WatchLo";
9055 break;
9056 default:
9057 goto cp0_unimplemented;
9059 break;
9060 case 19:
9061 switch (sel) {
9062 case 0:
9063 case 1:
9064 case 2:
9065 case 3:
9066 case 4:
9067 case 5:
9068 case 6:
9069 case 7:
9070 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9071 gen_helper_0e1i(mtc0_watchhi, arg, sel);
9072 rn = "WatchHi";
9073 break;
9074 default:
9075 goto cp0_unimplemented;
9077 break;
9078 case 20:
9079 switch (sel) {
9080 case 0:
9081 check_insn(ctx, ISA_MIPS3);
9082 gen_helper_mtc0_xcontext(cpu_env, arg);
9083 rn = "XContext";
9084 break;
9085 default:
9086 goto cp0_unimplemented;
9088 break;
9089 case 21:
9090 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9091 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9092 switch (sel) {
9093 case 0:
9094 gen_helper_mtc0_framemask(cpu_env, arg);
9095 rn = "Framemask";
9096 break;
9097 default:
9098 goto cp0_unimplemented;
9100 break;
9101 case 22:
9102 /* ignored */
9103 rn = "Diagnostic"; /* implementation dependent */
9104 break;
9105 case 23:
9106 switch (sel) {
9107 case 0:
9108 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
9109 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9110 gen_save_pc(ctx->base.pc_next + 4);
9111 ctx->base.is_jmp = DISAS_EXIT;
9112 rn = "Debug";
9113 break;
9114 case 1:
9115 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
9116 /* Stop translation as we may have switched the execution mode */
9117 ctx->base.is_jmp = DISAS_STOP;
9118 rn = "TraceControl";
9119 goto cp0_unimplemented;
9120 case 2:
9121 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
9122 /* Stop translation as we may have switched the execution mode */
9123 ctx->base.is_jmp = DISAS_STOP;
9124 rn = "TraceControl2";
9125 goto cp0_unimplemented;
9126 case 3:
9127 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
9128 /* Stop translation as we may have switched the execution mode */
9129 ctx->base.is_jmp = DISAS_STOP;
9130 rn = "UserTraceData";
9131 goto cp0_unimplemented;
9132 case 4:
9133 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
9134 /* Stop translation as we may have switched the execution mode */
9135 ctx->base.is_jmp = DISAS_STOP;
9136 rn = "TraceBPC";
9137 goto cp0_unimplemented;
9138 default:
9139 goto cp0_unimplemented;
9141 break;
9142 case 24:
9143 switch (sel) {
9144 case 0:
9145 /* EJTAG support */
9146 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9147 rn = "DEPC";
9148 break;
9149 default:
9150 goto cp0_unimplemented;
9152 break;
9153 case 25:
9154 switch (sel) {
9155 case 0:
9156 gen_helper_mtc0_performance0(cpu_env, arg);
9157 rn = "Performance0";
9158 break;
9159 case 1:
9160 // gen_helper_mtc0_performance1(cpu_env, arg);
9161 rn = "Performance1";
9162 goto cp0_unimplemented;
9163 case 2:
9164 // gen_helper_mtc0_performance2(cpu_env, arg);
9165 rn = "Performance2";
9166 goto cp0_unimplemented;
9167 case 3:
9168 // gen_helper_mtc0_performance3(cpu_env, arg);
9169 rn = "Performance3";
9170 goto cp0_unimplemented;
9171 case 4:
9172 // gen_helper_mtc0_performance4(cpu_env, arg);
9173 rn = "Performance4";
9174 goto cp0_unimplemented;
9175 case 5:
9176 // gen_helper_mtc0_performance5(cpu_env, arg);
9177 rn = "Performance5";
9178 goto cp0_unimplemented;
9179 case 6:
9180 // gen_helper_mtc0_performance6(cpu_env, arg);
9181 rn = "Performance6";
9182 goto cp0_unimplemented;
9183 case 7:
9184 // gen_helper_mtc0_performance7(cpu_env, arg);
9185 rn = "Performance7";
9186 goto cp0_unimplemented;
9187 default:
9188 goto cp0_unimplemented;
9190 break;
9191 case 26:
9192 switch (sel) {
9193 case 0:
9194 gen_helper_mtc0_errctl(cpu_env, arg);
9195 ctx->base.is_jmp = DISAS_STOP;
9196 rn = "ErrCtl";
9197 break;
9198 default:
9199 goto cp0_unimplemented;
9201 break;
9202 case 27:
9203 switch (sel) {
9204 case 0:
9205 case 1:
9206 case 2:
9207 case 3:
9208 /* ignored */
9209 rn = "CacheErr";
9210 break;
9211 default:
9212 goto cp0_unimplemented;
9214 break;
9215 case 28:
9216 switch (sel) {
9217 case 0:
9218 case 2:
9219 case 4:
9220 case 6:
9221 gen_helper_mtc0_taglo(cpu_env, arg);
9222 rn = "TagLo";
9223 break;
9224 case 1:
9225 case 3:
9226 case 5:
9227 case 7:
9228 gen_helper_mtc0_datalo(cpu_env, arg);
9229 rn = "DataLo";
9230 break;
9231 default:
9232 goto cp0_unimplemented;
9234 break;
9235 case 29:
9236 switch (sel) {
9237 case 0:
9238 case 2:
9239 case 4:
9240 case 6:
9241 gen_helper_mtc0_taghi(cpu_env, arg);
9242 rn = "TagHi";
9243 break;
9244 case 1:
9245 case 3:
9246 case 5:
9247 case 7:
9248 gen_helper_mtc0_datahi(cpu_env, arg);
9249 rn = "DataHi";
9250 break;
9251 default:
9252 rn = "invalid sel";
9253 goto cp0_unimplemented;
9255 break;
9256 case 30:
9257 switch (sel) {
9258 case 0:
9259 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9260 rn = "ErrorEPC";
9261 break;
9262 default:
9263 goto cp0_unimplemented;
9265 break;
9266 case 31:
9267 switch (sel) {
9268 case 0:
9269 /* EJTAG support */
9270 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9271 rn = "DESAVE";
9272 break;
9273 case 2:
9274 case 3:
9275 case 4:
9276 case 5:
9277 case 6:
9278 case 7:
9279 CP0_CHECK(ctx->kscrexist & (1 << sel));
9280 tcg_gen_st_tl(arg, cpu_env,
9281 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9282 rn = "KScratch";
9283 break;
9284 default:
9285 goto cp0_unimplemented;
9287 break;
9288 default:
9289 goto cp0_unimplemented;
9291 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9293 /* For simplicity assume that all writes can cause interrupts. */
9294 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9295 gen_io_end();
9296 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9297 * translated code to check for pending interrupts. */
9298 gen_save_pc(ctx->base.pc_next + 4);
9299 ctx->base.is_jmp = DISAS_EXIT;
9301 return;
9303 cp0_unimplemented:
9304 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9306 #endif /* TARGET_MIPS64 */
9308 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9309 int u, int sel, int h)
9311 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9312 TCGv t0 = tcg_temp_local_new();
9314 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9315 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9316 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9317 tcg_gen_movi_tl(t0, -1);
9318 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9319 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9320 tcg_gen_movi_tl(t0, -1);
9321 else if (u == 0) {
9322 switch (rt) {
9323 case 1:
9324 switch (sel) {
9325 case 1:
9326 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9327 break;
9328 case 2:
9329 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9330 break;
9331 default:
9332 goto die;
9333 break;
9335 break;
9336 case 2:
9337 switch (sel) {
9338 case 1:
9339 gen_helper_mftc0_tcstatus(t0, cpu_env);
9340 break;
9341 case 2:
9342 gen_helper_mftc0_tcbind(t0, cpu_env);
9343 break;
9344 case 3:
9345 gen_helper_mftc0_tcrestart(t0, cpu_env);
9346 break;
9347 case 4:
9348 gen_helper_mftc0_tchalt(t0, cpu_env);
9349 break;
9350 case 5:
9351 gen_helper_mftc0_tccontext(t0, cpu_env);
9352 break;
9353 case 6:
9354 gen_helper_mftc0_tcschedule(t0, cpu_env);
9355 break;
9356 case 7:
9357 gen_helper_mftc0_tcschefback(t0, cpu_env);
9358 break;
9359 default:
9360 gen_mfc0(ctx, t0, rt, sel);
9361 break;
9363 break;
9364 case 10:
9365 switch (sel) {
9366 case 0:
9367 gen_helper_mftc0_entryhi(t0, cpu_env);
9368 break;
9369 default:
9370 gen_mfc0(ctx, t0, rt, sel);
9371 break;
9373 case 12:
9374 switch (sel) {
9375 case 0:
9376 gen_helper_mftc0_status(t0, cpu_env);
9377 break;
9378 default:
9379 gen_mfc0(ctx, t0, rt, sel);
9380 break;
9382 case 13:
9383 switch (sel) {
9384 case 0:
9385 gen_helper_mftc0_cause(t0, cpu_env);
9386 break;
9387 default:
9388 goto die;
9389 break;
9391 break;
9392 case 14:
9393 switch (sel) {
9394 case 0:
9395 gen_helper_mftc0_epc(t0, cpu_env);
9396 break;
9397 default:
9398 goto die;
9399 break;
9401 break;
9402 case 15:
9403 switch (sel) {
9404 case 1:
9405 gen_helper_mftc0_ebase(t0, cpu_env);
9406 break;
9407 default:
9408 goto die;
9409 break;
9411 break;
9412 case 16:
9413 switch (sel) {
9414 case 0:
9415 case 1:
9416 case 2:
9417 case 3:
9418 case 4:
9419 case 5:
9420 case 6:
9421 case 7:
9422 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9423 break;
9424 default:
9425 goto die;
9426 break;
9428 break;
9429 case 23:
9430 switch (sel) {
9431 case 0:
9432 gen_helper_mftc0_debug(t0, cpu_env);
9433 break;
9434 default:
9435 gen_mfc0(ctx, t0, rt, sel);
9436 break;
9438 break;
9439 default:
9440 gen_mfc0(ctx, t0, rt, sel);
9442 } else switch (sel) {
9443 /* GPR registers. */
9444 case 0:
9445 gen_helper_1e0i(mftgpr, t0, rt);
9446 break;
9447 /* Auxiliary CPU registers */
9448 case 1:
9449 switch (rt) {
9450 case 0:
9451 gen_helper_1e0i(mftlo, t0, 0);
9452 break;
9453 case 1:
9454 gen_helper_1e0i(mfthi, t0, 0);
9455 break;
9456 case 2:
9457 gen_helper_1e0i(mftacx, t0, 0);
9458 break;
9459 case 4:
9460 gen_helper_1e0i(mftlo, t0, 1);
9461 break;
9462 case 5:
9463 gen_helper_1e0i(mfthi, t0, 1);
9464 break;
9465 case 6:
9466 gen_helper_1e0i(mftacx, t0, 1);
9467 break;
9468 case 8:
9469 gen_helper_1e0i(mftlo, t0, 2);
9470 break;
9471 case 9:
9472 gen_helper_1e0i(mfthi, t0, 2);
9473 break;
9474 case 10:
9475 gen_helper_1e0i(mftacx, t0, 2);
9476 break;
9477 case 12:
9478 gen_helper_1e0i(mftlo, t0, 3);
9479 break;
9480 case 13:
9481 gen_helper_1e0i(mfthi, t0, 3);
9482 break;
9483 case 14:
9484 gen_helper_1e0i(mftacx, t0, 3);
9485 break;
9486 case 16:
9487 gen_helper_mftdsp(t0, cpu_env);
9488 break;
9489 default:
9490 goto die;
9492 break;
9493 /* Floating point (COP1). */
9494 case 2:
9495 /* XXX: For now we support only a single FPU context. */
9496 if (h == 0) {
9497 TCGv_i32 fp0 = tcg_temp_new_i32();
9499 gen_load_fpr32(ctx, fp0, rt);
9500 tcg_gen_ext_i32_tl(t0, fp0);
9501 tcg_temp_free_i32(fp0);
9502 } else {
9503 TCGv_i32 fp0 = tcg_temp_new_i32();
9505 gen_load_fpr32h(ctx, fp0, rt);
9506 tcg_gen_ext_i32_tl(t0, fp0);
9507 tcg_temp_free_i32(fp0);
9509 break;
9510 case 3:
9511 /* XXX: For now we support only a single FPU context. */
9512 gen_helper_1e0i(cfc1, t0, rt);
9513 break;
9514 /* COP2: Not implemented. */
9515 case 4:
9516 case 5:
9517 /* fall through */
9518 default:
9519 goto die;
9521 trace_mips_translate_tr("mftr", rt, u, sel, h);
9522 gen_store_gpr(t0, rd);
9523 tcg_temp_free(t0);
9524 return;
9526 die:
9527 tcg_temp_free(t0);
9528 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9529 generate_exception_end(ctx, EXCP_RI);
9532 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9533 int u, int sel, int h)
9535 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9536 TCGv t0 = tcg_temp_local_new();
9538 gen_load_gpr(t0, rt);
9539 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9540 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9541 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9542 /* NOP */ ;
9543 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9544 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9545 /* NOP */ ;
9546 else if (u == 0) {
9547 switch (rd) {
9548 case 1:
9549 switch (sel) {
9550 case 1:
9551 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9552 break;
9553 case 2:
9554 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9555 break;
9556 default:
9557 goto die;
9558 break;
9560 break;
9561 case 2:
9562 switch (sel) {
9563 case 1:
9564 gen_helper_mttc0_tcstatus(cpu_env, t0);
9565 break;
9566 case 2:
9567 gen_helper_mttc0_tcbind(cpu_env, t0);
9568 break;
9569 case 3:
9570 gen_helper_mttc0_tcrestart(cpu_env, t0);
9571 break;
9572 case 4:
9573 gen_helper_mttc0_tchalt(cpu_env, t0);
9574 break;
9575 case 5:
9576 gen_helper_mttc0_tccontext(cpu_env, t0);
9577 break;
9578 case 6:
9579 gen_helper_mttc0_tcschedule(cpu_env, t0);
9580 break;
9581 case 7:
9582 gen_helper_mttc0_tcschefback(cpu_env, t0);
9583 break;
9584 default:
9585 gen_mtc0(ctx, t0, rd, sel);
9586 break;
9588 break;
9589 case 10:
9590 switch (sel) {
9591 case 0:
9592 gen_helper_mttc0_entryhi(cpu_env, t0);
9593 break;
9594 default:
9595 gen_mtc0(ctx, t0, rd, sel);
9596 break;
9598 case 12:
9599 switch (sel) {
9600 case 0:
9601 gen_helper_mttc0_status(cpu_env, t0);
9602 break;
9603 default:
9604 gen_mtc0(ctx, t0, rd, sel);
9605 break;
9607 case 13:
9608 switch (sel) {
9609 case 0:
9610 gen_helper_mttc0_cause(cpu_env, t0);
9611 break;
9612 default:
9613 goto die;
9614 break;
9616 break;
9617 case 15:
9618 switch (sel) {
9619 case 1:
9620 gen_helper_mttc0_ebase(cpu_env, t0);
9621 break;
9622 default:
9623 goto die;
9624 break;
9626 break;
9627 case 23:
9628 switch (sel) {
9629 case 0:
9630 gen_helper_mttc0_debug(cpu_env, t0);
9631 break;
9632 default:
9633 gen_mtc0(ctx, t0, rd, sel);
9634 break;
9636 break;
9637 default:
9638 gen_mtc0(ctx, t0, rd, sel);
9640 } else switch (sel) {
9641 /* GPR registers. */
9642 case 0:
9643 gen_helper_0e1i(mttgpr, t0, rd);
9644 break;
9645 /* Auxiliary CPU registers */
9646 case 1:
9647 switch (rd) {
9648 case 0:
9649 gen_helper_0e1i(mttlo, t0, 0);
9650 break;
9651 case 1:
9652 gen_helper_0e1i(mtthi, t0, 0);
9653 break;
9654 case 2:
9655 gen_helper_0e1i(mttacx, t0, 0);
9656 break;
9657 case 4:
9658 gen_helper_0e1i(mttlo, t0, 1);
9659 break;
9660 case 5:
9661 gen_helper_0e1i(mtthi, t0, 1);
9662 break;
9663 case 6:
9664 gen_helper_0e1i(mttacx, t0, 1);
9665 break;
9666 case 8:
9667 gen_helper_0e1i(mttlo, t0, 2);
9668 break;
9669 case 9:
9670 gen_helper_0e1i(mtthi, t0, 2);
9671 break;
9672 case 10:
9673 gen_helper_0e1i(mttacx, t0, 2);
9674 break;
9675 case 12:
9676 gen_helper_0e1i(mttlo, t0, 3);
9677 break;
9678 case 13:
9679 gen_helper_0e1i(mtthi, t0, 3);
9680 break;
9681 case 14:
9682 gen_helper_0e1i(mttacx, t0, 3);
9683 break;
9684 case 16:
9685 gen_helper_mttdsp(cpu_env, t0);
9686 break;
9687 default:
9688 goto die;
9690 break;
9691 /* Floating point (COP1). */
9692 case 2:
9693 /* XXX: For now we support only a single FPU context. */
9694 if (h == 0) {
9695 TCGv_i32 fp0 = tcg_temp_new_i32();
9697 tcg_gen_trunc_tl_i32(fp0, t0);
9698 gen_store_fpr32(ctx, fp0, rd);
9699 tcg_temp_free_i32(fp0);
9700 } else {
9701 TCGv_i32 fp0 = tcg_temp_new_i32();
9703 tcg_gen_trunc_tl_i32(fp0, t0);
9704 gen_store_fpr32h(ctx, fp0, rd);
9705 tcg_temp_free_i32(fp0);
9707 break;
9708 case 3:
9709 /* XXX: For now we support only a single FPU context. */
9711 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9713 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9714 tcg_temp_free_i32(fs_tmp);
9716 /* Stop translation as we may have changed hflags */
9717 ctx->base.is_jmp = DISAS_STOP;
9718 break;
9719 /* COP2: Not implemented. */
9720 case 4:
9721 case 5:
9722 /* fall through */
9723 default:
9724 goto die;
9726 trace_mips_translate_tr("mttr", rd, u, sel, h);
9727 tcg_temp_free(t0);
9728 return;
9730 die:
9731 tcg_temp_free(t0);
9732 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9733 generate_exception_end(ctx, EXCP_RI);
9736 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9738 const char *opn = "ldst";
9740 check_cp0_enabled(ctx);
9741 switch (opc) {
9742 case OPC_MFC0:
9743 if (rt == 0) {
9744 /* Treat as NOP. */
9745 return;
9747 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9748 opn = "mfc0";
9749 break;
9750 case OPC_MTC0:
9752 TCGv t0 = tcg_temp_new();
9754 gen_load_gpr(t0, rt);
9755 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9756 tcg_temp_free(t0);
9758 opn = "mtc0";
9759 break;
9760 #if defined(TARGET_MIPS64)
9761 case OPC_DMFC0:
9762 check_insn(ctx, ISA_MIPS3);
9763 if (rt == 0) {
9764 /* Treat as NOP. */
9765 return;
9767 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9768 opn = "dmfc0";
9769 break;
9770 case OPC_DMTC0:
9771 check_insn(ctx, ISA_MIPS3);
9773 TCGv t0 = tcg_temp_new();
9775 gen_load_gpr(t0, rt);
9776 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9777 tcg_temp_free(t0);
9779 opn = "dmtc0";
9780 break;
9781 #endif
9782 case OPC_MFHC0:
9783 check_mvh(ctx);
9784 if (rt == 0) {
9785 /* Treat as NOP. */
9786 return;
9788 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9789 opn = "mfhc0";
9790 break;
9791 case OPC_MTHC0:
9792 check_mvh(ctx);
9794 TCGv t0 = tcg_temp_new();
9795 gen_load_gpr(t0, rt);
9796 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9797 tcg_temp_free(t0);
9799 opn = "mthc0";
9800 break;
9801 case OPC_MFTR:
9802 check_cp0_enabled(ctx);
9803 if (rd == 0) {
9804 /* Treat as NOP. */
9805 return;
9807 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9808 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9809 opn = "mftr";
9810 break;
9811 case OPC_MTTR:
9812 check_cp0_enabled(ctx);
9813 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9814 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9815 opn = "mttr";
9816 break;
9817 case OPC_TLBWI:
9818 opn = "tlbwi";
9819 if (!env->tlb->helper_tlbwi)
9820 goto die;
9821 gen_helper_tlbwi(cpu_env);
9822 break;
9823 case OPC_TLBINV:
9824 opn = "tlbinv";
9825 if (ctx->ie >= 2) {
9826 if (!env->tlb->helper_tlbinv) {
9827 goto die;
9829 gen_helper_tlbinv(cpu_env);
9830 } /* treat as nop if TLBINV not supported */
9831 break;
9832 case OPC_TLBINVF:
9833 opn = "tlbinvf";
9834 if (ctx->ie >= 2) {
9835 if (!env->tlb->helper_tlbinvf) {
9836 goto die;
9838 gen_helper_tlbinvf(cpu_env);
9839 } /* treat as nop if TLBINV not supported */
9840 break;
9841 case OPC_TLBWR:
9842 opn = "tlbwr";
9843 if (!env->tlb->helper_tlbwr)
9844 goto die;
9845 gen_helper_tlbwr(cpu_env);
9846 break;
9847 case OPC_TLBP:
9848 opn = "tlbp";
9849 if (!env->tlb->helper_tlbp)
9850 goto die;
9851 gen_helper_tlbp(cpu_env);
9852 break;
9853 case OPC_TLBR:
9854 opn = "tlbr";
9855 if (!env->tlb->helper_tlbr)
9856 goto die;
9857 gen_helper_tlbr(cpu_env);
9858 break;
9859 case OPC_ERET: /* OPC_ERETNC */
9860 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9861 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9862 goto die;
9863 } else {
9864 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9865 if (ctx->opcode & (1 << bit_shift)) {
9866 /* OPC_ERETNC */
9867 opn = "eretnc";
9868 check_insn(ctx, ISA_MIPS32R5);
9869 gen_helper_eretnc(cpu_env);
9870 } else {
9871 /* OPC_ERET */
9872 opn = "eret";
9873 check_insn(ctx, ISA_MIPS2);
9874 gen_helper_eret(cpu_env);
9876 ctx->base.is_jmp = DISAS_EXIT;
9878 break;
9879 case OPC_DERET:
9880 opn = "deret";
9881 check_insn(ctx, ISA_MIPS32);
9882 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9883 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9884 goto die;
9886 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9887 MIPS_INVAL(opn);
9888 generate_exception_end(ctx, EXCP_RI);
9889 } else {
9890 gen_helper_deret(cpu_env);
9891 ctx->base.is_jmp = DISAS_EXIT;
9893 break;
9894 case OPC_WAIT:
9895 opn = "wait";
9896 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9897 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9898 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9899 goto die;
9901 /* If we get an exception, we want to restart at next instruction */
9902 ctx->base.pc_next += 4;
9903 save_cpu_state(ctx, 1);
9904 ctx->base.pc_next -= 4;
9905 gen_helper_wait(cpu_env);
9906 ctx->base.is_jmp = DISAS_NORETURN;
9907 break;
9908 default:
9909 die:
9910 MIPS_INVAL(opn);
9911 generate_exception_end(ctx, EXCP_RI);
9912 return;
9914 (void)opn; /* avoid a compiler warning */
9916 #endif /* !CONFIG_USER_ONLY */
9918 /* CP1 Branches (before delay slot) */
9919 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9920 int32_t cc, int32_t offset)
9922 target_ulong btarget;
9923 TCGv_i32 t0 = tcg_temp_new_i32();
9925 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9926 generate_exception_end(ctx, EXCP_RI);
9927 goto out;
9930 if (cc != 0)
9931 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9933 btarget = ctx->base.pc_next + 4 + offset;
9935 switch (op) {
9936 case OPC_BC1F:
9937 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9938 tcg_gen_not_i32(t0, t0);
9939 tcg_gen_andi_i32(t0, t0, 1);
9940 tcg_gen_extu_i32_tl(bcond, t0);
9941 goto not_likely;
9942 case OPC_BC1FL:
9943 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9944 tcg_gen_not_i32(t0, t0);
9945 tcg_gen_andi_i32(t0, t0, 1);
9946 tcg_gen_extu_i32_tl(bcond, t0);
9947 goto likely;
9948 case OPC_BC1T:
9949 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9950 tcg_gen_andi_i32(t0, t0, 1);
9951 tcg_gen_extu_i32_tl(bcond, t0);
9952 goto not_likely;
9953 case OPC_BC1TL:
9954 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9955 tcg_gen_andi_i32(t0, t0, 1);
9956 tcg_gen_extu_i32_tl(bcond, t0);
9957 likely:
9958 ctx->hflags |= MIPS_HFLAG_BL;
9959 break;
9960 case OPC_BC1FANY2:
9962 TCGv_i32 t1 = tcg_temp_new_i32();
9963 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9964 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9965 tcg_gen_nand_i32(t0, t0, t1);
9966 tcg_temp_free_i32(t1);
9967 tcg_gen_andi_i32(t0, t0, 1);
9968 tcg_gen_extu_i32_tl(bcond, t0);
9970 goto not_likely;
9971 case OPC_BC1TANY2:
9973 TCGv_i32 t1 = tcg_temp_new_i32();
9974 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9975 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9976 tcg_gen_or_i32(t0, t0, t1);
9977 tcg_temp_free_i32(t1);
9978 tcg_gen_andi_i32(t0, t0, 1);
9979 tcg_gen_extu_i32_tl(bcond, t0);
9981 goto not_likely;
9982 case OPC_BC1FANY4:
9984 TCGv_i32 t1 = tcg_temp_new_i32();
9985 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9986 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9987 tcg_gen_and_i32(t0, t0, t1);
9988 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9989 tcg_gen_and_i32(t0, t0, t1);
9990 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9991 tcg_gen_nand_i32(t0, t0, t1);
9992 tcg_temp_free_i32(t1);
9993 tcg_gen_andi_i32(t0, t0, 1);
9994 tcg_gen_extu_i32_tl(bcond, t0);
9996 goto not_likely;
9997 case OPC_BC1TANY4:
9999 TCGv_i32 t1 = tcg_temp_new_i32();
10000 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10001 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
10002 tcg_gen_or_i32(t0, t0, t1);
10003 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
10004 tcg_gen_or_i32(t0, t0, t1);
10005 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
10006 tcg_gen_or_i32(t0, t0, t1);
10007 tcg_temp_free_i32(t1);
10008 tcg_gen_andi_i32(t0, t0, 1);
10009 tcg_gen_extu_i32_tl(bcond, t0);
10011 not_likely:
10012 ctx->hflags |= MIPS_HFLAG_BC;
10013 break;
10014 default:
10015 MIPS_INVAL("cp1 cond branch");
10016 generate_exception_end(ctx, EXCP_RI);
10017 goto out;
10019 ctx->btarget = btarget;
10020 ctx->hflags |= MIPS_HFLAG_BDS32;
10021 out:
10022 tcg_temp_free_i32(t0);
10025 /* R6 CP1 Branches */
10026 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
10027 int32_t ft, int32_t offset,
10028 int delayslot_size)
10030 target_ulong btarget;
10031 TCGv_i64 t0 = tcg_temp_new_i64();
10033 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10034 #ifdef MIPS_DEBUG_DISAS
10035 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10036 "\n", ctx->base.pc_next);
10037 #endif
10038 generate_exception_end(ctx, EXCP_RI);
10039 goto out;
10042 gen_load_fpr64(ctx, t0, ft);
10043 tcg_gen_andi_i64(t0, t0, 1);
10045 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
10047 switch (op) {
10048 case OPC_BC1EQZ:
10049 tcg_gen_xori_i64(t0, t0, 1);
10050 ctx->hflags |= MIPS_HFLAG_BC;
10051 break;
10052 case OPC_BC1NEZ:
10053 /* t0 already set */
10054 ctx->hflags |= MIPS_HFLAG_BC;
10055 break;
10056 default:
10057 MIPS_INVAL("cp1 cond branch");
10058 generate_exception_end(ctx, EXCP_RI);
10059 goto out;
10062 tcg_gen_trunc_i64_tl(bcond, t0);
10064 ctx->btarget = btarget;
10066 switch (delayslot_size) {
10067 case 2:
10068 ctx->hflags |= MIPS_HFLAG_BDS16;
10069 break;
10070 case 4:
10071 ctx->hflags |= MIPS_HFLAG_BDS32;
10072 break;
10075 out:
10076 tcg_temp_free_i64(t0);
10079 /* Coprocessor 1 (FPU) */
10081 #define FOP(func, fmt) (((fmt) << 21) | (func))
10083 enum fopcode {
10084 OPC_ADD_S = FOP(0, FMT_S),
10085 OPC_SUB_S = FOP(1, FMT_S),
10086 OPC_MUL_S = FOP(2, FMT_S),
10087 OPC_DIV_S = FOP(3, FMT_S),
10088 OPC_SQRT_S = FOP(4, FMT_S),
10089 OPC_ABS_S = FOP(5, FMT_S),
10090 OPC_MOV_S = FOP(6, FMT_S),
10091 OPC_NEG_S = FOP(7, FMT_S),
10092 OPC_ROUND_L_S = FOP(8, FMT_S),
10093 OPC_TRUNC_L_S = FOP(9, FMT_S),
10094 OPC_CEIL_L_S = FOP(10, FMT_S),
10095 OPC_FLOOR_L_S = FOP(11, FMT_S),
10096 OPC_ROUND_W_S = FOP(12, FMT_S),
10097 OPC_TRUNC_W_S = FOP(13, FMT_S),
10098 OPC_CEIL_W_S = FOP(14, FMT_S),
10099 OPC_FLOOR_W_S = FOP(15, FMT_S),
10100 OPC_SEL_S = FOP(16, FMT_S),
10101 OPC_MOVCF_S = FOP(17, FMT_S),
10102 OPC_MOVZ_S = FOP(18, FMT_S),
10103 OPC_MOVN_S = FOP(19, FMT_S),
10104 OPC_SELEQZ_S = FOP(20, FMT_S),
10105 OPC_RECIP_S = FOP(21, FMT_S),
10106 OPC_RSQRT_S = FOP(22, FMT_S),
10107 OPC_SELNEZ_S = FOP(23, FMT_S),
10108 OPC_MADDF_S = FOP(24, FMT_S),
10109 OPC_MSUBF_S = FOP(25, FMT_S),
10110 OPC_RINT_S = FOP(26, FMT_S),
10111 OPC_CLASS_S = FOP(27, FMT_S),
10112 OPC_MIN_S = FOP(28, FMT_S),
10113 OPC_RECIP2_S = FOP(28, FMT_S),
10114 OPC_MINA_S = FOP(29, FMT_S),
10115 OPC_RECIP1_S = FOP(29, FMT_S),
10116 OPC_MAX_S = FOP(30, FMT_S),
10117 OPC_RSQRT1_S = FOP(30, FMT_S),
10118 OPC_MAXA_S = FOP(31, FMT_S),
10119 OPC_RSQRT2_S = FOP(31, FMT_S),
10120 OPC_CVT_D_S = FOP(33, FMT_S),
10121 OPC_CVT_W_S = FOP(36, FMT_S),
10122 OPC_CVT_L_S = FOP(37, FMT_S),
10123 OPC_CVT_PS_S = FOP(38, FMT_S),
10124 OPC_CMP_F_S = FOP (48, FMT_S),
10125 OPC_CMP_UN_S = FOP (49, FMT_S),
10126 OPC_CMP_EQ_S = FOP (50, FMT_S),
10127 OPC_CMP_UEQ_S = FOP (51, FMT_S),
10128 OPC_CMP_OLT_S = FOP (52, FMT_S),
10129 OPC_CMP_ULT_S = FOP (53, FMT_S),
10130 OPC_CMP_OLE_S = FOP (54, FMT_S),
10131 OPC_CMP_ULE_S = FOP (55, FMT_S),
10132 OPC_CMP_SF_S = FOP (56, FMT_S),
10133 OPC_CMP_NGLE_S = FOP (57, FMT_S),
10134 OPC_CMP_SEQ_S = FOP (58, FMT_S),
10135 OPC_CMP_NGL_S = FOP (59, FMT_S),
10136 OPC_CMP_LT_S = FOP (60, FMT_S),
10137 OPC_CMP_NGE_S = FOP (61, FMT_S),
10138 OPC_CMP_LE_S = FOP (62, FMT_S),
10139 OPC_CMP_NGT_S = FOP (63, FMT_S),
10141 OPC_ADD_D = FOP(0, FMT_D),
10142 OPC_SUB_D = FOP(1, FMT_D),
10143 OPC_MUL_D = FOP(2, FMT_D),
10144 OPC_DIV_D = FOP(3, FMT_D),
10145 OPC_SQRT_D = FOP(4, FMT_D),
10146 OPC_ABS_D = FOP(5, FMT_D),
10147 OPC_MOV_D = FOP(6, FMT_D),
10148 OPC_NEG_D = FOP(7, FMT_D),
10149 OPC_ROUND_L_D = FOP(8, FMT_D),
10150 OPC_TRUNC_L_D = FOP(9, FMT_D),
10151 OPC_CEIL_L_D = FOP(10, FMT_D),
10152 OPC_FLOOR_L_D = FOP(11, FMT_D),
10153 OPC_ROUND_W_D = FOP(12, FMT_D),
10154 OPC_TRUNC_W_D = FOP(13, FMT_D),
10155 OPC_CEIL_W_D = FOP(14, FMT_D),
10156 OPC_FLOOR_W_D = FOP(15, FMT_D),
10157 OPC_SEL_D = FOP(16, FMT_D),
10158 OPC_MOVCF_D = FOP(17, FMT_D),
10159 OPC_MOVZ_D = FOP(18, FMT_D),
10160 OPC_MOVN_D = FOP(19, FMT_D),
10161 OPC_SELEQZ_D = FOP(20, FMT_D),
10162 OPC_RECIP_D = FOP(21, FMT_D),
10163 OPC_RSQRT_D = FOP(22, FMT_D),
10164 OPC_SELNEZ_D = FOP(23, FMT_D),
10165 OPC_MADDF_D = FOP(24, FMT_D),
10166 OPC_MSUBF_D = FOP(25, FMT_D),
10167 OPC_RINT_D = FOP(26, FMT_D),
10168 OPC_CLASS_D = FOP(27, FMT_D),
10169 OPC_MIN_D = FOP(28, FMT_D),
10170 OPC_RECIP2_D = FOP(28, FMT_D),
10171 OPC_MINA_D = FOP(29, FMT_D),
10172 OPC_RECIP1_D = FOP(29, FMT_D),
10173 OPC_MAX_D = FOP(30, FMT_D),
10174 OPC_RSQRT1_D = FOP(30, FMT_D),
10175 OPC_MAXA_D = FOP(31, FMT_D),
10176 OPC_RSQRT2_D = FOP(31, FMT_D),
10177 OPC_CVT_S_D = FOP(32, FMT_D),
10178 OPC_CVT_W_D = FOP(36, FMT_D),
10179 OPC_CVT_L_D = FOP(37, FMT_D),
10180 OPC_CMP_F_D = FOP (48, FMT_D),
10181 OPC_CMP_UN_D = FOP (49, FMT_D),
10182 OPC_CMP_EQ_D = FOP (50, FMT_D),
10183 OPC_CMP_UEQ_D = FOP (51, FMT_D),
10184 OPC_CMP_OLT_D = FOP (52, FMT_D),
10185 OPC_CMP_ULT_D = FOP (53, FMT_D),
10186 OPC_CMP_OLE_D = FOP (54, FMT_D),
10187 OPC_CMP_ULE_D = FOP (55, FMT_D),
10188 OPC_CMP_SF_D = FOP (56, FMT_D),
10189 OPC_CMP_NGLE_D = FOP (57, FMT_D),
10190 OPC_CMP_SEQ_D = FOP (58, FMT_D),
10191 OPC_CMP_NGL_D = FOP (59, FMT_D),
10192 OPC_CMP_LT_D = FOP (60, FMT_D),
10193 OPC_CMP_NGE_D = FOP (61, FMT_D),
10194 OPC_CMP_LE_D = FOP (62, FMT_D),
10195 OPC_CMP_NGT_D = FOP (63, FMT_D),
10197 OPC_CVT_S_W = FOP(32, FMT_W),
10198 OPC_CVT_D_W = FOP(33, FMT_W),
10199 OPC_CVT_S_L = FOP(32, FMT_L),
10200 OPC_CVT_D_L = FOP(33, FMT_L),
10201 OPC_CVT_PS_PW = FOP(38, FMT_W),
10203 OPC_ADD_PS = FOP(0, FMT_PS),
10204 OPC_SUB_PS = FOP(1, FMT_PS),
10205 OPC_MUL_PS = FOP(2, FMT_PS),
10206 OPC_DIV_PS = FOP(3, FMT_PS),
10207 OPC_ABS_PS = FOP(5, FMT_PS),
10208 OPC_MOV_PS = FOP(6, FMT_PS),
10209 OPC_NEG_PS = FOP(7, FMT_PS),
10210 OPC_MOVCF_PS = FOP(17, FMT_PS),
10211 OPC_MOVZ_PS = FOP(18, FMT_PS),
10212 OPC_MOVN_PS = FOP(19, FMT_PS),
10213 OPC_ADDR_PS = FOP(24, FMT_PS),
10214 OPC_MULR_PS = FOP(26, FMT_PS),
10215 OPC_RECIP2_PS = FOP(28, FMT_PS),
10216 OPC_RECIP1_PS = FOP(29, FMT_PS),
10217 OPC_RSQRT1_PS = FOP(30, FMT_PS),
10218 OPC_RSQRT2_PS = FOP(31, FMT_PS),
10220 OPC_CVT_S_PU = FOP(32, FMT_PS),
10221 OPC_CVT_PW_PS = FOP(36, FMT_PS),
10222 OPC_CVT_S_PL = FOP(40, FMT_PS),
10223 OPC_PLL_PS = FOP(44, FMT_PS),
10224 OPC_PLU_PS = FOP(45, FMT_PS),
10225 OPC_PUL_PS = FOP(46, FMT_PS),
10226 OPC_PUU_PS = FOP(47, FMT_PS),
10227 OPC_CMP_F_PS = FOP (48, FMT_PS),
10228 OPC_CMP_UN_PS = FOP (49, FMT_PS),
10229 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
10230 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
10231 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
10232 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
10233 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
10234 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
10235 OPC_CMP_SF_PS = FOP (56, FMT_PS),
10236 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
10237 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
10238 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
10239 OPC_CMP_LT_PS = FOP (60, FMT_PS),
10240 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
10241 OPC_CMP_LE_PS = FOP (62, FMT_PS),
10242 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
10245 enum r6_f_cmp_op {
10246 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
10247 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
10248 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
10249 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
10250 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
10251 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
10252 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
10253 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
10254 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
10255 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
10256 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
10257 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
10258 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
10259 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
10260 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
10261 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
10262 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
10263 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
10264 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
10265 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
10266 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10267 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10269 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10270 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10271 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10272 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10273 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10274 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10275 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10276 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10277 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10278 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10279 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10280 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10281 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10282 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10283 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10284 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10285 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10286 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10287 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10288 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10289 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10290 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10292 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10294 TCGv t0 = tcg_temp_new();
10296 switch (opc) {
10297 case OPC_MFC1:
10299 TCGv_i32 fp0 = tcg_temp_new_i32();
10301 gen_load_fpr32(ctx, fp0, fs);
10302 tcg_gen_ext_i32_tl(t0, fp0);
10303 tcg_temp_free_i32(fp0);
10305 gen_store_gpr(t0, rt);
10306 break;
10307 case OPC_MTC1:
10308 gen_load_gpr(t0, rt);
10310 TCGv_i32 fp0 = tcg_temp_new_i32();
10312 tcg_gen_trunc_tl_i32(fp0, t0);
10313 gen_store_fpr32(ctx, fp0, fs);
10314 tcg_temp_free_i32(fp0);
10316 break;
10317 case OPC_CFC1:
10318 gen_helper_1e0i(cfc1, t0, fs);
10319 gen_store_gpr(t0, rt);
10320 break;
10321 case OPC_CTC1:
10322 gen_load_gpr(t0, rt);
10323 save_cpu_state(ctx, 0);
10325 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10327 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10328 tcg_temp_free_i32(fs_tmp);
10330 /* Stop translation as we may have changed hflags */
10331 ctx->base.is_jmp = DISAS_STOP;
10332 break;
10333 #if defined(TARGET_MIPS64)
10334 case OPC_DMFC1:
10335 gen_load_fpr64(ctx, t0, fs);
10336 gen_store_gpr(t0, rt);
10337 break;
10338 case OPC_DMTC1:
10339 gen_load_gpr(t0, rt);
10340 gen_store_fpr64(ctx, t0, fs);
10341 break;
10342 #endif
10343 case OPC_MFHC1:
10345 TCGv_i32 fp0 = tcg_temp_new_i32();
10347 gen_load_fpr32h(ctx, fp0, fs);
10348 tcg_gen_ext_i32_tl(t0, fp0);
10349 tcg_temp_free_i32(fp0);
10351 gen_store_gpr(t0, rt);
10352 break;
10353 case OPC_MTHC1:
10354 gen_load_gpr(t0, rt);
10356 TCGv_i32 fp0 = tcg_temp_new_i32();
10358 tcg_gen_trunc_tl_i32(fp0, t0);
10359 gen_store_fpr32h(ctx, fp0, fs);
10360 tcg_temp_free_i32(fp0);
10362 break;
10363 default:
10364 MIPS_INVAL("cp1 move");
10365 generate_exception_end(ctx, EXCP_RI);
10366 goto out;
10369 out:
10370 tcg_temp_free(t0);
10373 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10375 TCGLabel *l1;
10376 TCGCond cond;
10377 TCGv_i32 t0;
10379 if (rd == 0) {
10380 /* Treat as NOP. */
10381 return;
10384 if (tf)
10385 cond = TCG_COND_EQ;
10386 else
10387 cond = TCG_COND_NE;
10389 l1 = gen_new_label();
10390 t0 = tcg_temp_new_i32();
10391 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10392 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10393 tcg_temp_free_i32(t0);
10394 if (rs == 0) {
10395 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10396 } else {
10397 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10399 gen_set_label(l1);
10402 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10403 int tf)
10405 int cond;
10406 TCGv_i32 t0 = tcg_temp_new_i32();
10407 TCGLabel *l1 = gen_new_label();
10409 if (tf)
10410 cond = TCG_COND_EQ;
10411 else
10412 cond = TCG_COND_NE;
10414 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10415 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10416 gen_load_fpr32(ctx, t0, fs);
10417 gen_store_fpr32(ctx, t0, fd);
10418 gen_set_label(l1);
10419 tcg_temp_free_i32(t0);
10422 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10424 int cond;
10425 TCGv_i32 t0 = tcg_temp_new_i32();
10426 TCGv_i64 fp0;
10427 TCGLabel *l1 = gen_new_label();
10429 if (tf)
10430 cond = TCG_COND_EQ;
10431 else
10432 cond = TCG_COND_NE;
10434 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10435 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10436 tcg_temp_free_i32(t0);
10437 fp0 = tcg_temp_new_i64();
10438 gen_load_fpr64(ctx, fp0, fs);
10439 gen_store_fpr64(ctx, fp0, fd);
10440 tcg_temp_free_i64(fp0);
10441 gen_set_label(l1);
10444 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10445 int cc, int tf)
10447 int cond;
10448 TCGv_i32 t0 = tcg_temp_new_i32();
10449 TCGLabel *l1 = gen_new_label();
10450 TCGLabel *l2 = gen_new_label();
10452 if (tf)
10453 cond = TCG_COND_EQ;
10454 else
10455 cond = TCG_COND_NE;
10457 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10458 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10459 gen_load_fpr32(ctx, t0, fs);
10460 gen_store_fpr32(ctx, t0, fd);
10461 gen_set_label(l1);
10463 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10464 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10465 gen_load_fpr32h(ctx, t0, fs);
10466 gen_store_fpr32h(ctx, t0, fd);
10467 tcg_temp_free_i32(t0);
10468 gen_set_label(l2);
10471 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10472 int fs)
10474 TCGv_i32 t1 = tcg_const_i32(0);
10475 TCGv_i32 fp0 = tcg_temp_new_i32();
10476 TCGv_i32 fp1 = tcg_temp_new_i32();
10477 TCGv_i32 fp2 = tcg_temp_new_i32();
10478 gen_load_fpr32(ctx, fp0, fd);
10479 gen_load_fpr32(ctx, fp1, ft);
10480 gen_load_fpr32(ctx, fp2, fs);
10482 switch (op1) {
10483 case OPC_SEL_S:
10484 tcg_gen_andi_i32(fp0, fp0, 1);
10485 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10486 break;
10487 case OPC_SELEQZ_S:
10488 tcg_gen_andi_i32(fp1, fp1, 1);
10489 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10490 break;
10491 case OPC_SELNEZ_S:
10492 tcg_gen_andi_i32(fp1, fp1, 1);
10493 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10494 break;
10495 default:
10496 MIPS_INVAL("gen_sel_s");
10497 generate_exception_end(ctx, EXCP_RI);
10498 break;
10501 gen_store_fpr32(ctx, fp0, fd);
10502 tcg_temp_free_i32(fp2);
10503 tcg_temp_free_i32(fp1);
10504 tcg_temp_free_i32(fp0);
10505 tcg_temp_free_i32(t1);
10508 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10509 int fs)
10511 TCGv_i64 t1 = tcg_const_i64(0);
10512 TCGv_i64 fp0 = tcg_temp_new_i64();
10513 TCGv_i64 fp1 = tcg_temp_new_i64();
10514 TCGv_i64 fp2 = tcg_temp_new_i64();
10515 gen_load_fpr64(ctx, fp0, fd);
10516 gen_load_fpr64(ctx, fp1, ft);
10517 gen_load_fpr64(ctx, fp2, fs);
10519 switch (op1) {
10520 case OPC_SEL_D:
10521 tcg_gen_andi_i64(fp0, fp0, 1);
10522 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10523 break;
10524 case OPC_SELEQZ_D:
10525 tcg_gen_andi_i64(fp1, fp1, 1);
10526 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10527 break;
10528 case OPC_SELNEZ_D:
10529 tcg_gen_andi_i64(fp1, fp1, 1);
10530 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10531 break;
10532 default:
10533 MIPS_INVAL("gen_sel_d");
10534 generate_exception_end(ctx, EXCP_RI);
10535 break;
10538 gen_store_fpr64(ctx, fp0, fd);
10539 tcg_temp_free_i64(fp2);
10540 tcg_temp_free_i64(fp1);
10541 tcg_temp_free_i64(fp0);
10542 tcg_temp_free_i64(t1);
10545 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10546 int ft, int fs, int fd, int cc)
10548 uint32_t func = ctx->opcode & 0x3f;
10549 switch (op1) {
10550 case OPC_ADD_S:
10552 TCGv_i32 fp0 = tcg_temp_new_i32();
10553 TCGv_i32 fp1 = tcg_temp_new_i32();
10555 gen_load_fpr32(ctx, fp0, fs);
10556 gen_load_fpr32(ctx, fp1, ft);
10557 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10558 tcg_temp_free_i32(fp1);
10559 gen_store_fpr32(ctx, fp0, fd);
10560 tcg_temp_free_i32(fp0);
10562 break;
10563 case OPC_SUB_S:
10565 TCGv_i32 fp0 = tcg_temp_new_i32();
10566 TCGv_i32 fp1 = tcg_temp_new_i32();
10568 gen_load_fpr32(ctx, fp0, fs);
10569 gen_load_fpr32(ctx, fp1, ft);
10570 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10571 tcg_temp_free_i32(fp1);
10572 gen_store_fpr32(ctx, fp0, fd);
10573 tcg_temp_free_i32(fp0);
10575 break;
10576 case OPC_MUL_S:
10578 TCGv_i32 fp0 = tcg_temp_new_i32();
10579 TCGv_i32 fp1 = tcg_temp_new_i32();
10581 gen_load_fpr32(ctx, fp0, fs);
10582 gen_load_fpr32(ctx, fp1, ft);
10583 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10584 tcg_temp_free_i32(fp1);
10585 gen_store_fpr32(ctx, fp0, fd);
10586 tcg_temp_free_i32(fp0);
10588 break;
10589 case OPC_DIV_S:
10591 TCGv_i32 fp0 = tcg_temp_new_i32();
10592 TCGv_i32 fp1 = tcg_temp_new_i32();
10594 gen_load_fpr32(ctx, fp0, fs);
10595 gen_load_fpr32(ctx, fp1, ft);
10596 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10597 tcg_temp_free_i32(fp1);
10598 gen_store_fpr32(ctx, fp0, fd);
10599 tcg_temp_free_i32(fp0);
10601 break;
10602 case OPC_SQRT_S:
10604 TCGv_i32 fp0 = tcg_temp_new_i32();
10606 gen_load_fpr32(ctx, fp0, fs);
10607 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10608 gen_store_fpr32(ctx, fp0, fd);
10609 tcg_temp_free_i32(fp0);
10611 break;
10612 case OPC_ABS_S:
10614 TCGv_i32 fp0 = tcg_temp_new_i32();
10616 gen_load_fpr32(ctx, fp0, fs);
10617 if (ctx->abs2008) {
10618 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10619 } else {
10620 gen_helper_float_abs_s(fp0, fp0);
10622 gen_store_fpr32(ctx, fp0, fd);
10623 tcg_temp_free_i32(fp0);
10625 break;
10626 case OPC_MOV_S:
10628 TCGv_i32 fp0 = tcg_temp_new_i32();
10630 gen_load_fpr32(ctx, fp0, fs);
10631 gen_store_fpr32(ctx, fp0, fd);
10632 tcg_temp_free_i32(fp0);
10634 break;
10635 case OPC_NEG_S:
10637 TCGv_i32 fp0 = tcg_temp_new_i32();
10639 gen_load_fpr32(ctx, fp0, fs);
10640 if (ctx->abs2008) {
10641 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10642 } else {
10643 gen_helper_float_chs_s(fp0, fp0);
10645 gen_store_fpr32(ctx, fp0, fd);
10646 tcg_temp_free_i32(fp0);
10648 break;
10649 case OPC_ROUND_L_S:
10650 check_cp1_64bitmode(ctx);
10652 TCGv_i32 fp32 = tcg_temp_new_i32();
10653 TCGv_i64 fp64 = tcg_temp_new_i64();
10655 gen_load_fpr32(ctx, fp32, fs);
10656 if (ctx->nan2008) {
10657 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10658 } else {
10659 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10661 tcg_temp_free_i32(fp32);
10662 gen_store_fpr64(ctx, fp64, fd);
10663 tcg_temp_free_i64(fp64);
10665 break;
10666 case OPC_TRUNC_L_S:
10667 check_cp1_64bitmode(ctx);
10669 TCGv_i32 fp32 = tcg_temp_new_i32();
10670 TCGv_i64 fp64 = tcg_temp_new_i64();
10672 gen_load_fpr32(ctx, fp32, fs);
10673 if (ctx->nan2008) {
10674 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10675 } else {
10676 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10678 tcg_temp_free_i32(fp32);
10679 gen_store_fpr64(ctx, fp64, fd);
10680 tcg_temp_free_i64(fp64);
10682 break;
10683 case OPC_CEIL_L_S:
10684 check_cp1_64bitmode(ctx);
10686 TCGv_i32 fp32 = tcg_temp_new_i32();
10687 TCGv_i64 fp64 = tcg_temp_new_i64();
10689 gen_load_fpr32(ctx, fp32, fs);
10690 if (ctx->nan2008) {
10691 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10692 } else {
10693 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10695 tcg_temp_free_i32(fp32);
10696 gen_store_fpr64(ctx, fp64, fd);
10697 tcg_temp_free_i64(fp64);
10699 break;
10700 case OPC_FLOOR_L_S:
10701 check_cp1_64bitmode(ctx);
10703 TCGv_i32 fp32 = tcg_temp_new_i32();
10704 TCGv_i64 fp64 = tcg_temp_new_i64();
10706 gen_load_fpr32(ctx, fp32, fs);
10707 if (ctx->nan2008) {
10708 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10709 } else {
10710 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10712 tcg_temp_free_i32(fp32);
10713 gen_store_fpr64(ctx, fp64, fd);
10714 tcg_temp_free_i64(fp64);
10716 break;
10717 case OPC_ROUND_W_S:
10719 TCGv_i32 fp0 = tcg_temp_new_i32();
10721 gen_load_fpr32(ctx, fp0, fs);
10722 if (ctx->nan2008) {
10723 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10724 } else {
10725 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10727 gen_store_fpr32(ctx, fp0, fd);
10728 tcg_temp_free_i32(fp0);
10730 break;
10731 case OPC_TRUNC_W_S:
10733 TCGv_i32 fp0 = tcg_temp_new_i32();
10735 gen_load_fpr32(ctx, fp0, fs);
10736 if (ctx->nan2008) {
10737 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10738 } else {
10739 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10741 gen_store_fpr32(ctx, fp0, fd);
10742 tcg_temp_free_i32(fp0);
10744 break;
10745 case OPC_CEIL_W_S:
10747 TCGv_i32 fp0 = tcg_temp_new_i32();
10749 gen_load_fpr32(ctx, fp0, fs);
10750 if (ctx->nan2008) {
10751 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10752 } else {
10753 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10755 gen_store_fpr32(ctx, fp0, fd);
10756 tcg_temp_free_i32(fp0);
10758 break;
10759 case OPC_FLOOR_W_S:
10761 TCGv_i32 fp0 = tcg_temp_new_i32();
10763 gen_load_fpr32(ctx, fp0, fs);
10764 if (ctx->nan2008) {
10765 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10766 } else {
10767 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10769 gen_store_fpr32(ctx, fp0, fd);
10770 tcg_temp_free_i32(fp0);
10772 break;
10773 case OPC_SEL_S:
10774 check_insn(ctx, ISA_MIPS32R6);
10775 gen_sel_s(ctx, op1, fd, ft, fs);
10776 break;
10777 case OPC_SELEQZ_S:
10778 check_insn(ctx, ISA_MIPS32R6);
10779 gen_sel_s(ctx, op1, fd, ft, fs);
10780 break;
10781 case OPC_SELNEZ_S:
10782 check_insn(ctx, ISA_MIPS32R6);
10783 gen_sel_s(ctx, op1, fd, ft, fs);
10784 break;
10785 case OPC_MOVCF_S:
10786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10787 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10788 break;
10789 case OPC_MOVZ_S:
10790 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10792 TCGLabel *l1 = gen_new_label();
10793 TCGv_i32 fp0;
10795 if (ft != 0) {
10796 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10798 fp0 = tcg_temp_new_i32();
10799 gen_load_fpr32(ctx, fp0, fs);
10800 gen_store_fpr32(ctx, fp0, fd);
10801 tcg_temp_free_i32(fp0);
10802 gen_set_label(l1);
10804 break;
10805 case OPC_MOVN_S:
10806 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10808 TCGLabel *l1 = gen_new_label();
10809 TCGv_i32 fp0;
10811 if (ft != 0) {
10812 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10813 fp0 = tcg_temp_new_i32();
10814 gen_load_fpr32(ctx, fp0, fs);
10815 gen_store_fpr32(ctx, fp0, fd);
10816 tcg_temp_free_i32(fp0);
10817 gen_set_label(l1);
10820 break;
10821 case OPC_RECIP_S:
10823 TCGv_i32 fp0 = tcg_temp_new_i32();
10825 gen_load_fpr32(ctx, fp0, fs);
10826 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10827 gen_store_fpr32(ctx, fp0, fd);
10828 tcg_temp_free_i32(fp0);
10830 break;
10831 case OPC_RSQRT_S:
10833 TCGv_i32 fp0 = tcg_temp_new_i32();
10835 gen_load_fpr32(ctx, fp0, fs);
10836 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10837 gen_store_fpr32(ctx, fp0, fd);
10838 tcg_temp_free_i32(fp0);
10840 break;
10841 case OPC_MADDF_S:
10842 check_insn(ctx, ISA_MIPS32R6);
10844 TCGv_i32 fp0 = tcg_temp_new_i32();
10845 TCGv_i32 fp1 = tcg_temp_new_i32();
10846 TCGv_i32 fp2 = tcg_temp_new_i32();
10847 gen_load_fpr32(ctx, fp0, fs);
10848 gen_load_fpr32(ctx, fp1, ft);
10849 gen_load_fpr32(ctx, fp2, fd);
10850 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10851 gen_store_fpr32(ctx, fp2, fd);
10852 tcg_temp_free_i32(fp2);
10853 tcg_temp_free_i32(fp1);
10854 tcg_temp_free_i32(fp0);
10856 break;
10857 case OPC_MSUBF_S:
10858 check_insn(ctx, ISA_MIPS32R6);
10860 TCGv_i32 fp0 = tcg_temp_new_i32();
10861 TCGv_i32 fp1 = tcg_temp_new_i32();
10862 TCGv_i32 fp2 = tcg_temp_new_i32();
10863 gen_load_fpr32(ctx, fp0, fs);
10864 gen_load_fpr32(ctx, fp1, ft);
10865 gen_load_fpr32(ctx, fp2, fd);
10866 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10867 gen_store_fpr32(ctx, fp2, fd);
10868 tcg_temp_free_i32(fp2);
10869 tcg_temp_free_i32(fp1);
10870 tcg_temp_free_i32(fp0);
10872 break;
10873 case OPC_RINT_S:
10874 check_insn(ctx, ISA_MIPS32R6);
10876 TCGv_i32 fp0 = tcg_temp_new_i32();
10877 gen_load_fpr32(ctx, fp0, fs);
10878 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10879 gen_store_fpr32(ctx, fp0, fd);
10880 tcg_temp_free_i32(fp0);
10882 break;
10883 case OPC_CLASS_S:
10884 check_insn(ctx, ISA_MIPS32R6);
10886 TCGv_i32 fp0 = tcg_temp_new_i32();
10887 gen_load_fpr32(ctx, fp0, fs);
10888 gen_helper_float_class_s(fp0, cpu_env, fp0);
10889 gen_store_fpr32(ctx, fp0, fd);
10890 tcg_temp_free_i32(fp0);
10892 break;
10893 case OPC_MIN_S: /* OPC_RECIP2_S */
10894 if (ctx->insn_flags & ISA_MIPS32R6) {
10895 /* OPC_MIN_S */
10896 TCGv_i32 fp0 = tcg_temp_new_i32();
10897 TCGv_i32 fp1 = tcg_temp_new_i32();
10898 TCGv_i32 fp2 = tcg_temp_new_i32();
10899 gen_load_fpr32(ctx, fp0, fs);
10900 gen_load_fpr32(ctx, fp1, ft);
10901 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10902 gen_store_fpr32(ctx, fp2, fd);
10903 tcg_temp_free_i32(fp2);
10904 tcg_temp_free_i32(fp1);
10905 tcg_temp_free_i32(fp0);
10906 } else {
10907 /* OPC_RECIP2_S */
10908 check_cp1_64bitmode(ctx);
10910 TCGv_i32 fp0 = tcg_temp_new_i32();
10911 TCGv_i32 fp1 = tcg_temp_new_i32();
10913 gen_load_fpr32(ctx, fp0, fs);
10914 gen_load_fpr32(ctx, fp1, ft);
10915 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10916 tcg_temp_free_i32(fp1);
10917 gen_store_fpr32(ctx, fp0, fd);
10918 tcg_temp_free_i32(fp0);
10921 break;
10922 case OPC_MINA_S: /* OPC_RECIP1_S */
10923 if (ctx->insn_flags & ISA_MIPS32R6) {
10924 /* OPC_MINA_S */
10925 TCGv_i32 fp0 = tcg_temp_new_i32();
10926 TCGv_i32 fp1 = tcg_temp_new_i32();
10927 TCGv_i32 fp2 = tcg_temp_new_i32();
10928 gen_load_fpr32(ctx, fp0, fs);
10929 gen_load_fpr32(ctx, fp1, ft);
10930 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10931 gen_store_fpr32(ctx, fp2, fd);
10932 tcg_temp_free_i32(fp2);
10933 tcg_temp_free_i32(fp1);
10934 tcg_temp_free_i32(fp0);
10935 } else {
10936 /* OPC_RECIP1_S */
10937 check_cp1_64bitmode(ctx);
10939 TCGv_i32 fp0 = tcg_temp_new_i32();
10941 gen_load_fpr32(ctx, fp0, fs);
10942 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10943 gen_store_fpr32(ctx, fp0, fd);
10944 tcg_temp_free_i32(fp0);
10947 break;
10948 case OPC_MAX_S: /* OPC_RSQRT1_S */
10949 if (ctx->insn_flags & ISA_MIPS32R6) {
10950 /* OPC_MAX_S */
10951 TCGv_i32 fp0 = tcg_temp_new_i32();
10952 TCGv_i32 fp1 = tcg_temp_new_i32();
10953 gen_load_fpr32(ctx, fp0, fs);
10954 gen_load_fpr32(ctx, fp1, ft);
10955 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10956 gen_store_fpr32(ctx, fp1, fd);
10957 tcg_temp_free_i32(fp1);
10958 tcg_temp_free_i32(fp0);
10959 } else {
10960 /* OPC_RSQRT1_S */
10961 check_cp1_64bitmode(ctx);
10963 TCGv_i32 fp0 = tcg_temp_new_i32();
10965 gen_load_fpr32(ctx, fp0, fs);
10966 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10967 gen_store_fpr32(ctx, fp0, fd);
10968 tcg_temp_free_i32(fp0);
10971 break;
10972 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10973 if (ctx->insn_flags & ISA_MIPS32R6) {
10974 /* OPC_MAXA_S */
10975 TCGv_i32 fp0 = tcg_temp_new_i32();
10976 TCGv_i32 fp1 = tcg_temp_new_i32();
10977 gen_load_fpr32(ctx, fp0, fs);
10978 gen_load_fpr32(ctx, fp1, ft);
10979 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10980 gen_store_fpr32(ctx, fp1, fd);
10981 tcg_temp_free_i32(fp1);
10982 tcg_temp_free_i32(fp0);
10983 } else {
10984 /* OPC_RSQRT2_S */
10985 check_cp1_64bitmode(ctx);
10987 TCGv_i32 fp0 = tcg_temp_new_i32();
10988 TCGv_i32 fp1 = tcg_temp_new_i32();
10990 gen_load_fpr32(ctx, fp0, fs);
10991 gen_load_fpr32(ctx, fp1, ft);
10992 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10993 tcg_temp_free_i32(fp1);
10994 gen_store_fpr32(ctx, fp0, fd);
10995 tcg_temp_free_i32(fp0);
10998 break;
10999 case OPC_CVT_D_S:
11000 check_cp1_registers(ctx, fd);
11002 TCGv_i32 fp32 = tcg_temp_new_i32();
11003 TCGv_i64 fp64 = tcg_temp_new_i64();
11005 gen_load_fpr32(ctx, fp32, fs);
11006 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
11007 tcg_temp_free_i32(fp32);
11008 gen_store_fpr64(ctx, fp64, fd);
11009 tcg_temp_free_i64(fp64);
11011 break;
11012 case OPC_CVT_W_S:
11014 TCGv_i32 fp0 = tcg_temp_new_i32();
11016 gen_load_fpr32(ctx, fp0, fs);
11017 if (ctx->nan2008) {
11018 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
11019 } else {
11020 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
11022 gen_store_fpr32(ctx, fp0, fd);
11023 tcg_temp_free_i32(fp0);
11025 break;
11026 case OPC_CVT_L_S:
11027 check_cp1_64bitmode(ctx);
11029 TCGv_i32 fp32 = tcg_temp_new_i32();
11030 TCGv_i64 fp64 = tcg_temp_new_i64();
11032 gen_load_fpr32(ctx, fp32, fs);
11033 if (ctx->nan2008) {
11034 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
11035 } else {
11036 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
11038 tcg_temp_free_i32(fp32);
11039 gen_store_fpr64(ctx, fp64, fd);
11040 tcg_temp_free_i64(fp64);
11042 break;
11043 case OPC_CVT_PS_S:
11044 check_ps(ctx);
11046 TCGv_i64 fp64 = tcg_temp_new_i64();
11047 TCGv_i32 fp32_0 = tcg_temp_new_i32();
11048 TCGv_i32 fp32_1 = tcg_temp_new_i32();
11050 gen_load_fpr32(ctx, fp32_0, fs);
11051 gen_load_fpr32(ctx, fp32_1, ft);
11052 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
11053 tcg_temp_free_i32(fp32_1);
11054 tcg_temp_free_i32(fp32_0);
11055 gen_store_fpr64(ctx, fp64, fd);
11056 tcg_temp_free_i64(fp64);
11058 break;
11059 case OPC_CMP_F_S:
11060 case OPC_CMP_UN_S:
11061 case OPC_CMP_EQ_S:
11062 case OPC_CMP_UEQ_S:
11063 case OPC_CMP_OLT_S:
11064 case OPC_CMP_ULT_S:
11065 case OPC_CMP_OLE_S:
11066 case OPC_CMP_ULE_S:
11067 case OPC_CMP_SF_S:
11068 case OPC_CMP_NGLE_S:
11069 case OPC_CMP_SEQ_S:
11070 case OPC_CMP_NGL_S:
11071 case OPC_CMP_LT_S:
11072 case OPC_CMP_NGE_S:
11073 case OPC_CMP_LE_S:
11074 case OPC_CMP_NGT_S:
11075 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11076 if (ctx->opcode & (1 << 6)) {
11077 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
11078 } else {
11079 gen_cmp_s(ctx, func-48, ft, fs, cc);
11081 break;
11082 case OPC_ADD_D:
11083 check_cp1_registers(ctx, fs | ft | fd);
11085 TCGv_i64 fp0 = tcg_temp_new_i64();
11086 TCGv_i64 fp1 = tcg_temp_new_i64();
11088 gen_load_fpr64(ctx, fp0, fs);
11089 gen_load_fpr64(ctx, fp1, ft);
11090 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
11091 tcg_temp_free_i64(fp1);
11092 gen_store_fpr64(ctx, fp0, fd);
11093 tcg_temp_free_i64(fp0);
11095 break;
11096 case OPC_SUB_D:
11097 check_cp1_registers(ctx, fs | ft | fd);
11099 TCGv_i64 fp0 = tcg_temp_new_i64();
11100 TCGv_i64 fp1 = tcg_temp_new_i64();
11102 gen_load_fpr64(ctx, fp0, fs);
11103 gen_load_fpr64(ctx, fp1, ft);
11104 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
11105 tcg_temp_free_i64(fp1);
11106 gen_store_fpr64(ctx, fp0, fd);
11107 tcg_temp_free_i64(fp0);
11109 break;
11110 case OPC_MUL_D:
11111 check_cp1_registers(ctx, fs | ft | fd);
11113 TCGv_i64 fp0 = tcg_temp_new_i64();
11114 TCGv_i64 fp1 = tcg_temp_new_i64();
11116 gen_load_fpr64(ctx, fp0, fs);
11117 gen_load_fpr64(ctx, fp1, ft);
11118 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
11119 tcg_temp_free_i64(fp1);
11120 gen_store_fpr64(ctx, fp0, fd);
11121 tcg_temp_free_i64(fp0);
11123 break;
11124 case OPC_DIV_D:
11125 check_cp1_registers(ctx, fs | ft | fd);
11127 TCGv_i64 fp0 = tcg_temp_new_i64();
11128 TCGv_i64 fp1 = tcg_temp_new_i64();
11130 gen_load_fpr64(ctx, fp0, fs);
11131 gen_load_fpr64(ctx, fp1, ft);
11132 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
11133 tcg_temp_free_i64(fp1);
11134 gen_store_fpr64(ctx, fp0, fd);
11135 tcg_temp_free_i64(fp0);
11137 break;
11138 case OPC_SQRT_D:
11139 check_cp1_registers(ctx, fs | fd);
11141 TCGv_i64 fp0 = tcg_temp_new_i64();
11143 gen_load_fpr64(ctx, fp0, fs);
11144 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
11145 gen_store_fpr64(ctx, fp0, fd);
11146 tcg_temp_free_i64(fp0);
11148 break;
11149 case OPC_ABS_D:
11150 check_cp1_registers(ctx, fs | fd);
11152 TCGv_i64 fp0 = tcg_temp_new_i64();
11154 gen_load_fpr64(ctx, fp0, fs);
11155 if (ctx->abs2008) {
11156 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
11157 } else {
11158 gen_helper_float_abs_d(fp0, fp0);
11160 gen_store_fpr64(ctx, fp0, fd);
11161 tcg_temp_free_i64(fp0);
11163 break;
11164 case OPC_MOV_D:
11165 check_cp1_registers(ctx, fs | fd);
11167 TCGv_i64 fp0 = tcg_temp_new_i64();
11169 gen_load_fpr64(ctx, fp0, fs);
11170 gen_store_fpr64(ctx, fp0, fd);
11171 tcg_temp_free_i64(fp0);
11173 break;
11174 case OPC_NEG_D:
11175 check_cp1_registers(ctx, fs | fd);
11177 TCGv_i64 fp0 = tcg_temp_new_i64();
11179 gen_load_fpr64(ctx, fp0, fs);
11180 if (ctx->abs2008) {
11181 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
11182 } else {
11183 gen_helper_float_chs_d(fp0, fp0);
11185 gen_store_fpr64(ctx, fp0, fd);
11186 tcg_temp_free_i64(fp0);
11188 break;
11189 case OPC_ROUND_L_D:
11190 check_cp1_64bitmode(ctx);
11192 TCGv_i64 fp0 = tcg_temp_new_i64();
11194 gen_load_fpr64(ctx, fp0, fs);
11195 if (ctx->nan2008) {
11196 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
11197 } else {
11198 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
11200 gen_store_fpr64(ctx, fp0, fd);
11201 tcg_temp_free_i64(fp0);
11203 break;
11204 case OPC_TRUNC_L_D:
11205 check_cp1_64bitmode(ctx);
11207 TCGv_i64 fp0 = tcg_temp_new_i64();
11209 gen_load_fpr64(ctx, fp0, fs);
11210 if (ctx->nan2008) {
11211 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
11212 } else {
11213 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
11215 gen_store_fpr64(ctx, fp0, fd);
11216 tcg_temp_free_i64(fp0);
11218 break;
11219 case OPC_CEIL_L_D:
11220 check_cp1_64bitmode(ctx);
11222 TCGv_i64 fp0 = tcg_temp_new_i64();
11224 gen_load_fpr64(ctx, fp0, fs);
11225 if (ctx->nan2008) {
11226 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
11227 } else {
11228 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
11230 gen_store_fpr64(ctx, fp0, fd);
11231 tcg_temp_free_i64(fp0);
11233 break;
11234 case OPC_FLOOR_L_D:
11235 check_cp1_64bitmode(ctx);
11237 TCGv_i64 fp0 = tcg_temp_new_i64();
11239 gen_load_fpr64(ctx, fp0, fs);
11240 if (ctx->nan2008) {
11241 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
11242 } else {
11243 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
11245 gen_store_fpr64(ctx, fp0, fd);
11246 tcg_temp_free_i64(fp0);
11248 break;
11249 case OPC_ROUND_W_D:
11250 check_cp1_registers(ctx, fs);
11252 TCGv_i32 fp32 = tcg_temp_new_i32();
11253 TCGv_i64 fp64 = tcg_temp_new_i64();
11255 gen_load_fpr64(ctx, fp64, fs);
11256 if (ctx->nan2008) {
11257 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
11258 } else {
11259 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
11261 tcg_temp_free_i64(fp64);
11262 gen_store_fpr32(ctx, fp32, fd);
11263 tcg_temp_free_i32(fp32);
11265 break;
11266 case OPC_TRUNC_W_D:
11267 check_cp1_registers(ctx, fs);
11269 TCGv_i32 fp32 = tcg_temp_new_i32();
11270 TCGv_i64 fp64 = tcg_temp_new_i64();
11272 gen_load_fpr64(ctx, fp64, fs);
11273 if (ctx->nan2008) {
11274 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11275 } else {
11276 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11278 tcg_temp_free_i64(fp64);
11279 gen_store_fpr32(ctx, fp32, fd);
11280 tcg_temp_free_i32(fp32);
11282 break;
11283 case OPC_CEIL_W_D:
11284 check_cp1_registers(ctx, fs);
11286 TCGv_i32 fp32 = tcg_temp_new_i32();
11287 TCGv_i64 fp64 = tcg_temp_new_i64();
11289 gen_load_fpr64(ctx, fp64, fs);
11290 if (ctx->nan2008) {
11291 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11292 } else {
11293 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11295 tcg_temp_free_i64(fp64);
11296 gen_store_fpr32(ctx, fp32, fd);
11297 tcg_temp_free_i32(fp32);
11299 break;
11300 case OPC_FLOOR_W_D:
11301 check_cp1_registers(ctx, fs);
11303 TCGv_i32 fp32 = tcg_temp_new_i32();
11304 TCGv_i64 fp64 = tcg_temp_new_i64();
11306 gen_load_fpr64(ctx, fp64, fs);
11307 if (ctx->nan2008) {
11308 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11309 } else {
11310 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11312 tcg_temp_free_i64(fp64);
11313 gen_store_fpr32(ctx, fp32, fd);
11314 tcg_temp_free_i32(fp32);
11316 break;
11317 case OPC_SEL_D:
11318 check_insn(ctx, ISA_MIPS32R6);
11319 gen_sel_d(ctx, op1, fd, ft, fs);
11320 break;
11321 case OPC_SELEQZ_D:
11322 check_insn(ctx, ISA_MIPS32R6);
11323 gen_sel_d(ctx, op1, fd, ft, fs);
11324 break;
11325 case OPC_SELNEZ_D:
11326 check_insn(ctx, ISA_MIPS32R6);
11327 gen_sel_d(ctx, op1, fd, ft, fs);
11328 break;
11329 case OPC_MOVCF_D:
11330 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11331 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11332 break;
11333 case OPC_MOVZ_D:
11334 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11336 TCGLabel *l1 = gen_new_label();
11337 TCGv_i64 fp0;
11339 if (ft != 0) {
11340 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11342 fp0 = tcg_temp_new_i64();
11343 gen_load_fpr64(ctx, fp0, fs);
11344 gen_store_fpr64(ctx, fp0, fd);
11345 tcg_temp_free_i64(fp0);
11346 gen_set_label(l1);
11348 break;
11349 case OPC_MOVN_D:
11350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11352 TCGLabel *l1 = gen_new_label();
11353 TCGv_i64 fp0;
11355 if (ft != 0) {
11356 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11357 fp0 = tcg_temp_new_i64();
11358 gen_load_fpr64(ctx, fp0, fs);
11359 gen_store_fpr64(ctx, fp0, fd);
11360 tcg_temp_free_i64(fp0);
11361 gen_set_label(l1);
11364 break;
11365 case OPC_RECIP_D:
11366 check_cp1_registers(ctx, fs | fd);
11368 TCGv_i64 fp0 = tcg_temp_new_i64();
11370 gen_load_fpr64(ctx, fp0, fs);
11371 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11372 gen_store_fpr64(ctx, fp0, fd);
11373 tcg_temp_free_i64(fp0);
11375 break;
11376 case OPC_RSQRT_D:
11377 check_cp1_registers(ctx, fs | fd);
11379 TCGv_i64 fp0 = tcg_temp_new_i64();
11381 gen_load_fpr64(ctx, fp0, fs);
11382 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11383 gen_store_fpr64(ctx, fp0, fd);
11384 tcg_temp_free_i64(fp0);
11386 break;
11387 case OPC_MADDF_D:
11388 check_insn(ctx, ISA_MIPS32R6);
11390 TCGv_i64 fp0 = tcg_temp_new_i64();
11391 TCGv_i64 fp1 = tcg_temp_new_i64();
11392 TCGv_i64 fp2 = tcg_temp_new_i64();
11393 gen_load_fpr64(ctx, fp0, fs);
11394 gen_load_fpr64(ctx, fp1, ft);
11395 gen_load_fpr64(ctx, fp2, fd);
11396 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11397 gen_store_fpr64(ctx, fp2, fd);
11398 tcg_temp_free_i64(fp2);
11399 tcg_temp_free_i64(fp1);
11400 tcg_temp_free_i64(fp0);
11402 break;
11403 case OPC_MSUBF_D:
11404 check_insn(ctx, ISA_MIPS32R6);
11406 TCGv_i64 fp0 = tcg_temp_new_i64();
11407 TCGv_i64 fp1 = tcg_temp_new_i64();
11408 TCGv_i64 fp2 = tcg_temp_new_i64();
11409 gen_load_fpr64(ctx, fp0, fs);
11410 gen_load_fpr64(ctx, fp1, ft);
11411 gen_load_fpr64(ctx, fp2, fd);
11412 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11413 gen_store_fpr64(ctx, fp2, fd);
11414 tcg_temp_free_i64(fp2);
11415 tcg_temp_free_i64(fp1);
11416 tcg_temp_free_i64(fp0);
11418 break;
11419 case OPC_RINT_D:
11420 check_insn(ctx, ISA_MIPS32R6);
11422 TCGv_i64 fp0 = tcg_temp_new_i64();
11423 gen_load_fpr64(ctx, fp0, fs);
11424 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11425 gen_store_fpr64(ctx, fp0, fd);
11426 tcg_temp_free_i64(fp0);
11428 break;
11429 case OPC_CLASS_D:
11430 check_insn(ctx, ISA_MIPS32R6);
11432 TCGv_i64 fp0 = tcg_temp_new_i64();
11433 gen_load_fpr64(ctx, fp0, fs);
11434 gen_helper_float_class_d(fp0, cpu_env, fp0);
11435 gen_store_fpr64(ctx, fp0, fd);
11436 tcg_temp_free_i64(fp0);
11438 break;
11439 case OPC_MIN_D: /* OPC_RECIP2_D */
11440 if (ctx->insn_flags & ISA_MIPS32R6) {
11441 /* OPC_MIN_D */
11442 TCGv_i64 fp0 = tcg_temp_new_i64();
11443 TCGv_i64 fp1 = tcg_temp_new_i64();
11444 gen_load_fpr64(ctx, fp0, fs);
11445 gen_load_fpr64(ctx, fp1, ft);
11446 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11447 gen_store_fpr64(ctx, fp1, fd);
11448 tcg_temp_free_i64(fp1);
11449 tcg_temp_free_i64(fp0);
11450 } else {
11451 /* OPC_RECIP2_D */
11452 check_cp1_64bitmode(ctx);
11454 TCGv_i64 fp0 = tcg_temp_new_i64();
11455 TCGv_i64 fp1 = tcg_temp_new_i64();
11457 gen_load_fpr64(ctx, fp0, fs);
11458 gen_load_fpr64(ctx, fp1, ft);
11459 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11460 tcg_temp_free_i64(fp1);
11461 gen_store_fpr64(ctx, fp0, fd);
11462 tcg_temp_free_i64(fp0);
11465 break;
11466 case OPC_MINA_D: /* OPC_RECIP1_D */
11467 if (ctx->insn_flags & ISA_MIPS32R6) {
11468 /* OPC_MINA_D */
11469 TCGv_i64 fp0 = tcg_temp_new_i64();
11470 TCGv_i64 fp1 = tcg_temp_new_i64();
11471 gen_load_fpr64(ctx, fp0, fs);
11472 gen_load_fpr64(ctx, fp1, ft);
11473 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11474 gen_store_fpr64(ctx, fp1, fd);
11475 tcg_temp_free_i64(fp1);
11476 tcg_temp_free_i64(fp0);
11477 } else {
11478 /* OPC_RECIP1_D */
11479 check_cp1_64bitmode(ctx);
11481 TCGv_i64 fp0 = tcg_temp_new_i64();
11483 gen_load_fpr64(ctx, fp0, fs);
11484 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11485 gen_store_fpr64(ctx, fp0, fd);
11486 tcg_temp_free_i64(fp0);
11489 break;
11490 case OPC_MAX_D: /* OPC_RSQRT1_D */
11491 if (ctx->insn_flags & ISA_MIPS32R6) {
11492 /* OPC_MAX_D */
11493 TCGv_i64 fp0 = tcg_temp_new_i64();
11494 TCGv_i64 fp1 = tcg_temp_new_i64();
11495 gen_load_fpr64(ctx, fp0, fs);
11496 gen_load_fpr64(ctx, fp1, ft);
11497 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11498 gen_store_fpr64(ctx, fp1, fd);
11499 tcg_temp_free_i64(fp1);
11500 tcg_temp_free_i64(fp0);
11501 } else {
11502 /* OPC_RSQRT1_D */
11503 check_cp1_64bitmode(ctx);
11505 TCGv_i64 fp0 = tcg_temp_new_i64();
11507 gen_load_fpr64(ctx, fp0, fs);
11508 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11509 gen_store_fpr64(ctx, fp0, fd);
11510 tcg_temp_free_i64(fp0);
11513 break;
11514 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11515 if (ctx->insn_flags & ISA_MIPS32R6) {
11516 /* OPC_MAXA_D */
11517 TCGv_i64 fp0 = tcg_temp_new_i64();
11518 TCGv_i64 fp1 = tcg_temp_new_i64();
11519 gen_load_fpr64(ctx, fp0, fs);
11520 gen_load_fpr64(ctx, fp1, ft);
11521 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11522 gen_store_fpr64(ctx, fp1, fd);
11523 tcg_temp_free_i64(fp1);
11524 tcg_temp_free_i64(fp0);
11525 } else {
11526 /* OPC_RSQRT2_D */
11527 check_cp1_64bitmode(ctx);
11529 TCGv_i64 fp0 = tcg_temp_new_i64();
11530 TCGv_i64 fp1 = tcg_temp_new_i64();
11532 gen_load_fpr64(ctx, fp0, fs);
11533 gen_load_fpr64(ctx, fp1, ft);
11534 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11535 tcg_temp_free_i64(fp1);
11536 gen_store_fpr64(ctx, fp0, fd);
11537 tcg_temp_free_i64(fp0);
11540 break;
11541 case OPC_CMP_F_D:
11542 case OPC_CMP_UN_D:
11543 case OPC_CMP_EQ_D:
11544 case OPC_CMP_UEQ_D:
11545 case OPC_CMP_OLT_D:
11546 case OPC_CMP_ULT_D:
11547 case OPC_CMP_OLE_D:
11548 case OPC_CMP_ULE_D:
11549 case OPC_CMP_SF_D:
11550 case OPC_CMP_NGLE_D:
11551 case OPC_CMP_SEQ_D:
11552 case OPC_CMP_NGL_D:
11553 case OPC_CMP_LT_D:
11554 case OPC_CMP_NGE_D:
11555 case OPC_CMP_LE_D:
11556 case OPC_CMP_NGT_D:
11557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11558 if (ctx->opcode & (1 << 6)) {
11559 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11560 } else {
11561 gen_cmp_d(ctx, func-48, ft, fs, cc);
11563 break;
11564 case OPC_CVT_S_D:
11565 check_cp1_registers(ctx, fs);
11567 TCGv_i32 fp32 = tcg_temp_new_i32();
11568 TCGv_i64 fp64 = tcg_temp_new_i64();
11570 gen_load_fpr64(ctx, fp64, fs);
11571 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11572 tcg_temp_free_i64(fp64);
11573 gen_store_fpr32(ctx, fp32, fd);
11574 tcg_temp_free_i32(fp32);
11576 break;
11577 case OPC_CVT_W_D:
11578 check_cp1_registers(ctx, fs);
11580 TCGv_i32 fp32 = tcg_temp_new_i32();
11581 TCGv_i64 fp64 = tcg_temp_new_i64();
11583 gen_load_fpr64(ctx, fp64, fs);
11584 if (ctx->nan2008) {
11585 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11586 } else {
11587 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11589 tcg_temp_free_i64(fp64);
11590 gen_store_fpr32(ctx, fp32, fd);
11591 tcg_temp_free_i32(fp32);
11593 break;
11594 case OPC_CVT_L_D:
11595 check_cp1_64bitmode(ctx);
11597 TCGv_i64 fp0 = tcg_temp_new_i64();
11599 gen_load_fpr64(ctx, fp0, fs);
11600 if (ctx->nan2008) {
11601 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11602 } else {
11603 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11605 gen_store_fpr64(ctx, fp0, fd);
11606 tcg_temp_free_i64(fp0);
11608 break;
11609 case OPC_CVT_S_W:
11611 TCGv_i32 fp0 = tcg_temp_new_i32();
11613 gen_load_fpr32(ctx, fp0, fs);
11614 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11615 gen_store_fpr32(ctx, fp0, fd);
11616 tcg_temp_free_i32(fp0);
11618 break;
11619 case OPC_CVT_D_W:
11620 check_cp1_registers(ctx, fd);
11622 TCGv_i32 fp32 = tcg_temp_new_i32();
11623 TCGv_i64 fp64 = tcg_temp_new_i64();
11625 gen_load_fpr32(ctx, fp32, fs);
11626 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11627 tcg_temp_free_i32(fp32);
11628 gen_store_fpr64(ctx, fp64, fd);
11629 tcg_temp_free_i64(fp64);
11631 break;
11632 case OPC_CVT_S_L:
11633 check_cp1_64bitmode(ctx);
11635 TCGv_i32 fp32 = tcg_temp_new_i32();
11636 TCGv_i64 fp64 = tcg_temp_new_i64();
11638 gen_load_fpr64(ctx, fp64, fs);
11639 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11640 tcg_temp_free_i64(fp64);
11641 gen_store_fpr32(ctx, fp32, fd);
11642 tcg_temp_free_i32(fp32);
11644 break;
11645 case OPC_CVT_D_L:
11646 check_cp1_64bitmode(ctx);
11648 TCGv_i64 fp0 = tcg_temp_new_i64();
11650 gen_load_fpr64(ctx, fp0, fs);
11651 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11652 gen_store_fpr64(ctx, fp0, fd);
11653 tcg_temp_free_i64(fp0);
11655 break;
11656 case OPC_CVT_PS_PW:
11657 check_ps(ctx);
11659 TCGv_i64 fp0 = tcg_temp_new_i64();
11661 gen_load_fpr64(ctx, fp0, fs);
11662 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11663 gen_store_fpr64(ctx, fp0, fd);
11664 tcg_temp_free_i64(fp0);
11666 break;
11667 case OPC_ADD_PS:
11668 check_ps(ctx);
11670 TCGv_i64 fp0 = tcg_temp_new_i64();
11671 TCGv_i64 fp1 = tcg_temp_new_i64();
11673 gen_load_fpr64(ctx, fp0, fs);
11674 gen_load_fpr64(ctx, fp1, ft);
11675 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11676 tcg_temp_free_i64(fp1);
11677 gen_store_fpr64(ctx, fp0, fd);
11678 tcg_temp_free_i64(fp0);
11680 break;
11681 case OPC_SUB_PS:
11682 check_ps(ctx);
11684 TCGv_i64 fp0 = tcg_temp_new_i64();
11685 TCGv_i64 fp1 = tcg_temp_new_i64();
11687 gen_load_fpr64(ctx, fp0, fs);
11688 gen_load_fpr64(ctx, fp1, ft);
11689 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11690 tcg_temp_free_i64(fp1);
11691 gen_store_fpr64(ctx, fp0, fd);
11692 tcg_temp_free_i64(fp0);
11694 break;
11695 case OPC_MUL_PS:
11696 check_ps(ctx);
11698 TCGv_i64 fp0 = tcg_temp_new_i64();
11699 TCGv_i64 fp1 = tcg_temp_new_i64();
11701 gen_load_fpr64(ctx, fp0, fs);
11702 gen_load_fpr64(ctx, fp1, ft);
11703 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11704 tcg_temp_free_i64(fp1);
11705 gen_store_fpr64(ctx, fp0, fd);
11706 tcg_temp_free_i64(fp0);
11708 break;
11709 case OPC_ABS_PS:
11710 check_ps(ctx);
11712 TCGv_i64 fp0 = tcg_temp_new_i64();
11714 gen_load_fpr64(ctx, fp0, fs);
11715 gen_helper_float_abs_ps(fp0, fp0);
11716 gen_store_fpr64(ctx, fp0, fd);
11717 tcg_temp_free_i64(fp0);
11719 break;
11720 case OPC_MOV_PS:
11721 check_ps(ctx);
11723 TCGv_i64 fp0 = tcg_temp_new_i64();
11725 gen_load_fpr64(ctx, fp0, fs);
11726 gen_store_fpr64(ctx, fp0, fd);
11727 tcg_temp_free_i64(fp0);
11729 break;
11730 case OPC_NEG_PS:
11731 check_ps(ctx);
11733 TCGv_i64 fp0 = tcg_temp_new_i64();
11735 gen_load_fpr64(ctx, fp0, fs);
11736 gen_helper_float_chs_ps(fp0, fp0);
11737 gen_store_fpr64(ctx, fp0, fd);
11738 tcg_temp_free_i64(fp0);
11740 break;
11741 case OPC_MOVCF_PS:
11742 check_ps(ctx);
11743 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11744 break;
11745 case OPC_MOVZ_PS:
11746 check_ps(ctx);
11748 TCGLabel *l1 = gen_new_label();
11749 TCGv_i64 fp0;
11751 if (ft != 0)
11752 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11753 fp0 = tcg_temp_new_i64();
11754 gen_load_fpr64(ctx, fp0, fs);
11755 gen_store_fpr64(ctx, fp0, fd);
11756 tcg_temp_free_i64(fp0);
11757 gen_set_label(l1);
11759 break;
11760 case OPC_MOVN_PS:
11761 check_ps(ctx);
11763 TCGLabel *l1 = gen_new_label();
11764 TCGv_i64 fp0;
11766 if (ft != 0) {
11767 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11768 fp0 = tcg_temp_new_i64();
11769 gen_load_fpr64(ctx, fp0, fs);
11770 gen_store_fpr64(ctx, fp0, fd);
11771 tcg_temp_free_i64(fp0);
11772 gen_set_label(l1);
11775 break;
11776 case OPC_ADDR_PS:
11777 check_ps(ctx);
11779 TCGv_i64 fp0 = tcg_temp_new_i64();
11780 TCGv_i64 fp1 = tcg_temp_new_i64();
11782 gen_load_fpr64(ctx, fp0, ft);
11783 gen_load_fpr64(ctx, fp1, fs);
11784 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11785 tcg_temp_free_i64(fp1);
11786 gen_store_fpr64(ctx, fp0, fd);
11787 tcg_temp_free_i64(fp0);
11789 break;
11790 case OPC_MULR_PS:
11791 check_ps(ctx);
11793 TCGv_i64 fp0 = tcg_temp_new_i64();
11794 TCGv_i64 fp1 = tcg_temp_new_i64();
11796 gen_load_fpr64(ctx, fp0, ft);
11797 gen_load_fpr64(ctx, fp1, fs);
11798 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11799 tcg_temp_free_i64(fp1);
11800 gen_store_fpr64(ctx, fp0, fd);
11801 tcg_temp_free_i64(fp0);
11803 break;
11804 case OPC_RECIP2_PS:
11805 check_ps(ctx);
11807 TCGv_i64 fp0 = tcg_temp_new_i64();
11808 TCGv_i64 fp1 = tcg_temp_new_i64();
11810 gen_load_fpr64(ctx, fp0, fs);
11811 gen_load_fpr64(ctx, fp1, ft);
11812 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11813 tcg_temp_free_i64(fp1);
11814 gen_store_fpr64(ctx, fp0, fd);
11815 tcg_temp_free_i64(fp0);
11817 break;
11818 case OPC_RECIP1_PS:
11819 check_ps(ctx);
11821 TCGv_i64 fp0 = tcg_temp_new_i64();
11823 gen_load_fpr64(ctx, fp0, fs);
11824 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11825 gen_store_fpr64(ctx, fp0, fd);
11826 tcg_temp_free_i64(fp0);
11828 break;
11829 case OPC_RSQRT1_PS:
11830 check_ps(ctx);
11832 TCGv_i64 fp0 = tcg_temp_new_i64();
11834 gen_load_fpr64(ctx, fp0, fs);
11835 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11836 gen_store_fpr64(ctx, fp0, fd);
11837 tcg_temp_free_i64(fp0);
11839 break;
11840 case OPC_RSQRT2_PS:
11841 check_ps(ctx);
11843 TCGv_i64 fp0 = tcg_temp_new_i64();
11844 TCGv_i64 fp1 = tcg_temp_new_i64();
11846 gen_load_fpr64(ctx, fp0, fs);
11847 gen_load_fpr64(ctx, fp1, ft);
11848 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11849 tcg_temp_free_i64(fp1);
11850 gen_store_fpr64(ctx, fp0, fd);
11851 tcg_temp_free_i64(fp0);
11853 break;
11854 case OPC_CVT_S_PU:
11855 check_cp1_64bitmode(ctx);
11857 TCGv_i32 fp0 = tcg_temp_new_i32();
11859 gen_load_fpr32h(ctx, fp0, fs);
11860 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11861 gen_store_fpr32(ctx, fp0, fd);
11862 tcg_temp_free_i32(fp0);
11864 break;
11865 case OPC_CVT_PW_PS:
11866 check_ps(ctx);
11868 TCGv_i64 fp0 = tcg_temp_new_i64();
11870 gen_load_fpr64(ctx, fp0, fs);
11871 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11872 gen_store_fpr64(ctx, fp0, fd);
11873 tcg_temp_free_i64(fp0);
11875 break;
11876 case OPC_CVT_S_PL:
11877 check_cp1_64bitmode(ctx);
11879 TCGv_i32 fp0 = tcg_temp_new_i32();
11881 gen_load_fpr32(ctx, fp0, fs);
11882 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11883 gen_store_fpr32(ctx, fp0, fd);
11884 tcg_temp_free_i32(fp0);
11886 break;
11887 case OPC_PLL_PS:
11888 check_ps(ctx);
11890 TCGv_i32 fp0 = tcg_temp_new_i32();
11891 TCGv_i32 fp1 = tcg_temp_new_i32();
11893 gen_load_fpr32(ctx, fp0, fs);
11894 gen_load_fpr32(ctx, fp1, ft);
11895 gen_store_fpr32h(ctx, fp0, fd);
11896 gen_store_fpr32(ctx, fp1, fd);
11897 tcg_temp_free_i32(fp0);
11898 tcg_temp_free_i32(fp1);
11900 break;
11901 case OPC_PLU_PS:
11902 check_ps(ctx);
11904 TCGv_i32 fp0 = tcg_temp_new_i32();
11905 TCGv_i32 fp1 = tcg_temp_new_i32();
11907 gen_load_fpr32(ctx, fp0, fs);
11908 gen_load_fpr32h(ctx, fp1, ft);
11909 gen_store_fpr32(ctx, fp1, fd);
11910 gen_store_fpr32h(ctx, fp0, fd);
11911 tcg_temp_free_i32(fp0);
11912 tcg_temp_free_i32(fp1);
11914 break;
11915 case OPC_PUL_PS:
11916 check_ps(ctx);
11918 TCGv_i32 fp0 = tcg_temp_new_i32();
11919 TCGv_i32 fp1 = tcg_temp_new_i32();
11921 gen_load_fpr32h(ctx, fp0, fs);
11922 gen_load_fpr32(ctx, fp1, ft);
11923 gen_store_fpr32(ctx, fp1, fd);
11924 gen_store_fpr32h(ctx, fp0, fd);
11925 tcg_temp_free_i32(fp0);
11926 tcg_temp_free_i32(fp1);
11928 break;
11929 case OPC_PUU_PS:
11930 check_ps(ctx);
11932 TCGv_i32 fp0 = tcg_temp_new_i32();
11933 TCGv_i32 fp1 = tcg_temp_new_i32();
11935 gen_load_fpr32h(ctx, fp0, fs);
11936 gen_load_fpr32h(ctx, fp1, ft);
11937 gen_store_fpr32(ctx, fp1, fd);
11938 gen_store_fpr32h(ctx, fp0, fd);
11939 tcg_temp_free_i32(fp0);
11940 tcg_temp_free_i32(fp1);
11942 break;
11943 case OPC_CMP_F_PS:
11944 case OPC_CMP_UN_PS:
11945 case OPC_CMP_EQ_PS:
11946 case OPC_CMP_UEQ_PS:
11947 case OPC_CMP_OLT_PS:
11948 case OPC_CMP_ULT_PS:
11949 case OPC_CMP_OLE_PS:
11950 case OPC_CMP_ULE_PS:
11951 case OPC_CMP_SF_PS:
11952 case OPC_CMP_NGLE_PS:
11953 case OPC_CMP_SEQ_PS:
11954 case OPC_CMP_NGL_PS:
11955 case OPC_CMP_LT_PS:
11956 case OPC_CMP_NGE_PS:
11957 case OPC_CMP_LE_PS:
11958 case OPC_CMP_NGT_PS:
11959 if (ctx->opcode & (1 << 6)) {
11960 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
11961 } else {
11962 gen_cmp_ps(ctx, func-48, ft, fs, cc);
11964 break;
11965 default:
11966 MIPS_INVAL("farith");
11967 generate_exception_end(ctx, EXCP_RI);
11968 return;
11972 /* Coprocessor 3 (FPU) */
11973 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
11974 int fd, int fs, int base, int index)
11976 TCGv t0 = tcg_temp_new();
11978 if (base == 0) {
11979 gen_load_gpr(t0, index);
11980 } else if (index == 0) {
11981 gen_load_gpr(t0, base);
11982 } else {
11983 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11985 /* Don't do NOP if destination is zero: we must perform the actual
11986 memory access. */
11987 switch (opc) {
11988 case OPC_LWXC1:
11989 check_cop1x(ctx);
11991 TCGv_i32 fp0 = tcg_temp_new_i32();
11993 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11994 tcg_gen_trunc_tl_i32(fp0, t0);
11995 gen_store_fpr32(ctx, fp0, fd);
11996 tcg_temp_free_i32(fp0);
11998 break;
11999 case OPC_LDXC1:
12000 check_cop1x(ctx);
12001 check_cp1_registers(ctx, fd);
12003 TCGv_i64 fp0 = tcg_temp_new_i64();
12004 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12005 gen_store_fpr64(ctx, fp0, fd);
12006 tcg_temp_free_i64(fp0);
12008 break;
12009 case OPC_LUXC1:
12010 check_cp1_64bitmode(ctx);
12011 tcg_gen_andi_tl(t0, t0, ~0x7);
12013 TCGv_i64 fp0 = tcg_temp_new_i64();
12015 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12016 gen_store_fpr64(ctx, fp0, fd);
12017 tcg_temp_free_i64(fp0);
12019 break;
12020 case OPC_SWXC1:
12021 check_cop1x(ctx);
12023 TCGv_i32 fp0 = tcg_temp_new_i32();
12024 gen_load_fpr32(ctx, fp0, fs);
12025 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
12026 tcg_temp_free_i32(fp0);
12028 break;
12029 case OPC_SDXC1:
12030 check_cop1x(ctx);
12031 check_cp1_registers(ctx, fs);
12033 TCGv_i64 fp0 = tcg_temp_new_i64();
12034 gen_load_fpr64(ctx, fp0, fs);
12035 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12036 tcg_temp_free_i64(fp0);
12038 break;
12039 case OPC_SUXC1:
12040 check_cp1_64bitmode(ctx);
12041 tcg_gen_andi_tl(t0, t0, ~0x7);
12043 TCGv_i64 fp0 = tcg_temp_new_i64();
12044 gen_load_fpr64(ctx, fp0, fs);
12045 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
12046 tcg_temp_free_i64(fp0);
12048 break;
12050 tcg_temp_free(t0);
12053 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
12054 int fd, int fr, int fs, int ft)
12056 switch (opc) {
12057 case OPC_ALNV_PS:
12058 check_ps(ctx);
12060 TCGv t0 = tcg_temp_local_new();
12061 TCGv_i32 fp = tcg_temp_new_i32();
12062 TCGv_i32 fph = tcg_temp_new_i32();
12063 TCGLabel *l1 = gen_new_label();
12064 TCGLabel *l2 = gen_new_label();
12066 gen_load_gpr(t0, fr);
12067 tcg_gen_andi_tl(t0, t0, 0x7);
12069 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
12070 gen_load_fpr32(ctx, fp, fs);
12071 gen_load_fpr32h(ctx, fph, fs);
12072 gen_store_fpr32(ctx, fp, fd);
12073 gen_store_fpr32h(ctx, fph, fd);
12074 tcg_gen_br(l2);
12075 gen_set_label(l1);
12076 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
12077 tcg_temp_free(t0);
12078 #ifdef TARGET_WORDS_BIGENDIAN
12079 gen_load_fpr32(ctx, fp, fs);
12080 gen_load_fpr32h(ctx, fph, ft);
12081 gen_store_fpr32h(ctx, fp, fd);
12082 gen_store_fpr32(ctx, fph, fd);
12083 #else
12084 gen_load_fpr32h(ctx, fph, fs);
12085 gen_load_fpr32(ctx, fp, ft);
12086 gen_store_fpr32(ctx, fph, fd);
12087 gen_store_fpr32h(ctx, fp, fd);
12088 #endif
12089 gen_set_label(l2);
12090 tcg_temp_free_i32(fp);
12091 tcg_temp_free_i32(fph);
12093 break;
12094 case OPC_MADD_S:
12095 check_cop1x(ctx);
12097 TCGv_i32 fp0 = tcg_temp_new_i32();
12098 TCGv_i32 fp1 = tcg_temp_new_i32();
12099 TCGv_i32 fp2 = tcg_temp_new_i32();
12101 gen_load_fpr32(ctx, fp0, fs);
12102 gen_load_fpr32(ctx, fp1, ft);
12103 gen_load_fpr32(ctx, fp2, fr);
12104 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
12105 tcg_temp_free_i32(fp0);
12106 tcg_temp_free_i32(fp1);
12107 gen_store_fpr32(ctx, fp2, fd);
12108 tcg_temp_free_i32(fp2);
12110 break;
12111 case OPC_MADD_D:
12112 check_cop1x(ctx);
12113 check_cp1_registers(ctx, fd | fs | ft | fr);
12115 TCGv_i64 fp0 = tcg_temp_new_i64();
12116 TCGv_i64 fp1 = tcg_temp_new_i64();
12117 TCGv_i64 fp2 = tcg_temp_new_i64();
12119 gen_load_fpr64(ctx, fp0, fs);
12120 gen_load_fpr64(ctx, fp1, ft);
12121 gen_load_fpr64(ctx, fp2, fr);
12122 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
12123 tcg_temp_free_i64(fp0);
12124 tcg_temp_free_i64(fp1);
12125 gen_store_fpr64(ctx, fp2, fd);
12126 tcg_temp_free_i64(fp2);
12128 break;
12129 case OPC_MADD_PS:
12130 check_ps(ctx);
12132 TCGv_i64 fp0 = tcg_temp_new_i64();
12133 TCGv_i64 fp1 = tcg_temp_new_i64();
12134 TCGv_i64 fp2 = tcg_temp_new_i64();
12136 gen_load_fpr64(ctx, fp0, fs);
12137 gen_load_fpr64(ctx, fp1, ft);
12138 gen_load_fpr64(ctx, fp2, fr);
12139 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
12140 tcg_temp_free_i64(fp0);
12141 tcg_temp_free_i64(fp1);
12142 gen_store_fpr64(ctx, fp2, fd);
12143 tcg_temp_free_i64(fp2);
12145 break;
12146 case OPC_MSUB_S:
12147 check_cop1x(ctx);
12149 TCGv_i32 fp0 = tcg_temp_new_i32();
12150 TCGv_i32 fp1 = tcg_temp_new_i32();
12151 TCGv_i32 fp2 = tcg_temp_new_i32();
12153 gen_load_fpr32(ctx, fp0, fs);
12154 gen_load_fpr32(ctx, fp1, ft);
12155 gen_load_fpr32(ctx, fp2, fr);
12156 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
12157 tcg_temp_free_i32(fp0);
12158 tcg_temp_free_i32(fp1);
12159 gen_store_fpr32(ctx, fp2, fd);
12160 tcg_temp_free_i32(fp2);
12162 break;
12163 case OPC_MSUB_D:
12164 check_cop1x(ctx);
12165 check_cp1_registers(ctx, fd | fs | ft | fr);
12167 TCGv_i64 fp0 = tcg_temp_new_i64();
12168 TCGv_i64 fp1 = tcg_temp_new_i64();
12169 TCGv_i64 fp2 = tcg_temp_new_i64();
12171 gen_load_fpr64(ctx, fp0, fs);
12172 gen_load_fpr64(ctx, fp1, ft);
12173 gen_load_fpr64(ctx, fp2, fr);
12174 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
12175 tcg_temp_free_i64(fp0);
12176 tcg_temp_free_i64(fp1);
12177 gen_store_fpr64(ctx, fp2, fd);
12178 tcg_temp_free_i64(fp2);
12180 break;
12181 case OPC_MSUB_PS:
12182 check_ps(ctx);
12184 TCGv_i64 fp0 = tcg_temp_new_i64();
12185 TCGv_i64 fp1 = tcg_temp_new_i64();
12186 TCGv_i64 fp2 = tcg_temp_new_i64();
12188 gen_load_fpr64(ctx, fp0, fs);
12189 gen_load_fpr64(ctx, fp1, ft);
12190 gen_load_fpr64(ctx, fp2, fr);
12191 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
12192 tcg_temp_free_i64(fp0);
12193 tcg_temp_free_i64(fp1);
12194 gen_store_fpr64(ctx, fp2, fd);
12195 tcg_temp_free_i64(fp2);
12197 break;
12198 case OPC_NMADD_S:
12199 check_cop1x(ctx);
12201 TCGv_i32 fp0 = tcg_temp_new_i32();
12202 TCGv_i32 fp1 = tcg_temp_new_i32();
12203 TCGv_i32 fp2 = tcg_temp_new_i32();
12205 gen_load_fpr32(ctx, fp0, fs);
12206 gen_load_fpr32(ctx, fp1, ft);
12207 gen_load_fpr32(ctx, fp2, fr);
12208 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
12209 tcg_temp_free_i32(fp0);
12210 tcg_temp_free_i32(fp1);
12211 gen_store_fpr32(ctx, fp2, fd);
12212 tcg_temp_free_i32(fp2);
12214 break;
12215 case OPC_NMADD_D:
12216 check_cop1x(ctx);
12217 check_cp1_registers(ctx, fd | fs | ft | fr);
12219 TCGv_i64 fp0 = tcg_temp_new_i64();
12220 TCGv_i64 fp1 = tcg_temp_new_i64();
12221 TCGv_i64 fp2 = tcg_temp_new_i64();
12223 gen_load_fpr64(ctx, fp0, fs);
12224 gen_load_fpr64(ctx, fp1, ft);
12225 gen_load_fpr64(ctx, fp2, fr);
12226 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
12227 tcg_temp_free_i64(fp0);
12228 tcg_temp_free_i64(fp1);
12229 gen_store_fpr64(ctx, fp2, fd);
12230 tcg_temp_free_i64(fp2);
12232 break;
12233 case OPC_NMADD_PS:
12234 check_ps(ctx);
12236 TCGv_i64 fp0 = tcg_temp_new_i64();
12237 TCGv_i64 fp1 = tcg_temp_new_i64();
12238 TCGv_i64 fp2 = tcg_temp_new_i64();
12240 gen_load_fpr64(ctx, fp0, fs);
12241 gen_load_fpr64(ctx, fp1, ft);
12242 gen_load_fpr64(ctx, fp2, fr);
12243 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
12244 tcg_temp_free_i64(fp0);
12245 tcg_temp_free_i64(fp1);
12246 gen_store_fpr64(ctx, fp2, fd);
12247 tcg_temp_free_i64(fp2);
12249 break;
12250 case OPC_NMSUB_S:
12251 check_cop1x(ctx);
12253 TCGv_i32 fp0 = tcg_temp_new_i32();
12254 TCGv_i32 fp1 = tcg_temp_new_i32();
12255 TCGv_i32 fp2 = tcg_temp_new_i32();
12257 gen_load_fpr32(ctx, fp0, fs);
12258 gen_load_fpr32(ctx, fp1, ft);
12259 gen_load_fpr32(ctx, fp2, fr);
12260 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
12261 tcg_temp_free_i32(fp0);
12262 tcg_temp_free_i32(fp1);
12263 gen_store_fpr32(ctx, fp2, fd);
12264 tcg_temp_free_i32(fp2);
12266 break;
12267 case OPC_NMSUB_D:
12268 check_cop1x(ctx);
12269 check_cp1_registers(ctx, fd | fs | ft | fr);
12271 TCGv_i64 fp0 = tcg_temp_new_i64();
12272 TCGv_i64 fp1 = tcg_temp_new_i64();
12273 TCGv_i64 fp2 = tcg_temp_new_i64();
12275 gen_load_fpr64(ctx, fp0, fs);
12276 gen_load_fpr64(ctx, fp1, ft);
12277 gen_load_fpr64(ctx, fp2, fr);
12278 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12279 tcg_temp_free_i64(fp0);
12280 tcg_temp_free_i64(fp1);
12281 gen_store_fpr64(ctx, fp2, fd);
12282 tcg_temp_free_i64(fp2);
12284 break;
12285 case OPC_NMSUB_PS:
12286 check_ps(ctx);
12288 TCGv_i64 fp0 = tcg_temp_new_i64();
12289 TCGv_i64 fp1 = tcg_temp_new_i64();
12290 TCGv_i64 fp2 = tcg_temp_new_i64();
12292 gen_load_fpr64(ctx, fp0, fs);
12293 gen_load_fpr64(ctx, fp1, ft);
12294 gen_load_fpr64(ctx, fp2, fr);
12295 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12296 tcg_temp_free_i64(fp0);
12297 tcg_temp_free_i64(fp1);
12298 gen_store_fpr64(ctx, fp2, fd);
12299 tcg_temp_free_i64(fp2);
12301 break;
12302 default:
12303 MIPS_INVAL("flt3_arith");
12304 generate_exception_end(ctx, EXCP_RI);
12305 return;
12309 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12311 TCGv t0;
12313 #if !defined(CONFIG_USER_ONLY)
12314 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12315 Therefore only check the ISA in system mode. */
12316 check_insn(ctx, ISA_MIPS32R2);
12317 #endif
12318 t0 = tcg_temp_new();
12320 switch (rd) {
12321 case 0:
12322 gen_helper_rdhwr_cpunum(t0, cpu_env);
12323 gen_store_gpr(t0, rt);
12324 break;
12325 case 1:
12326 gen_helper_rdhwr_synci_step(t0, cpu_env);
12327 gen_store_gpr(t0, rt);
12328 break;
12329 case 2:
12330 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12331 gen_io_start();
12333 gen_helper_rdhwr_cc(t0, cpu_env);
12334 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12335 gen_io_end();
12337 gen_store_gpr(t0, rt);
12338 /* Break the TB to be able to take timer interrupts immediately
12339 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12340 we break completely out of translated code. */
12341 gen_save_pc(ctx->base.pc_next + 4);
12342 ctx->base.is_jmp = DISAS_EXIT;
12343 break;
12344 case 3:
12345 gen_helper_rdhwr_ccres(t0, cpu_env);
12346 gen_store_gpr(t0, rt);
12347 break;
12348 case 4:
12349 check_insn(ctx, ISA_MIPS32R6);
12350 if (sel != 0) {
12351 /* Performance counter registers are not implemented other than
12352 * control register 0.
12354 generate_exception(ctx, EXCP_RI);
12356 gen_helper_rdhwr_performance(t0, cpu_env);
12357 gen_store_gpr(t0, rt);
12358 break;
12359 case 5:
12360 check_insn(ctx, ISA_MIPS32R6);
12361 gen_helper_rdhwr_xnp(t0, cpu_env);
12362 gen_store_gpr(t0, rt);
12363 break;
12364 case 29:
12365 #if defined(CONFIG_USER_ONLY)
12366 tcg_gen_ld_tl(t0, cpu_env,
12367 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12368 gen_store_gpr(t0, rt);
12369 break;
12370 #else
12371 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12372 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12373 tcg_gen_ld_tl(t0, cpu_env,
12374 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12375 gen_store_gpr(t0, rt);
12376 } else {
12377 generate_exception_end(ctx, EXCP_RI);
12379 break;
12380 #endif
12381 default: /* Invalid */
12382 MIPS_INVAL("rdhwr");
12383 generate_exception_end(ctx, EXCP_RI);
12384 break;
12386 tcg_temp_free(t0);
12389 static inline void clear_branch_hflags(DisasContext *ctx)
12391 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12392 if (ctx->base.is_jmp == DISAS_NEXT) {
12393 save_cpu_state(ctx, 0);
12394 } else {
12395 /* it is not safe to save ctx->hflags as hflags may be changed
12396 in execution time by the instruction in delay / forbidden slot. */
12397 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12401 static void gen_branch(DisasContext *ctx, int insn_bytes)
12403 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12404 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12405 /* Branches completion */
12406 clear_branch_hflags(ctx);
12407 ctx->base.is_jmp = DISAS_NORETURN;
12408 /* FIXME: Need to clear can_do_io. */
12409 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12410 case MIPS_HFLAG_FBNSLOT:
12411 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12412 break;
12413 case MIPS_HFLAG_B:
12414 /* unconditional branch */
12415 if (proc_hflags & MIPS_HFLAG_BX) {
12416 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12418 gen_goto_tb(ctx, 0, ctx->btarget);
12419 break;
12420 case MIPS_HFLAG_BL:
12421 /* blikely taken case */
12422 gen_goto_tb(ctx, 0, ctx->btarget);
12423 break;
12424 case MIPS_HFLAG_BC:
12425 /* Conditional branch */
12427 TCGLabel *l1 = gen_new_label();
12429 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12430 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12431 gen_set_label(l1);
12432 gen_goto_tb(ctx, 0, ctx->btarget);
12434 break;
12435 case MIPS_HFLAG_BR:
12436 /* unconditional branch to register */
12437 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12438 TCGv t0 = tcg_temp_new();
12439 TCGv_i32 t1 = tcg_temp_new_i32();
12441 tcg_gen_andi_tl(t0, btarget, 0x1);
12442 tcg_gen_trunc_tl_i32(t1, t0);
12443 tcg_temp_free(t0);
12444 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12445 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12446 tcg_gen_or_i32(hflags, hflags, t1);
12447 tcg_temp_free_i32(t1);
12449 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12450 } else {
12451 tcg_gen_mov_tl(cpu_PC, btarget);
12453 if (ctx->base.singlestep_enabled) {
12454 save_cpu_state(ctx, 0);
12455 gen_helper_raise_exception_debug(cpu_env);
12457 tcg_gen_lookup_and_goto_ptr();
12458 break;
12459 default:
12460 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12461 abort();
12466 /* Compact Branches */
12467 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12468 int rs, int rt, int32_t offset)
12470 int bcond_compute = 0;
12471 TCGv t0 = tcg_temp_new();
12472 TCGv t1 = tcg_temp_new();
12473 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12475 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12476 #ifdef MIPS_DEBUG_DISAS
12477 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12478 "\n", ctx->base.pc_next);
12479 #endif
12480 generate_exception_end(ctx, EXCP_RI);
12481 goto out;
12484 /* Load needed operands and calculate btarget */
12485 switch (opc) {
12486 /* compact branch */
12487 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12488 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12489 gen_load_gpr(t0, rs);
12490 gen_load_gpr(t1, rt);
12491 bcond_compute = 1;
12492 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12493 if (rs <= rt && rs == 0) {
12494 /* OPC_BEQZALC, OPC_BNEZALC */
12495 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12497 break;
12498 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12499 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12500 gen_load_gpr(t0, rs);
12501 gen_load_gpr(t1, rt);
12502 bcond_compute = 1;
12503 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12504 break;
12505 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12506 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12507 if (rs == 0 || rs == rt) {
12508 /* OPC_BLEZALC, OPC_BGEZALC */
12509 /* OPC_BGTZALC, OPC_BLTZALC */
12510 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12512 gen_load_gpr(t0, rs);
12513 gen_load_gpr(t1, rt);
12514 bcond_compute = 1;
12515 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12516 break;
12517 case OPC_BC:
12518 case OPC_BALC:
12519 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12520 break;
12521 case OPC_BEQZC:
12522 case OPC_BNEZC:
12523 if (rs != 0) {
12524 /* OPC_BEQZC, OPC_BNEZC */
12525 gen_load_gpr(t0, rs);
12526 bcond_compute = 1;
12527 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12528 } else {
12529 /* OPC_JIC, OPC_JIALC */
12530 TCGv tbase = tcg_temp_new();
12531 TCGv toffset = tcg_temp_new();
12533 gen_load_gpr(tbase, rt);
12534 tcg_gen_movi_tl(toffset, offset);
12535 gen_op_addr_add(ctx, btarget, tbase, toffset);
12536 tcg_temp_free(tbase);
12537 tcg_temp_free(toffset);
12539 break;
12540 default:
12541 MIPS_INVAL("Compact branch/jump");
12542 generate_exception_end(ctx, EXCP_RI);
12543 goto out;
12546 if (bcond_compute == 0) {
12547 /* Uncoditional compact branch */
12548 switch (opc) {
12549 case OPC_JIALC:
12550 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12551 /* Fallthrough */
12552 case OPC_JIC:
12553 ctx->hflags |= MIPS_HFLAG_BR;
12554 break;
12555 case OPC_BALC:
12556 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12557 /* Fallthrough */
12558 case OPC_BC:
12559 ctx->hflags |= MIPS_HFLAG_B;
12560 break;
12561 default:
12562 MIPS_INVAL("Compact branch/jump");
12563 generate_exception_end(ctx, EXCP_RI);
12564 goto out;
12567 /* Generating branch here as compact branches don't have delay slot */
12568 gen_branch(ctx, 4);
12569 } else {
12570 /* Conditional compact branch */
12571 TCGLabel *fs = gen_new_label();
12572 save_cpu_state(ctx, 0);
12574 switch (opc) {
12575 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12576 if (rs == 0 && rt != 0) {
12577 /* OPC_BLEZALC */
12578 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12579 } else if (rs != 0 && rt != 0 && rs == rt) {
12580 /* OPC_BGEZALC */
12581 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12582 } else {
12583 /* OPC_BGEUC */
12584 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12586 break;
12587 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12588 if (rs == 0 && rt != 0) {
12589 /* OPC_BGTZALC */
12590 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12591 } else if (rs != 0 && rt != 0 && rs == rt) {
12592 /* OPC_BLTZALC */
12593 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12594 } else {
12595 /* OPC_BLTUC */
12596 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12598 break;
12599 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12600 if (rs == 0 && rt != 0) {
12601 /* OPC_BLEZC */
12602 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12603 } else if (rs != 0 && rt != 0 && rs == rt) {
12604 /* OPC_BGEZC */
12605 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12606 } else {
12607 /* OPC_BGEC */
12608 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12610 break;
12611 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12612 if (rs == 0 && rt != 0) {
12613 /* OPC_BGTZC */
12614 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12615 } else if (rs != 0 && rt != 0 && rs == rt) {
12616 /* OPC_BLTZC */
12617 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12618 } else {
12619 /* OPC_BLTC */
12620 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12622 break;
12623 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12624 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12625 if (rs >= rt) {
12626 /* OPC_BOVC, OPC_BNVC */
12627 TCGv t2 = tcg_temp_new();
12628 TCGv t3 = tcg_temp_new();
12629 TCGv t4 = tcg_temp_new();
12630 TCGv input_overflow = tcg_temp_new();
12632 gen_load_gpr(t0, rs);
12633 gen_load_gpr(t1, rt);
12634 tcg_gen_ext32s_tl(t2, t0);
12635 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12636 tcg_gen_ext32s_tl(t3, t1);
12637 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12638 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12640 tcg_gen_add_tl(t4, t2, t3);
12641 tcg_gen_ext32s_tl(t4, t4);
12642 tcg_gen_xor_tl(t2, t2, t3);
12643 tcg_gen_xor_tl(t3, t4, t3);
12644 tcg_gen_andc_tl(t2, t3, t2);
12645 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12646 tcg_gen_or_tl(t4, t4, input_overflow);
12647 if (opc == OPC_BOVC) {
12648 /* OPC_BOVC */
12649 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12650 } else {
12651 /* OPC_BNVC */
12652 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12654 tcg_temp_free(input_overflow);
12655 tcg_temp_free(t4);
12656 tcg_temp_free(t3);
12657 tcg_temp_free(t2);
12658 } else if (rs < rt && rs == 0) {
12659 /* OPC_BEQZALC, OPC_BNEZALC */
12660 if (opc == OPC_BEQZALC) {
12661 /* OPC_BEQZALC */
12662 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12663 } else {
12664 /* OPC_BNEZALC */
12665 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12667 } else {
12668 /* OPC_BEQC, OPC_BNEC */
12669 if (opc == OPC_BEQC) {
12670 /* OPC_BEQC */
12671 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12672 } else {
12673 /* OPC_BNEC */
12674 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12677 break;
12678 case OPC_BEQZC:
12679 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12680 break;
12681 case OPC_BNEZC:
12682 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12683 break;
12684 default:
12685 MIPS_INVAL("Compact conditional branch/jump");
12686 generate_exception_end(ctx, EXCP_RI);
12687 goto out;
12690 /* Generating branch here as compact branches don't have delay slot */
12691 gen_goto_tb(ctx, 1, ctx->btarget);
12692 gen_set_label(fs);
12694 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12697 out:
12698 tcg_temp_free(t0);
12699 tcg_temp_free(t1);
12702 /* ISA extensions (ASEs) */
12703 /* MIPS16 extension to MIPS32 */
12705 /* MIPS16 major opcodes */
12706 enum {
12707 M16_OPC_ADDIUSP = 0x00,
12708 M16_OPC_ADDIUPC = 0x01,
12709 M16_OPC_B = 0x02,
12710 M16_OPC_JAL = 0x03,
12711 M16_OPC_BEQZ = 0x04,
12712 M16_OPC_BNEQZ = 0x05,
12713 M16_OPC_SHIFT = 0x06,
12714 M16_OPC_LD = 0x07,
12715 M16_OPC_RRIA = 0x08,
12716 M16_OPC_ADDIU8 = 0x09,
12717 M16_OPC_SLTI = 0x0a,
12718 M16_OPC_SLTIU = 0x0b,
12719 M16_OPC_I8 = 0x0c,
12720 M16_OPC_LI = 0x0d,
12721 M16_OPC_CMPI = 0x0e,
12722 M16_OPC_SD = 0x0f,
12723 M16_OPC_LB = 0x10,
12724 M16_OPC_LH = 0x11,
12725 M16_OPC_LWSP = 0x12,
12726 M16_OPC_LW = 0x13,
12727 M16_OPC_LBU = 0x14,
12728 M16_OPC_LHU = 0x15,
12729 M16_OPC_LWPC = 0x16,
12730 M16_OPC_LWU = 0x17,
12731 M16_OPC_SB = 0x18,
12732 M16_OPC_SH = 0x19,
12733 M16_OPC_SWSP = 0x1a,
12734 M16_OPC_SW = 0x1b,
12735 M16_OPC_RRR = 0x1c,
12736 M16_OPC_RR = 0x1d,
12737 M16_OPC_EXTEND = 0x1e,
12738 M16_OPC_I64 = 0x1f
12741 /* I8 funct field */
12742 enum {
12743 I8_BTEQZ = 0x0,
12744 I8_BTNEZ = 0x1,
12745 I8_SWRASP = 0x2,
12746 I8_ADJSP = 0x3,
12747 I8_SVRS = 0x4,
12748 I8_MOV32R = 0x5,
12749 I8_MOVR32 = 0x7
12752 /* RRR f field */
12753 enum {
12754 RRR_DADDU = 0x0,
12755 RRR_ADDU = 0x1,
12756 RRR_DSUBU = 0x2,
12757 RRR_SUBU = 0x3
12760 /* RR funct field */
12761 enum {
12762 RR_JR = 0x00,
12763 RR_SDBBP = 0x01,
12764 RR_SLT = 0x02,
12765 RR_SLTU = 0x03,
12766 RR_SLLV = 0x04,
12767 RR_BREAK = 0x05,
12768 RR_SRLV = 0x06,
12769 RR_SRAV = 0x07,
12770 RR_DSRL = 0x08,
12771 RR_CMP = 0x0a,
12772 RR_NEG = 0x0b,
12773 RR_AND = 0x0c,
12774 RR_OR = 0x0d,
12775 RR_XOR = 0x0e,
12776 RR_NOT = 0x0f,
12777 RR_MFHI = 0x10,
12778 RR_CNVT = 0x11,
12779 RR_MFLO = 0x12,
12780 RR_DSRA = 0x13,
12781 RR_DSLLV = 0x14,
12782 RR_DSRLV = 0x16,
12783 RR_DSRAV = 0x17,
12784 RR_MULT = 0x18,
12785 RR_MULTU = 0x19,
12786 RR_DIV = 0x1a,
12787 RR_DIVU = 0x1b,
12788 RR_DMULT = 0x1c,
12789 RR_DMULTU = 0x1d,
12790 RR_DDIV = 0x1e,
12791 RR_DDIVU = 0x1f
12794 /* I64 funct field */
12795 enum {
12796 I64_LDSP = 0x0,
12797 I64_SDSP = 0x1,
12798 I64_SDRASP = 0x2,
12799 I64_DADJSP = 0x3,
12800 I64_LDPC = 0x4,
12801 I64_DADDIU5 = 0x5,
12802 I64_DADDIUPC = 0x6,
12803 I64_DADDIUSP = 0x7
12806 /* RR ry field for CNVT */
12807 enum {
12808 RR_RY_CNVT_ZEB = 0x0,
12809 RR_RY_CNVT_ZEH = 0x1,
12810 RR_RY_CNVT_ZEW = 0x2,
12811 RR_RY_CNVT_SEB = 0x4,
12812 RR_RY_CNVT_SEH = 0x5,
12813 RR_RY_CNVT_SEW = 0x6,
12816 static int xlat (int r)
12818 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12820 return map[r];
12823 static void gen_mips16_save (DisasContext *ctx,
12824 int xsregs, int aregs,
12825 int do_ra, int do_s0, int do_s1,
12826 int framesize)
12828 TCGv t0 = tcg_temp_new();
12829 TCGv t1 = tcg_temp_new();
12830 TCGv t2 = tcg_temp_new();
12831 int args, astatic;
12833 switch (aregs) {
12834 case 0:
12835 case 1:
12836 case 2:
12837 case 3:
12838 case 11:
12839 args = 0;
12840 break;
12841 case 4:
12842 case 5:
12843 case 6:
12844 case 7:
12845 args = 1;
12846 break;
12847 case 8:
12848 case 9:
12849 case 10:
12850 args = 2;
12851 break;
12852 case 12:
12853 case 13:
12854 args = 3;
12855 break;
12856 case 14:
12857 args = 4;
12858 break;
12859 default:
12860 generate_exception_end(ctx, EXCP_RI);
12861 return;
12864 switch (args) {
12865 case 4:
12866 gen_base_offset_addr(ctx, t0, 29, 12);
12867 gen_load_gpr(t1, 7);
12868 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12869 /* Fall through */
12870 case 3:
12871 gen_base_offset_addr(ctx, t0, 29, 8);
12872 gen_load_gpr(t1, 6);
12873 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12874 /* Fall through */
12875 case 2:
12876 gen_base_offset_addr(ctx, t0, 29, 4);
12877 gen_load_gpr(t1, 5);
12878 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12879 /* Fall through */
12880 case 1:
12881 gen_base_offset_addr(ctx, t0, 29, 0);
12882 gen_load_gpr(t1, 4);
12883 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12886 gen_load_gpr(t0, 29);
12888 #define DECR_AND_STORE(reg) do { \
12889 tcg_gen_movi_tl(t2, -4); \
12890 gen_op_addr_add(ctx, t0, t0, t2); \
12891 gen_load_gpr(t1, reg); \
12892 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12893 } while (0)
12895 if (do_ra) {
12896 DECR_AND_STORE(31);
12899 switch (xsregs) {
12900 case 7:
12901 DECR_AND_STORE(30);
12902 /* Fall through */
12903 case 6:
12904 DECR_AND_STORE(23);
12905 /* Fall through */
12906 case 5:
12907 DECR_AND_STORE(22);
12908 /* Fall through */
12909 case 4:
12910 DECR_AND_STORE(21);
12911 /* Fall through */
12912 case 3:
12913 DECR_AND_STORE(20);
12914 /* Fall through */
12915 case 2:
12916 DECR_AND_STORE(19);
12917 /* Fall through */
12918 case 1:
12919 DECR_AND_STORE(18);
12922 if (do_s1) {
12923 DECR_AND_STORE(17);
12925 if (do_s0) {
12926 DECR_AND_STORE(16);
12929 switch (aregs) {
12930 case 0:
12931 case 4:
12932 case 8:
12933 case 12:
12934 case 14:
12935 astatic = 0;
12936 break;
12937 case 1:
12938 case 5:
12939 case 9:
12940 case 13:
12941 astatic = 1;
12942 break;
12943 case 2:
12944 case 6:
12945 case 10:
12946 astatic = 2;
12947 break;
12948 case 3:
12949 case 7:
12950 astatic = 3;
12951 break;
12952 case 11:
12953 astatic = 4;
12954 break;
12955 default:
12956 generate_exception_end(ctx, EXCP_RI);
12957 return;
12960 if (astatic > 0) {
12961 DECR_AND_STORE(7);
12962 if (astatic > 1) {
12963 DECR_AND_STORE(6);
12964 if (astatic > 2) {
12965 DECR_AND_STORE(5);
12966 if (astatic > 3) {
12967 DECR_AND_STORE(4);
12972 #undef DECR_AND_STORE
12974 tcg_gen_movi_tl(t2, -framesize);
12975 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12976 tcg_temp_free(t0);
12977 tcg_temp_free(t1);
12978 tcg_temp_free(t2);
12981 static void gen_mips16_restore (DisasContext *ctx,
12982 int xsregs, int aregs,
12983 int do_ra, int do_s0, int do_s1,
12984 int framesize)
12986 int astatic;
12987 TCGv t0 = tcg_temp_new();
12988 TCGv t1 = tcg_temp_new();
12989 TCGv t2 = tcg_temp_new();
12991 tcg_gen_movi_tl(t2, framesize);
12992 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12994 #define DECR_AND_LOAD(reg) do { \
12995 tcg_gen_movi_tl(t2, -4); \
12996 gen_op_addr_add(ctx, t0, t0, t2); \
12997 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12998 gen_store_gpr(t1, reg); \
12999 } while (0)
13001 if (do_ra) {
13002 DECR_AND_LOAD(31);
13005 switch (xsregs) {
13006 case 7:
13007 DECR_AND_LOAD(30);
13008 /* Fall through */
13009 case 6:
13010 DECR_AND_LOAD(23);
13011 /* Fall through */
13012 case 5:
13013 DECR_AND_LOAD(22);
13014 /* Fall through */
13015 case 4:
13016 DECR_AND_LOAD(21);
13017 /* Fall through */
13018 case 3:
13019 DECR_AND_LOAD(20);
13020 /* Fall through */
13021 case 2:
13022 DECR_AND_LOAD(19);
13023 /* Fall through */
13024 case 1:
13025 DECR_AND_LOAD(18);
13028 if (do_s1) {
13029 DECR_AND_LOAD(17);
13031 if (do_s0) {
13032 DECR_AND_LOAD(16);
13035 switch (aregs) {
13036 case 0:
13037 case 4:
13038 case 8:
13039 case 12:
13040 case 14:
13041 astatic = 0;
13042 break;
13043 case 1:
13044 case 5:
13045 case 9:
13046 case 13:
13047 astatic = 1;
13048 break;
13049 case 2:
13050 case 6:
13051 case 10:
13052 astatic = 2;
13053 break;
13054 case 3:
13055 case 7:
13056 astatic = 3;
13057 break;
13058 case 11:
13059 astatic = 4;
13060 break;
13061 default:
13062 generate_exception_end(ctx, EXCP_RI);
13063 return;
13066 if (astatic > 0) {
13067 DECR_AND_LOAD(7);
13068 if (astatic > 1) {
13069 DECR_AND_LOAD(6);
13070 if (astatic > 2) {
13071 DECR_AND_LOAD(5);
13072 if (astatic > 3) {
13073 DECR_AND_LOAD(4);
13078 #undef DECR_AND_LOAD
13080 tcg_gen_movi_tl(t2, framesize);
13081 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13082 tcg_temp_free(t0);
13083 tcg_temp_free(t1);
13084 tcg_temp_free(t2);
13087 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
13088 int is_64_bit, int extended)
13090 TCGv t0;
13092 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13093 generate_exception_end(ctx, EXCP_RI);
13094 return;
13097 t0 = tcg_temp_new();
13099 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
13100 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
13101 if (!is_64_bit) {
13102 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13105 tcg_temp_free(t0);
13108 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
13109 int16_t offset)
13111 TCGv_i32 t0 = tcg_const_i32(op);
13112 TCGv t1 = tcg_temp_new();
13113 gen_base_offset_addr(ctx, t1, base, offset);
13114 gen_helper_cache(cpu_env, t1, t0);
13117 #if defined(TARGET_MIPS64)
13118 static void decode_i64_mips16 (DisasContext *ctx,
13119 int ry, int funct, int16_t offset,
13120 int extended)
13122 switch (funct) {
13123 case I64_LDSP:
13124 check_insn(ctx, ISA_MIPS3);
13125 check_mips_64(ctx);
13126 offset = extended ? offset : offset << 3;
13127 gen_ld(ctx, OPC_LD, ry, 29, offset);
13128 break;
13129 case I64_SDSP:
13130 check_insn(ctx, ISA_MIPS3);
13131 check_mips_64(ctx);
13132 offset = extended ? offset : offset << 3;
13133 gen_st(ctx, OPC_SD, ry, 29, offset);
13134 break;
13135 case I64_SDRASP:
13136 check_insn(ctx, ISA_MIPS3);
13137 check_mips_64(ctx);
13138 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
13139 gen_st(ctx, OPC_SD, 31, 29, offset);
13140 break;
13141 case I64_DADJSP:
13142 check_insn(ctx, ISA_MIPS3);
13143 check_mips_64(ctx);
13144 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
13145 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
13146 break;
13147 case I64_LDPC:
13148 check_insn(ctx, ISA_MIPS3);
13149 check_mips_64(ctx);
13150 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
13151 generate_exception_end(ctx, EXCP_RI);
13152 } else {
13153 offset = extended ? offset : offset << 3;
13154 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
13156 break;
13157 case I64_DADDIU5:
13158 check_insn(ctx, ISA_MIPS3);
13159 check_mips_64(ctx);
13160 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
13161 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
13162 break;
13163 case I64_DADDIUPC:
13164 check_insn(ctx, ISA_MIPS3);
13165 check_mips_64(ctx);
13166 offset = extended ? offset : offset << 2;
13167 gen_addiupc(ctx, ry, offset, 1, extended);
13168 break;
13169 case I64_DADDIUSP:
13170 check_insn(ctx, ISA_MIPS3);
13171 check_mips_64(ctx);
13172 offset = extended ? offset : offset << 2;
13173 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
13174 break;
13177 #endif
13179 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13181 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
13182 int op, rx, ry, funct, sa;
13183 int16_t imm, offset;
13185 ctx->opcode = (ctx->opcode << 16) | extend;
13186 op = (ctx->opcode >> 11) & 0x1f;
13187 sa = (ctx->opcode >> 22) & 0x1f;
13188 funct = (ctx->opcode >> 8) & 0x7;
13189 rx = xlat((ctx->opcode >> 8) & 0x7);
13190 ry = xlat((ctx->opcode >> 5) & 0x7);
13191 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
13192 | ((ctx->opcode >> 21) & 0x3f) << 5
13193 | (ctx->opcode & 0x1f));
13195 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
13196 counterparts. */
13197 switch (op) {
13198 case M16_OPC_ADDIUSP:
13199 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13200 break;
13201 case M16_OPC_ADDIUPC:
13202 gen_addiupc(ctx, rx, imm, 0, 1);
13203 break;
13204 case M16_OPC_B:
13205 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
13206 /* No delay slot, so just process as a normal instruction */
13207 break;
13208 case M16_OPC_BEQZ:
13209 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
13210 /* No delay slot, so just process as a normal instruction */
13211 break;
13212 case M16_OPC_BNEQZ:
13213 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
13214 /* No delay slot, so just process as a normal instruction */
13215 break;
13216 case M16_OPC_SHIFT:
13217 switch (ctx->opcode & 0x3) {
13218 case 0x0:
13219 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13220 break;
13221 case 0x1:
13222 #if defined(TARGET_MIPS64)
13223 check_mips_64(ctx);
13224 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13225 #else
13226 generate_exception_end(ctx, EXCP_RI);
13227 #endif
13228 break;
13229 case 0x2:
13230 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13231 break;
13232 case 0x3:
13233 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13234 break;
13236 break;
13237 #if defined(TARGET_MIPS64)
13238 case M16_OPC_LD:
13239 check_insn(ctx, ISA_MIPS3);
13240 check_mips_64(ctx);
13241 gen_ld(ctx, OPC_LD, ry, rx, offset);
13242 break;
13243 #endif
13244 case M16_OPC_RRIA:
13245 imm = ctx->opcode & 0xf;
13246 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
13247 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
13248 imm = (int16_t) (imm << 1) >> 1;
13249 if ((ctx->opcode >> 4) & 0x1) {
13250 #if defined(TARGET_MIPS64)
13251 check_mips_64(ctx);
13252 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13253 #else
13254 generate_exception_end(ctx, EXCP_RI);
13255 #endif
13256 } else {
13257 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13259 break;
13260 case M16_OPC_ADDIU8:
13261 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13262 break;
13263 case M16_OPC_SLTI:
13264 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13265 break;
13266 case M16_OPC_SLTIU:
13267 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13268 break;
13269 case M16_OPC_I8:
13270 switch (funct) {
13271 case I8_BTEQZ:
13272 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13273 break;
13274 case I8_BTNEZ:
13275 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13276 break;
13277 case I8_SWRASP:
13278 gen_st(ctx, OPC_SW, 31, 29, imm);
13279 break;
13280 case I8_ADJSP:
13281 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13282 break;
13283 case I8_SVRS:
13284 check_insn(ctx, ISA_MIPS32);
13286 int xsregs = (ctx->opcode >> 24) & 0x7;
13287 int aregs = (ctx->opcode >> 16) & 0xf;
13288 int do_ra = (ctx->opcode >> 6) & 0x1;
13289 int do_s0 = (ctx->opcode >> 5) & 0x1;
13290 int do_s1 = (ctx->opcode >> 4) & 0x1;
13291 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13292 | (ctx->opcode & 0xf)) << 3;
13294 if (ctx->opcode & (1 << 7)) {
13295 gen_mips16_save(ctx, xsregs, aregs,
13296 do_ra, do_s0, do_s1,
13297 framesize);
13298 } else {
13299 gen_mips16_restore(ctx, xsregs, aregs,
13300 do_ra, do_s0, do_s1,
13301 framesize);
13304 break;
13305 default:
13306 generate_exception_end(ctx, EXCP_RI);
13307 break;
13309 break;
13310 case M16_OPC_LI:
13311 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13312 break;
13313 case M16_OPC_CMPI:
13314 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13315 break;
13316 #if defined(TARGET_MIPS64)
13317 case M16_OPC_SD:
13318 check_insn(ctx, ISA_MIPS3);
13319 check_mips_64(ctx);
13320 gen_st(ctx, OPC_SD, ry, rx, offset);
13321 break;
13322 #endif
13323 case M16_OPC_LB:
13324 gen_ld(ctx, OPC_LB, ry, rx, offset);
13325 break;
13326 case M16_OPC_LH:
13327 gen_ld(ctx, OPC_LH, ry, rx, offset);
13328 break;
13329 case M16_OPC_LWSP:
13330 gen_ld(ctx, OPC_LW, rx, 29, offset);
13331 break;
13332 case M16_OPC_LW:
13333 gen_ld(ctx, OPC_LW, ry, rx, offset);
13334 break;
13335 case M16_OPC_LBU:
13336 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13337 break;
13338 case M16_OPC_LHU:
13339 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13340 break;
13341 case M16_OPC_LWPC:
13342 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13343 break;
13344 #if defined(TARGET_MIPS64)
13345 case M16_OPC_LWU:
13346 check_insn(ctx, ISA_MIPS3);
13347 check_mips_64(ctx);
13348 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13349 break;
13350 #endif
13351 case M16_OPC_SB:
13352 gen_st(ctx, OPC_SB, ry, rx, offset);
13353 break;
13354 case M16_OPC_SH:
13355 gen_st(ctx, OPC_SH, ry, rx, offset);
13356 break;
13357 case M16_OPC_SWSP:
13358 gen_st(ctx, OPC_SW, rx, 29, offset);
13359 break;
13360 case M16_OPC_SW:
13361 gen_st(ctx, OPC_SW, ry, rx, offset);
13362 break;
13363 #if defined(TARGET_MIPS64)
13364 case M16_OPC_I64:
13365 decode_i64_mips16(ctx, ry, funct, offset, 1);
13366 break;
13367 #endif
13368 default:
13369 generate_exception_end(ctx, EXCP_RI);
13370 break;
13373 return 4;
13376 static inline bool is_uhi(int sdbbp_code)
13378 #ifdef CONFIG_USER_ONLY
13379 return false;
13380 #else
13381 return semihosting_enabled() && sdbbp_code == 1;
13382 #endif
13385 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13387 int rx, ry;
13388 int sa;
13389 int op, cnvt_op, op1, offset;
13390 int funct;
13391 int n_bytes;
13393 op = (ctx->opcode >> 11) & 0x1f;
13394 sa = (ctx->opcode >> 2) & 0x7;
13395 sa = sa == 0 ? 8 : sa;
13396 rx = xlat((ctx->opcode >> 8) & 0x7);
13397 cnvt_op = (ctx->opcode >> 5) & 0x7;
13398 ry = xlat((ctx->opcode >> 5) & 0x7);
13399 op1 = offset = ctx->opcode & 0x1f;
13401 n_bytes = 2;
13403 switch (op) {
13404 case M16_OPC_ADDIUSP:
13406 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13408 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13410 break;
13411 case M16_OPC_ADDIUPC:
13412 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13413 break;
13414 case M16_OPC_B:
13415 offset = (ctx->opcode & 0x7ff) << 1;
13416 offset = (int16_t)(offset << 4) >> 4;
13417 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13418 /* No delay slot, so just process as a normal instruction */
13419 break;
13420 case M16_OPC_JAL:
13421 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13422 offset = (((ctx->opcode & 0x1f) << 21)
13423 | ((ctx->opcode >> 5) & 0x1f) << 16
13424 | offset) << 2;
13425 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13426 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13427 n_bytes = 4;
13428 break;
13429 case M16_OPC_BEQZ:
13430 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13431 ((int8_t)ctx->opcode) << 1, 0);
13432 /* No delay slot, so just process as a normal instruction */
13433 break;
13434 case M16_OPC_BNEQZ:
13435 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13436 ((int8_t)ctx->opcode) << 1, 0);
13437 /* No delay slot, so just process as a normal instruction */
13438 break;
13439 case M16_OPC_SHIFT:
13440 switch (ctx->opcode & 0x3) {
13441 case 0x0:
13442 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13443 break;
13444 case 0x1:
13445 #if defined(TARGET_MIPS64)
13446 check_insn(ctx, ISA_MIPS3);
13447 check_mips_64(ctx);
13448 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13449 #else
13450 generate_exception_end(ctx, EXCP_RI);
13451 #endif
13452 break;
13453 case 0x2:
13454 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13455 break;
13456 case 0x3:
13457 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13458 break;
13460 break;
13461 #if defined(TARGET_MIPS64)
13462 case M16_OPC_LD:
13463 check_insn(ctx, ISA_MIPS3);
13464 check_mips_64(ctx);
13465 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13466 break;
13467 #endif
13468 case M16_OPC_RRIA:
13470 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13472 if ((ctx->opcode >> 4) & 1) {
13473 #if defined(TARGET_MIPS64)
13474 check_insn(ctx, ISA_MIPS3);
13475 check_mips_64(ctx);
13476 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13477 #else
13478 generate_exception_end(ctx, EXCP_RI);
13479 #endif
13480 } else {
13481 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13484 break;
13485 case M16_OPC_ADDIU8:
13487 int16_t imm = (int8_t) ctx->opcode;
13489 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13491 break;
13492 case M16_OPC_SLTI:
13494 int16_t imm = (uint8_t) ctx->opcode;
13495 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13497 break;
13498 case M16_OPC_SLTIU:
13500 int16_t imm = (uint8_t) ctx->opcode;
13501 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13503 break;
13504 case M16_OPC_I8:
13506 int reg32;
13508 funct = (ctx->opcode >> 8) & 0x7;
13509 switch (funct) {
13510 case I8_BTEQZ:
13511 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13512 ((int8_t)ctx->opcode) << 1, 0);
13513 break;
13514 case I8_BTNEZ:
13515 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13516 ((int8_t)ctx->opcode) << 1, 0);
13517 break;
13518 case I8_SWRASP:
13519 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13520 break;
13521 case I8_ADJSP:
13522 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13523 ((int8_t)ctx->opcode) << 3);
13524 break;
13525 case I8_SVRS:
13526 check_insn(ctx, ISA_MIPS32);
13528 int do_ra = ctx->opcode & (1 << 6);
13529 int do_s0 = ctx->opcode & (1 << 5);
13530 int do_s1 = ctx->opcode & (1 << 4);
13531 int framesize = ctx->opcode & 0xf;
13533 if (framesize == 0) {
13534 framesize = 128;
13535 } else {
13536 framesize = framesize << 3;
13539 if (ctx->opcode & (1 << 7)) {
13540 gen_mips16_save(ctx, 0, 0,
13541 do_ra, do_s0, do_s1, framesize);
13542 } else {
13543 gen_mips16_restore(ctx, 0, 0,
13544 do_ra, do_s0, do_s1, framesize);
13547 break;
13548 case I8_MOV32R:
13550 int rz = xlat(ctx->opcode & 0x7);
13552 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13553 ((ctx->opcode >> 5) & 0x7);
13554 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13556 break;
13557 case I8_MOVR32:
13558 reg32 = ctx->opcode & 0x1f;
13559 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13560 break;
13561 default:
13562 generate_exception_end(ctx, EXCP_RI);
13563 break;
13566 break;
13567 case M16_OPC_LI:
13569 int16_t imm = (uint8_t) ctx->opcode;
13571 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13573 break;
13574 case M16_OPC_CMPI:
13576 int16_t imm = (uint8_t) ctx->opcode;
13577 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13579 break;
13580 #if defined(TARGET_MIPS64)
13581 case M16_OPC_SD:
13582 check_insn(ctx, ISA_MIPS3);
13583 check_mips_64(ctx);
13584 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13585 break;
13586 #endif
13587 case M16_OPC_LB:
13588 gen_ld(ctx, OPC_LB, ry, rx, offset);
13589 break;
13590 case M16_OPC_LH:
13591 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13592 break;
13593 case M16_OPC_LWSP:
13594 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13595 break;
13596 case M16_OPC_LW:
13597 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13598 break;
13599 case M16_OPC_LBU:
13600 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13601 break;
13602 case M16_OPC_LHU:
13603 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13604 break;
13605 case M16_OPC_LWPC:
13606 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13607 break;
13608 #if defined (TARGET_MIPS64)
13609 case M16_OPC_LWU:
13610 check_insn(ctx, ISA_MIPS3);
13611 check_mips_64(ctx);
13612 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13613 break;
13614 #endif
13615 case M16_OPC_SB:
13616 gen_st(ctx, OPC_SB, ry, rx, offset);
13617 break;
13618 case M16_OPC_SH:
13619 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13620 break;
13621 case M16_OPC_SWSP:
13622 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13623 break;
13624 case M16_OPC_SW:
13625 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13626 break;
13627 case M16_OPC_RRR:
13629 int rz = xlat((ctx->opcode >> 2) & 0x7);
13630 int mips32_op;
13632 switch (ctx->opcode & 0x3) {
13633 case RRR_ADDU:
13634 mips32_op = OPC_ADDU;
13635 break;
13636 case RRR_SUBU:
13637 mips32_op = OPC_SUBU;
13638 break;
13639 #if defined(TARGET_MIPS64)
13640 case RRR_DADDU:
13641 mips32_op = OPC_DADDU;
13642 check_insn(ctx, ISA_MIPS3);
13643 check_mips_64(ctx);
13644 break;
13645 case RRR_DSUBU:
13646 mips32_op = OPC_DSUBU;
13647 check_insn(ctx, ISA_MIPS3);
13648 check_mips_64(ctx);
13649 break;
13650 #endif
13651 default:
13652 generate_exception_end(ctx, EXCP_RI);
13653 goto done;
13656 gen_arith(ctx, mips32_op, rz, rx, ry);
13657 done:
13660 break;
13661 case M16_OPC_RR:
13662 switch (op1) {
13663 case RR_JR:
13665 int nd = (ctx->opcode >> 7) & 0x1;
13666 int link = (ctx->opcode >> 6) & 0x1;
13667 int ra = (ctx->opcode >> 5) & 0x1;
13669 if (nd) {
13670 check_insn(ctx, ISA_MIPS32);
13673 if (link) {
13674 op = OPC_JALR;
13675 } else {
13676 op = OPC_JR;
13679 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13680 (nd ? 0 : 2));
13682 break;
13683 case RR_SDBBP:
13684 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13685 gen_helper_do_semihosting(cpu_env);
13686 } else {
13687 /* XXX: not clear which exception should be raised
13688 * when in debug mode...
13690 check_insn(ctx, ISA_MIPS32);
13691 generate_exception_end(ctx, EXCP_DBp);
13693 break;
13694 case RR_SLT:
13695 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13696 break;
13697 case RR_SLTU:
13698 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13699 break;
13700 case RR_BREAK:
13701 generate_exception_end(ctx, EXCP_BREAK);
13702 break;
13703 case RR_SLLV:
13704 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13705 break;
13706 case RR_SRLV:
13707 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13708 break;
13709 case RR_SRAV:
13710 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13711 break;
13712 #if defined (TARGET_MIPS64)
13713 case RR_DSRL:
13714 check_insn(ctx, ISA_MIPS3);
13715 check_mips_64(ctx);
13716 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13717 break;
13718 #endif
13719 case RR_CMP:
13720 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13721 break;
13722 case RR_NEG:
13723 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13724 break;
13725 case RR_AND:
13726 gen_logic(ctx, OPC_AND, rx, rx, ry);
13727 break;
13728 case RR_OR:
13729 gen_logic(ctx, OPC_OR, rx, rx, ry);
13730 break;
13731 case RR_XOR:
13732 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13733 break;
13734 case RR_NOT:
13735 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13736 break;
13737 case RR_MFHI:
13738 gen_HILO(ctx, OPC_MFHI, 0, rx);
13739 break;
13740 case RR_CNVT:
13741 check_insn(ctx, ISA_MIPS32);
13742 switch (cnvt_op) {
13743 case RR_RY_CNVT_ZEB:
13744 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13745 break;
13746 case RR_RY_CNVT_ZEH:
13747 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13748 break;
13749 case RR_RY_CNVT_SEB:
13750 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13751 break;
13752 case RR_RY_CNVT_SEH:
13753 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13754 break;
13755 #if defined (TARGET_MIPS64)
13756 case RR_RY_CNVT_ZEW:
13757 check_insn(ctx, ISA_MIPS64);
13758 check_mips_64(ctx);
13759 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13760 break;
13761 case RR_RY_CNVT_SEW:
13762 check_insn(ctx, ISA_MIPS64);
13763 check_mips_64(ctx);
13764 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13765 break;
13766 #endif
13767 default:
13768 generate_exception_end(ctx, EXCP_RI);
13769 break;
13771 break;
13772 case RR_MFLO:
13773 gen_HILO(ctx, OPC_MFLO, 0, rx);
13774 break;
13775 #if defined (TARGET_MIPS64)
13776 case RR_DSRA:
13777 check_insn(ctx, ISA_MIPS3);
13778 check_mips_64(ctx);
13779 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13780 break;
13781 case RR_DSLLV:
13782 check_insn(ctx, ISA_MIPS3);
13783 check_mips_64(ctx);
13784 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13785 break;
13786 case RR_DSRLV:
13787 check_insn(ctx, ISA_MIPS3);
13788 check_mips_64(ctx);
13789 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13790 break;
13791 case RR_DSRAV:
13792 check_insn(ctx, ISA_MIPS3);
13793 check_mips_64(ctx);
13794 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13795 break;
13796 #endif
13797 case RR_MULT:
13798 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13799 break;
13800 case RR_MULTU:
13801 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13802 break;
13803 case RR_DIV:
13804 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13805 break;
13806 case RR_DIVU:
13807 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13808 break;
13809 #if defined (TARGET_MIPS64)
13810 case RR_DMULT:
13811 check_insn(ctx, ISA_MIPS3);
13812 check_mips_64(ctx);
13813 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13814 break;
13815 case RR_DMULTU:
13816 check_insn(ctx, ISA_MIPS3);
13817 check_mips_64(ctx);
13818 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13819 break;
13820 case RR_DDIV:
13821 check_insn(ctx, ISA_MIPS3);
13822 check_mips_64(ctx);
13823 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13824 break;
13825 case RR_DDIVU:
13826 check_insn(ctx, ISA_MIPS3);
13827 check_mips_64(ctx);
13828 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13829 break;
13830 #endif
13831 default:
13832 generate_exception_end(ctx, EXCP_RI);
13833 break;
13835 break;
13836 case M16_OPC_EXTEND:
13837 decode_extended_mips16_opc(env, ctx);
13838 n_bytes = 4;
13839 break;
13840 #if defined(TARGET_MIPS64)
13841 case M16_OPC_I64:
13842 funct = (ctx->opcode >> 8) & 0x7;
13843 decode_i64_mips16(ctx, ry, funct, offset, 0);
13844 break;
13845 #endif
13846 default:
13847 generate_exception_end(ctx, EXCP_RI);
13848 break;
13851 return n_bytes;
13854 /* microMIPS extension to MIPS32/MIPS64 */
13857 * microMIPS32/microMIPS64 major opcodes
13859 * 1. MIPS Architecture for Programmers Volume II-B:
13860 * The microMIPS32 Instruction Set (Revision 3.05)
13862 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13864 * 2. MIPS Architecture For Programmers Volume II-A:
13865 * The MIPS64 Instruction Set (Revision 3.51)
13868 enum {
13869 POOL32A = 0x00,
13870 POOL16A = 0x01,
13871 LBU16 = 0x02,
13872 MOVE16 = 0x03,
13873 ADDI32 = 0x04,
13874 R6_LUI = 0x04,
13875 AUI = 0x04,
13876 LBU32 = 0x05,
13877 SB32 = 0x06,
13878 LB32 = 0x07,
13880 POOL32B = 0x08,
13881 POOL16B = 0x09,
13882 LHU16 = 0x0a,
13883 ANDI16 = 0x0b,
13884 ADDIU32 = 0x0c,
13885 LHU32 = 0x0d,
13886 SH32 = 0x0e,
13887 LH32 = 0x0f,
13889 POOL32I = 0x10,
13890 POOL16C = 0x11,
13891 LWSP16 = 0x12,
13892 POOL16D = 0x13,
13893 ORI32 = 0x14,
13894 POOL32F = 0x15,
13895 POOL32S = 0x16, /* MIPS64 */
13896 DADDIU32 = 0x17, /* MIPS64 */
13898 POOL32C = 0x18,
13899 LWGP16 = 0x19,
13900 LW16 = 0x1a,
13901 POOL16E = 0x1b,
13902 XORI32 = 0x1c,
13903 JALS32 = 0x1d,
13904 BOVC = 0x1d,
13905 BEQC = 0x1d,
13906 BEQZALC = 0x1d,
13907 ADDIUPC = 0x1e,
13908 PCREL = 0x1e,
13909 BNVC = 0x1f,
13910 BNEC = 0x1f,
13911 BNEZALC = 0x1f,
13913 R6_BEQZC = 0x20,
13914 JIC = 0x20,
13915 POOL16F = 0x21,
13916 SB16 = 0x22,
13917 BEQZ16 = 0x23,
13918 BEQZC16 = 0x23,
13919 SLTI32 = 0x24,
13920 BEQ32 = 0x25,
13921 BC = 0x25,
13922 SWC132 = 0x26,
13923 LWC132 = 0x27,
13925 /* 0x29 is reserved */
13926 RES_29 = 0x29,
13927 R6_BNEZC = 0x28,
13928 JIALC = 0x28,
13929 SH16 = 0x2a,
13930 BNEZ16 = 0x2b,
13931 BNEZC16 = 0x2b,
13932 SLTIU32 = 0x2c,
13933 BNE32 = 0x2d,
13934 BALC = 0x2d,
13935 SDC132 = 0x2e,
13936 LDC132 = 0x2f,
13938 /* 0x31 is reserved */
13939 RES_31 = 0x31,
13940 BLEZALC = 0x30,
13941 BGEZALC = 0x30,
13942 BGEUC = 0x30,
13943 SWSP16 = 0x32,
13944 B16 = 0x33,
13945 BC16 = 0x33,
13946 ANDI32 = 0x34,
13947 J32 = 0x35,
13948 BGTZC = 0x35,
13949 BLTZC = 0x35,
13950 BLTC = 0x35,
13951 SD32 = 0x36, /* MIPS64 */
13952 LD32 = 0x37, /* MIPS64 */
13954 /* 0x39 is reserved */
13955 RES_39 = 0x39,
13956 BGTZALC = 0x38,
13957 BLTZALC = 0x38,
13958 BLTUC = 0x38,
13959 SW16 = 0x3a,
13960 LI16 = 0x3b,
13961 JALX32 = 0x3c,
13962 JAL32 = 0x3d,
13963 BLEZC = 0x3d,
13964 BGEZC = 0x3d,
13965 BGEC = 0x3d,
13966 SW32 = 0x3e,
13967 LW32 = 0x3f
13970 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13971 enum {
13972 ADDIUPC_00 = 0x00,
13973 ADDIUPC_01 = 0x01,
13974 ADDIUPC_02 = 0x02,
13975 ADDIUPC_03 = 0x03,
13976 ADDIUPC_04 = 0x04,
13977 ADDIUPC_05 = 0x05,
13978 ADDIUPC_06 = 0x06,
13979 ADDIUPC_07 = 0x07,
13980 AUIPC = 0x1e,
13981 ALUIPC = 0x1f,
13982 LWPC_08 = 0x08,
13983 LWPC_09 = 0x09,
13984 LWPC_0A = 0x0A,
13985 LWPC_0B = 0x0B,
13986 LWPC_0C = 0x0C,
13987 LWPC_0D = 0x0D,
13988 LWPC_0E = 0x0E,
13989 LWPC_0F = 0x0F,
13992 /* POOL32A encoding of minor opcode field */
13994 enum {
13995 /* These opcodes are distinguished only by bits 9..6; those bits are
13996 * what are recorded below. */
13997 SLL32 = 0x0,
13998 SRL32 = 0x1,
13999 SRA = 0x2,
14000 ROTR = 0x3,
14001 SELEQZ = 0x5,
14002 SELNEZ = 0x6,
14003 R6_RDHWR = 0x7,
14005 SLLV = 0x0,
14006 SRLV = 0x1,
14007 SRAV = 0x2,
14008 ROTRV = 0x3,
14009 ADD = 0x4,
14010 ADDU32 = 0x5,
14011 SUB = 0x6,
14012 SUBU32 = 0x7,
14013 MUL = 0x8,
14014 AND = 0x9,
14015 OR32 = 0xa,
14016 NOR = 0xb,
14017 XOR32 = 0xc,
14018 SLT = 0xd,
14019 SLTU = 0xe,
14021 MOVN = 0x0,
14022 R6_MUL = 0x0,
14023 MOVZ = 0x1,
14024 MUH = 0x1,
14025 MULU = 0x2,
14026 MUHU = 0x3,
14027 LWXS = 0x4,
14028 R6_DIV = 0x4,
14029 MOD = 0x5,
14030 R6_DIVU = 0x6,
14031 MODU = 0x7,
14033 /* The following can be distinguished by their lower 6 bits. */
14034 BREAK32 = 0x07,
14035 INS = 0x0c,
14036 LSA = 0x0f,
14037 ALIGN = 0x1f,
14038 EXT = 0x2c,
14039 POOL32AXF = 0x3c,
14040 SIGRIE = 0x3f
14043 /* POOL32AXF encoding of minor opcode field extension */
14046 * 1. MIPS Architecture for Programmers Volume II-B:
14047 * The microMIPS32 Instruction Set (Revision 3.05)
14049 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
14051 * 2. MIPS Architecture for Programmers VolumeIV-e:
14052 * The MIPS DSP Application-Specific Extension
14053 * to the microMIPS32 Architecture (Revision 2.34)
14055 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
14058 enum {
14059 /* bits 11..6 */
14060 TEQ = 0x00,
14061 TGE = 0x08,
14062 TGEU = 0x10,
14063 TLT = 0x20,
14064 TLTU = 0x28,
14065 TNE = 0x30,
14067 MFC0 = 0x03,
14068 MTC0 = 0x0b,
14070 /* begin of microMIPS32 DSP */
14072 /* bits 13..12 for 0x01 */
14073 MFHI_ACC = 0x0,
14074 MFLO_ACC = 0x1,
14075 MTHI_ACC = 0x2,
14076 MTLO_ACC = 0x3,
14078 /* bits 13..12 for 0x2a */
14079 MADD_ACC = 0x0,
14080 MADDU_ACC = 0x1,
14081 MSUB_ACC = 0x2,
14082 MSUBU_ACC = 0x3,
14084 /* bits 13..12 for 0x32 */
14085 MULT_ACC = 0x0,
14086 MULTU_ACC = 0x1,
14088 /* end of microMIPS32 DSP */
14090 /* bits 15..12 for 0x2c */
14091 BITSWAP = 0x0,
14092 SEB = 0x2,
14093 SEH = 0x3,
14094 CLO = 0x4,
14095 CLZ = 0x5,
14096 RDHWR = 0x6,
14097 WSBH = 0x7,
14098 MULT = 0x8,
14099 MULTU = 0x9,
14100 DIV = 0xa,
14101 DIVU = 0xb,
14102 MADD = 0xc,
14103 MADDU = 0xd,
14104 MSUB = 0xe,
14105 MSUBU = 0xf,
14107 /* bits 15..12 for 0x34 */
14108 MFC2 = 0x4,
14109 MTC2 = 0x5,
14110 MFHC2 = 0x8,
14111 MTHC2 = 0x9,
14112 CFC2 = 0xc,
14113 CTC2 = 0xd,
14115 /* bits 15..12 for 0x3c */
14116 JALR = 0x0,
14117 JR = 0x0, /* alias */
14118 JALRC = 0x0,
14119 JRC = 0x0,
14120 JALR_HB = 0x1,
14121 JALRC_HB = 0x1,
14122 JALRS = 0x4,
14123 JALRS_HB = 0x5,
14125 /* bits 15..12 for 0x05 */
14126 RDPGPR = 0xe,
14127 WRPGPR = 0xf,
14129 /* bits 15..12 for 0x0d */
14130 TLBP = 0x0,
14131 TLBR = 0x1,
14132 TLBWI = 0x2,
14133 TLBWR = 0x3,
14134 TLBINV = 0x4,
14135 TLBINVF = 0x5,
14136 WAIT = 0x9,
14137 IRET = 0xd,
14138 DERET = 0xe,
14139 ERET = 0xf,
14141 /* bits 15..12 for 0x15 */
14142 DMT = 0x0,
14143 DVPE = 0x1,
14144 EMT = 0x2,
14145 EVPE = 0x3,
14147 /* bits 15..12 for 0x1d */
14148 DI = 0x4,
14149 EI = 0x5,
14151 /* bits 15..12 for 0x2d */
14152 SYNC = 0x6,
14153 SYSCALL = 0x8,
14154 SDBBP = 0xd,
14156 /* bits 15..12 for 0x35 */
14157 MFHI32 = 0x0,
14158 MFLO32 = 0x1,
14159 MTHI32 = 0x2,
14160 MTLO32 = 0x3,
14163 /* POOL32B encoding of minor opcode field (bits 15..12) */
14165 enum {
14166 LWC2 = 0x0,
14167 LWP = 0x1,
14168 LDP = 0x4,
14169 LWM32 = 0x5,
14170 CACHE = 0x6,
14171 LDM = 0x7,
14172 SWC2 = 0x8,
14173 SWP = 0x9,
14174 SDP = 0xc,
14175 SWM32 = 0xd,
14176 SDM = 0xf
14179 /* POOL32C encoding of minor opcode field (bits 15..12) */
14181 enum {
14182 LWL = 0x0,
14183 SWL = 0x8,
14184 LWR = 0x1,
14185 SWR = 0x9,
14186 PREF = 0x2,
14187 ST_EVA = 0xa,
14188 LL = 0x3,
14189 SC = 0xb,
14190 LDL = 0x4,
14191 SDL = 0xc,
14192 LDR = 0x5,
14193 SDR = 0xd,
14194 LD_EVA = 0x6,
14195 LWU = 0xe,
14196 LLD = 0x7,
14197 SCD = 0xf
14200 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
14202 enum {
14203 LBUE = 0x0,
14204 LHUE = 0x1,
14205 LWLE = 0x2,
14206 LWRE = 0x3,
14207 LBE = 0x4,
14208 LHE = 0x5,
14209 LLE = 0x6,
14210 LWE = 0x7,
14213 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
14215 enum {
14216 SWLE = 0x0,
14217 SWRE = 0x1,
14218 PREFE = 0x2,
14219 CACHEE = 0x3,
14220 SBE = 0x4,
14221 SHE = 0x5,
14222 SCE = 0x6,
14223 SWE = 0x7,
14226 /* POOL32F encoding of minor opcode field (bits 5..0) */
14228 enum {
14229 /* These are the bit 7..6 values */
14230 ADD_FMT = 0x0,
14232 SUB_FMT = 0x1,
14234 MUL_FMT = 0x2,
14236 DIV_FMT = 0x3,
14238 /* These are the bit 8..6 values */
14239 MOVN_FMT = 0x0,
14240 RSQRT2_FMT = 0x0,
14241 MOVF_FMT = 0x0,
14242 RINT_FMT = 0x0,
14243 SELNEZ_FMT = 0x0,
14245 MOVZ_FMT = 0x1,
14246 LWXC1 = 0x1,
14247 MOVT_FMT = 0x1,
14248 CLASS_FMT = 0x1,
14249 SELEQZ_FMT = 0x1,
14251 PLL_PS = 0x2,
14252 SWXC1 = 0x2,
14253 SEL_FMT = 0x2,
14255 PLU_PS = 0x3,
14256 LDXC1 = 0x3,
14258 MOVN_FMT_04 = 0x4,
14259 PUL_PS = 0x4,
14260 SDXC1 = 0x4,
14261 RECIP2_FMT = 0x4,
14263 MOVZ_FMT_05 = 0x05,
14264 PUU_PS = 0x5,
14265 LUXC1 = 0x5,
14267 CVT_PS_S = 0x6,
14268 SUXC1 = 0x6,
14269 ADDR_PS = 0x6,
14270 PREFX = 0x6,
14271 MADDF_FMT = 0x6,
14273 MULR_PS = 0x7,
14274 MSUBF_FMT = 0x7,
14276 MADD_S = 0x01,
14277 MADD_D = 0x09,
14278 MADD_PS = 0x11,
14279 ALNV_PS = 0x19,
14280 MSUB_S = 0x21,
14281 MSUB_D = 0x29,
14282 MSUB_PS = 0x31,
14284 NMADD_S = 0x02,
14285 NMADD_D = 0x0a,
14286 NMADD_PS = 0x12,
14287 NMSUB_S = 0x22,
14288 NMSUB_D = 0x2a,
14289 NMSUB_PS = 0x32,
14291 MIN_FMT = 0x3,
14292 MAX_FMT = 0xb,
14293 MINA_FMT = 0x23,
14294 MAXA_FMT = 0x2b,
14295 POOL32FXF = 0x3b,
14297 CABS_COND_FMT = 0x1c, /* MIPS3D */
14298 C_COND_FMT = 0x3c,
14300 CMP_CONDN_S = 0x5,
14301 CMP_CONDN_D = 0x15
14304 /* POOL32Fxf encoding of minor opcode extension field */
14306 enum {
14307 CVT_L = 0x04,
14308 RSQRT_FMT = 0x08,
14309 FLOOR_L = 0x0c,
14310 CVT_PW_PS = 0x1c,
14311 CVT_W = 0x24,
14312 SQRT_FMT = 0x28,
14313 FLOOR_W = 0x2c,
14314 CVT_PS_PW = 0x3c,
14315 CFC1 = 0x40,
14316 RECIP_FMT = 0x48,
14317 CEIL_L = 0x4c,
14318 CTC1 = 0x60,
14319 CEIL_W = 0x6c,
14320 MFC1 = 0x80,
14321 CVT_S_PL = 0x84,
14322 TRUNC_L = 0x8c,
14323 MTC1 = 0xa0,
14324 CVT_S_PU = 0xa4,
14325 TRUNC_W = 0xac,
14326 MFHC1 = 0xc0,
14327 ROUND_L = 0xcc,
14328 MTHC1 = 0xe0,
14329 ROUND_W = 0xec,
14331 MOV_FMT = 0x01,
14332 MOVF = 0x05,
14333 ABS_FMT = 0x0d,
14334 RSQRT1_FMT = 0x1d,
14335 MOVT = 0x25,
14336 NEG_FMT = 0x2d,
14337 CVT_D = 0x4d,
14338 RECIP1_FMT = 0x5d,
14339 CVT_S = 0x6d
14342 /* POOL32I encoding of minor opcode field (bits 25..21) */
14344 enum {
14345 BLTZ = 0x00,
14346 BLTZAL = 0x01,
14347 BGEZ = 0x02,
14348 BGEZAL = 0x03,
14349 BLEZ = 0x04,
14350 BNEZC = 0x05,
14351 BGTZ = 0x06,
14352 BEQZC = 0x07,
14353 TLTI = 0x08,
14354 BC1EQZC = 0x08,
14355 TGEI = 0x09,
14356 BC1NEZC = 0x09,
14357 TLTIU = 0x0a,
14358 BC2EQZC = 0x0a,
14359 TGEIU = 0x0b,
14360 BC2NEZC = 0x0a,
14361 TNEI = 0x0c,
14362 R6_SYNCI = 0x0c,
14363 LUI = 0x0d,
14364 TEQI = 0x0e,
14365 SYNCI = 0x10,
14366 BLTZALS = 0x11,
14367 BGEZALS = 0x13,
14368 BC2F = 0x14,
14369 BC2T = 0x15,
14370 BPOSGE64 = 0x1a,
14371 BPOSGE32 = 0x1b,
14372 /* These overlap and are distinguished by bit16 of the instruction */
14373 BC1F = 0x1c,
14374 BC1T = 0x1d,
14375 BC1ANY2F = 0x1c,
14376 BC1ANY2T = 0x1d,
14377 BC1ANY4F = 0x1e,
14378 BC1ANY4T = 0x1f
14381 /* POOL16A encoding of minor opcode field */
14383 enum {
14384 ADDU16 = 0x0,
14385 SUBU16 = 0x1
14388 /* POOL16B encoding of minor opcode field */
14390 enum {
14391 SLL16 = 0x0,
14392 SRL16 = 0x1
14395 /* POOL16C encoding of minor opcode field */
14397 enum {
14398 NOT16 = 0x00,
14399 XOR16 = 0x04,
14400 AND16 = 0x08,
14401 OR16 = 0x0c,
14402 LWM16 = 0x10,
14403 SWM16 = 0x14,
14404 JR16 = 0x18,
14405 JRC16 = 0x1a,
14406 JALR16 = 0x1c,
14407 JALR16S = 0x1e,
14408 MFHI16 = 0x20,
14409 MFLO16 = 0x24,
14410 BREAK16 = 0x28,
14411 SDBBP16 = 0x2c,
14412 JRADDIUSP = 0x30
14415 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14417 enum {
14418 R6_NOT16 = 0x00,
14419 R6_AND16 = 0x01,
14420 R6_LWM16 = 0x02,
14421 R6_JRC16 = 0x03,
14422 MOVEP = 0x04,
14423 MOVEP_05 = 0x05,
14424 MOVEP_06 = 0x06,
14425 MOVEP_07 = 0x07,
14426 R6_XOR16 = 0x08,
14427 R6_OR16 = 0x09,
14428 R6_SWM16 = 0x0a,
14429 JALRC16 = 0x0b,
14430 MOVEP_0C = 0x0c,
14431 MOVEP_0D = 0x0d,
14432 MOVEP_0E = 0x0e,
14433 MOVEP_0F = 0x0f,
14434 JRCADDIUSP = 0x13,
14435 R6_BREAK16 = 0x1b,
14436 R6_SDBBP16 = 0x3b
14439 /* POOL16D encoding of minor opcode field */
14441 enum {
14442 ADDIUS5 = 0x0,
14443 ADDIUSP = 0x1
14446 /* POOL16E encoding of minor opcode field */
14448 enum {
14449 ADDIUR2 = 0x0,
14450 ADDIUR1SP = 0x1
14453 static int mmreg (int r)
14455 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14457 return map[r];
14460 /* Used for 16-bit store instructions. */
14461 static int mmreg2 (int r)
14463 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14465 return map[r];
14468 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14469 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14470 #define uMIPS_RS2(op) uMIPS_RS(op)
14471 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14472 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14473 #define uMIPS_RS5(op) (op & 0x1f)
14475 /* Signed immediate */
14476 #define SIMM(op, start, width) \
14477 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14478 << (32-width)) \
14479 >> (32-width))
14480 /* Zero-extended immediate */
14481 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14483 static void gen_addiur1sp(DisasContext *ctx)
14485 int rd = mmreg(uMIPS_RD(ctx->opcode));
14487 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14490 static void gen_addiur2(DisasContext *ctx)
14492 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14493 int rd = mmreg(uMIPS_RD(ctx->opcode));
14494 int rs = mmreg(uMIPS_RS(ctx->opcode));
14496 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14499 static void gen_addiusp(DisasContext *ctx)
14501 int encoded = ZIMM(ctx->opcode, 1, 9);
14502 int decoded;
14504 if (encoded <= 1) {
14505 decoded = 256 + encoded;
14506 } else if (encoded <= 255) {
14507 decoded = encoded;
14508 } else if (encoded <= 509) {
14509 decoded = encoded - 512;
14510 } else {
14511 decoded = encoded - 768;
14514 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14517 static void gen_addius5(DisasContext *ctx)
14519 int imm = SIMM(ctx->opcode, 1, 4);
14520 int rd = (ctx->opcode >> 5) & 0x1f;
14522 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14525 static void gen_andi16(DisasContext *ctx)
14527 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14528 31, 32, 63, 64, 255, 32768, 65535 };
14529 int rd = mmreg(uMIPS_RD(ctx->opcode));
14530 int rs = mmreg(uMIPS_RS(ctx->opcode));
14531 int encoded = ZIMM(ctx->opcode, 0, 4);
14533 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14536 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14537 int base, int16_t offset)
14539 TCGv t0, t1;
14540 TCGv_i32 t2;
14542 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14543 generate_exception_end(ctx, EXCP_RI);
14544 return;
14547 t0 = tcg_temp_new();
14549 gen_base_offset_addr(ctx, t0, base, offset);
14551 t1 = tcg_const_tl(reglist);
14552 t2 = tcg_const_i32(ctx->mem_idx);
14554 save_cpu_state(ctx, 1);
14555 switch (opc) {
14556 case LWM32:
14557 gen_helper_lwm(cpu_env, t0, t1, t2);
14558 break;
14559 case SWM32:
14560 gen_helper_swm(cpu_env, t0, t1, t2);
14561 break;
14562 #ifdef TARGET_MIPS64
14563 case LDM:
14564 gen_helper_ldm(cpu_env, t0, t1, t2);
14565 break;
14566 case SDM:
14567 gen_helper_sdm(cpu_env, t0, t1, t2);
14568 break;
14569 #endif
14571 tcg_temp_free(t0);
14572 tcg_temp_free(t1);
14573 tcg_temp_free_i32(t2);
14577 static void gen_pool16c_insn(DisasContext *ctx)
14579 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14580 int rs = mmreg(ctx->opcode & 0x7);
14582 switch (((ctx->opcode) >> 4) & 0x3f) {
14583 case NOT16 + 0:
14584 case NOT16 + 1:
14585 case NOT16 + 2:
14586 case NOT16 + 3:
14587 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14588 break;
14589 case XOR16 + 0:
14590 case XOR16 + 1:
14591 case XOR16 + 2:
14592 case XOR16 + 3:
14593 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14594 break;
14595 case AND16 + 0:
14596 case AND16 + 1:
14597 case AND16 + 2:
14598 case AND16 + 3:
14599 gen_logic(ctx, OPC_AND, rd, rd, rs);
14600 break;
14601 case OR16 + 0:
14602 case OR16 + 1:
14603 case OR16 + 2:
14604 case OR16 + 3:
14605 gen_logic(ctx, OPC_OR, rd, rd, rs);
14606 break;
14607 case LWM16 + 0:
14608 case LWM16 + 1:
14609 case LWM16 + 2:
14610 case LWM16 + 3:
14612 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14613 int offset = ZIMM(ctx->opcode, 0, 4);
14615 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14616 29, offset << 2);
14618 break;
14619 case SWM16 + 0:
14620 case SWM16 + 1:
14621 case SWM16 + 2:
14622 case SWM16 + 3:
14624 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14625 int offset = ZIMM(ctx->opcode, 0, 4);
14627 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14628 29, offset << 2);
14630 break;
14631 case JR16 + 0:
14632 case JR16 + 1:
14634 int reg = ctx->opcode & 0x1f;
14636 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14638 break;
14639 case JRC16 + 0:
14640 case JRC16 + 1:
14642 int reg = ctx->opcode & 0x1f;
14643 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14644 /* Let normal delay slot handling in our caller take us
14645 to the branch target. */
14647 break;
14648 case JALR16 + 0:
14649 case JALR16 + 1:
14650 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14651 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14652 break;
14653 case JALR16S + 0:
14654 case JALR16S + 1:
14655 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14656 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14657 break;
14658 case MFHI16 + 0:
14659 case MFHI16 + 1:
14660 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14661 break;
14662 case MFLO16 + 0:
14663 case MFLO16 + 1:
14664 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14665 break;
14666 case BREAK16:
14667 generate_exception_end(ctx, EXCP_BREAK);
14668 break;
14669 case SDBBP16:
14670 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14671 gen_helper_do_semihosting(cpu_env);
14672 } else {
14673 /* XXX: not clear which exception should be raised
14674 * when in debug mode...
14676 check_insn(ctx, ISA_MIPS32);
14677 generate_exception_end(ctx, EXCP_DBp);
14679 break;
14680 case JRADDIUSP + 0:
14681 case JRADDIUSP + 1:
14683 int imm = ZIMM(ctx->opcode, 0, 5);
14684 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14685 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14686 /* Let normal delay slot handling in our caller take us
14687 to the branch target. */
14689 break;
14690 default:
14691 generate_exception_end(ctx, EXCP_RI);
14692 break;
14696 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14697 int enc_rs)
14699 int rd, rs, re, rt;
14700 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14701 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14702 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14703 rd = rd_enc[enc_dest];
14704 re = re_enc[enc_dest];
14705 rs = rs_rt_enc[enc_rs];
14706 rt = rs_rt_enc[enc_rt];
14707 if (rs) {
14708 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14709 } else {
14710 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14712 if (rt) {
14713 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14714 } else {
14715 tcg_gen_movi_tl(cpu_gpr[re], 0);
14719 static void gen_pool16c_r6_insn(DisasContext *ctx)
14721 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14722 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14724 switch (ctx->opcode & 0xf) {
14725 case R6_NOT16:
14726 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14727 break;
14728 case R6_AND16:
14729 gen_logic(ctx, OPC_AND, rt, rt, rs);
14730 break;
14731 case R6_LWM16:
14733 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14734 int offset = extract32(ctx->opcode, 4, 4);
14735 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14737 break;
14738 case R6_JRC16: /* JRCADDIUSP */
14739 if ((ctx->opcode >> 4) & 1) {
14740 /* JRCADDIUSP */
14741 int imm = extract32(ctx->opcode, 5, 5);
14742 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14743 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14744 } else {
14745 /* JRC16 */
14746 rs = extract32(ctx->opcode, 5, 5);
14747 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14749 break;
14750 case MOVEP:
14751 case MOVEP_05:
14752 case MOVEP_06:
14753 case MOVEP_07:
14754 case MOVEP_0C:
14755 case MOVEP_0D:
14756 case MOVEP_0E:
14757 case MOVEP_0F:
14759 int enc_dest = uMIPS_RD(ctx->opcode);
14760 int enc_rt = uMIPS_RS2(ctx->opcode);
14761 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14762 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14764 break;
14765 case R6_XOR16:
14766 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14767 break;
14768 case R6_OR16:
14769 gen_logic(ctx, OPC_OR, rt, rt, rs);
14770 break;
14771 case R6_SWM16:
14773 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14774 int offset = extract32(ctx->opcode, 4, 4);
14775 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14777 break;
14778 case JALRC16: /* BREAK16, SDBBP16 */
14779 switch (ctx->opcode & 0x3f) {
14780 case JALRC16:
14781 case JALRC16 + 0x20:
14782 /* JALRC16 */
14783 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14784 31, 0, 0);
14785 break;
14786 case R6_BREAK16:
14787 /* BREAK16 */
14788 generate_exception(ctx, EXCP_BREAK);
14789 break;
14790 case R6_SDBBP16:
14791 /* SDBBP16 */
14792 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14793 gen_helper_do_semihosting(cpu_env);
14794 } else {
14795 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14796 generate_exception(ctx, EXCP_RI);
14797 } else {
14798 generate_exception(ctx, EXCP_DBp);
14801 break;
14803 break;
14804 default:
14805 generate_exception(ctx, EXCP_RI);
14806 break;
14810 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14812 TCGv t0 = tcg_temp_new();
14813 TCGv t1 = tcg_temp_new();
14815 gen_load_gpr(t0, base);
14817 if (index != 0) {
14818 gen_load_gpr(t1, index);
14819 tcg_gen_shli_tl(t1, t1, 2);
14820 gen_op_addr_add(ctx, t0, t1, t0);
14823 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14824 gen_store_gpr(t1, rd);
14826 tcg_temp_free(t0);
14827 tcg_temp_free(t1);
14830 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14831 int base, int16_t offset)
14833 TCGv t0, t1;
14835 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14836 generate_exception_end(ctx, EXCP_RI);
14837 return;
14840 t0 = tcg_temp_new();
14841 t1 = tcg_temp_new();
14843 gen_base_offset_addr(ctx, t0, base, offset);
14845 switch (opc) {
14846 case LWP:
14847 if (rd == base) {
14848 generate_exception_end(ctx, EXCP_RI);
14849 return;
14851 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14852 gen_store_gpr(t1, rd);
14853 tcg_gen_movi_tl(t1, 4);
14854 gen_op_addr_add(ctx, t0, t0, t1);
14855 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14856 gen_store_gpr(t1, rd+1);
14857 break;
14858 case SWP:
14859 gen_load_gpr(t1, rd);
14860 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14861 tcg_gen_movi_tl(t1, 4);
14862 gen_op_addr_add(ctx, t0, t0, t1);
14863 gen_load_gpr(t1, rd+1);
14864 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14865 break;
14866 #ifdef TARGET_MIPS64
14867 case LDP:
14868 if (rd == base) {
14869 generate_exception_end(ctx, EXCP_RI);
14870 return;
14872 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14873 gen_store_gpr(t1, rd);
14874 tcg_gen_movi_tl(t1, 8);
14875 gen_op_addr_add(ctx, t0, t0, t1);
14876 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14877 gen_store_gpr(t1, rd+1);
14878 break;
14879 case SDP:
14880 gen_load_gpr(t1, rd);
14881 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14882 tcg_gen_movi_tl(t1, 8);
14883 gen_op_addr_add(ctx, t0, t0, t1);
14884 gen_load_gpr(t1, rd+1);
14885 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14886 break;
14887 #endif
14889 tcg_temp_free(t0);
14890 tcg_temp_free(t1);
14893 static void gen_sync(int stype)
14895 TCGBar tcg_mo = TCG_BAR_SC;
14897 switch (stype) {
14898 case 0x4: /* SYNC_WMB */
14899 tcg_mo |= TCG_MO_ST_ST;
14900 break;
14901 case 0x10: /* SYNC_MB */
14902 tcg_mo |= TCG_MO_ALL;
14903 break;
14904 case 0x11: /* SYNC_ACQUIRE */
14905 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14906 break;
14907 case 0x12: /* SYNC_RELEASE */
14908 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14909 break;
14910 case 0x13: /* SYNC_RMB */
14911 tcg_mo |= TCG_MO_LD_LD;
14912 break;
14913 default:
14914 tcg_mo |= TCG_MO_ALL;
14915 break;
14918 tcg_gen_mb(tcg_mo);
14921 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14923 int extension = (ctx->opcode >> 6) & 0x3f;
14924 int minor = (ctx->opcode >> 12) & 0xf;
14925 uint32_t mips32_op;
14927 switch (extension) {
14928 case TEQ:
14929 mips32_op = OPC_TEQ;
14930 goto do_trap;
14931 case TGE:
14932 mips32_op = OPC_TGE;
14933 goto do_trap;
14934 case TGEU:
14935 mips32_op = OPC_TGEU;
14936 goto do_trap;
14937 case TLT:
14938 mips32_op = OPC_TLT;
14939 goto do_trap;
14940 case TLTU:
14941 mips32_op = OPC_TLTU;
14942 goto do_trap;
14943 case TNE:
14944 mips32_op = OPC_TNE;
14945 do_trap:
14946 gen_trap(ctx, mips32_op, rs, rt, -1);
14947 break;
14948 #ifndef CONFIG_USER_ONLY
14949 case MFC0:
14950 case MFC0 + 32:
14951 check_cp0_enabled(ctx);
14952 if (rt == 0) {
14953 /* Treat as NOP. */
14954 break;
14956 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14957 break;
14958 case MTC0:
14959 case MTC0 + 32:
14960 check_cp0_enabled(ctx);
14962 TCGv t0 = tcg_temp_new();
14964 gen_load_gpr(t0, rt);
14965 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14966 tcg_temp_free(t0);
14968 break;
14969 #endif
14970 case 0x2a:
14971 switch (minor & 3) {
14972 case MADD_ACC:
14973 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14974 break;
14975 case MADDU_ACC:
14976 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14977 break;
14978 case MSUB_ACC:
14979 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14980 break;
14981 case MSUBU_ACC:
14982 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14983 break;
14984 default:
14985 goto pool32axf_invalid;
14987 break;
14988 case 0x32:
14989 switch (minor & 3) {
14990 case MULT_ACC:
14991 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14992 break;
14993 case MULTU_ACC:
14994 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14995 break;
14996 default:
14997 goto pool32axf_invalid;
14999 break;
15000 case 0x2c:
15001 switch (minor) {
15002 case BITSWAP:
15003 check_insn(ctx, ISA_MIPS32R6);
15004 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
15005 break;
15006 case SEB:
15007 gen_bshfl(ctx, OPC_SEB, rs, rt);
15008 break;
15009 case SEH:
15010 gen_bshfl(ctx, OPC_SEH, rs, rt);
15011 break;
15012 case CLO:
15013 mips32_op = OPC_CLO;
15014 goto do_cl;
15015 case CLZ:
15016 mips32_op = OPC_CLZ;
15017 do_cl:
15018 check_insn(ctx, ISA_MIPS32);
15019 gen_cl(ctx, mips32_op, rt, rs);
15020 break;
15021 case RDHWR:
15022 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15023 gen_rdhwr(ctx, rt, rs, 0);
15024 break;
15025 case WSBH:
15026 gen_bshfl(ctx, OPC_WSBH, rs, rt);
15027 break;
15028 case MULT:
15029 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15030 mips32_op = OPC_MULT;
15031 goto do_mul;
15032 case MULTU:
15033 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15034 mips32_op = OPC_MULTU;
15035 goto do_mul;
15036 case DIV:
15037 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15038 mips32_op = OPC_DIV;
15039 goto do_div;
15040 case DIVU:
15041 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15042 mips32_op = OPC_DIVU;
15043 goto do_div;
15044 do_div:
15045 check_insn(ctx, ISA_MIPS32);
15046 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15047 break;
15048 case MADD:
15049 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15050 mips32_op = OPC_MADD;
15051 goto do_mul;
15052 case MADDU:
15053 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15054 mips32_op = OPC_MADDU;
15055 goto do_mul;
15056 case MSUB:
15057 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15058 mips32_op = OPC_MSUB;
15059 goto do_mul;
15060 case MSUBU:
15061 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15062 mips32_op = OPC_MSUBU;
15063 do_mul:
15064 check_insn(ctx, ISA_MIPS32);
15065 gen_muldiv(ctx, mips32_op, 0, rs, rt);
15066 break;
15067 default:
15068 goto pool32axf_invalid;
15070 break;
15071 case 0x34:
15072 switch (minor) {
15073 case MFC2:
15074 case MTC2:
15075 case MFHC2:
15076 case MTHC2:
15077 case CFC2:
15078 case CTC2:
15079 generate_exception_err(ctx, EXCP_CpU, 2);
15080 break;
15081 default:
15082 goto pool32axf_invalid;
15084 break;
15085 case 0x3c:
15086 switch (minor) {
15087 case JALR: /* JALRC */
15088 case JALR_HB: /* JALRC_HB */
15089 if (ctx->insn_flags & ISA_MIPS32R6) {
15090 /* JALRC, JALRC_HB */
15091 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
15092 } else {
15093 /* JALR, JALR_HB */
15094 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
15095 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15097 break;
15098 case JALRS:
15099 case JALRS_HB:
15100 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15101 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
15102 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15103 break;
15104 default:
15105 goto pool32axf_invalid;
15107 break;
15108 case 0x05:
15109 switch (minor) {
15110 case RDPGPR:
15111 check_cp0_enabled(ctx);
15112 check_insn(ctx, ISA_MIPS32R2);
15113 gen_load_srsgpr(rs, rt);
15114 break;
15115 case WRPGPR:
15116 check_cp0_enabled(ctx);
15117 check_insn(ctx, ISA_MIPS32R2);
15118 gen_store_srsgpr(rs, rt);
15119 break;
15120 default:
15121 goto pool32axf_invalid;
15123 break;
15124 #ifndef CONFIG_USER_ONLY
15125 case 0x0d:
15126 switch (minor) {
15127 case TLBP:
15128 mips32_op = OPC_TLBP;
15129 goto do_cp0;
15130 case TLBR:
15131 mips32_op = OPC_TLBR;
15132 goto do_cp0;
15133 case TLBWI:
15134 mips32_op = OPC_TLBWI;
15135 goto do_cp0;
15136 case TLBWR:
15137 mips32_op = OPC_TLBWR;
15138 goto do_cp0;
15139 case TLBINV:
15140 mips32_op = OPC_TLBINV;
15141 goto do_cp0;
15142 case TLBINVF:
15143 mips32_op = OPC_TLBINVF;
15144 goto do_cp0;
15145 case WAIT:
15146 mips32_op = OPC_WAIT;
15147 goto do_cp0;
15148 case DERET:
15149 mips32_op = OPC_DERET;
15150 goto do_cp0;
15151 case ERET:
15152 mips32_op = OPC_ERET;
15153 do_cp0:
15154 gen_cp0(env, ctx, mips32_op, rt, rs);
15155 break;
15156 default:
15157 goto pool32axf_invalid;
15159 break;
15160 case 0x1d:
15161 switch (minor) {
15162 case DI:
15163 check_cp0_enabled(ctx);
15165 TCGv t0 = tcg_temp_new();
15167 save_cpu_state(ctx, 1);
15168 gen_helper_di(t0, cpu_env);
15169 gen_store_gpr(t0, rs);
15170 /* Stop translation as we may have switched the execution mode */
15171 ctx->base.is_jmp = DISAS_STOP;
15172 tcg_temp_free(t0);
15174 break;
15175 case EI:
15176 check_cp0_enabled(ctx);
15178 TCGv t0 = tcg_temp_new();
15180 save_cpu_state(ctx, 1);
15181 gen_helper_ei(t0, cpu_env);
15182 gen_store_gpr(t0, rs);
15183 /* DISAS_STOP isn't sufficient, we need to ensure we break out
15184 of translated code to check for pending interrupts. */
15185 gen_save_pc(ctx->base.pc_next + 4);
15186 ctx->base.is_jmp = DISAS_EXIT;
15187 tcg_temp_free(t0);
15189 break;
15190 default:
15191 goto pool32axf_invalid;
15193 break;
15194 #endif
15195 case 0x2d:
15196 switch (minor) {
15197 case SYNC:
15198 gen_sync(extract32(ctx->opcode, 16, 5));
15199 break;
15200 case SYSCALL:
15201 generate_exception_end(ctx, EXCP_SYSCALL);
15202 break;
15203 case SDBBP:
15204 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
15205 gen_helper_do_semihosting(cpu_env);
15206 } else {
15207 check_insn(ctx, ISA_MIPS32);
15208 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15209 generate_exception_end(ctx, EXCP_RI);
15210 } else {
15211 generate_exception_end(ctx, EXCP_DBp);
15214 break;
15215 default:
15216 goto pool32axf_invalid;
15218 break;
15219 case 0x01:
15220 switch (minor & 3) {
15221 case MFHI_ACC:
15222 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
15223 break;
15224 case MFLO_ACC:
15225 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
15226 break;
15227 case MTHI_ACC:
15228 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
15229 break;
15230 case MTLO_ACC:
15231 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
15232 break;
15233 default:
15234 goto pool32axf_invalid;
15236 break;
15237 case 0x35:
15238 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15239 switch (minor) {
15240 case MFHI32:
15241 gen_HILO(ctx, OPC_MFHI, 0, rs);
15242 break;
15243 case MFLO32:
15244 gen_HILO(ctx, OPC_MFLO, 0, rs);
15245 break;
15246 case MTHI32:
15247 gen_HILO(ctx, OPC_MTHI, 0, rs);
15248 break;
15249 case MTLO32:
15250 gen_HILO(ctx, OPC_MTLO, 0, rs);
15251 break;
15252 default:
15253 goto pool32axf_invalid;
15255 break;
15256 default:
15257 pool32axf_invalid:
15258 MIPS_INVAL("pool32axf");
15259 generate_exception_end(ctx, EXCP_RI);
15260 break;
15264 /* Values for microMIPS fmt field. Variable-width, depending on which
15265 formats the instruction supports. */
15267 enum {
15268 FMT_SD_S = 0,
15269 FMT_SD_D = 1,
15271 FMT_SDPS_S = 0,
15272 FMT_SDPS_D = 1,
15273 FMT_SDPS_PS = 2,
15275 FMT_SWL_S = 0,
15276 FMT_SWL_W = 1,
15277 FMT_SWL_L = 2,
15279 FMT_DWL_D = 0,
15280 FMT_DWL_W = 1,
15281 FMT_DWL_L = 2
15284 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15286 int extension = (ctx->opcode >> 6) & 0x3ff;
15287 uint32_t mips32_op;
15289 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15290 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15291 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15293 switch (extension) {
15294 case FLOAT_1BIT_FMT(CFC1, 0):
15295 mips32_op = OPC_CFC1;
15296 goto do_cp1;
15297 case FLOAT_1BIT_FMT(CTC1, 0):
15298 mips32_op = OPC_CTC1;
15299 goto do_cp1;
15300 case FLOAT_1BIT_FMT(MFC1, 0):
15301 mips32_op = OPC_MFC1;
15302 goto do_cp1;
15303 case FLOAT_1BIT_FMT(MTC1, 0):
15304 mips32_op = OPC_MTC1;
15305 goto do_cp1;
15306 case FLOAT_1BIT_FMT(MFHC1, 0):
15307 mips32_op = OPC_MFHC1;
15308 goto do_cp1;
15309 case FLOAT_1BIT_FMT(MTHC1, 0):
15310 mips32_op = OPC_MTHC1;
15311 do_cp1:
15312 gen_cp1(ctx, mips32_op, rt, rs);
15313 break;
15315 /* Reciprocal square root */
15316 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15317 mips32_op = OPC_RSQRT_S;
15318 goto do_unaryfp;
15319 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15320 mips32_op = OPC_RSQRT_D;
15321 goto do_unaryfp;
15323 /* Square root */
15324 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15325 mips32_op = OPC_SQRT_S;
15326 goto do_unaryfp;
15327 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15328 mips32_op = OPC_SQRT_D;
15329 goto do_unaryfp;
15331 /* Reciprocal */
15332 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15333 mips32_op = OPC_RECIP_S;
15334 goto do_unaryfp;
15335 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15336 mips32_op = OPC_RECIP_D;
15337 goto do_unaryfp;
15339 /* Floor */
15340 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15341 mips32_op = OPC_FLOOR_L_S;
15342 goto do_unaryfp;
15343 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15344 mips32_op = OPC_FLOOR_L_D;
15345 goto do_unaryfp;
15346 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15347 mips32_op = OPC_FLOOR_W_S;
15348 goto do_unaryfp;
15349 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15350 mips32_op = OPC_FLOOR_W_D;
15351 goto do_unaryfp;
15353 /* Ceiling */
15354 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15355 mips32_op = OPC_CEIL_L_S;
15356 goto do_unaryfp;
15357 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15358 mips32_op = OPC_CEIL_L_D;
15359 goto do_unaryfp;
15360 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15361 mips32_op = OPC_CEIL_W_S;
15362 goto do_unaryfp;
15363 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15364 mips32_op = OPC_CEIL_W_D;
15365 goto do_unaryfp;
15367 /* Truncation */
15368 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15369 mips32_op = OPC_TRUNC_L_S;
15370 goto do_unaryfp;
15371 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15372 mips32_op = OPC_TRUNC_L_D;
15373 goto do_unaryfp;
15374 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15375 mips32_op = OPC_TRUNC_W_S;
15376 goto do_unaryfp;
15377 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15378 mips32_op = OPC_TRUNC_W_D;
15379 goto do_unaryfp;
15381 /* Round */
15382 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15383 mips32_op = OPC_ROUND_L_S;
15384 goto do_unaryfp;
15385 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15386 mips32_op = OPC_ROUND_L_D;
15387 goto do_unaryfp;
15388 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15389 mips32_op = OPC_ROUND_W_S;
15390 goto do_unaryfp;
15391 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15392 mips32_op = OPC_ROUND_W_D;
15393 goto do_unaryfp;
15395 /* Integer to floating-point conversion */
15396 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15397 mips32_op = OPC_CVT_L_S;
15398 goto do_unaryfp;
15399 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15400 mips32_op = OPC_CVT_L_D;
15401 goto do_unaryfp;
15402 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15403 mips32_op = OPC_CVT_W_S;
15404 goto do_unaryfp;
15405 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15406 mips32_op = OPC_CVT_W_D;
15407 goto do_unaryfp;
15409 /* Paired-foo conversions */
15410 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15411 mips32_op = OPC_CVT_S_PL;
15412 goto do_unaryfp;
15413 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15414 mips32_op = OPC_CVT_S_PU;
15415 goto do_unaryfp;
15416 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15417 mips32_op = OPC_CVT_PW_PS;
15418 goto do_unaryfp;
15419 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15420 mips32_op = OPC_CVT_PS_PW;
15421 goto do_unaryfp;
15423 /* Floating-point moves */
15424 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15425 mips32_op = OPC_MOV_S;
15426 goto do_unaryfp;
15427 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15428 mips32_op = OPC_MOV_D;
15429 goto do_unaryfp;
15430 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15431 mips32_op = OPC_MOV_PS;
15432 goto do_unaryfp;
15434 /* Absolute value */
15435 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15436 mips32_op = OPC_ABS_S;
15437 goto do_unaryfp;
15438 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15439 mips32_op = OPC_ABS_D;
15440 goto do_unaryfp;
15441 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15442 mips32_op = OPC_ABS_PS;
15443 goto do_unaryfp;
15445 /* Negation */
15446 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15447 mips32_op = OPC_NEG_S;
15448 goto do_unaryfp;
15449 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15450 mips32_op = OPC_NEG_D;
15451 goto do_unaryfp;
15452 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15453 mips32_op = OPC_NEG_PS;
15454 goto do_unaryfp;
15456 /* Reciprocal square root step */
15457 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15458 mips32_op = OPC_RSQRT1_S;
15459 goto do_unaryfp;
15460 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15461 mips32_op = OPC_RSQRT1_D;
15462 goto do_unaryfp;
15463 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15464 mips32_op = OPC_RSQRT1_PS;
15465 goto do_unaryfp;
15467 /* Reciprocal step */
15468 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15469 mips32_op = OPC_RECIP1_S;
15470 goto do_unaryfp;
15471 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15472 mips32_op = OPC_RECIP1_S;
15473 goto do_unaryfp;
15474 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15475 mips32_op = OPC_RECIP1_PS;
15476 goto do_unaryfp;
15478 /* Conversions from double */
15479 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15480 mips32_op = OPC_CVT_D_S;
15481 goto do_unaryfp;
15482 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15483 mips32_op = OPC_CVT_D_W;
15484 goto do_unaryfp;
15485 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15486 mips32_op = OPC_CVT_D_L;
15487 goto do_unaryfp;
15489 /* Conversions from single */
15490 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15491 mips32_op = OPC_CVT_S_D;
15492 goto do_unaryfp;
15493 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15494 mips32_op = OPC_CVT_S_W;
15495 goto do_unaryfp;
15496 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15497 mips32_op = OPC_CVT_S_L;
15498 do_unaryfp:
15499 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15500 break;
15502 /* Conditional moves on floating-point codes */
15503 case COND_FLOAT_MOV(MOVT, 0):
15504 case COND_FLOAT_MOV(MOVT, 1):
15505 case COND_FLOAT_MOV(MOVT, 2):
15506 case COND_FLOAT_MOV(MOVT, 3):
15507 case COND_FLOAT_MOV(MOVT, 4):
15508 case COND_FLOAT_MOV(MOVT, 5):
15509 case COND_FLOAT_MOV(MOVT, 6):
15510 case COND_FLOAT_MOV(MOVT, 7):
15511 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15512 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15513 break;
15514 case COND_FLOAT_MOV(MOVF, 0):
15515 case COND_FLOAT_MOV(MOVF, 1):
15516 case COND_FLOAT_MOV(MOVF, 2):
15517 case COND_FLOAT_MOV(MOVF, 3):
15518 case COND_FLOAT_MOV(MOVF, 4):
15519 case COND_FLOAT_MOV(MOVF, 5):
15520 case COND_FLOAT_MOV(MOVF, 6):
15521 case COND_FLOAT_MOV(MOVF, 7):
15522 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15523 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15524 break;
15525 default:
15526 MIPS_INVAL("pool32fxf");
15527 generate_exception_end(ctx, EXCP_RI);
15528 break;
15532 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15534 int32_t offset;
15535 uint16_t insn;
15536 int rt, rs, rd, rr;
15537 int16_t imm;
15538 uint32_t op, minor, minor2, mips32_op;
15539 uint32_t cond, fmt, cc;
15541 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15542 ctx->opcode = (ctx->opcode << 16) | insn;
15544 rt = (ctx->opcode >> 21) & 0x1f;
15545 rs = (ctx->opcode >> 16) & 0x1f;
15546 rd = (ctx->opcode >> 11) & 0x1f;
15547 rr = (ctx->opcode >> 6) & 0x1f;
15548 imm = (int16_t) ctx->opcode;
15550 op = (ctx->opcode >> 26) & 0x3f;
15551 switch (op) {
15552 case POOL32A:
15553 minor = ctx->opcode & 0x3f;
15554 switch (minor) {
15555 case 0x00:
15556 minor = (ctx->opcode >> 6) & 0xf;
15557 switch (minor) {
15558 case SLL32:
15559 mips32_op = OPC_SLL;
15560 goto do_shifti;
15561 case SRA:
15562 mips32_op = OPC_SRA;
15563 goto do_shifti;
15564 case SRL32:
15565 mips32_op = OPC_SRL;
15566 goto do_shifti;
15567 case ROTR:
15568 mips32_op = OPC_ROTR;
15569 do_shifti:
15570 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15571 break;
15572 case SELEQZ:
15573 check_insn(ctx, ISA_MIPS32R6);
15574 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15575 break;
15576 case SELNEZ:
15577 check_insn(ctx, ISA_MIPS32R6);
15578 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15579 break;
15580 case R6_RDHWR:
15581 check_insn(ctx, ISA_MIPS32R6);
15582 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15583 break;
15584 default:
15585 goto pool32a_invalid;
15587 break;
15588 case 0x10:
15589 minor = (ctx->opcode >> 6) & 0xf;
15590 switch (minor) {
15591 /* Arithmetic */
15592 case ADD:
15593 mips32_op = OPC_ADD;
15594 goto do_arith;
15595 case ADDU32:
15596 mips32_op = OPC_ADDU;
15597 goto do_arith;
15598 case SUB:
15599 mips32_op = OPC_SUB;
15600 goto do_arith;
15601 case SUBU32:
15602 mips32_op = OPC_SUBU;
15603 goto do_arith;
15604 case MUL:
15605 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15606 mips32_op = OPC_MUL;
15607 do_arith:
15608 gen_arith(ctx, mips32_op, rd, rs, rt);
15609 break;
15610 /* Shifts */
15611 case SLLV:
15612 mips32_op = OPC_SLLV;
15613 goto do_shift;
15614 case SRLV:
15615 mips32_op = OPC_SRLV;
15616 goto do_shift;
15617 case SRAV:
15618 mips32_op = OPC_SRAV;
15619 goto do_shift;
15620 case ROTRV:
15621 mips32_op = OPC_ROTRV;
15622 do_shift:
15623 gen_shift(ctx, mips32_op, rd, rs, rt);
15624 break;
15625 /* Logical operations */
15626 case AND:
15627 mips32_op = OPC_AND;
15628 goto do_logic;
15629 case OR32:
15630 mips32_op = OPC_OR;
15631 goto do_logic;
15632 case NOR:
15633 mips32_op = OPC_NOR;
15634 goto do_logic;
15635 case XOR32:
15636 mips32_op = OPC_XOR;
15637 do_logic:
15638 gen_logic(ctx, mips32_op, rd, rs, rt);
15639 break;
15640 /* Set less than */
15641 case SLT:
15642 mips32_op = OPC_SLT;
15643 goto do_slt;
15644 case SLTU:
15645 mips32_op = OPC_SLTU;
15646 do_slt:
15647 gen_slt(ctx, mips32_op, rd, rs, rt);
15648 break;
15649 default:
15650 goto pool32a_invalid;
15652 break;
15653 case 0x18:
15654 minor = (ctx->opcode >> 6) & 0xf;
15655 switch (minor) {
15656 /* Conditional moves */
15657 case MOVN: /* MUL */
15658 if (ctx->insn_flags & ISA_MIPS32R6) {
15659 /* MUL */
15660 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15661 } else {
15662 /* MOVN */
15663 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15665 break;
15666 case MOVZ: /* MUH */
15667 if (ctx->insn_flags & ISA_MIPS32R6) {
15668 /* MUH */
15669 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15670 } else {
15671 /* MOVZ */
15672 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15674 break;
15675 case MULU:
15676 check_insn(ctx, ISA_MIPS32R6);
15677 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15678 break;
15679 case MUHU:
15680 check_insn(ctx, ISA_MIPS32R6);
15681 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15682 break;
15683 case LWXS: /* DIV */
15684 if (ctx->insn_flags & ISA_MIPS32R6) {
15685 /* DIV */
15686 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15687 } else {
15688 /* LWXS */
15689 gen_ldxs(ctx, rs, rt, rd);
15691 break;
15692 case MOD:
15693 check_insn(ctx, ISA_MIPS32R6);
15694 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15695 break;
15696 case R6_DIVU:
15697 check_insn(ctx, ISA_MIPS32R6);
15698 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15699 break;
15700 case MODU:
15701 check_insn(ctx, ISA_MIPS32R6);
15702 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15703 break;
15704 default:
15705 goto pool32a_invalid;
15707 break;
15708 case INS:
15709 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15710 return;
15711 case LSA:
15712 check_insn(ctx, ISA_MIPS32R6);
15713 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15714 extract32(ctx->opcode, 9, 2));
15715 break;
15716 case ALIGN:
15717 check_insn(ctx, ISA_MIPS32R6);
15718 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15719 break;
15720 case EXT:
15721 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15722 return;
15723 case POOL32AXF:
15724 gen_pool32axf(env, ctx, rt, rs);
15725 break;
15726 case BREAK32:
15727 generate_exception_end(ctx, EXCP_BREAK);
15728 break;
15729 case SIGRIE:
15730 check_insn(ctx, ISA_MIPS32R6);
15731 generate_exception_end(ctx, EXCP_RI);
15732 break;
15733 default:
15734 pool32a_invalid:
15735 MIPS_INVAL("pool32a");
15736 generate_exception_end(ctx, EXCP_RI);
15737 break;
15739 break;
15740 case POOL32B:
15741 minor = (ctx->opcode >> 12) & 0xf;
15742 switch (minor) {
15743 case CACHE:
15744 check_cp0_enabled(ctx);
15745 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15746 gen_cache_operation(ctx, rt, rs, imm);
15748 break;
15749 case LWC2:
15750 case SWC2:
15751 /* COP2: Not implemented. */
15752 generate_exception_err(ctx, EXCP_CpU, 2);
15753 break;
15754 #ifdef TARGET_MIPS64
15755 case LDP:
15756 case SDP:
15757 check_insn(ctx, ISA_MIPS3);
15758 check_mips_64(ctx);
15759 #endif
15760 /* fall through */
15761 case LWP:
15762 case SWP:
15763 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15764 break;
15765 #ifdef TARGET_MIPS64
15766 case LDM:
15767 case SDM:
15768 check_insn(ctx, ISA_MIPS3);
15769 check_mips_64(ctx);
15770 #endif
15771 /* fall through */
15772 case LWM32:
15773 case SWM32:
15774 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15775 break;
15776 default:
15777 MIPS_INVAL("pool32b");
15778 generate_exception_end(ctx, EXCP_RI);
15779 break;
15781 break;
15782 case POOL32F:
15783 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15784 minor = ctx->opcode & 0x3f;
15785 check_cp1_enabled(ctx);
15786 switch (minor) {
15787 case ALNV_PS:
15788 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15789 mips32_op = OPC_ALNV_PS;
15790 goto do_madd;
15791 case MADD_S:
15792 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15793 mips32_op = OPC_MADD_S;
15794 goto do_madd;
15795 case MADD_D:
15796 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15797 mips32_op = OPC_MADD_D;
15798 goto do_madd;
15799 case MADD_PS:
15800 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15801 mips32_op = OPC_MADD_PS;
15802 goto do_madd;
15803 case MSUB_S:
15804 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15805 mips32_op = OPC_MSUB_S;
15806 goto do_madd;
15807 case MSUB_D:
15808 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15809 mips32_op = OPC_MSUB_D;
15810 goto do_madd;
15811 case MSUB_PS:
15812 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15813 mips32_op = OPC_MSUB_PS;
15814 goto do_madd;
15815 case NMADD_S:
15816 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15817 mips32_op = OPC_NMADD_S;
15818 goto do_madd;
15819 case NMADD_D:
15820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15821 mips32_op = OPC_NMADD_D;
15822 goto do_madd;
15823 case NMADD_PS:
15824 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15825 mips32_op = OPC_NMADD_PS;
15826 goto do_madd;
15827 case NMSUB_S:
15828 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15829 mips32_op = OPC_NMSUB_S;
15830 goto do_madd;
15831 case NMSUB_D:
15832 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15833 mips32_op = OPC_NMSUB_D;
15834 goto do_madd;
15835 case NMSUB_PS:
15836 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15837 mips32_op = OPC_NMSUB_PS;
15838 do_madd:
15839 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15840 break;
15841 case CABS_COND_FMT:
15842 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15843 cond = (ctx->opcode >> 6) & 0xf;
15844 cc = (ctx->opcode >> 13) & 0x7;
15845 fmt = (ctx->opcode >> 10) & 0x3;
15846 switch (fmt) {
15847 case 0x0:
15848 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15849 break;
15850 case 0x1:
15851 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15852 break;
15853 case 0x2:
15854 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15855 break;
15856 default:
15857 goto pool32f_invalid;
15859 break;
15860 case C_COND_FMT:
15861 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15862 cond = (ctx->opcode >> 6) & 0xf;
15863 cc = (ctx->opcode >> 13) & 0x7;
15864 fmt = (ctx->opcode >> 10) & 0x3;
15865 switch (fmt) {
15866 case 0x0:
15867 gen_cmp_s(ctx, cond, rt, rs, cc);
15868 break;
15869 case 0x1:
15870 gen_cmp_d(ctx, cond, rt, rs, cc);
15871 break;
15872 case 0x2:
15873 gen_cmp_ps(ctx, cond, rt, rs, cc);
15874 break;
15875 default:
15876 goto pool32f_invalid;
15878 break;
15879 case CMP_CONDN_S:
15880 check_insn(ctx, ISA_MIPS32R6);
15881 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15882 break;
15883 case CMP_CONDN_D:
15884 check_insn(ctx, ISA_MIPS32R6);
15885 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15886 break;
15887 case POOL32FXF:
15888 gen_pool32fxf(ctx, rt, rs);
15889 break;
15890 case 0x00:
15891 /* PLL foo */
15892 switch ((ctx->opcode >> 6) & 0x7) {
15893 case PLL_PS:
15894 mips32_op = OPC_PLL_PS;
15895 goto do_ps;
15896 case PLU_PS:
15897 mips32_op = OPC_PLU_PS;
15898 goto do_ps;
15899 case PUL_PS:
15900 mips32_op = OPC_PUL_PS;
15901 goto do_ps;
15902 case PUU_PS:
15903 mips32_op = OPC_PUU_PS;
15904 goto do_ps;
15905 case CVT_PS_S:
15906 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15907 mips32_op = OPC_CVT_PS_S;
15908 do_ps:
15909 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15910 break;
15911 default:
15912 goto pool32f_invalid;
15914 break;
15915 case MIN_FMT:
15916 check_insn(ctx, ISA_MIPS32R6);
15917 switch ((ctx->opcode >> 9) & 0x3) {
15918 case FMT_SDPS_S:
15919 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15920 break;
15921 case FMT_SDPS_D:
15922 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15923 break;
15924 default:
15925 goto pool32f_invalid;
15927 break;
15928 case 0x08:
15929 /* [LS][WDU]XC1 */
15930 switch ((ctx->opcode >> 6) & 0x7) {
15931 case LWXC1:
15932 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15933 mips32_op = OPC_LWXC1;
15934 goto do_ldst_cp1;
15935 case SWXC1:
15936 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15937 mips32_op = OPC_SWXC1;
15938 goto do_ldst_cp1;
15939 case LDXC1:
15940 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15941 mips32_op = OPC_LDXC1;
15942 goto do_ldst_cp1;
15943 case SDXC1:
15944 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15945 mips32_op = OPC_SDXC1;
15946 goto do_ldst_cp1;
15947 case LUXC1:
15948 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15949 mips32_op = OPC_LUXC1;
15950 goto do_ldst_cp1;
15951 case SUXC1:
15952 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15953 mips32_op = OPC_SUXC1;
15954 do_ldst_cp1:
15955 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15956 break;
15957 default:
15958 goto pool32f_invalid;
15960 break;
15961 case MAX_FMT:
15962 check_insn(ctx, ISA_MIPS32R6);
15963 switch ((ctx->opcode >> 9) & 0x3) {
15964 case FMT_SDPS_S:
15965 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15966 break;
15967 case FMT_SDPS_D:
15968 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15969 break;
15970 default:
15971 goto pool32f_invalid;
15973 break;
15974 case 0x18:
15975 /* 3D insns */
15976 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15977 fmt = (ctx->opcode >> 9) & 0x3;
15978 switch ((ctx->opcode >> 6) & 0x7) {
15979 case RSQRT2_FMT:
15980 switch (fmt) {
15981 case FMT_SDPS_S:
15982 mips32_op = OPC_RSQRT2_S;
15983 goto do_3d;
15984 case FMT_SDPS_D:
15985 mips32_op = OPC_RSQRT2_D;
15986 goto do_3d;
15987 case FMT_SDPS_PS:
15988 mips32_op = OPC_RSQRT2_PS;
15989 goto do_3d;
15990 default:
15991 goto pool32f_invalid;
15993 break;
15994 case RECIP2_FMT:
15995 switch (fmt) {
15996 case FMT_SDPS_S:
15997 mips32_op = OPC_RECIP2_S;
15998 goto do_3d;
15999 case FMT_SDPS_D:
16000 mips32_op = OPC_RECIP2_D;
16001 goto do_3d;
16002 case FMT_SDPS_PS:
16003 mips32_op = OPC_RECIP2_PS;
16004 goto do_3d;
16005 default:
16006 goto pool32f_invalid;
16008 break;
16009 case ADDR_PS:
16010 mips32_op = OPC_ADDR_PS;
16011 goto do_3d;
16012 case MULR_PS:
16013 mips32_op = OPC_MULR_PS;
16014 do_3d:
16015 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16016 break;
16017 default:
16018 goto pool32f_invalid;
16020 break;
16021 case 0x20:
16022 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
16023 cc = (ctx->opcode >> 13) & 0x7;
16024 fmt = (ctx->opcode >> 9) & 0x3;
16025 switch ((ctx->opcode >> 6) & 0x7) {
16026 case MOVF_FMT: /* RINT_FMT */
16027 if (ctx->insn_flags & ISA_MIPS32R6) {
16028 /* RINT_FMT */
16029 switch (fmt) {
16030 case FMT_SDPS_S:
16031 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
16032 break;
16033 case FMT_SDPS_D:
16034 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
16035 break;
16036 default:
16037 goto pool32f_invalid;
16039 } else {
16040 /* MOVF_FMT */
16041 switch (fmt) {
16042 case FMT_SDPS_S:
16043 gen_movcf_s(ctx, rs, rt, cc, 0);
16044 break;
16045 case FMT_SDPS_D:
16046 gen_movcf_d(ctx, rs, rt, cc, 0);
16047 break;
16048 case FMT_SDPS_PS:
16049 check_ps(ctx);
16050 gen_movcf_ps(ctx, rs, rt, cc, 0);
16051 break;
16052 default:
16053 goto pool32f_invalid;
16056 break;
16057 case MOVT_FMT: /* CLASS_FMT */
16058 if (ctx->insn_flags & ISA_MIPS32R6) {
16059 /* CLASS_FMT */
16060 switch (fmt) {
16061 case FMT_SDPS_S:
16062 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
16063 break;
16064 case FMT_SDPS_D:
16065 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
16066 break;
16067 default:
16068 goto pool32f_invalid;
16070 } else {
16071 /* MOVT_FMT */
16072 switch (fmt) {
16073 case FMT_SDPS_S:
16074 gen_movcf_s(ctx, rs, rt, cc, 1);
16075 break;
16076 case FMT_SDPS_D:
16077 gen_movcf_d(ctx, rs, rt, cc, 1);
16078 break;
16079 case FMT_SDPS_PS:
16080 check_ps(ctx);
16081 gen_movcf_ps(ctx, rs, rt, cc, 1);
16082 break;
16083 default:
16084 goto pool32f_invalid;
16087 break;
16088 case PREFX:
16089 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16090 break;
16091 default:
16092 goto pool32f_invalid;
16094 break;
16095 #define FINSN_3ARG_SDPS(prfx) \
16096 switch ((ctx->opcode >> 8) & 0x3) { \
16097 case FMT_SDPS_S: \
16098 mips32_op = OPC_##prfx##_S; \
16099 goto do_fpop; \
16100 case FMT_SDPS_D: \
16101 mips32_op = OPC_##prfx##_D; \
16102 goto do_fpop; \
16103 case FMT_SDPS_PS: \
16104 check_ps(ctx); \
16105 mips32_op = OPC_##prfx##_PS; \
16106 goto do_fpop; \
16107 default: \
16108 goto pool32f_invalid; \
16110 case MINA_FMT:
16111 check_insn(ctx, ISA_MIPS32R6);
16112 switch ((ctx->opcode >> 9) & 0x3) {
16113 case FMT_SDPS_S:
16114 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
16115 break;
16116 case FMT_SDPS_D:
16117 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
16118 break;
16119 default:
16120 goto pool32f_invalid;
16122 break;
16123 case MAXA_FMT:
16124 check_insn(ctx, ISA_MIPS32R6);
16125 switch ((ctx->opcode >> 9) & 0x3) {
16126 case FMT_SDPS_S:
16127 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
16128 break;
16129 case FMT_SDPS_D:
16130 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
16131 break;
16132 default:
16133 goto pool32f_invalid;
16135 break;
16136 case 0x30:
16137 /* regular FP ops */
16138 switch ((ctx->opcode >> 6) & 0x3) {
16139 case ADD_FMT:
16140 FINSN_3ARG_SDPS(ADD);
16141 break;
16142 case SUB_FMT:
16143 FINSN_3ARG_SDPS(SUB);
16144 break;
16145 case MUL_FMT:
16146 FINSN_3ARG_SDPS(MUL);
16147 break;
16148 case DIV_FMT:
16149 fmt = (ctx->opcode >> 8) & 0x3;
16150 if (fmt == 1) {
16151 mips32_op = OPC_DIV_D;
16152 } else if (fmt == 0) {
16153 mips32_op = OPC_DIV_S;
16154 } else {
16155 goto pool32f_invalid;
16157 goto do_fpop;
16158 default:
16159 goto pool32f_invalid;
16161 break;
16162 case 0x38:
16163 /* cmovs */
16164 switch ((ctx->opcode >> 6) & 0x7) {
16165 case MOVN_FMT: /* SELEQZ_FMT */
16166 if (ctx->insn_flags & ISA_MIPS32R6) {
16167 /* SELEQZ_FMT */
16168 switch ((ctx->opcode >> 9) & 0x3) {
16169 case FMT_SDPS_S:
16170 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
16171 break;
16172 case FMT_SDPS_D:
16173 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
16174 break;
16175 default:
16176 goto pool32f_invalid;
16178 } else {
16179 /* MOVN_FMT */
16180 FINSN_3ARG_SDPS(MOVN);
16182 break;
16183 case MOVN_FMT_04:
16184 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16185 FINSN_3ARG_SDPS(MOVN);
16186 break;
16187 case MOVZ_FMT: /* SELNEZ_FMT */
16188 if (ctx->insn_flags & ISA_MIPS32R6) {
16189 /* SELNEZ_FMT */
16190 switch ((ctx->opcode >> 9) & 0x3) {
16191 case FMT_SDPS_S:
16192 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
16193 break;
16194 case FMT_SDPS_D:
16195 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
16196 break;
16197 default:
16198 goto pool32f_invalid;
16200 } else {
16201 /* MOVZ_FMT */
16202 FINSN_3ARG_SDPS(MOVZ);
16204 break;
16205 case MOVZ_FMT_05:
16206 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16207 FINSN_3ARG_SDPS(MOVZ);
16208 break;
16209 case SEL_FMT:
16210 check_insn(ctx, ISA_MIPS32R6);
16211 switch ((ctx->opcode >> 9) & 0x3) {
16212 case FMT_SDPS_S:
16213 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
16214 break;
16215 case FMT_SDPS_D:
16216 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
16217 break;
16218 default:
16219 goto pool32f_invalid;
16221 break;
16222 case MADDF_FMT:
16223 check_insn(ctx, ISA_MIPS32R6);
16224 switch ((ctx->opcode >> 9) & 0x3) {
16225 case FMT_SDPS_S:
16226 mips32_op = OPC_MADDF_S;
16227 goto do_fpop;
16228 case FMT_SDPS_D:
16229 mips32_op = OPC_MADDF_D;
16230 goto do_fpop;
16231 default:
16232 goto pool32f_invalid;
16234 break;
16235 case MSUBF_FMT:
16236 check_insn(ctx, ISA_MIPS32R6);
16237 switch ((ctx->opcode >> 9) & 0x3) {
16238 case FMT_SDPS_S:
16239 mips32_op = OPC_MSUBF_S;
16240 goto do_fpop;
16241 case FMT_SDPS_D:
16242 mips32_op = OPC_MSUBF_D;
16243 goto do_fpop;
16244 default:
16245 goto pool32f_invalid;
16247 break;
16248 default:
16249 goto pool32f_invalid;
16251 break;
16252 do_fpop:
16253 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16254 break;
16255 default:
16256 pool32f_invalid:
16257 MIPS_INVAL("pool32f");
16258 generate_exception_end(ctx, EXCP_RI);
16259 break;
16261 } else {
16262 generate_exception_err(ctx, EXCP_CpU, 1);
16264 break;
16265 case POOL32I:
16266 minor = (ctx->opcode >> 21) & 0x1f;
16267 switch (minor) {
16268 case BLTZ:
16269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16270 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16271 break;
16272 case BLTZAL:
16273 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16274 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16275 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16276 break;
16277 case BLTZALS:
16278 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16279 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16280 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16281 break;
16282 case BGEZ:
16283 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16284 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16285 break;
16286 case BGEZAL:
16287 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16288 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16289 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16290 break;
16291 case BGEZALS:
16292 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16293 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16294 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16295 break;
16296 case BLEZ:
16297 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16298 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16299 break;
16300 case BGTZ:
16301 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16302 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16303 break;
16305 /* Traps */
16306 case TLTI: /* BC1EQZC */
16307 if (ctx->insn_flags & ISA_MIPS32R6) {
16308 /* BC1EQZC */
16309 check_cp1_enabled(ctx);
16310 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16311 } else {
16312 /* TLTI */
16313 mips32_op = OPC_TLTI;
16314 goto do_trapi;
16316 break;
16317 case TGEI: /* BC1NEZC */
16318 if (ctx->insn_flags & ISA_MIPS32R6) {
16319 /* BC1NEZC */
16320 check_cp1_enabled(ctx);
16321 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16322 } else {
16323 /* TGEI */
16324 mips32_op = OPC_TGEI;
16325 goto do_trapi;
16327 break;
16328 case TLTIU:
16329 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16330 mips32_op = OPC_TLTIU;
16331 goto do_trapi;
16332 case TGEIU:
16333 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16334 mips32_op = OPC_TGEIU;
16335 goto do_trapi;
16336 case TNEI: /* SYNCI */
16337 if (ctx->insn_flags & ISA_MIPS32R6) {
16338 /* SYNCI */
16339 /* Break the TB to be able to sync copied instructions
16340 immediately */
16341 ctx->base.is_jmp = DISAS_STOP;
16342 } else {
16343 /* TNEI */
16344 mips32_op = OPC_TNEI;
16345 goto do_trapi;
16347 break;
16348 case TEQI:
16349 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16350 mips32_op = OPC_TEQI;
16351 do_trapi:
16352 gen_trap(ctx, mips32_op, rs, -1, imm);
16353 break;
16355 case BNEZC:
16356 case BEQZC:
16357 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16358 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16359 4, rs, 0, imm << 1, 0);
16360 /* Compact branches don't have a delay slot, so just let
16361 the normal delay slot handling take us to the branch
16362 target. */
16363 break;
16364 case LUI:
16365 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16366 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16367 break;
16368 case SYNCI:
16369 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16370 /* Break the TB to be able to sync copied instructions
16371 immediately */
16372 ctx->base.is_jmp = DISAS_STOP;
16373 break;
16374 case BC2F:
16375 case BC2T:
16376 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16377 /* COP2: Not implemented. */
16378 generate_exception_err(ctx, EXCP_CpU, 2);
16379 break;
16380 case BC1F:
16381 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16382 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16383 goto do_cp1branch;
16384 case BC1T:
16385 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16386 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16387 goto do_cp1branch;
16388 case BC1ANY4F:
16389 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16390 mips32_op = OPC_BC1FANY4;
16391 goto do_cp1mips3d;
16392 case BC1ANY4T:
16393 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16394 mips32_op = OPC_BC1TANY4;
16395 do_cp1mips3d:
16396 check_cop1x(ctx);
16397 check_insn(ctx, ASE_MIPS3D);
16398 /* Fall through */
16399 do_cp1branch:
16400 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16401 check_cp1_enabled(ctx);
16402 gen_compute_branch1(ctx, mips32_op,
16403 (ctx->opcode >> 18) & 0x7, imm << 1);
16404 } else {
16405 generate_exception_err(ctx, EXCP_CpU, 1);
16407 break;
16408 case BPOSGE64:
16409 case BPOSGE32:
16410 /* MIPS DSP: not implemented */
16411 /* Fall through */
16412 default:
16413 MIPS_INVAL("pool32i");
16414 generate_exception_end(ctx, EXCP_RI);
16415 break;
16417 break;
16418 case POOL32C:
16419 minor = (ctx->opcode >> 12) & 0xf;
16420 offset = sextract32(ctx->opcode, 0,
16421 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16422 switch (minor) {
16423 case LWL:
16424 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16425 mips32_op = OPC_LWL;
16426 goto do_ld_lr;
16427 case SWL:
16428 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16429 mips32_op = OPC_SWL;
16430 goto do_st_lr;
16431 case LWR:
16432 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16433 mips32_op = OPC_LWR;
16434 goto do_ld_lr;
16435 case SWR:
16436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16437 mips32_op = OPC_SWR;
16438 goto do_st_lr;
16439 #if defined(TARGET_MIPS64)
16440 case LDL:
16441 check_insn(ctx, ISA_MIPS3);
16442 check_mips_64(ctx);
16443 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16444 mips32_op = OPC_LDL;
16445 goto do_ld_lr;
16446 case SDL:
16447 check_insn(ctx, ISA_MIPS3);
16448 check_mips_64(ctx);
16449 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16450 mips32_op = OPC_SDL;
16451 goto do_st_lr;
16452 case LDR:
16453 check_insn(ctx, ISA_MIPS3);
16454 check_mips_64(ctx);
16455 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16456 mips32_op = OPC_LDR;
16457 goto do_ld_lr;
16458 case SDR:
16459 check_insn(ctx, ISA_MIPS3);
16460 check_mips_64(ctx);
16461 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16462 mips32_op = OPC_SDR;
16463 goto do_st_lr;
16464 case LWU:
16465 check_insn(ctx, ISA_MIPS3);
16466 check_mips_64(ctx);
16467 mips32_op = OPC_LWU;
16468 goto do_ld_lr;
16469 case LLD:
16470 check_insn(ctx, ISA_MIPS3);
16471 check_mips_64(ctx);
16472 mips32_op = OPC_LLD;
16473 goto do_ld_lr;
16474 #endif
16475 case LL:
16476 mips32_op = OPC_LL;
16477 goto do_ld_lr;
16478 do_ld_lr:
16479 gen_ld(ctx, mips32_op, rt, rs, offset);
16480 break;
16481 do_st_lr:
16482 gen_st(ctx, mips32_op, rt, rs, offset);
16483 break;
16484 case SC:
16485 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16486 break;
16487 #if defined(TARGET_MIPS64)
16488 case SCD:
16489 check_insn(ctx, ISA_MIPS3);
16490 check_mips_64(ctx);
16491 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16492 break;
16493 #endif
16494 case LD_EVA:
16495 if (!ctx->eva) {
16496 MIPS_INVAL("pool32c ld-eva");
16497 generate_exception_end(ctx, EXCP_RI);
16498 break;
16500 check_cp0_enabled(ctx);
16502 minor2 = (ctx->opcode >> 9) & 0x7;
16503 offset = sextract32(ctx->opcode, 0, 9);
16504 switch (minor2) {
16505 case LBUE:
16506 mips32_op = OPC_LBUE;
16507 goto do_ld_lr;
16508 case LHUE:
16509 mips32_op = OPC_LHUE;
16510 goto do_ld_lr;
16511 case LWLE:
16512 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16513 mips32_op = OPC_LWLE;
16514 goto do_ld_lr;
16515 case LWRE:
16516 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16517 mips32_op = OPC_LWRE;
16518 goto do_ld_lr;
16519 case LBE:
16520 mips32_op = OPC_LBE;
16521 goto do_ld_lr;
16522 case LHE:
16523 mips32_op = OPC_LHE;
16524 goto do_ld_lr;
16525 case LLE:
16526 mips32_op = OPC_LLE;
16527 goto do_ld_lr;
16528 case LWE:
16529 mips32_op = OPC_LWE;
16530 goto do_ld_lr;
16532 break;
16533 case ST_EVA:
16534 if (!ctx->eva) {
16535 MIPS_INVAL("pool32c st-eva");
16536 generate_exception_end(ctx, EXCP_RI);
16537 break;
16539 check_cp0_enabled(ctx);
16541 minor2 = (ctx->opcode >> 9) & 0x7;
16542 offset = sextract32(ctx->opcode, 0, 9);
16543 switch (minor2) {
16544 case SWLE:
16545 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16546 mips32_op = OPC_SWLE;
16547 goto do_st_lr;
16548 case SWRE:
16549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16550 mips32_op = OPC_SWRE;
16551 goto do_st_lr;
16552 case PREFE:
16553 /* Treat as no-op */
16554 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16555 /* hint codes 24-31 are reserved and signal RI */
16556 generate_exception(ctx, EXCP_RI);
16558 break;
16559 case CACHEE:
16560 /* Treat as no-op */
16561 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16562 gen_cache_operation(ctx, rt, rs, offset);
16564 break;
16565 case SBE:
16566 mips32_op = OPC_SBE;
16567 goto do_st_lr;
16568 case SHE:
16569 mips32_op = OPC_SHE;
16570 goto do_st_lr;
16571 case SCE:
16572 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16573 break;
16574 case SWE:
16575 mips32_op = OPC_SWE;
16576 goto do_st_lr;
16578 break;
16579 case PREF:
16580 /* Treat as no-op */
16581 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16582 /* hint codes 24-31 are reserved and signal RI */
16583 generate_exception(ctx, EXCP_RI);
16585 break;
16586 default:
16587 MIPS_INVAL("pool32c");
16588 generate_exception_end(ctx, EXCP_RI);
16589 break;
16591 break;
16592 case ADDI32: /* AUI, LUI */
16593 if (ctx->insn_flags & ISA_MIPS32R6) {
16594 /* AUI, LUI */
16595 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16596 } else {
16597 /* ADDI32 */
16598 mips32_op = OPC_ADDI;
16599 goto do_addi;
16601 break;
16602 case ADDIU32:
16603 mips32_op = OPC_ADDIU;
16604 do_addi:
16605 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16606 break;
16608 /* Logical operations */
16609 case ORI32:
16610 mips32_op = OPC_ORI;
16611 goto do_logici;
16612 case XORI32:
16613 mips32_op = OPC_XORI;
16614 goto do_logici;
16615 case ANDI32:
16616 mips32_op = OPC_ANDI;
16617 do_logici:
16618 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16619 break;
16621 /* Set less than immediate */
16622 case SLTI32:
16623 mips32_op = OPC_SLTI;
16624 goto do_slti;
16625 case SLTIU32:
16626 mips32_op = OPC_SLTIU;
16627 do_slti:
16628 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16629 break;
16630 case JALX32:
16631 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16632 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16633 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16634 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16635 break;
16636 case JALS32: /* BOVC, BEQC, BEQZALC */
16637 if (ctx->insn_flags & ISA_MIPS32R6) {
16638 if (rs >= rt) {
16639 /* BOVC */
16640 mips32_op = OPC_BOVC;
16641 } else if (rs < rt && rs == 0) {
16642 /* BEQZALC */
16643 mips32_op = OPC_BEQZALC;
16644 } else {
16645 /* BEQC */
16646 mips32_op = OPC_BEQC;
16648 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16649 } else {
16650 /* JALS32 */
16651 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16652 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16653 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16655 break;
16656 case BEQ32: /* BC */
16657 if (ctx->insn_flags & ISA_MIPS32R6) {
16658 /* BC */
16659 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16660 sextract32(ctx->opcode << 1, 0, 27));
16661 } else {
16662 /* BEQ32 */
16663 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16665 break;
16666 case BNE32: /* BALC */
16667 if (ctx->insn_flags & ISA_MIPS32R6) {
16668 /* BALC */
16669 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16670 sextract32(ctx->opcode << 1, 0, 27));
16671 } else {
16672 /* BNE32 */
16673 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16675 break;
16676 case J32: /* BGTZC, BLTZC, BLTC */
16677 if (ctx->insn_flags & ISA_MIPS32R6) {
16678 if (rs == 0 && rt != 0) {
16679 /* BGTZC */
16680 mips32_op = OPC_BGTZC;
16681 } else if (rs != 0 && rt != 0 && rs == rt) {
16682 /* BLTZC */
16683 mips32_op = OPC_BLTZC;
16684 } else {
16685 /* BLTC */
16686 mips32_op = OPC_BLTC;
16688 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16689 } else {
16690 /* J32 */
16691 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16692 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16694 break;
16695 case JAL32: /* BLEZC, BGEZC, BGEC */
16696 if (ctx->insn_flags & ISA_MIPS32R6) {
16697 if (rs == 0 && rt != 0) {
16698 /* BLEZC */
16699 mips32_op = OPC_BLEZC;
16700 } else if (rs != 0 && rt != 0 && rs == rt) {
16701 /* BGEZC */
16702 mips32_op = OPC_BGEZC;
16703 } else {
16704 /* BGEC */
16705 mips32_op = OPC_BGEC;
16707 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16708 } else {
16709 /* JAL32 */
16710 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16711 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16712 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16714 break;
16715 /* Floating point (COP1) */
16716 case LWC132:
16717 mips32_op = OPC_LWC1;
16718 goto do_cop1;
16719 case LDC132:
16720 mips32_op = OPC_LDC1;
16721 goto do_cop1;
16722 case SWC132:
16723 mips32_op = OPC_SWC1;
16724 goto do_cop1;
16725 case SDC132:
16726 mips32_op = OPC_SDC1;
16727 do_cop1:
16728 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16729 break;
16730 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16731 if (ctx->insn_flags & ISA_MIPS32R6) {
16732 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16733 switch ((ctx->opcode >> 16) & 0x1f) {
16734 case ADDIUPC_00:
16735 case ADDIUPC_01:
16736 case ADDIUPC_02:
16737 case ADDIUPC_03:
16738 case ADDIUPC_04:
16739 case ADDIUPC_05:
16740 case ADDIUPC_06:
16741 case ADDIUPC_07:
16742 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16743 break;
16744 case AUIPC:
16745 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16746 break;
16747 case ALUIPC:
16748 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16749 break;
16750 case LWPC_08:
16751 case LWPC_09:
16752 case LWPC_0A:
16753 case LWPC_0B:
16754 case LWPC_0C:
16755 case LWPC_0D:
16756 case LWPC_0E:
16757 case LWPC_0F:
16758 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16759 break;
16760 default:
16761 generate_exception(ctx, EXCP_RI);
16762 break;
16764 } else {
16765 /* ADDIUPC */
16766 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16767 offset = SIMM(ctx->opcode, 0, 23) << 2;
16769 gen_addiupc(ctx, reg, offset, 0, 0);
16771 break;
16772 case BNVC: /* BNEC, BNEZALC */
16773 check_insn(ctx, ISA_MIPS32R6);
16774 if (rs >= rt) {
16775 /* BNVC */
16776 mips32_op = OPC_BNVC;
16777 } else if (rs < rt && rs == 0) {
16778 /* BNEZALC */
16779 mips32_op = OPC_BNEZALC;
16780 } else {
16781 /* BNEC */
16782 mips32_op = OPC_BNEC;
16784 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16785 break;
16786 case R6_BNEZC: /* JIALC */
16787 check_insn(ctx, ISA_MIPS32R6);
16788 if (rt != 0) {
16789 /* BNEZC */
16790 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16791 sextract32(ctx->opcode << 1, 0, 22));
16792 } else {
16793 /* JIALC */
16794 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16796 break;
16797 case R6_BEQZC: /* JIC */
16798 check_insn(ctx, ISA_MIPS32R6);
16799 if (rt != 0) {
16800 /* BEQZC */
16801 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16802 sextract32(ctx->opcode << 1, 0, 22));
16803 } else {
16804 /* JIC */
16805 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16807 break;
16808 case BLEZALC: /* BGEZALC, BGEUC */
16809 check_insn(ctx, ISA_MIPS32R6);
16810 if (rs == 0 && rt != 0) {
16811 /* BLEZALC */
16812 mips32_op = OPC_BLEZALC;
16813 } else if (rs != 0 && rt != 0 && rs == rt) {
16814 /* BGEZALC */
16815 mips32_op = OPC_BGEZALC;
16816 } else {
16817 /* BGEUC */
16818 mips32_op = OPC_BGEUC;
16820 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16821 break;
16822 case BGTZALC: /* BLTZALC, BLTUC */
16823 check_insn(ctx, ISA_MIPS32R6);
16824 if (rs == 0 && rt != 0) {
16825 /* BGTZALC */
16826 mips32_op = OPC_BGTZALC;
16827 } else if (rs != 0 && rt != 0 && rs == rt) {
16828 /* BLTZALC */
16829 mips32_op = OPC_BLTZALC;
16830 } else {
16831 /* BLTUC */
16832 mips32_op = OPC_BLTUC;
16834 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16835 break;
16836 /* Loads and stores */
16837 case LB32:
16838 mips32_op = OPC_LB;
16839 goto do_ld;
16840 case LBU32:
16841 mips32_op = OPC_LBU;
16842 goto do_ld;
16843 case LH32:
16844 mips32_op = OPC_LH;
16845 goto do_ld;
16846 case LHU32:
16847 mips32_op = OPC_LHU;
16848 goto do_ld;
16849 case LW32:
16850 mips32_op = OPC_LW;
16851 goto do_ld;
16852 #ifdef TARGET_MIPS64
16853 case LD32:
16854 check_insn(ctx, ISA_MIPS3);
16855 check_mips_64(ctx);
16856 mips32_op = OPC_LD;
16857 goto do_ld;
16858 case SD32:
16859 check_insn(ctx, ISA_MIPS3);
16860 check_mips_64(ctx);
16861 mips32_op = OPC_SD;
16862 goto do_st;
16863 #endif
16864 case SB32:
16865 mips32_op = OPC_SB;
16866 goto do_st;
16867 case SH32:
16868 mips32_op = OPC_SH;
16869 goto do_st;
16870 case SW32:
16871 mips32_op = OPC_SW;
16872 goto do_st;
16873 do_ld:
16874 gen_ld(ctx, mips32_op, rt, rs, imm);
16875 break;
16876 do_st:
16877 gen_st(ctx, mips32_op, rt, rs, imm);
16878 break;
16879 default:
16880 generate_exception_end(ctx, EXCP_RI);
16881 break;
16885 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16887 uint32_t op;
16889 /* make sure instructions are on a halfword boundary */
16890 if (ctx->base.pc_next & 0x1) {
16891 env->CP0_BadVAddr = ctx->base.pc_next;
16892 generate_exception_end(ctx, EXCP_AdEL);
16893 return 2;
16896 op = (ctx->opcode >> 10) & 0x3f;
16897 /* Enforce properly-sized instructions in a delay slot */
16898 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16899 switch (op & 0x7) { /* MSB-3..MSB-5 */
16900 case 0:
16901 /* POOL32A, POOL32B, POOL32I, POOL32C */
16902 case 4:
16903 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16904 case 5:
16905 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16906 case 6:
16907 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16908 case 7:
16909 /* LB32, LH32, LWC132, LDC132, LW32 */
16910 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16911 generate_exception_end(ctx, EXCP_RI);
16912 return 2;
16914 break;
16915 case 1:
16916 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16917 case 2:
16918 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16919 case 3:
16920 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16921 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16922 generate_exception_end(ctx, EXCP_RI);
16923 return 2;
16925 break;
16929 switch (op) {
16930 case POOL16A:
16932 int rd = mmreg(uMIPS_RD(ctx->opcode));
16933 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16934 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16935 uint32_t opc = 0;
16937 switch (ctx->opcode & 0x1) {
16938 case ADDU16:
16939 opc = OPC_ADDU;
16940 break;
16941 case SUBU16:
16942 opc = OPC_SUBU;
16943 break;
16945 if (ctx->insn_flags & ISA_MIPS32R6) {
16946 /* In the Release 6 the register number location in
16947 * the instruction encoding has changed.
16949 gen_arith(ctx, opc, rs1, rd, rs2);
16950 } else {
16951 gen_arith(ctx, opc, rd, rs1, rs2);
16954 break;
16955 case POOL16B:
16957 int rd = mmreg(uMIPS_RD(ctx->opcode));
16958 int rs = mmreg(uMIPS_RS(ctx->opcode));
16959 int amount = (ctx->opcode >> 1) & 0x7;
16960 uint32_t opc = 0;
16961 amount = amount == 0 ? 8 : amount;
16963 switch (ctx->opcode & 0x1) {
16964 case SLL16:
16965 opc = OPC_SLL;
16966 break;
16967 case SRL16:
16968 opc = OPC_SRL;
16969 break;
16972 gen_shift_imm(ctx, opc, rd, rs, amount);
16974 break;
16975 case POOL16C:
16976 if (ctx->insn_flags & ISA_MIPS32R6) {
16977 gen_pool16c_r6_insn(ctx);
16978 } else {
16979 gen_pool16c_insn(ctx);
16981 break;
16982 case LWGP16:
16984 int rd = mmreg(uMIPS_RD(ctx->opcode));
16985 int rb = 28; /* GP */
16986 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16988 gen_ld(ctx, OPC_LW, rd, rb, offset);
16990 break;
16991 case POOL16F:
16992 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16993 if (ctx->opcode & 1) {
16994 generate_exception_end(ctx, EXCP_RI);
16995 } else {
16996 /* MOVEP */
16997 int enc_dest = uMIPS_RD(ctx->opcode);
16998 int enc_rt = uMIPS_RS2(ctx->opcode);
16999 int enc_rs = uMIPS_RS1(ctx->opcode);
17000 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
17002 break;
17003 case LBU16:
17005 int rd = mmreg(uMIPS_RD(ctx->opcode));
17006 int rb = mmreg(uMIPS_RS(ctx->opcode));
17007 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17008 offset = (offset == 0xf ? -1 : offset);
17010 gen_ld(ctx, OPC_LBU, rd, rb, offset);
17012 break;
17013 case LHU16:
17015 int rd = mmreg(uMIPS_RD(ctx->opcode));
17016 int rb = mmreg(uMIPS_RS(ctx->opcode));
17017 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17019 gen_ld(ctx, OPC_LHU, rd, rb, offset);
17021 break;
17022 case LWSP16:
17024 int rd = (ctx->opcode >> 5) & 0x1f;
17025 int rb = 29; /* SP */
17026 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17028 gen_ld(ctx, OPC_LW, rd, rb, offset);
17030 break;
17031 case LW16:
17033 int rd = mmreg(uMIPS_RD(ctx->opcode));
17034 int rb = mmreg(uMIPS_RS(ctx->opcode));
17035 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17037 gen_ld(ctx, OPC_LW, rd, rb, offset);
17039 break;
17040 case SB16:
17042 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17043 int rb = mmreg(uMIPS_RS(ctx->opcode));
17044 int16_t offset = ZIMM(ctx->opcode, 0, 4);
17046 gen_st(ctx, OPC_SB, rd, rb, offset);
17048 break;
17049 case SH16:
17051 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17052 int rb = mmreg(uMIPS_RS(ctx->opcode));
17053 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
17055 gen_st(ctx, OPC_SH, rd, rb, offset);
17057 break;
17058 case SWSP16:
17060 int rd = (ctx->opcode >> 5) & 0x1f;
17061 int rb = 29; /* SP */
17062 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
17064 gen_st(ctx, OPC_SW, rd, rb, offset);
17066 break;
17067 case SW16:
17069 int rd = mmreg2(uMIPS_RD(ctx->opcode));
17070 int rb = mmreg(uMIPS_RS(ctx->opcode));
17071 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
17073 gen_st(ctx, OPC_SW, rd, rb, offset);
17075 break;
17076 case MOVE16:
17078 int rd = uMIPS_RD5(ctx->opcode);
17079 int rs = uMIPS_RS5(ctx->opcode);
17081 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
17083 break;
17084 case ANDI16:
17085 gen_andi16(ctx);
17086 break;
17087 case POOL16D:
17088 switch (ctx->opcode & 0x1) {
17089 case ADDIUS5:
17090 gen_addius5(ctx);
17091 break;
17092 case ADDIUSP:
17093 gen_addiusp(ctx);
17094 break;
17096 break;
17097 case POOL16E:
17098 switch (ctx->opcode & 0x1) {
17099 case ADDIUR2:
17100 gen_addiur2(ctx);
17101 break;
17102 case ADDIUR1SP:
17103 gen_addiur1sp(ctx);
17104 break;
17106 break;
17107 case B16: /* BC16 */
17108 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
17109 sextract32(ctx->opcode, 0, 10) << 1,
17110 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17111 break;
17112 case BNEZ16: /* BNEZC16 */
17113 case BEQZ16: /* BEQZC16 */
17114 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
17115 mmreg(uMIPS_RD(ctx->opcode)),
17116 0, sextract32(ctx->opcode, 0, 7) << 1,
17117 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
17119 break;
17120 case LI16:
17122 int reg = mmreg(uMIPS_RD(ctx->opcode));
17123 int imm = ZIMM(ctx->opcode, 0, 7);
17125 imm = (imm == 0x7f ? -1 : imm);
17126 tcg_gen_movi_tl(cpu_gpr[reg], imm);
17128 break;
17129 case RES_29:
17130 case RES_31:
17131 case RES_39:
17132 generate_exception_end(ctx, EXCP_RI);
17133 break;
17134 default:
17135 decode_micromips32_opc(env, ctx);
17136 return 4;
17139 return 2;
17144 * nanoMIPS opcodes
17148 /* MAJOR, P16, and P32 pools opcodes */
17149 enum {
17150 NM_P_ADDIU = 0x00,
17151 NM_ADDIUPC = 0x01,
17152 NM_MOVE_BALC = 0x02,
17153 NM_P16_MV = 0x04,
17154 NM_LW16 = 0x05,
17155 NM_BC16 = 0x06,
17156 NM_P16_SR = 0x07,
17158 NM_POOL32A = 0x08,
17159 NM_P_BAL = 0x0a,
17160 NM_P16_SHIFT = 0x0c,
17161 NM_LWSP16 = 0x0d,
17162 NM_BALC16 = 0x0e,
17163 NM_P16_4X4 = 0x0f,
17165 NM_P_GP_W = 0x10,
17166 NM_P_GP_BH = 0x11,
17167 NM_P_J = 0x12,
17168 NM_P16C = 0x14,
17169 NM_LWGP16 = 0x15,
17170 NM_P16_LB = 0x17,
17172 NM_P48I = 0x18,
17173 NM_P16_A1 = 0x1c,
17174 NM_LW4X4 = 0x1d,
17175 NM_P16_LH = 0x1f,
17177 NM_P_U12 = 0x20,
17178 NM_P_LS_U12 = 0x21,
17179 NM_P_BR1 = 0x22,
17180 NM_P16_A2 = 0x24,
17181 NM_SW16 = 0x25,
17182 NM_BEQZC16 = 0x26,
17184 NM_POOL32F = 0x28,
17185 NM_P_LS_S9 = 0x29,
17186 NM_P_BR2 = 0x2a,
17188 NM_P16_ADDU = 0x2c,
17189 NM_SWSP16 = 0x2d,
17190 NM_BNEZC16 = 0x2e,
17191 NM_MOVEP = 0x2f,
17193 NM_POOL32S = 0x30,
17194 NM_P_BRI = 0x32,
17195 NM_LI16 = 0x34,
17196 NM_SWGP16 = 0x35,
17197 NM_P16_BR = 0x36,
17199 NM_P_LUI = 0x38,
17200 NM_ANDI16 = 0x3c,
17201 NM_SW4X4 = 0x3d,
17202 NM_MOVEPREV = 0x3f,
17205 /* POOL32A instruction pool */
17206 enum {
17207 NM_POOL32A0 = 0x00,
17208 NM_SPECIAL2 = 0x01,
17209 NM_COP2_1 = 0x02,
17210 NM_UDI = 0x03,
17211 NM_POOL32A5 = 0x05,
17212 NM_POOL32A7 = 0x07,
17215 /* P.GP.W instruction pool */
17216 enum {
17217 NM_ADDIUGP_W = 0x00,
17218 NM_LWGP = 0x02,
17219 NM_SWGP = 0x03,
17222 /* P48I instruction pool */
17223 enum {
17224 NM_LI48 = 0x00,
17225 NM_ADDIU48 = 0x01,
17226 NM_ADDIUGP48 = 0x02,
17227 NM_ADDIUPC48 = 0x03,
17228 NM_LWPC48 = 0x0b,
17229 NM_SWPC48 = 0x0f,
17232 /* P.U12 instruction pool */
17233 enum {
17234 NM_ORI = 0x00,
17235 NM_XORI = 0x01,
17236 NM_ANDI = 0x02,
17237 NM_P_SR = 0x03,
17238 NM_SLTI = 0x04,
17239 NM_SLTIU = 0x05,
17240 NM_SEQI = 0x06,
17241 NM_ADDIUNEG = 0x08,
17242 NM_P_SHIFT = 0x0c,
17243 NM_P_ROTX = 0x0d,
17244 NM_P_INS = 0x0e,
17245 NM_P_EXT = 0x0f,
17248 /* POOL32F instruction pool */
17249 enum {
17250 NM_POOL32F_0 = 0x00,
17251 NM_POOL32F_3 = 0x03,
17252 NM_POOL32F_5 = 0x05,
17255 /* POOL32S instruction pool */
17256 enum {
17257 NM_POOL32S_0 = 0x00,
17258 NM_POOL32S_4 = 0x04,
17261 /* P.LUI instruction pool */
17262 enum {
17263 NM_LUI = 0x00,
17264 NM_ALUIPC = 0x01,
17267 /* P.GP.BH instruction pool */
17268 enum {
17269 NM_LBGP = 0x00,
17270 NM_SBGP = 0x01,
17271 NM_LBUGP = 0x02,
17272 NM_ADDIUGP_B = 0x03,
17273 NM_P_GP_LH = 0x04,
17274 NM_P_GP_SH = 0x05,
17275 NM_P_GP_CP1 = 0x06,
17278 /* P.LS.U12 instruction pool */
17279 enum {
17280 NM_LB = 0x00,
17281 NM_SB = 0x01,
17282 NM_LBU = 0x02,
17283 NM_P_PREFU12 = 0x03,
17284 NM_LH = 0x04,
17285 NM_SH = 0x05,
17286 NM_LHU = 0x06,
17287 NM_LWU = 0x07,
17288 NM_LW = 0x08,
17289 NM_SW = 0x09,
17290 NM_LWC1 = 0x0a,
17291 NM_SWC1 = 0x0b,
17292 NM_LDC1 = 0x0e,
17293 NM_SDC1 = 0x0f,
17296 /* P.LS.S9 instruction pool */
17297 enum {
17298 NM_P_LS_S0 = 0x00,
17299 NM_P_LS_S1 = 0x01,
17300 NM_P_LS_E0 = 0x02,
17301 NM_P_LS_WM = 0x04,
17302 NM_P_LS_UAWM = 0x05,
17305 /* P.BAL instruction pool */
17306 enum {
17307 NM_BC = 0x00,
17308 NM_BALC = 0x01,
17311 /* P.J instruction pool */
17312 enum {
17313 NM_JALRC = 0x00,
17314 NM_JALRC_HB = 0x01,
17315 NM_P_BALRSC = 0x08,
17318 /* P.BR1 instruction pool */
17319 enum {
17320 NM_BEQC = 0x00,
17321 NM_P_BR3A = 0x01,
17322 NM_BGEC = 0x02,
17323 NM_BGEUC = 0x03,
17326 /* P.BR2 instruction pool */
17327 enum {
17328 NM_BNEC = 0x00,
17329 NM_BLTC = 0x02,
17330 NM_BLTUC = 0x03,
17333 /* P.BRI instruction pool */
17334 enum {
17335 NM_BEQIC = 0x00,
17336 NM_BBEQZC = 0x01,
17337 NM_BGEIC = 0x02,
17338 NM_BGEIUC = 0x03,
17339 NM_BNEIC = 0x04,
17340 NM_BBNEZC = 0x05,
17341 NM_BLTIC = 0x06,
17342 NM_BLTIUC = 0x07,
17345 /* P16.SHIFT instruction pool */
17346 enum {
17347 NM_SLL16 = 0x00,
17348 NM_SRL16 = 0x01,
17351 /* POOL16C instruction pool */
17352 enum {
17353 NM_POOL16C_0 = 0x00,
17354 NM_LWXS16 = 0x01,
17357 /* P16.A1 instruction pool */
17358 enum {
17359 NM_ADDIUR1SP = 0x01,
17362 /* P16.A2 instruction pool */
17363 enum {
17364 NM_ADDIUR2 = 0x00,
17365 NM_P_ADDIURS5 = 0x01,
17368 /* P16.ADDU instruction pool */
17369 enum {
17370 NM_ADDU16 = 0x00,
17371 NM_SUBU16 = 0x01,
17374 /* P16.SR instruction pool */
17375 enum {
17376 NM_SAVE16 = 0x00,
17377 NM_RESTORE_JRC16 = 0x01,
17380 /* P16.4X4 instruction pool */
17381 enum {
17382 NM_ADDU4X4 = 0x00,
17383 NM_MUL4X4 = 0x01,
17386 /* P16.LB instruction pool */
17387 enum {
17388 NM_LB16 = 0x00,
17389 NM_SB16 = 0x01,
17390 NM_LBU16 = 0x02,
17393 /* P16.LH instruction pool */
17394 enum {
17395 NM_LH16 = 0x00,
17396 NM_SH16 = 0x01,
17397 NM_LHU16 = 0x02,
17400 /* P.RI instruction pool */
17401 enum {
17402 NM_SIGRIE = 0x00,
17403 NM_P_SYSCALL = 0x01,
17404 NM_BREAK = 0x02,
17405 NM_SDBBP = 0x03,
17408 /* POOL32A0 instruction pool */
17409 enum {
17410 NM_P_TRAP = 0x00,
17411 NM_SEB = 0x01,
17412 NM_SLLV = 0x02,
17413 NM_MUL = 0x03,
17414 NM_MFC0 = 0x06,
17415 NM_MFHC0 = 0x07,
17416 NM_SEH = 0x09,
17417 NM_SRLV = 0x0a,
17418 NM_MUH = 0x0b,
17419 NM_MTC0 = 0x0e,
17420 NM_MTHC0 = 0x0f,
17421 NM_SRAV = 0x12,
17422 NM_MULU = 0x13,
17423 NM_ROTRV = 0x1a,
17424 NM_MUHU = 0x1b,
17425 NM_ADD = 0x22,
17426 NM_DIV = 0x23,
17427 NM_ADDU = 0x2a,
17428 NM_MOD = 0x2b,
17429 NM_SUB = 0x32,
17430 NM_DIVU = 0x33,
17431 NM_RDHWR = 0x38,
17432 NM_SUBU = 0x3a,
17433 NM_MODU = 0x3b,
17434 NM_P_CMOVE = 0x42,
17435 NM_FORK = 0x45,
17436 NM_MFTR = 0x46,
17437 NM_MFHTR = 0x47,
17438 NM_AND = 0x4a,
17439 NM_YIELD = 0x4d,
17440 NM_MTTR = 0x4e,
17441 NM_MTHTR = 0x4f,
17442 NM_OR = 0x52,
17443 NM_D_E_MT_VPE = 0x56,
17444 NM_NOR = 0x5a,
17445 NM_XOR = 0x62,
17446 NM_SLT = 0x6a,
17447 NM_P_SLTU = 0x72,
17448 NM_SOV = 0x7a,
17451 /* POOL32A5 instruction pool */
17452 enum {
17453 NM_CMP_EQ_PH = 0x00,
17454 NM_CMP_LT_PH = 0x08,
17455 NM_CMP_LE_PH = 0x10,
17456 NM_CMPGU_EQ_QB = 0x18,
17457 NM_CMPGU_LT_QB = 0x20,
17458 NM_CMPGU_LE_QB = 0x28,
17459 NM_CMPGDU_EQ_QB = 0x30,
17460 NM_CMPGDU_LT_QB = 0x38,
17461 NM_CMPGDU_LE_QB = 0x40,
17462 NM_CMPU_EQ_QB = 0x48,
17463 NM_CMPU_LT_QB = 0x50,
17464 NM_CMPU_LE_QB = 0x58,
17465 NM_ADDQ_S_W = 0x60,
17466 NM_SUBQ_S_W = 0x68,
17467 NM_ADDSC = 0x70,
17468 NM_ADDWC = 0x78,
17470 NM_ADDQ_S_PH = 0x01,
17471 NM_ADDQH_R_PH = 0x09,
17472 NM_ADDQH_R_W = 0x11,
17473 NM_ADDU_S_QB = 0x19,
17474 NM_ADDU_S_PH = 0x21,
17475 NM_ADDUH_R_QB = 0x29,
17476 NM_SHRAV_R_PH = 0x31,
17477 NM_SHRAV_R_QB = 0x39,
17478 NM_SUBQ_S_PH = 0x41,
17479 NM_SUBQH_R_PH = 0x49,
17480 NM_SUBQH_R_W = 0x51,
17481 NM_SUBU_S_QB = 0x59,
17482 NM_SUBU_S_PH = 0x61,
17483 NM_SUBUH_R_QB = 0x69,
17484 NM_SHLLV_S_PH = 0x71,
17485 NM_PRECR_SRA_R_PH_W = 0x79,
17487 NM_MULEU_S_PH_QBL = 0x12,
17488 NM_MULEU_S_PH_QBR = 0x1a,
17489 NM_MULQ_RS_PH = 0x22,
17490 NM_MULQ_S_PH = 0x2a,
17491 NM_MULQ_RS_W = 0x32,
17492 NM_MULQ_S_W = 0x3a,
17493 NM_APPEND = 0x42,
17494 NM_MODSUB = 0x52,
17495 NM_SHRAV_R_W = 0x5a,
17496 NM_SHRLV_PH = 0x62,
17497 NM_SHRLV_QB = 0x6a,
17498 NM_SHLLV_QB = 0x72,
17499 NM_SHLLV_S_W = 0x7a,
17501 NM_SHILO = 0x03,
17503 NM_MULEQ_S_W_PHL = 0x04,
17504 NM_MULEQ_S_W_PHR = 0x0c,
17506 NM_MUL_S_PH = 0x05,
17507 NM_PRECR_QB_PH = 0x0d,
17508 NM_PRECRQ_QB_PH = 0x15,
17509 NM_PRECRQ_PH_W = 0x1d,
17510 NM_PRECRQ_RS_PH_W = 0x25,
17511 NM_PRECRQU_S_QB_PH = 0x2d,
17512 NM_PACKRL_PH = 0x35,
17513 NM_PICK_QB = 0x3d,
17514 NM_PICK_PH = 0x45,
17516 NM_SHRA_R_W = 0x5e,
17517 NM_SHRA_R_PH = 0x66,
17518 NM_SHLL_S_PH = 0x76,
17519 NM_SHLL_S_W = 0x7e,
17521 NM_REPL_PH = 0x07
17524 /* POOL32A7 instruction pool */
17525 enum {
17526 NM_P_LSX = 0x00,
17527 NM_LSA = 0x01,
17528 NM_EXTW = 0x03,
17529 NM_POOL32AXF = 0x07,
17532 /* P.SR instruction pool */
17533 enum {
17534 NM_PP_SR = 0x00,
17535 NM_P_SR_F = 0x01,
17538 /* P.SHIFT instruction pool */
17539 enum {
17540 NM_P_SLL = 0x00,
17541 NM_SRL = 0x02,
17542 NM_SRA = 0x04,
17543 NM_ROTR = 0x06,
17546 /* P.ROTX instruction pool */
17547 enum {
17548 NM_ROTX = 0x00,
17551 /* P.INS instruction pool */
17552 enum {
17553 NM_INS = 0x00,
17556 /* P.EXT instruction pool */
17557 enum {
17558 NM_EXT = 0x00,
17561 /* POOL32F_0 (fmt) instruction pool */
17562 enum {
17563 NM_RINT_S = 0x04,
17564 NM_RINT_D = 0x44,
17565 NM_ADD_S = 0x06,
17566 NM_SELEQZ_S = 0x07,
17567 NM_SELEQZ_D = 0x47,
17568 NM_CLASS_S = 0x0c,
17569 NM_CLASS_D = 0x4c,
17570 NM_SUB_S = 0x0e,
17571 NM_SELNEZ_S = 0x0f,
17572 NM_SELNEZ_D = 0x4f,
17573 NM_MUL_S = 0x16,
17574 NM_SEL_S = 0x17,
17575 NM_SEL_D = 0x57,
17576 NM_DIV_S = 0x1e,
17577 NM_ADD_D = 0x26,
17578 NM_SUB_D = 0x2e,
17579 NM_MUL_D = 0x36,
17580 NM_MADDF_S = 0x37,
17581 NM_MADDF_D = 0x77,
17582 NM_DIV_D = 0x3e,
17583 NM_MSUBF_S = 0x3f,
17584 NM_MSUBF_D = 0x7f,
17587 /* POOL32F_3 instruction pool */
17588 enum {
17589 NM_MIN_FMT = 0x00,
17590 NM_MAX_FMT = 0x01,
17591 NM_MINA_FMT = 0x04,
17592 NM_MAXA_FMT = 0x05,
17593 NM_POOL32FXF = 0x07,
17596 /* POOL32F_5 instruction pool */
17597 enum {
17598 NM_CMP_CONDN_S = 0x00,
17599 NM_CMP_CONDN_D = 0x02,
17602 /* P.GP.LH instruction pool */
17603 enum {
17604 NM_LHGP = 0x00,
17605 NM_LHUGP = 0x01,
17608 /* P.GP.SH instruction pool */
17609 enum {
17610 NM_SHGP = 0x00,
17613 /* P.GP.CP1 instruction pool */
17614 enum {
17615 NM_LWC1GP = 0x00,
17616 NM_SWC1GP = 0x01,
17617 NM_LDC1GP = 0x02,
17618 NM_SDC1GP = 0x03,
17621 /* P.LS.S0 instruction pool */
17622 enum {
17623 NM_LBS9 = 0x00,
17624 NM_LHS9 = 0x04,
17625 NM_LWS9 = 0x08,
17626 NM_LDS9 = 0x0c,
17628 NM_SBS9 = 0x01,
17629 NM_SHS9 = 0x05,
17630 NM_SWS9 = 0x09,
17631 NM_SDS9 = 0x0d,
17633 NM_LBUS9 = 0x02,
17634 NM_LHUS9 = 0x06,
17635 NM_LWC1S9 = 0x0a,
17636 NM_LDC1S9 = 0x0e,
17638 NM_P_PREFS9 = 0x03,
17639 NM_LWUS9 = 0x07,
17640 NM_SWC1S9 = 0x0b,
17641 NM_SDC1S9 = 0x0f,
17644 /* P.LS.S1 instruction pool */
17645 enum {
17646 NM_ASET_ACLR = 0x02,
17647 NM_UALH = 0x04,
17648 NM_UASH = 0x05,
17649 NM_CACHE = 0x07,
17650 NM_P_LL = 0x0a,
17651 NM_P_SC = 0x0b,
17654 /* P.LS.E0 instruction pool */
17655 enum {
17656 NM_LBE = 0x00,
17657 NM_SBE = 0x01,
17658 NM_LBUE = 0x02,
17659 NM_P_PREFE = 0x03,
17660 NM_LHE = 0x04,
17661 NM_SHE = 0x05,
17662 NM_LHUE = 0x06,
17663 NM_CACHEE = 0x07,
17664 NM_LWE = 0x08,
17665 NM_SWE = 0x09,
17666 NM_P_LLE = 0x0a,
17667 NM_P_SCE = 0x0b,
17670 /* P.PREFE instruction pool */
17671 enum {
17672 NM_SYNCIE = 0x00,
17673 NM_PREFE = 0x01,
17676 /* P.LLE instruction pool */
17677 enum {
17678 NM_LLE = 0x00,
17679 NM_LLWPE = 0x01,
17682 /* P.SCE instruction pool */
17683 enum {
17684 NM_SCE = 0x00,
17685 NM_SCWPE = 0x01,
17688 /* P.LS.WM instruction pool */
17689 enum {
17690 NM_LWM = 0x00,
17691 NM_SWM = 0x01,
17694 /* P.LS.UAWM instruction pool */
17695 enum {
17696 NM_UALWM = 0x00,
17697 NM_UASWM = 0x01,
17700 /* P.BR3A instruction pool */
17701 enum {
17702 NM_BC1EQZC = 0x00,
17703 NM_BC1NEZC = 0x01,
17704 NM_BC2EQZC = 0x02,
17705 NM_BC2NEZC = 0x03,
17706 NM_BPOSGE32C = 0x04,
17709 /* P16.RI instruction pool */
17710 enum {
17711 NM_P16_SYSCALL = 0x01,
17712 NM_BREAK16 = 0x02,
17713 NM_SDBBP16 = 0x03,
17716 /* POOL16C_0 instruction pool */
17717 enum {
17718 NM_POOL16C_00 = 0x00,
17721 /* P16.JRC instruction pool */
17722 enum {
17723 NM_JRC = 0x00,
17724 NM_JALRC16 = 0x01,
17727 /* P.SYSCALL instruction pool */
17728 enum {
17729 NM_SYSCALL = 0x00,
17730 NM_HYPCALL = 0x01,
17733 /* P.TRAP instruction pool */
17734 enum {
17735 NM_TEQ = 0x00,
17736 NM_TNE = 0x01,
17739 /* P.CMOVE instruction pool */
17740 enum {
17741 NM_MOVZ = 0x00,
17742 NM_MOVN = 0x01,
17745 /* POOL32Axf instruction pool */
17746 enum {
17747 NM_POOL32AXF_1 = 0x01,
17748 NM_POOL32AXF_2 = 0x02,
17749 NM_POOL32AXF_4 = 0x04,
17750 NM_POOL32AXF_5 = 0x05,
17751 NM_POOL32AXF_7 = 0x07,
17754 /* POOL32Axf_1 instruction pool */
17755 enum {
17756 NM_POOL32AXF_1_0 = 0x00,
17757 NM_POOL32AXF_1_1 = 0x01,
17758 NM_POOL32AXF_1_3 = 0x03,
17759 NM_POOL32AXF_1_4 = 0x04,
17760 NM_POOL32AXF_1_5 = 0x05,
17761 NM_POOL32AXF_1_7 = 0x07,
17764 /* POOL32Axf_2 instruction pool */
17765 enum {
17766 NM_POOL32AXF_2_0_7 = 0x00,
17767 NM_POOL32AXF_2_8_15 = 0x01,
17768 NM_POOL32AXF_2_16_23 = 0x02,
17769 NM_POOL32AXF_2_24_31 = 0x03,
17772 /* POOL32Axf_7 instruction pool */
17773 enum {
17774 NM_SHRA_R_QB = 0x0,
17775 NM_SHRL_PH = 0x1,
17776 NM_REPL_QB = 0x2,
17779 /* POOL32Axf_1_0 instruction pool */
17780 enum {
17781 NM_MFHI = 0x0,
17782 NM_MFLO = 0x1,
17783 NM_MTHI = 0x2,
17784 NM_MTLO = 0x3,
17787 /* POOL32Axf_1_1 instruction pool */
17788 enum {
17789 NM_MTHLIP = 0x0,
17790 NM_SHILOV = 0x1,
17793 /* POOL32Axf_1_3 instruction pool */
17794 enum {
17795 NM_RDDSP = 0x0,
17796 NM_WRDSP = 0x1,
17797 NM_EXTP = 0x2,
17798 NM_EXTPDP = 0x3,
17801 /* POOL32Axf_1_4 instruction pool */
17802 enum {
17803 NM_SHLL_QB = 0x0,
17804 NM_SHRL_QB = 0x1,
17807 /* POOL32Axf_1_5 instruction pool */
17808 enum {
17809 NM_MAQ_S_W_PHR = 0x0,
17810 NM_MAQ_S_W_PHL = 0x1,
17811 NM_MAQ_SA_W_PHR = 0x2,
17812 NM_MAQ_SA_W_PHL = 0x3,
17815 /* POOL32Axf_1_7 instruction pool */
17816 enum {
17817 NM_EXTR_W = 0x0,
17818 NM_EXTR_R_W = 0x1,
17819 NM_EXTR_RS_W = 0x2,
17820 NM_EXTR_S_H = 0x3,
17823 /* POOL32Axf_2_0_7 instruction pool */
17824 enum {
17825 NM_DPA_W_PH = 0x0,
17826 NM_DPAQ_S_W_PH = 0x1,
17827 NM_DPS_W_PH = 0x2,
17828 NM_DPSQ_S_W_PH = 0x3,
17829 NM_BALIGN = 0x4,
17830 NM_MADD = 0x5,
17831 NM_MULT = 0x6,
17832 NM_EXTRV_W = 0x7,
17835 /* POOL32Axf_2_8_15 instruction pool */
17836 enum {
17837 NM_DPAX_W_PH = 0x0,
17838 NM_DPAQ_SA_L_W = 0x1,
17839 NM_DPSX_W_PH = 0x2,
17840 NM_DPSQ_SA_L_W = 0x3,
17841 NM_MADDU = 0x5,
17842 NM_MULTU = 0x6,
17843 NM_EXTRV_R_W = 0x7,
17846 /* POOL32Axf_2_16_23 instruction pool */
17847 enum {
17848 NM_DPAU_H_QBL = 0x0,
17849 NM_DPAQX_S_W_PH = 0x1,
17850 NM_DPSU_H_QBL = 0x2,
17851 NM_DPSQX_S_W_PH = 0x3,
17852 NM_EXTPV = 0x4,
17853 NM_MSUB = 0x5,
17854 NM_MULSA_W_PH = 0x6,
17855 NM_EXTRV_RS_W = 0x7,
17858 /* POOL32Axf_2_24_31 instruction pool */
17859 enum {
17860 NM_DPAU_H_QBR = 0x0,
17861 NM_DPAQX_SA_W_PH = 0x1,
17862 NM_DPSU_H_QBR = 0x2,
17863 NM_DPSQX_SA_W_PH = 0x3,
17864 NM_EXTPDPV = 0x4,
17865 NM_MSUBU = 0x5,
17866 NM_MULSAQ_S_W_PH = 0x6,
17867 NM_EXTRV_S_H = 0x7,
17870 /* POOL32Axf_{4, 5} instruction pool */
17871 enum {
17872 NM_CLO = 0x25,
17873 NM_CLZ = 0x2d,
17875 NM_TLBP = 0x01,
17876 NM_TLBR = 0x09,
17877 NM_TLBWI = 0x11,
17878 NM_TLBWR = 0x19,
17879 NM_TLBINV = 0x03,
17880 NM_TLBINVF = 0x0b,
17881 NM_DI = 0x23,
17882 NM_EI = 0x2b,
17883 NM_RDPGPR = 0x70,
17884 NM_WRPGPR = 0x78,
17885 NM_WAIT = 0x61,
17886 NM_DERET = 0x71,
17887 NM_ERETX = 0x79,
17889 /* nanoMIPS DSP instructions */
17890 NM_ABSQ_S_QB = 0x00,
17891 NM_ABSQ_S_PH = 0x08,
17892 NM_ABSQ_S_W = 0x10,
17893 NM_PRECEQ_W_PHL = 0x28,
17894 NM_PRECEQ_W_PHR = 0x30,
17895 NM_PRECEQU_PH_QBL = 0x38,
17896 NM_PRECEQU_PH_QBR = 0x48,
17897 NM_PRECEU_PH_QBL = 0x58,
17898 NM_PRECEU_PH_QBR = 0x68,
17899 NM_PRECEQU_PH_QBLA = 0x39,
17900 NM_PRECEQU_PH_QBRA = 0x49,
17901 NM_PRECEU_PH_QBLA = 0x59,
17902 NM_PRECEU_PH_QBRA = 0x69,
17903 NM_REPLV_PH = 0x01,
17904 NM_REPLV_QB = 0x09,
17905 NM_BITREV = 0x18,
17906 NM_INSV = 0x20,
17907 NM_RADDU_W_QB = 0x78,
17909 NM_BITSWAP = 0x05,
17910 NM_WSBH = 0x3d,
17913 /* PP.SR instruction pool */
17914 enum {
17915 NM_SAVE = 0x00,
17916 NM_RESTORE = 0x02,
17917 NM_RESTORE_JRC = 0x03,
17920 /* P.SR.F instruction pool */
17921 enum {
17922 NM_SAVEF = 0x00,
17923 NM_RESTOREF = 0x01,
17926 /* P16.SYSCALL instruction pool */
17927 enum {
17928 NM_SYSCALL16 = 0x00,
17929 NM_HYPCALL16 = 0x01,
17932 /* POOL16C_00 instruction pool */
17933 enum {
17934 NM_NOT16 = 0x00,
17935 NM_XOR16 = 0x01,
17936 NM_AND16 = 0x02,
17937 NM_OR16 = 0x03,
17940 /* PP.LSX and PP.LSXS instruction pool */
17941 enum {
17942 NM_LBX = 0x00,
17943 NM_LHX = 0x04,
17944 NM_LWX = 0x08,
17945 NM_LDX = 0x0c,
17947 NM_SBX = 0x01,
17948 NM_SHX = 0x05,
17949 NM_SWX = 0x09,
17950 NM_SDX = 0x0d,
17952 NM_LBUX = 0x02,
17953 NM_LHUX = 0x06,
17954 NM_LWC1X = 0x0a,
17955 NM_LDC1X = 0x0e,
17957 NM_LWUX = 0x07,
17958 NM_SWC1X = 0x0b,
17959 NM_SDC1X = 0x0f,
17961 NM_LHXS = 0x04,
17962 NM_LWXS = 0x08,
17963 NM_LDXS = 0x0c,
17965 NM_SHXS = 0x05,
17966 NM_SWXS = 0x09,
17967 NM_SDXS = 0x0d,
17969 NM_LHUXS = 0x06,
17970 NM_LWC1XS = 0x0a,
17971 NM_LDC1XS = 0x0e,
17973 NM_LWUXS = 0x07,
17974 NM_SWC1XS = 0x0b,
17975 NM_SDC1XS = 0x0f,
17978 /* ERETx instruction pool */
17979 enum {
17980 NM_ERET = 0x00,
17981 NM_ERETNC = 0x01,
17984 /* POOL32FxF_{0, 1} insturction pool */
17985 enum {
17986 NM_CFC1 = 0x40,
17987 NM_CTC1 = 0x60,
17988 NM_MFC1 = 0x80,
17989 NM_MTC1 = 0xa0,
17990 NM_MFHC1 = 0xc0,
17991 NM_MTHC1 = 0xe0,
17993 NM_CVT_S_PL = 0x84,
17994 NM_CVT_S_PU = 0xa4,
17996 NM_CVT_L_S = 0x004,
17997 NM_CVT_L_D = 0x104,
17998 NM_CVT_W_S = 0x024,
17999 NM_CVT_W_D = 0x124,
18001 NM_RSQRT_S = 0x008,
18002 NM_RSQRT_D = 0x108,
18004 NM_SQRT_S = 0x028,
18005 NM_SQRT_D = 0x128,
18007 NM_RECIP_S = 0x048,
18008 NM_RECIP_D = 0x148,
18010 NM_FLOOR_L_S = 0x00c,
18011 NM_FLOOR_L_D = 0x10c,
18013 NM_FLOOR_W_S = 0x02c,
18014 NM_FLOOR_W_D = 0x12c,
18016 NM_CEIL_L_S = 0x04c,
18017 NM_CEIL_L_D = 0x14c,
18018 NM_CEIL_W_S = 0x06c,
18019 NM_CEIL_W_D = 0x16c,
18020 NM_TRUNC_L_S = 0x08c,
18021 NM_TRUNC_L_D = 0x18c,
18022 NM_TRUNC_W_S = 0x0ac,
18023 NM_TRUNC_W_D = 0x1ac,
18024 NM_ROUND_L_S = 0x0cc,
18025 NM_ROUND_L_D = 0x1cc,
18026 NM_ROUND_W_S = 0x0ec,
18027 NM_ROUND_W_D = 0x1ec,
18029 NM_MOV_S = 0x01,
18030 NM_MOV_D = 0x81,
18031 NM_ABS_S = 0x0d,
18032 NM_ABS_D = 0x8d,
18033 NM_NEG_S = 0x2d,
18034 NM_NEG_D = 0xad,
18035 NM_CVT_D_S = 0x04d,
18036 NM_CVT_D_W = 0x0cd,
18037 NM_CVT_D_L = 0x14d,
18038 NM_CVT_S_D = 0x06d,
18039 NM_CVT_S_W = 0x0ed,
18040 NM_CVT_S_L = 0x16d,
18043 /* P.LL instruction pool */
18044 enum {
18045 NM_LL = 0x00,
18046 NM_LLWP = 0x01,
18049 /* P.SC instruction pool */
18050 enum {
18051 NM_SC = 0x00,
18052 NM_SCWP = 0x01,
18055 /* P.DVP instruction pool */
18056 enum {
18057 NM_DVP = 0x00,
18058 NM_EVP = 0x01,
18064 * nanoMIPS decoding engine
18069 /* extraction utilities */
18071 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18072 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18073 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18074 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18075 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18076 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18078 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
18079 static inline int decode_gpr_gpr3(int r)
18081 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
18083 return map[r & 0x7];
18086 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
18087 static inline int decode_gpr_gpr3_src_store(int r)
18089 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
18091 return map[r & 0x7];
18094 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
18095 static inline int decode_gpr_gpr4(int r)
18097 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
18098 16, 17, 18, 19, 20, 21, 22, 23 };
18100 return map[r & 0xf];
18103 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
18104 static inline int decode_gpr_gpr4_zero(int r)
18106 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
18107 16, 17, 18, 19, 20, 21, 22, 23 };
18109 return map[r & 0xf];
18113 /* extraction utilities */
18115 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
18116 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
18117 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
18118 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
18119 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
18120 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
18123 static void gen_adjust_sp(DisasContext *ctx, int u)
18125 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
18128 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
18129 uint8_t gp, uint16_t u)
18131 int counter = 0;
18132 TCGv va = tcg_temp_new();
18133 TCGv t0 = tcg_temp_new();
18135 while (counter != count) {
18136 bool use_gp = gp && (counter == count - 1);
18137 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18138 int this_offset = -((counter + 1) << 2);
18139 gen_base_offset_addr(ctx, va, 29, this_offset);
18140 gen_load_gpr(t0, this_rt);
18141 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
18142 (MO_TEUL | ctx->default_tcg_memop_mask));
18143 counter++;
18146 /* adjust stack pointer */
18147 gen_adjust_sp(ctx, -u);
18149 tcg_temp_free(t0);
18150 tcg_temp_free(va);
18153 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
18154 uint8_t gp, uint16_t u)
18156 int counter = 0;
18157 TCGv va = tcg_temp_new();
18158 TCGv t0 = tcg_temp_new();
18160 while (counter != count) {
18161 bool use_gp = gp && (counter == count - 1);
18162 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
18163 int this_offset = u - ((counter + 1) << 2);
18164 gen_base_offset_addr(ctx, va, 29, this_offset);
18165 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
18166 ctx->default_tcg_memop_mask);
18167 tcg_gen_ext32s_tl(t0, t0);
18168 gen_store_gpr(t0, this_rt);
18169 counter++;
18172 /* adjust stack pointer */
18173 gen_adjust_sp(ctx, u);
18175 tcg_temp_free(t0);
18176 tcg_temp_free(va);
18179 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
18181 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
18182 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
18184 switch (extract32(ctx->opcode, 2, 2)) {
18185 case NM_NOT16:
18186 gen_logic(ctx, OPC_NOR, rt, rs, 0);
18187 break;
18188 case NM_AND16:
18189 gen_logic(ctx, OPC_AND, rt, rt, rs);
18190 break;
18191 case NM_XOR16:
18192 gen_logic(ctx, OPC_XOR, rt, rt, rs);
18193 break;
18194 case NM_OR16:
18195 gen_logic(ctx, OPC_OR, rt, rt, rs);
18196 break;
18200 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18202 int rt = extract32(ctx->opcode, 21, 5);
18203 int rs = extract32(ctx->opcode, 16, 5);
18204 int rd = extract32(ctx->opcode, 11, 5);
18206 switch (extract32(ctx->opcode, 3, 7)) {
18207 case NM_P_TRAP:
18208 switch (extract32(ctx->opcode, 10, 1)) {
18209 case NM_TEQ:
18210 check_nms(ctx);
18211 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
18212 break;
18213 case NM_TNE:
18214 check_nms(ctx);
18215 gen_trap(ctx, OPC_TNE, rs, rt, -1);
18216 break;
18218 break;
18219 case NM_RDHWR:
18220 check_nms(ctx);
18221 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
18222 break;
18223 case NM_SEB:
18224 check_nms(ctx);
18225 gen_bshfl(ctx, OPC_SEB, rs, rt);
18226 break;
18227 case NM_SEH:
18228 gen_bshfl(ctx, OPC_SEH, rs, rt);
18229 break;
18230 case NM_SLLV:
18231 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
18232 break;
18233 case NM_SRLV:
18234 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
18235 break;
18236 case NM_SRAV:
18237 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
18238 break;
18239 case NM_ROTRV:
18240 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
18241 break;
18242 case NM_ADD:
18243 gen_arith(ctx, OPC_ADD, rd, rs, rt);
18244 break;
18245 case NM_ADDU:
18246 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
18247 break;
18248 case NM_SUB:
18249 check_nms(ctx);
18250 gen_arith(ctx, OPC_SUB, rd, rs, rt);
18251 break;
18252 case NM_SUBU:
18253 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
18254 break;
18255 case NM_P_CMOVE:
18256 switch (extract32(ctx->opcode, 10, 1)) {
18257 case NM_MOVZ:
18258 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
18259 break;
18260 case NM_MOVN:
18261 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
18262 break;
18264 break;
18265 case NM_AND:
18266 gen_logic(ctx, OPC_AND, rd, rs, rt);
18267 break;
18268 case NM_OR:
18269 gen_logic(ctx, OPC_OR, rd, rs, rt);
18270 break;
18271 case NM_NOR:
18272 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18273 break;
18274 case NM_XOR:
18275 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18276 break;
18277 case NM_SLT:
18278 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18279 break;
18280 case NM_P_SLTU:
18281 if (rd == 0) {
18282 /* P_DVP */
18283 #ifndef CONFIG_USER_ONLY
18284 TCGv t0 = tcg_temp_new();
18285 switch (extract32(ctx->opcode, 10, 1)) {
18286 case NM_DVP:
18287 if (ctx->vp) {
18288 check_cp0_enabled(ctx);
18289 gen_helper_dvp(t0, cpu_env);
18290 gen_store_gpr(t0, rt);
18292 break;
18293 case NM_EVP:
18294 if (ctx->vp) {
18295 check_cp0_enabled(ctx);
18296 gen_helper_evp(t0, cpu_env);
18297 gen_store_gpr(t0, rt);
18299 break;
18301 tcg_temp_free(t0);
18302 #endif
18303 } else {
18304 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18306 break;
18307 case NM_SOV:
18309 TCGv t0 = tcg_temp_new();
18310 TCGv t1 = tcg_temp_new();
18311 TCGv t2 = tcg_temp_new();
18313 gen_load_gpr(t1, rs);
18314 gen_load_gpr(t2, rt);
18315 tcg_gen_add_tl(t0, t1, t2);
18316 tcg_gen_ext32s_tl(t0, t0);
18317 tcg_gen_xor_tl(t1, t1, t2);
18318 tcg_gen_xor_tl(t2, t0, t2);
18319 tcg_gen_andc_tl(t1, t2, t1);
18321 /* operands of same sign, result different sign */
18322 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18323 gen_store_gpr(t0, rd);
18325 tcg_temp_free(t0);
18326 tcg_temp_free(t1);
18327 tcg_temp_free(t2);
18329 break;
18330 case NM_MUL:
18331 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18332 break;
18333 case NM_MUH:
18334 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18335 break;
18336 case NM_MULU:
18337 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18338 break;
18339 case NM_MUHU:
18340 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18341 break;
18342 case NM_DIV:
18343 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18344 break;
18345 case NM_MOD:
18346 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18347 break;
18348 case NM_DIVU:
18349 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18350 break;
18351 case NM_MODU:
18352 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18353 break;
18354 #ifndef CONFIG_USER_ONLY
18355 case NM_MFC0:
18356 check_cp0_enabled(ctx);
18357 if (rt == 0) {
18358 /* Treat as NOP. */
18359 break;
18361 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18362 break;
18363 case NM_MTC0:
18364 check_cp0_enabled(ctx);
18366 TCGv t0 = tcg_temp_new();
18368 gen_load_gpr(t0, rt);
18369 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18370 tcg_temp_free(t0);
18372 break;
18373 case NM_D_E_MT_VPE:
18375 uint8_t sc = extract32(ctx->opcode, 10, 1);
18376 TCGv t0 = tcg_temp_new();
18378 switch (sc) {
18379 case 0:
18380 if (rs == 1) {
18381 /* DMT */
18382 check_cp0_mt(ctx);
18383 gen_helper_dmt(t0);
18384 gen_store_gpr(t0, rt);
18385 } else if (rs == 0) {
18386 /* DVPE */
18387 check_cp0_mt(ctx);
18388 gen_helper_dvpe(t0, cpu_env);
18389 gen_store_gpr(t0, rt);
18390 } else {
18391 generate_exception_end(ctx, EXCP_RI);
18393 break;
18394 case 1:
18395 if (rs == 1) {
18396 /* EMT */
18397 check_cp0_mt(ctx);
18398 gen_helper_emt(t0);
18399 gen_store_gpr(t0, rt);
18400 } else if (rs == 0) {
18401 /* EVPE */
18402 check_cp0_mt(ctx);
18403 gen_helper_evpe(t0, cpu_env);
18404 gen_store_gpr(t0, rt);
18405 } else {
18406 generate_exception_end(ctx, EXCP_RI);
18408 break;
18411 tcg_temp_free(t0);
18413 break;
18414 case NM_FORK:
18415 check_mt(ctx);
18417 TCGv t0 = tcg_temp_new();
18418 TCGv t1 = tcg_temp_new();
18420 gen_load_gpr(t0, rt);
18421 gen_load_gpr(t1, rs);
18422 gen_helper_fork(t0, t1);
18423 tcg_temp_free(t0);
18424 tcg_temp_free(t1);
18426 break;
18427 case NM_MFTR:
18428 case NM_MFHTR:
18429 check_cp0_enabled(ctx);
18430 if (rd == 0) {
18431 /* Treat as NOP. */
18432 return;
18434 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18435 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18436 break;
18437 case NM_MTTR:
18438 case NM_MTHTR:
18439 check_cp0_enabled(ctx);
18440 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18441 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18442 break;
18443 case NM_YIELD:
18444 check_mt(ctx);
18446 TCGv t0 = tcg_temp_new();
18448 gen_load_gpr(t0, rs);
18449 gen_helper_yield(t0, cpu_env, t0);
18450 gen_store_gpr(t0, rt);
18451 tcg_temp_free(t0);
18453 break;
18454 #endif
18455 default:
18456 generate_exception_end(ctx, EXCP_RI);
18457 break;
18461 /* dsp */
18462 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18463 int ret, int v1, int v2)
18465 TCGv_i32 t0;
18466 TCGv v0_t;
18467 TCGv v1_t;
18469 t0 = tcg_temp_new_i32();
18471 v0_t = tcg_temp_new();
18472 v1_t = tcg_temp_new();
18474 tcg_gen_movi_i32(t0, v2 >> 3);
18476 gen_load_gpr(v0_t, ret);
18477 gen_load_gpr(v1_t, v1);
18479 switch (opc) {
18480 case NM_MAQ_S_W_PHR:
18481 check_dsp(ctx);
18482 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18483 break;
18484 case NM_MAQ_S_W_PHL:
18485 check_dsp(ctx);
18486 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18487 break;
18488 case NM_MAQ_SA_W_PHR:
18489 check_dsp(ctx);
18490 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18491 break;
18492 case NM_MAQ_SA_W_PHL:
18493 check_dsp(ctx);
18494 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18495 break;
18496 default:
18497 generate_exception_end(ctx, EXCP_RI);
18498 break;
18501 tcg_temp_free_i32(t0);
18503 tcg_temp_free(v0_t);
18504 tcg_temp_free(v1_t);
18508 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18509 int ret, int v1, int v2)
18511 int16_t imm;
18512 TCGv t0 = tcg_temp_new();
18513 TCGv t1 = tcg_temp_new();
18514 TCGv v0_t = tcg_temp_new();
18516 gen_load_gpr(v0_t, v1);
18518 switch (opc) {
18519 case NM_POOL32AXF_1_0:
18520 check_dsp(ctx);
18521 switch (extract32(ctx->opcode, 12, 2)) {
18522 case NM_MFHI:
18523 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18524 break;
18525 case NM_MFLO:
18526 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18527 break;
18528 case NM_MTHI:
18529 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18530 break;
18531 case NM_MTLO:
18532 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18533 break;
18535 break;
18536 case NM_POOL32AXF_1_1:
18537 check_dsp(ctx);
18538 switch (extract32(ctx->opcode, 12, 2)) {
18539 case NM_MTHLIP:
18540 tcg_gen_movi_tl(t0, v2);
18541 gen_helper_mthlip(t0, v0_t, cpu_env);
18542 break;
18543 case NM_SHILOV:
18544 tcg_gen_movi_tl(t0, v2 >> 3);
18545 gen_helper_shilo(t0, v0_t, cpu_env);
18546 break;
18547 default:
18548 generate_exception_end(ctx, EXCP_RI);
18549 break;
18551 break;
18552 case NM_POOL32AXF_1_3:
18553 check_dsp(ctx);
18554 imm = extract32(ctx->opcode, 14, 7);
18555 switch (extract32(ctx->opcode, 12, 2)) {
18556 case NM_RDDSP:
18557 tcg_gen_movi_tl(t0, imm);
18558 gen_helper_rddsp(t0, t0, cpu_env);
18559 gen_store_gpr(t0, ret);
18560 break;
18561 case NM_WRDSP:
18562 gen_load_gpr(t0, ret);
18563 tcg_gen_movi_tl(t1, imm);
18564 gen_helper_wrdsp(t0, t1, cpu_env);
18565 break;
18566 case NM_EXTP:
18567 tcg_gen_movi_tl(t0, v2 >> 3);
18568 tcg_gen_movi_tl(t1, v1);
18569 gen_helper_extp(t0, t0, t1, cpu_env);
18570 gen_store_gpr(t0, ret);
18571 break;
18572 case NM_EXTPDP:
18573 tcg_gen_movi_tl(t0, v2 >> 3);
18574 tcg_gen_movi_tl(t1, v1);
18575 gen_helper_extpdp(t0, t0, t1, cpu_env);
18576 gen_store_gpr(t0, ret);
18577 break;
18579 break;
18580 case NM_POOL32AXF_1_4:
18581 check_dsp(ctx);
18582 tcg_gen_movi_tl(t0, v2 >> 2);
18583 switch (extract32(ctx->opcode, 12, 1)) {
18584 case NM_SHLL_QB:
18585 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18586 gen_store_gpr(t0, ret);
18587 break;
18588 case NM_SHRL_QB:
18589 gen_helper_shrl_qb(t0, t0, v0_t);
18590 gen_store_gpr(t0, ret);
18591 break;
18593 break;
18594 case NM_POOL32AXF_1_5:
18595 opc = extract32(ctx->opcode, 12, 2);
18596 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18597 break;
18598 case NM_POOL32AXF_1_7:
18599 check_dsp(ctx);
18600 tcg_gen_movi_tl(t0, v2 >> 3);
18601 tcg_gen_movi_tl(t1, v1);
18602 switch (extract32(ctx->opcode, 12, 2)) {
18603 case NM_EXTR_W:
18604 gen_helper_extr_w(t0, t0, t1, cpu_env);
18605 gen_store_gpr(t0, ret);
18606 break;
18607 case NM_EXTR_R_W:
18608 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18609 gen_store_gpr(t0, ret);
18610 break;
18611 case NM_EXTR_RS_W:
18612 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18613 gen_store_gpr(t0, ret);
18614 break;
18615 case NM_EXTR_S_H:
18616 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18617 gen_store_gpr(t0, ret);
18618 break;
18620 break;
18621 default:
18622 generate_exception_end(ctx, EXCP_RI);
18623 break;
18626 tcg_temp_free(t0);
18627 tcg_temp_free(t1);
18628 tcg_temp_free(v0_t);
18631 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18632 TCGv v0, TCGv v1, int rd)
18634 TCGv_i32 t0;
18636 t0 = tcg_temp_new_i32();
18638 tcg_gen_movi_i32(t0, rd >> 3);
18640 switch (opc) {
18641 case NM_POOL32AXF_2_0_7:
18642 switch (extract32(ctx->opcode, 9, 3)) {
18643 case NM_DPA_W_PH:
18644 check_dsp_r2(ctx);
18645 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18646 break;
18647 case NM_DPAQ_S_W_PH:
18648 check_dsp(ctx);
18649 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18650 break;
18651 case NM_DPS_W_PH:
18652 check_dsp_r2(ctx);
18653 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18654 break;
18655 case NM_DPSQ_S_W_PH:
18656 check_dsp(ctx);
18657 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18658 break;
18659 default:
18660 generate_exception_end(ctx, EXCP_RI);
18661 break;
18663 break;
18664 case NM_POOL32AXF_2_8_15:
18665 switch (extract32(ctx->opcode, 9, 3)) {
18666 case NM_DPAX_W_PH:
18667 check_dsp_r2(ctx);
18668 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18669 break;
18670 case NM_DPAQ_SA_L_W:
18671 check_dsp(ctx);
18672 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18673 break;
18674 case NM_DPSX_W_PH:
18675 check_dsp_r2(ctx);
18676 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18677 break;
18678 case NM_DPSQ_SA_L_W:
18679 check_dsp(ctx);
18680 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18681 break;
18682 default:
18683 generate_exception_end(ctx, EXCP_RI);
18684 break;
18686 break;
18687 case NM_POOL32AXF_2_16_23:
18688 switch (extract32(ctx->opcode, 9, 3)) {
18689 case NM_DPAU_H_QBL:
18690 check_dsp(ctx);
18691 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18692 break;
18693 case NM_DPAQX_S_W_PH:
18694 check_dsp_r2(ctx);
18695 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18696 break;
18697 case NM_DPSU_H_QBL:
18698 check_dsp(ctx);
18699 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18700 break;
18701 case NM_DPSQX_S_W_PH:
18702 check_dsp_r2(ctx);
18703 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18704 break;
18705 case NM_MULSA_W_PH:
18706 check_dsp_r2(ctx);
18707 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18708 break;
18709 default:
18710 generate_exception_end(ctx, EXCP_RI);
18711 break;
18713 break;
18714 case NM_POOL32AXF_2_24_31:
18715 switch (extract32(ctx->opcode, 9, 3)) {
18716 case NM_DPAU_H_QBR:
18717 check_dsp(ctx);
18718 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18719 break;
18720 case NM_DPAQX_SA_W_PH:
18721 check_dsp_r2(ctx);
18722 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18723 break;
18724 case NM_DPSU_H_QBR:
18725 check_dsp(ctx);
18726 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18727 break;
18728 case NM_DPSQX_SA_W_PH:
18729 check_dsp_r2(ctx);
18730 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18731 break;
18732 case NM_MULSAQ_S_W_PH:
18733 check_dsp(ctx);
18734 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18735 break;
18736 default:
18737 generate_exception_end(ctx, EXCP_RI);
18738 break;
18740 break;
18741 default:
18742 generate_exception_end(ctx, EXCP_RI);
18743 break;
18746 tcg_temp_free_i32(t0);
18749 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18750 int rt, int rs, int rd)
18752 int ret = rt;
18753 TCGv t0 = tcg_temp_new();
18754 TCGv t1 = tcg_temp_new();
18755 TCGv v0_t = tcg_temp_new();
18756 TCGv v1_t = tcg_temp_new();
18758 gen_load_gpr(v0_t, rt);
18759 gen_load_gpr(v1_t, rs);
18761 switch (opc) {
18762 case NM_POOL32AXF_2_0_7:
18763 switch (extract32(ctx->opcode, 9, 3)) {
18764 case NM_DPA_W_PH:
18765 case NM_DPAQ_S_W_PH:
18766 case NM_DPS_W_PH:
18767 case NM_DPSQ_S_W_PH:
18768 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18769 break;
18770 case NM_BALIGN:
18771 check_dsp_r2(ctx);
18772 if (rt != 0) {
18773 gen_load_gpr(t0, rs);
18774 rd &= 3;
18775 if (rd != 0 && rd != 2) {
18776 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18777 tcg_gen_ext32u_tl(t0, t0);
18778 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18779 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18781 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18783 break;
18784 case NM_MADD:
18785 check_dsp(ctx);
18787 int acc = extract32(ctx->opcode, 14, 2);
18788 TCGv_i64 t2 = tcg_temp_new_i64();
18789 TCGv_i64 t3 = tcg_temp_new_i64();
18791 gen_load_gpr(t0, rt);
18792 gen_load_gpr(t1, rs);
18793 tcg_gen_ext_tl_i64(t2, t0);
18794 tcg_gen_ext_tl_i64(t3, t1);
18795 tcg_gen_mul_i64(t2, t2, t3);
18796 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18797 tcg_gen_add_i64(t2, t2, t3);
18798 tcg_temp_free_i64(t3);
18799 gen_move_low32(cpu_LO[acc], t2);
18800 gen_move_high32(cpu_HI[acc], t2);
18801 tcg_temp_free_i64(t2);
18803 break;
18804 case NM_MULT:
18805 check_dsp(ctx);
18807 int acc = extract32(ctx->opcode, 14, 2);
18808 TCGv_i32 t2 = tcg_temp_new_i32();
18809 TCGv_i32 t3 = tcg_temp_new_i32();
18811 gen_load_gpr(t0, rs);
18812 gen_load_gpr(t1, rt);
18813 tcg_gen_trunc_tl_i32(t2, t0);
18814 tcg_gen_trunc_tl_i32(t3, t1);
18815 tcg_gen_muls2_i32(t2, t3, t2, t3);
18816 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18817 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18818 tcg_temp_free_i32(t2);
18819 tcg_temp_free_i32(t3);
18821 break;
18822 case NM_EXTRV_W:
18823 check_dsp(ctx);
18824 gen_load_gpr(v1_t, rs);
18825 tcg_gen_movi_tl(t0, rd >> 3);
18826 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18827 gen_store_gpr(t0, ret);
18828 break;
18830 break;
18831 case NM_POOL32AXF_2_8_15:
18832 switch (extract32(ctx->opcode, 9, 3)) {
18833 case NM_DPAX_W_PH:
18834 case NM_DPAQ_SA_L_W:
18835 case NM_DPSX_W_PH:
18836 case NM_DPSQ_SA_L_W:
18837 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18838 break;
18839 case NM_MADDU:
18840 check_dsp(ctx);
18842 int acc = extract32(ctx->opcode, 14, 2);
18843 TCGv_i64 t2 = tcg_temp_new_i64();
18844 TCGv_i64 t3 = tcg_temp_new_i64();
18846 gen_load_gpr(t0, rs);
18847 gen_load_gpr(t1, rt);
18848 tcg_gen_ext32u_tl(t0, t0);
18849 tcg_gen_ext32u_tl(t1, t1);
18850 tcg_gen_extu_tl_i64(t2, t0);
18851 tcg_gen_extu_tl_i64(t3, t1);
18852 tcg_gen_mul_i64(t2, t2, t3);
18853 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18854 tcg_gen_add_i64(t2, t2, t3);
18855 tcg_temp_free_i64(t3);
18856 gen_move_low32(cpu_LO[acc], t2);
18857 gen_move_high32(cpu_HI[acc], t2);
18858 tcg_temp_free_i64(t2);
18860 break;
18861 case NM_MULTU:
18862 check_dsp(ctx);
18864 int acc = extract32(ctx->opcode, 14, 2);
18865 TCGv_i32 t2 = tcg_temp_new_i32();
18866 TCGv_i32 t3 = tcg_temp_new_i32();
18868 gen_load_gpr(t0, rs);
18869 gen_load_gpr(t1, rt);
18870 tcg_gen_trunc_tl_i32(t2, t0);
18871 tcg_gen_trunc_tl_i32(t3, t1);
18872 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18873 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18874 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18875 tcg_temp_free_i32(t2);
18876 tcg_temp_free_i32(t3);
18878 break;
18879 case NM_EXTRV_R_W:
18880 check_dsp(ctx);
18881 tcg_gen_movi_tl(t0, rd >> 3);
18882 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18883 gen_store_gpr(t0, ret);
18884 break;
18885 default:
18886 generate_exception_end(ctx, EXCP_RI);
18887 break;
18889 break;
18890 case NM_POOL32AXF_2_16_23:
18891 switch (extract32(ctx->opcode, 9, 3)) {
18892 case NM_DPAU_H_QBL:
18893 case NM_DPAQX_S_W_PH:
18894 case NM_DPSU_H_QBL:
18895 case NM_DPSQX_S_W_PH:
18896 case NM_MULSA_W_PH:
18897 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18898 break;
18899 case NM_EXTPV:
18900 check_dsp(ctx);
18901 tcg_gen_movi_tl(t0, rd >> 3);
18902 gen_helper_extp(t0, t0, v1_t, cpu_env);
18903 gen_store_gpr(t0, ret);
18904 break;
18905 case NM_MSUB:
18906 check_dsp(ctx);
18908 int acc = extract32(ctx->opcode, 14, 2);
18909 TCGv_i64 t2 = tcg_temp_new_i64();
18910 TCGv_i64 t3 = tcg_temp_new_i64();
18912 gen_load_gpr(t0, rs);
18913 gen_load_gpr(t1, rt);
18914 tcg_gen_ext_tl_i64(t2, t0);
18915 tcg_gen_ext_tl_i64(t3, t1);
18916 tcg_gen_mul_i64(t2, t2, t3);
18917 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18918 tcg_gen_sub_i64(t2, t3, t2);
18919 tcg_temp_free_i64(t3);
18920 gen_move_low32(cpu_LO[acc], t2);
18921 gen_move_high32(cpu_HI[acc], t2);
18922 tcg_temp_free_i64(t2);
18924 break;
18925 case NM_EXTRV_RS_W:
18926 check_dsp(ctx);
18927 tcg_gen_movi_tl(t0, rd >> 3);
18928 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18929 gen_store_gpr(t0, ret);
18930 break;
18932 break;
18933 case NM_POOL32AXF_2_24_31:
18934 switch (extract32(ctx->opcode, 9, 3)) {
18935 case NM_DPAU_H_QBR:
18936 case NM_DPAQX_SA_W_PH:
18937 case NM_DPSU_H_QBR:
18938 case NM_DPSQX_SA_W_PH:
18939 case NM_MULSAQ_S_W_PH:
18940 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18941 break;
18942 case NM_EXTPDPV:
18943 check_dsp(ctx);
18944 tcg_gen_movi_tl(t0, rd >> 3);
18945 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18946 gen_store_gpr(t0, ret);
18947 break;
18948 case NM_MSUBU:
18949 check_dsp(ctx);
18951 int acc = extract32(ctx->opcode, 14, 2);
18952 TCGv_i64 t2 = tcg_temp_new_i64();
18953 TCGv_i64 t3 = tcg_temp_new_i64();
18955 gen_load_gpr(t0, rs);
18956 gen_load_gpr(t1, rt);
18957 tcg_gen_ext32u_tl(t0, t0);
18958 tcg_gen_ext32u_tl(t1, t1);
18959 tcg_gen_extu_tl_i64(t2, t0);
18960 tcg_gen_extu_tl_i64(t3, t1);
18961 tcg_gen_mul_i64(t2, t2, t3);
18962 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18963 tcg_gen_sub_i64(t2, t3, t2);
18964 tcg_temp_free_i64(t3);
18965 gen_move_low32(cpu_LO[acc], t2);
18966 gen_move_high32(cpu_HI[acc], t2);
18967 tcg_temp_free_i64(t2);
18969 break;
18970 case NM_EXTRV_S_H:
18971 check_dsp(ctx);
18972 tcg_gen_movi_tl(t0, rd >> 3);
18973 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18974 gen_store_gpr(t0, ret);
18975 break;
18977 break;
18978 default:
18979 generate_exception_end(ctx, EXCP_RI);
18980 break;
18983 tcg_temp_free(t0);
18984 tcg_temp_free(t1);
18986 tcg_temp_free(v0_t);
18987 tcg_temp_free(v1_t);
18990 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18991 int rt, int rs)
18993 int ret = rt;
18994 TCGv t0 = tcg_temp_new();
18995 TCGv v0_t = tcg_temp_new();
18997 gen_load_gpr(v0_t, rs);
18999 switch (opc) {
19000 case NM_ABSQ_S_QB:
19001 check_dsp_r2(ctx);
19002 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
19003 gen_store_gpr(v0_t, ret);
19004 break;
19005 case NM_ABSQ_S_PH:
19006 check_dsp(ctx);
19007 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
19008 gen_store_gpr(v0_t, ret);
19009 break;
19010 case NM_ABSQ_S_W:
19011 check_dsp(ctx);
19012 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
19013 gen_store_gpr(v0_t, ret);
19014 break;
19015 case NM_PRECEQ_W_PHL:
19016 check_dsp(ctx);
19017 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
19018 tcg_gen_ext32s_tl(v0_t, v0_t);
19019 gen_store_gpr(v0_t, ret);
19020 break;
19021 case NM_PRECEQ_W_PHR:
19022 check_dsp(ctx);
19023 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
19024 tcg_gen_shli_tl(v0_t, v0_t, 16);
19025 tcg_gen_ext32s_tl(v0_t, v0_t);
19026 gen_store_gpr(v0_t, ret);
19027 break;
19028 case NM_PRECEQU_PH_QBL:
19029 check_dsp(ctx);
19030 gen_helper_precequ_ph_qbl(v0_t, v0_t);
19031 gen_store_gpr(v0_t, ret);
19032 break;
19033 case NM_PRECEQU_PH_QBR:
19034 check_dsp(ctx);
19035 gen_helper_precequ_ph_qbr(v0_t, v0_t);
19036 gen_store_gpr(v0_t, ret);
19037 break;
19038 case NM_PRECEQU_PH_QBLA:
19039 check_dsp(ctx);
19040 gen_helper_precequ_ph_qbla(v0_t, v0_t);
19041 gen_store_gpr(v0_t, ret);
19042 break;
19043 case NM_PRECEQU_PH_QBRA:
19044 check_dsp(ctx);
19045 gen_helper_precequ_ph_qbra(v0_t, v0_t);
19046 gen_store_gpr(v0_t, ret);
19047 break;
19048 case NM_PRECEU_PH_QBL:
19049 check_dsp(ctx);
19050 gen_helper_preceu_ph_qbl(v0_t, v0_t);
19051 gen_store_gpr(v0_t, ret);
19052 break;
19053 case NM_PRECEU_PH_QBR:
19054 check_dsp(ctx);
19055 gen_helper_preceu_ph_qbr(v0_t, v0_t);
19056 gen_store_gpr(v0_t, ret);
19057 break;
19058 case NM_PRECEU_PH_QBLA:
19059 check_dsp(ctx);
19060 gen_helper_preceu_ph_qbla(v0_t, v0_t);
19061 gen_store_gpr(v0_t, ret);
19062 break;
19063 case NM_PRECEU_PH_QBRA:
19064 check_dsp(ctx);
19065 gen_helper_preceu_ph_qbra(v0_t, v0_t);
19066 gen_store_gpr(v0_t, ret);
19067 break;
19068 case NM_REPLV_PH:
19069 check_dsp(ctx);
19070 tcg_gen_ext16u_tl(v0_t, v0_t);
19071 tcg_gen_shli_tl(t0, v0_t, 16);
19072 tcg_gen_or_tl(v0_t, v0_t, t0);
19073 tcg_gen_ext32s_tl(v0_t, v0_t);
19074 gen_store_gpr(v0_t, ret);
19075 break;
19076 case NM_REPLV_QB:
19077 check_dsp(ctx);
19078 tcg_gen_ext8u_tl(v0_t, v0_t);
19079 tcg_gen_shli_tl(t0, v0_t, 8);
19080 tcg_gen_or_tl(v0_t, v0_t, t0);
19081 tcg_gen_shli_tl(t0, v0_t, 16);
19082 tcg_gen_or_tl(v0_t, v0_t, t0);
19083 tcg_gen_ext32s_tl(v0_t, v0_t);
19084 gen_store_gpr(v0_t, ret);
19085 break;
19086 case NM_BITREV:
19087 check_dsp(ctx);
19088 gen_helper_bitrev(v0_t, v0_t);
19089 gen_store_gpr(v0_t, ret);
19090 break;
19091 case NM_INSV:
19092 check_dsp(ctx);
19094 TCGv tv0 = tcg_temp_new();
19096 gen_load_gpr(tv0, rt);
19097 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
19098 gen_store_gpr(v0_t, ret);
19099 tcg_temp_free(tv0);
19101 break;
19102 case NM_RADDU_W_QB:
19103 check_dsp(ctx);
19104 gen_helper_raddu_w_qb(v0_t, v0_t);
19105 gen_store_gpr(v0_t, ret);
19106 break;
19107 case NM_BITSWAP:
19108 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
19109 break;
19110 case NM_CLO:
19111 check_nms(ctx);
19112 gen_cl(ctx, OPC_CLO, ret, rs);
19113 break;
19114 case NM_CLZ:
19115 check_nms(ctx);
19116 gen_cl(ctx, OPC_CLZ, ret, rs);
19117 break;
19118 case NM_WSBH:
19119 gen_bshfl(ctx, OPC_WSBH, ret, rs);
19120 break;
19121 default:
19122 generate_exception_end(ctx, EXCP_RI);
19123 break;
19126 tcg_temp_free(v0_t);
19127 tcg_temp_free(t0);
19130 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
19131 int rt, int rs, int rd)
19133 TCGv t0 = tcg_temp_new();
19134 TCGv rs_t = tcg_temp_new();
19136 gen_load_gpr(rs_t, rs);
19138 switch (opc) {
19139 case NM_SHRA_R_QB:
19140 check_dsp_r2(ctx);
19141 tcg_gen_movi_tl(t0, rd >> 2);
19142 switch (extract32(ctx->opcode, 12, 1)) {
19143 case 0:
19144 /* NM_SHRA_QB */
19145 gen_helper_shra_qb(t0, t0, rs_t);
19146 gen_store_gpr(t0, rt);
19147 break;
19148 case 1:
19149 /* NM_SHRA_R_QB */
19150 gen_helper_shra_r_qb(t0, t0, rs_t);
19151 gen_store_gpr(t0, rt);
19152 break;
19154 break;
19155 case NM_SHRL_PH:
19156 check_dsp_r2(ctx);
19157 tcg_gen_movi_tl(t0, rd >> 1);
19158 gen_helper_shrl_ph(t0, t0, rs_t);
19159 gen_store_gpr(t0, rt);
19160 break;
19161 case NM_REPL_QB:
19162 check_dsp(ctx);
19164 int16_t imm;
19165 target_long result;
19166 imm = extract32(ctx->opcode, 13, 8);
19167 result = (uint32_t)imm << 24 |
19168 (uint32_t)imm << 16 |
19169 (uint32_t)imm << 8 |
19170 (uint32_t)imm;
19171 result = (int32_t)result;
19172 tcg_gen_movi_tl(t0, result);
19173 gen_store_gpr(t0, rt);
19175 break;
19176 default:
19177 generate_exception_end(ctx, EXCP_RI);
19178 break;
19180 tcg_temp_free(t0);
19181 tcg_temp_free(rs_t);
19185 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19187 int rt = extract32(ctx->opcode, 21, 5);
19188 int rs = extract32(ctx->opcode, 16, 5);
19189 int rd = extract32(ctx->opcode, 11, 5);
19191 switch (extract32(ctx->opcode, 6, 3)) {
19192 case NM_POOL32AXF_1:
19194 int32_t op1 = extract32(ctx->opcode, 9, 3);
19195 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
19197 break;
19198 case NM_POOL32AXF_2:
19200 int32_t op1 = extract32(ctx->opcode, 12, 2);
19201 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
19203 break;
19204 case NM_POOL32AXF_4:
19206 int32_t op1 = extract32(ctx->opcode, 9, 7);
19207 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
19209 break;
19210 case NM_POOL32AXF_5:
19211 switch (extract32(ctx->opcode, 9, 7)) {
19212 #ifndef CONFIG_USER_ONLY
19213 case NM_TLBP:
19214 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
19215 break;
19216 case NM_TLBR:
19217 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
19218 break;
19219 case NM_TLBWI:
19220 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
19221 break;
19222 case NM_TLBWR:
19223 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
19224 break;
19225 case NM_TLBINV:
19226 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
19227 break;
19228 case NM_TLBINVF:
19229 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
19230 break;
19231 case NM_DI:
19232 check_cp0_enabled(ctx);
19234 TCGv t0 = tcg_temp_new();
19236 save_cpu_state(ctx, 1);
19237 gen_helper_di(t0, cpu_env);
19238 gen_store_gpr(t0, rt);
19239 /* Stop translation as we may have switched the execution mode */
19240 ctx->base.is_jmp = DISAS_STOP;
19241 tcg_temp_free(t0);
19243 break;
19244 case NM_EI:
19245 check_cp0_enabled(ctx);
19247 TCGv t0 = tcg_temp_new();
19249 save_cpu_state(ctx, 1);
19250 gen_helper_ei(t0, cpu_env);
19251 gen_store_gpr(t0, rt);
19252 /* Stop translation as we may have switched the execution mode */
19253 ctx->base.is_jmp = DISAS_STOP;
19254 tcg_temp_free(t0);
19256 break;
19257 case NM_RDPGPR:
19258 gen_load_srsgpr(rs, rt);
19259 break;
19260 case NM_WRPGPR:
19261 gen_store_srsgpr(rs, rt);
19262 break;
19263 case NM_WAIT:
19264 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
19265 break;
19266 case NM_DERET:
19267 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19268 break;
19269 case NM_ERETX:
19270 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19271 break;
19272 #endif
19273 default:
19274 generate_exception_end(ctx, EXCP_RI);
19275 break;
19277 break;
19278 case NM_POOL32AXF_7:
19280 int32_t op1 = extract32(ctx->opcode, 9, 3);
19281 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19283 break;
19284 default:
19285 generate_exception_end(ctx, EXCP_RI);
19286 break;
19290 /* Immediate Value Compact Branches */
19291 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19292 int rt, int32_t imm, int32_t offset)
19294 TCGCond cond;
19295 int bcond_compute = 0;
19296 TCGv t0 = tcg_temp_new();
19297 TCGv t1 = tcg_temp_new();
19299 gen_load_gpr(t0, rt);
19300 tcg_gen_movi_tl(t1, imm);
19301 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19303 /* Load needed operands and calculate btarget */
19304 switch (opc) {
19305 case NM_BEQIC:
19306 if (rt == 0 && imm == 0) {
19307 /* Unconditional branch */
19308 } else if (rt == 0 && imm != 0) {
19309 /* Treat as NOP */
19310 goto out;
19311 } else {
19312 bcond_compute = 1;
19313 cond = TCG_COND_EQ;
19315 break;
19316 case NM_BBEQZC:
19317 case NM_BBNEZC:
19318 check_nms(ctx);
19319 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19320 generate_exception_end(ctx, EXCP_RI);
19321 goto out;
19322 } else if (rt == 0 && opc == NM_BBEQZC) {
19323 /* Unconditional branch */
19324 } else if (rt == 0 && opc == NM_BBNEZC) {
19325 /* Treat as NOP */
19326 goto out;
19327 } else {
19328 tcg_gen_shri_tl(t0, t0, imm);
19329 tcg_gen_andi_tl(t0, t0, 1);
19330 tcg_gen_movi_tl(t1, 0);
19331 bcond_compute = 1;
19332 if (opc == NM_BBEQZC) {
19333 cond = TCG_COND_EQ;
19334 } else {
19335 cond = TCG_COND_NE;
19338 break;
19339 case NM_BNEIC:
19340 if (rt == 0 && imm == 0) {
19341 /* Treat as NOP */
19342 goto out;
19343 } else if (rt == 0 && imm != 0) {
19344 /* Unconditional branch */
19345 } else {
19346 bcond_compute = 1;
19347 cond = TCG_COND_NE;
19349 break;
19350 case NM_BGEIC:
19351 if (rt == 0 && imm == 0) {
19352 /* Unconditional branch */
19353 } else {
19354 bcond_compute = 1;
19355 cond = TCG_COND_GE;
19357 break;
19358 case NM_BLTIC:
19359 bcond_compute = 1;
19360 cond = TCG_COND_LT;
19361 break;
19362 case NM_BGEIUC:
19363 if (rt == 0 && imm == 0) {
19364 /* Unconditional branch */
19365 } else {
19366 bcond_compute = 1;
19367 cond = TCG_COND_GEU;
19369 break;
19370 case NM_BLTIUC:
19371 bcond_compute = 1;
19372 cond = TCG_COND_LTU;
19373 break;
19374 default:
19375 MIPS_INVAL("Immediate Value Compact branch");
19376 generate_exception_end(ctx, EXCP_RI);
19377 goto out;
19380 if (bcond_compute == 0) {
19381 /* Uncoditional compact branch */
19382 gen_goto_tb(ctx, 0, ctx->btarget);
19383 } else {
19384 /* Conditional compact branch */
19385 TCGLabel *fs = gen_new_label();
19387 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19389 gen_goto_tb(ctx, 1, ctx->btarget);
19390 gen_set_label(fs);
19392 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19395 out:
19396 tcg_temp_free(t0);
19397 tcg_temp_free(t1);
19400 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19401 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19402 int rt)
19404 TCGv t0 = tcg_temp_new();
19405 TCGv t1 = tcg_temp_new();
19407 /* load rs */
19408 gen_load_gpr(t0, rs);
19410 /* link */
19411 if (rt != 0) {
19412 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19415 /* calculate btarget */
19416 tcg_gen_shli_tl(t0, t0, 1);
19417 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19418 gen_op_addr_add(ctx, btarget, t1, t0);
19420 /* unconditional branch to register */
19421 tcg_gen_mov_tl(cpu_PC, btarget);
19422 tcg_gen_lookup_and_goto_ptr();
19424 tcg_temp_free(t0);
19425 tcg_temp_free(t1);
19428 /* nanoMIPS Branches */
19429 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19430 int rs, int rt, int32_t offset)
19432 int bcond_compute = 0;
19433 TCGv t0 = tcg_temp_new();
19434 TCGv t1 = tcg_temp_new();
19436 /* Load needed operands and calculate btarget */
19437 switch (opc) {
19438 /* compact branch */
19439 case OPC_BGEC:
19440 case OPC_BLTC:
19441 gen_load_gpr(t0, rs);
19442 gen_load_gpr(t1, rt);
19443 bcond_compute = 1;
19444 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19445 break;
19446 case OPC_BGEUC:
19447 case OPC_BLTUC:
19448 if (rs == 0 || rs == rt) {
19449 /* OPC_BLEZALC, OPC_BGEZALC */
19450 /* OPC_BGTZALC, OPC_BLTZALC */
19451 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19453 gen_load_gpr(t0, rs);
19454 gen_load_gpr(t1, rt);
19455 bcond_compute = 1;
19456 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19457 break;
19458 case OPC_BC:
19459 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19460 break;
19461 case OPC_BEQZC:
19462 if (rs != 0) {
19463 /* OPC_BEQZC, OPC_BNEZC */
19464 gen_load_gpr(t0, rs);
19465 bcond_compute = 1;
19466 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19467 } else {
19468 /* OPC_JIC, OPC_JIALC */
19469 TCGv tbase = tcg_temp_new();
19470 TCGv toffset = tcg_temp_new();
19472 gen_load_gpr(tbase, rt);
19473 tcg_gen_movi_tl(toffset, offset);
19474 gen_op_addr_add(ctx, btarget, tbase, toffset);
19475 tcg_temp_free(tbase);
19476 tcg_temp_free(toffset);
19478 break;
19479 default:
19480 MIPS_INVAL("Compact branch/jump");
19481 generate_exception_end(ctx, EXCP_RI);
19482 goto out;
19485 if (bcond_compute == 0) {
19486 /* Uncoditional compact branch */
19487 switch (opc) {
19488 case OPC_BC:
19489 gen_goto_tb(ctx, 0, ctx->btarget);
19490 break;
19491 default:
19492 MIPS_INVAL("Compact branch/jump");
19493 generate_exception_end(ctx, EXCP_RI);
19494 goto out;
19496 } else {
19497 /* Conditional compact branch */
19498 TCGLabel *fs = gen_new_label();
19500 switch (opc) {
19501 case OPC_BGEUC:
19502 if (rs == 0 && rt != 0) {
19503 /* OPC_BLEZALC */
19504 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19505 } else if (rs != 0 && rt != 0 && rs == rt) {
19506 /* OPC_BGEZALC */
19507 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19508 } else {
19509 /* OPC_BGEUC */
19510 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19512 break;
19513 case OPC_BLTUC:
19514 if (rs == 0 && rt != 0) {
19515 /* OPC_BGTZALC */
19516 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19517 } else if (rs != 0 && rt != 0 && rs == rt) {
19518 /* OPC_BLTZALC */
19519 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19520 } else {
19521 /* OPC_BLTUC */
19522 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19524 break;
19525 case OPC_BGEC:
19526 if (rs == 0 && rt != 0) {
19527 /* OPC_BLEZC */
19528 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19529 } else if (rs != 0 && rt != 0 && rs == rt) {
19530 /* OPC_BGEZC */
19531 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19532 } else {
19533 /* OPC_BGEC */
19534 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19536 break;
19537 case OPC_BLTC:
19538 if (rs == 0 && rt != 0) {
19539 /* OPC_BGTZC */
19540 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19541 } else if (rs != 0 && rt != 0 && rs == rt) {
19542 /* OPC_BLTZC */
19543 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19544 } else {
19545 /* OPC_BLTC */
19546 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19548 break;
19549 case OPC_BEQZC:
19550 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19551 break;
19552 default:
19553 MIPS_INVAL("Compact conditional branch/jump");
19554 generate_exception_end(ctx, EXCP_RI);
19555 goto out;
19558 /* Generating branch here as compact branches don't have delay slot */
19559 gen_goto_tb(ctx, 1, ctx->btarget);
19560 gen_set_label(fs);
19562 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19565 out:
19566 tcg_temp_free(t0);
19567 tcg_temp_free(t1);
19571 /* nanoMIPS CP1 Branches */
19572 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19573 int32_t ft, int32_t offset)
19575 target_ulong btarget;
19576 TCGv_i64 t0 = tcg_temp_new_i64();
19578 gen_load_fpr64(ctx, t0, ft);
19579 tcg_gen_andi_i64(t0, t0, 1);
19581 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19583 switch (op) {
19584 case NM_BC1EQZC:
19585 tcg_gen_xori_i64(t0, t0, 1);
19586 ctx->hflags |= MIPS_HFLAG_BC;
19587 break;
19588 case NM_BC1NEZC:
19589 /* t0 already set */
19590 ctx->hflags |= MIPS_HFLAG_BC;
19591 break;
19592 default:
19593 MIPS_INVAL("cp1 cond branch");
19594 generate_exception_end(ctx, EXCP_RI);
19595 goto out;
19598 tcg_gen_trunc_i64_tl(bcond, t0);
19600 ctx->btarget = btarget;
19602 out:
19603 tcg_temp_free_i64(t0);
19607 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19609 TCGv t0, t1;
19610 t0 = tcg_temp_new();
19611 t1 = tcg_temp_new();
19613 gen_load_gpr(t0, rs);
19614 gen_load_gpr(t1, rt);
19616 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19617 /* PP.LSXS instructions require shifting */
19618 switch (extract32(ctx->opcode, 7, 4)) {
19619 case NM_SHXS:
19620 check_nms(ctx);
19621 case NM_LHXS:
19622 case NM_LHUXS:
19623 tcg_gen_shli_tl(t0, t0, 1);
19624 break;
19625 case NM_SWXS:
19626 check_nms(ctx);
19627 case NM_LWXS:
19628 case NM_LWC1XS:
19629 case NM_SWC1XS:
19630 tcg_gen_shli_tl(t0, t0, 2);
19631 break;
19632 case NM_LDC1XS:
19633 case NM_SDC1XS:
19634 tcg_gen_shli_tl(t0, t0, 3);
19635 break;
19638 gen_op_addr_add(ctx, t0, t0, t1);
19640 switch (extract32(ctx->opcode, 7, 4)) {
19641 case NM_LBX:
19642 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19643 MO_SB);
19644 gen_store_gpr(t0, rd);
19645 break;
19646 case NM_LHX:
19647 /*case NM_LHXS:*/
19648 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19649 MO_TESW);
19650 gen_store_gpr(t0, rd);
19651 break;
19652 case NM_LWX:
19653 /*case NM_LWXS:*/
19654 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19655 MO_TESL);
19656 gen_store_gpr(t0, rd);
19657 break;
19658 case NM_LBUX:
19659 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19660 MO_UB);
19661 gen_store_gpr(t0, rd);
19662 break;
19663 case NM_LHUX:
19664 /*case NM_LHUXS:*/
19665 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19666 MO_TEUW);
19667 gen_store_gpr(t0, rd);
19668 break;
19669 case NM_SBX:
19670 check_nms(ctx);
19671 gen_load_gpr(t1, rd);
19672 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19673 MO_8);
19674 break;
19675 case NM_SHX:
19676 /*case NM_SHXS:*/
19677 check_nms(ctx);
19678 gen_load_gpr(t1, rd);
19679 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19680 MO_TEUW);
19681 break;
19682 case NM_SWX:
19683 /*case NM_SWXS:*/
19684 check_nms(ctx);
19685 gen_load_gpr(t1, rd);
19686 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19687 MO_TEUL);
19688 break;
19689 case NM_LWC1X:
19690 /*case NM_LWC1XS:*/
19691 case NM_LDC1X:
19692 /*case NM_LDC1XS:*/
19693 case NM_SWC1X:
19694 /*case NM_SWC1XS:*/
19695 case NM_SDC1X:
19696 /*case NM_SDC1XS:*/
19697 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19698 check_cp1_enabled(ctx);
19699 switch (extract32(ctx->opcode, 7, 4)) {
19700 case NM_LWC1X:
19701 /*case NM_LWC1XS:*/
19702 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19703 break;
19704 case NM_LDC1X:
19705 /*case NM_LDC1XS:*/
19706 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19707 break;
19708 case NM_SWC1X:
19709 /*case NM_SWC1XS:*/
19710 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19711 break;
19712 case NM_SDC1X:
19713 /*case NM_SDC1XS:*/
19714 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19715 break;
19717 } else {
19718 generate_exception_err(ctx, EXCP_CpU, 1);
19720 break;
19721 default:
19722 generate_exception_end(ctx, EXCP_RI);
19723 break;
19726 tcg_temp_free(t0);
19727 tcg_temp_free(t1);
19730 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19732 int rt, rs, rd;
19734 rt = extract32(ctx->opcode, 21, 5);
19735 rs = extract32(ctx->opcode, 16, 5);
19736 rd = extract32(ctx->opcode, 11, 5);
19738 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19739 generate_exception_end(ctx, EXCP_RI);
19740 return;
19742 check_cp1_enabled(ctx);
19743 switch (extract32(ctx->opcode, 0, 3)) {
19744 case NM_POOL32F_0:
19745 switch (extract32(ctx->opcode, 3, 7)) {
19746 case NM_RINT_S:
19747 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19748 break;
19749 case NM_RINT_D:
19750 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19751 break;
19752 case NM_CLASS_S:
19753 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19754 break;
19755 case NM_CLASS_D:
19756 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19757 break;
19758 case NM_ADD_S:
19759 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19760 break;
19761 case NM_ADD_D:
19762 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19763 break;
19764 case NM_SUB_S:
19765 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19766 break;
19767 case NM_SUB_D:
19768 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19769 break;
19770 case NM_MUL_S:
19771 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19772 break;
19773 case NM_MUL_D:
19774 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19775 break;
19776 case NM_DIV_S:
19777 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19778 break;
19779 case NM_DIV_D:
19780 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19781 break;
19782 case NM_SELEQZ_S:
19783 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19784 break;
19785 case NM_SELEQZ_D:
19786 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19787 break;
19788 case NM_SELNEZ_S:
19789 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19790 break;
19791 case NM_SELNEZ_D:
19792 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19793 break;
19794 case NM_SEL_S:
19795 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19796 break;
19797 case NM_SEL_D:
19798 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19799 break;
19800 case NM_MADDF_S:
19801 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19802 break;
19803 case NM_MADDF_D:
19804 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19805 break;
19806 case NM_MSUBF_S:
19807 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19808 break;
19809 case NM_MSUBF_D:
19810 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19811 break;
19812 default:
19813 generate_exception_end(ctx, EXCP_RI);
19814 break;
19816 break;
19817 case NM_POOL32F_3:
19818 switch (extract32(ctx->opcode, 3, 3)) {
19819 case NM_MIN_FMT:
19820 switch (extract32(ctx->opcode, 9, 1)) {
19821 case FMT_SDPS_S:
19822 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19823 break;
19824 case FMT_SDPS_D:
19825 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19826 break;
19828 break;
19829 case NM_MAX_FMT:
19830 switch (extract32(ctx->opcode, 9, 1)) {
19831 case FMT_SDPS_S:
19832 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19833 break;
19834 case FMT_SDPS_D:
19835 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19836 break;
19838 break;
19839 case NM_MINA_FMT:
19840 switch (extract32(ctx->opcode, 9, 1)) {
19841 case FMT_SDPS_S:
19842 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19843 break;
19844 case FMT_SDPS_D:
19845 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19846 break;
19848 break;
19849 case NM_MAXA_FMT:
19850 switch (extract32(ctx->opcode, 9, 1)) {
19851 case FMT_SDPS_S:
19852 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19853 break;
19854 case FMT_SDPS_D:
19855 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19856 break;
19858 break;
19859 case NM_POOL32FXF:
19860 switch (extract32(ctx->opcode, 6, 8)) {
19861 case NM_CFC1:
19862 gen_cp1(ctx, OPC_CFC1, rt, rs);
19863 break;
19864 case NM_CTC1:
19865 gen_cp1(ctx, OPC_CTC1, rt, rs);
19866 break;
19867 case NM_MFC1:
19868 gen_cp1(ctx, OPC_MFC1, rt, rs);
19869 break;
19870 case NM_MTC1:
19871 gen_cp1(ctx, OPC_MTC1, rt, rs);
19872 break;
19873 case NM_MFHC1:
19874 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19875 break;
19876 case NM_MTHC1:
19877 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19878 break;
19879 case NM_CVT_S_PL:
19880 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19881 break;
19882 case NM_CVT_S_PU:
19883 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19884 break;
19885 default:
19886 switch (extract32(ctx->opcode, 6, 9)) {
19887 case NM_CVT_L_S:
19888 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19889 break;
19890 case NM_CVT_L_D:
19891 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19892 break;
19893 case NM_CVT_W_S:
19894 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19895 break;
19896 case NM_CVT_W_D:
19897 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19898 break;
19899 case NM_RSQRT_S:
19900 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19901 break;
19902 case NM_RSQRT_D:
19903 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19904 break;
19905 case NM_SQRT_S:
19906 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19907 break;
19908 case NM_SQRT_D:
19909 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19910 break;
19911 case NM_RECIP_S:
19912 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19913 break;
19914 case NM_RECIP_D:
19915 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19916 break;
19917 case NM_FLOOR_L_S:
19918 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19919 break;
19920 case NM_FLOOR_L_D:
19921 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19922 break;
19923 case NM_FLOOR_W_S:
19924 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19925 break;
19926 case NM_FLOOR_W_D:
19927 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19928 break;
19929 case NM_CEIL_L_S:
19930 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19931 break;
19932 case NM_CEIL_L_D:
19933 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19934 break;
19935 case NM_CEIL_W_S:
19936 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19937 break;
19938 case NM_CEIL_W_D:
19939 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19940 break;
19941 case NM_TRUNC_L_S:
19942 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19943 break;
19944 case NM_TRUNC_L_D:
19945 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19946 break;
19947 case NM_TRUNC_W_S:
19948 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19949 break;
19950 case NM_TRUNC_W_D:
19951 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19952 break;
19953 case NM_ROUND_L_S:
19954 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19955 break;
19956 case NM_ROUND_L_D:
19957 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19958 break;
19959 case NM_ROUND_W_S:
19960 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19961 break;
19962 case NM_ROUND_W_D:
19963 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19964 break;
19965 case NM_MOV_S:
19966 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19967 break;
19968 case NM_MOV_D:
19969 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19970 break;
19971 case NM_ABS_S:
19972 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19973 break;
19974 case NM_ABS_D:
19975 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19976 break;
19977 case NM_NEG_S:
19978 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19979 break;
19980 case NM_NEG_D:
19981 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19982 break;
19983 case NM_CVT_D_S:
19984 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19985 break;
19986 case NM_CVT_D_W:
19987 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19988 break;
19989 case NM_CVT_D_L:
19990 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19991 break;
19992 case NM_CVT_S_D:
19993 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19994 break;
19995 case NM_CVT_S_W:
19996 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19997 break;
19998 case NM_CVT_S_L:
19999 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
20000 break;
20001 default:
20002 generate_exception_end(ctx, EXCP_RI);
20003 break;
20005 break;
20007 break;
20009 break;
20010 case NM_POOL32F_5:
20011 switch (extract32(ctx->opcode, 3, 3)) {
20012 case NM_CMP_CONDN_S:
20013 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20014 break;
20015 case NM_CMP_CONDN_D:
20016 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
20017 break;
20018 default:
20019 generate_exception_end(ctx, EXCP_RI);
20020 break;
20022 break;
20023 default:
20024 generate_exception_end(ctx, EXCP_RI);
20025 break;
20029 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
20030 int rd, int rs, int rt)
20032 int ret = rd;
20033 TCGv t0 = tcg_temp_new();
20034 TCGv v1_t = tcg_temp_new();
20035 TCGv v2_t = tcg_temp_new();
20037 gen_load_gpr(v1_t, rs);
20038 gen_load_gpr(v2_t, rt);
20040 switch (opc) {
20041 case NM_CMP_EQ_PH:
20042 check_dsp(ctx);
20043 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
20044 break;
20045 case NM_CMP_LT_PH:
20046 check_dsp(ctx);
20047 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
20048 break;
20049 case NM_CMP_LE_PH:
20050 check_dsp(ctx);
20051 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
20052 break;
20053 case NM_CMPU_EQ_QB:
20054 check_dsp(ctx);
20055 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
20056 break;
20057 case NM_CMPU_LT_QB:
20058 check_dsp(ctx);
20059 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
20060 break;
20061 case NM_CMPU_LE_QB:
20062 check_dsp(ctx);
20063 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
20064 break;
20065 case NM_CMPGU_EQ_QB:
20066 check_dsp(ctx);
20067 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20068 gen_store_gpr(v1_t, ret);
20069 break;
20070 case NM_CMPGU_LT_QB:
20071 check_dsp(ctx);
20072 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20073 gen_store_gpr(v1_t, ret);
20074 break;
20075 case NM_CMPGU_LE_QB:
20076 check_dsp(ctx);
20077 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20078 gen_store_gpr(v1_t, ret);
20079 break;
20080 case NM_CMPGDU_EQ_QB:
20081 check_dsp_r2(ctx);
20082 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
20083 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20084 gen_store_gpr(v1_t, ret);
20085 break;
20086 case NM_CMPGDU_LT_QB:
20087 check_dsp_r2(ctx);
20088 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
20089 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20090 gen_store_gpr(v1_t, ret);
20091 break;
20092 case NM_CMPGDU_LE_QB:
20093 check_dsp_r2(ctx);
20094 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
20095 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
20096 gen_store_gpr(v1_t, ret);
20097 break;
20098 case NM_PACKRL_PH:
20099 check_dsp(ctx);
20100 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
20101 gen_store_gpr(v1_t, ret);
20102 break;
20103 case NM_PICK_QB:
20104 check_dsp(ctx);
20105 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
20106 gen_store_gpr(v1_t, ret);
20107 break;
20108 case NM_PICK_PH:
20109 check_dsp(ctx);
20110 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
20111 gen_store_gpr(v1_t, ret);
20112 break;
20113 case NM_ADDQ_S_W:
20114 check_dsp(ctx);
20115 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
20116 gen_store_gpr(v1_t, ret);
20117 break;
20118 case NM_SUBQ_S_W:
20119 check_dsp(ctx);
20120 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
20121 gen_store_gpr(v1_t, ret);
20122 break;
20123 case NM_ADDSC:
20124 check_dsp(ctx);
20125 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
20126 gen_store_gpr(v1_t, ret);
20127 break;
20128 case NM_ADDWC:
20129 check_dsp(ctx);
20130 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
20131 gen_store_gpr(v1_t, ret);
20132 break;
20133 case NM_ADDQ_S_PH:
20134 check_dsp(ctx);
20135 switch (extract32(ctx->opcode, 10, 1)) {
20136 case 0:
20137 /* ADDQ_PH */
20138 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
20139 gen_store_gpr(v1_t, ret);
20140 break;
20141 case 1:
20142 /* ADDQ_S_PH */
20143 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20144 gen_store_gpr(v1_t, ret);
20145 break;
20147 break;
20148 case NM_ADDQH_R_PH:
20149 check_dsp_r2(ctx);
20150 switch (extract32(ctx->opcode, 10, 1)) {
20151 case 0:
20152 /* ADDQH_PH */
20153 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
20154 gen_store_gpr(v1_t, ret);
20155 break;
20156 case 1:
20157 /* ADDQH_R_PH */
20158 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
20159 gen_store_gpr(v1_t, ret);
20160 break;
20162 break;
20163 case NM_ADDQH_R_W:
20164 check_dsp_r2(ctx);
20165 switch (extract32(ctx->opcode, 10, 1)) {
20166 case 0:
20167 /* ADDQH_W */
20168 gen_helper_addqh_w(v1_t, v1_t, v2_t);
20169 gen_store_gpr(v1_t, ret);
20170 break;
20171 case 1:
20172 /* ADDQH_R_W */
20173 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
20174 gen_store_gpr(v1_t, ret);
20175 break;
20177 break;
20178 case NM_ADDU_S_QB:
20179 check_dsp(ctx);
20180 switch (extract32(ctx->opcode, 10, 1)) {
20181 case 0:
20182 /* ADDU_QB */
20183 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
20184 gen_store_gpr(v1_t, ret);
20185 break;
20186 case 1:
20187 /* ADDU_S_QB */
20188 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20189 gen_store_gpr(v1_t, ret);
20190 break;
20192 break;
20193 case NM_ADDU_S_PH:
20194 check_dsp_r2(ctx);
20195 switch (extract32(ctx->opcode, 10, 1)) {
20196 case 0:
20197 /* ADDU_PH */
20198 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
20199 gen_store_gpr(v1_t, ret);
20200 break;
20201 case 1:
20202 /* ADDU_S_PH */
20203 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20204 gen_store_gpr(v1_t, ret);
20205 break;
20207 break;
20208 case NM_ADDUH_R_QB:
20209 check_dsp_r2(ctx);
20210 switch (extract32(ctx->opcode, 10, 1)) {
20211 case 0:
20212 /* ADDUH_QB */
20213 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
20214 gen_store_gpr(v1_t, ret);
20215 break;
20216 case 1:
20217 /* ADDUH_R_QB */
20218 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
20219 gen_store_gpr(v1_t, ret);
20220 break;
20222 break;
20223 case NM_SHRAV_R_PH:
20224 check_dsp(ctx);
20225 switch (extract32(ctx->opcode, 10, 1)) {
20226 case 0:
20227 /* SHRAV_PH */
20228 gen_helper_shra_ph(v1_t, v1_t, v2_t);
20229 gen_store_gpr(v1_t, ret);
20230 break;
20231 case 1:
20232 /* SHRAV_R_PH */
20233 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
20234 gen_store_gpr(v1_t, ret);
20235 break;
20237 break;
20238 case NM_SHRAV_R_QB:
20239 check_dsp_r2(ctx);
20240 switch (extract32(ctx->opcode, 10, 1)) {
20241 case 0:
20242 /* SHRAV_QB */
20243 gen_helper_shra_qb(v1_t, v1_t, v2_t);
20244 gen_store_gpr(v1_t, ret);
20245 break;
20246 case 1:
20247 /* SHRAV_R_QB */
20248 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
20249 gen_store_gpr(v1_t, ret);
20250 break;
20252 break;
20253 case NM_SUBQ_S_PH:
20254 check_dsp(ctx);
20255 switch (extract32(ctx->opcode, 10, 1)) {
20256 case 0:
20257 /* SUBQ_PH */
20258 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
20259 gen_store_gpr(v1_t, ret);
20260 break;
20261 case 1:
20262 /* SUBQ_S_PH */
20263 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20264 gen_store_gpr(v1_t, ret);
20265 break;
20267 break;
20268 case NM_SUBQH_R_PH:
20269 check_dsp_r2(ctx);
20270 switch (extract32(ctx->opcode, 10, 1)) {
20271 case 0:
20272 /* SUBQH_PH */
20273 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20274 gen_store_gpr(v1_t, ret);
20275 break;
20276 case 1:
20277 /* SUBQH_R_PH */
20278 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20279 gen_store_gpr(v1_t, ret);
20280 break;
20282 break;
20283 case NM_SUBQH_R_W:
20284 check_dsp_r2(ctx);
20285 switch (extract32(ctx->opcode, 10, 1)) {
20286 case 0:
20287 /* SUBQH_W */
20288 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20289 gen_store_gpr(v1_t, ret);
20290 break;
20291 case 1:
20292 /* SUBQH_R_W */
20293 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20294 gen_store_gpr(v1_t, ret);
20295 break;
20297 break;
20298 case NM_SUBU_S_QB:
20299 check_dsp(ctx);
20300 switch (extract32(ctx->opcode, 10, 1)) {
20301 case 0:
20302 /* SUBU_QB */
20303 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20304 gen_store_gpr(v1_t, ret);
20305 break;
20306 case 1:
20307 /* SUBU_S_QB */
20308 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20309 gen_store_gpr(v1_t, ret);
20310 break;
20312 break;
20313 case NM_SUBU_S_PH:
20314 check_dsp_r2(ctx);
20315 switch (extract32(ctx->opcode, 10, 1)) {
20316 case 0:
20317 /* SUBU_PH */
20318 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20319 gen_store_gpr(v1_t, ret);
20320 break;
20321 case 1:
20322 /* SUBU_S_PH */
20323 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20324 gen_store_gpr(v1_t, ret);
20325 break;
20327 break;
20328 case NM_SUBUH_R_QB:
20329 check_dsp_r2(ctx);
20330 switch (extract32(ctx->opcode, 10, 1)) {
20331 case 0:
20332 /* SUBUH_QB */
20333 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20334 gen_store_gpr(v1_t, ret);
20335 break;
20336 case 1:
20337 /* SUBUH_R_QB */
20338 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20339 gen_store_gpr(v1_t, ret);
20340 break;
20342 break;
20343 case NM_SHLLV_S_PH:
20344 check_dsp(ctx);
20345 switch (extract32(ctx->opcode, 10, 1)) {
20346 case 0:
20347 /* SHLLV_PH */
20348 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20349 gen_store_gpr(v1_t, ret);
20350 break;
20351 case 1:
20352 /* SHLLV_S_PH */
20353 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20354 gen_store_gpr(v1_t, ret);
20355 break;
20357 break;
20358 case NM_PRECR_SRA_R_PH_W:
20359 check_dsp_r2(ctx);
20360 switch (extract32(ctx->opcode, 10, 1)) {
20361 case 0:
20362 /* PRECR_SRA_PH_W */
20364 TCGv_i32 sa_t = tcg_const_i32(rd);
20365 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20366 cpu_gpr[rt]);
20367 gen_store_gpr(v1_t, rt);
20368 tcg_temp_free_i32(sa_t);
20370 break;
20371 case 1:
20372 /* PRECR_SRA_R_PH_W */
20374 TCGv_i32 sa_t = tcg_const_i32(rd);
20375 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20376 cpu_gpr[rt]);
20377 gen_store_gpr(v1_t, rt);
20378 tcg_temp_free_i32(sa_t);
20380 break;
20382 break;
20383 case NM_MULEU_S_PH_QBL:
20384 check_dsp(ctx);
20385 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20386 gen_store_gpr(v1_t, ret);
20387 break;
20388 case NM_MULEU_S_PH_QBR:
20389 check_dsp(ctx);
20390 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20391 gen_store_gpr(v1_t, ret);
20392 break;
20393 case NM_MULQ_RS_PH:
20394 check_dsp(ctx);
20395 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20396 gen_store_gpr(v1_t, ret);
20397 break;
20398 case NM_MULQ_S_PH:
20399 check_dsp_r2(ctx);
20400 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20401 gen_store_gpr(v1_t, ret);
20402 break;
20403 case NM_MULQ_RS_W:
20404 check_dsp_r2(ctx);
20405 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20406 gen_store_gpr(v1_t, ret);
20407 break;
20408 case NM_MULQ_S_W:
20409 check_dsp_r2(ctx);
20410 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20411 gen_store_gpr(v1_t, ret);
20412 break;
20413 case NM_APPEND:
20414 check_dsp_r2(ctx);
20415 gen_load_gpr(t0, rs);
20416 if (rd != 0) {
20417 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20419 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20420 break;
20421 case NM_MODSUB:
20422 check_dsp(ctx);
20423 gen_helper_modsub(v1_t, v1_t, v2_t);
20424 gen_store_gpr(v1_t, ret);
20425 break;
20426 case NM_SHRAV_R_W:
20427 check_dsp(ctx);
20428 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20429 gen_store_gpr(v1_t, ret);
20430 break;
20431 case NM_SHRLV_PH:
20432 check_dsp_r2(ctx);
20433 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20434 gen_store_gpr(v1_t, ret);
20435 break;
20436 case NM_SHRLV_QB:
20437 check_dsp(ctx);
20438 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20439 gen_store_gpr(v1_t, ret);
20440 break;
20441 case NM_SHLLV_QB:
20442 check_dsp(ctx);
20443 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20444 gen_store_gpr(v1_t, ret);
20445 break;
20446 case NM_SHLLV_S_W:
20447 check_dsp(ctx);
20448 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20449 gen_store_gpr(v1_t, ret);
20450 break;
20451 case NM_SHILO:
20452 check_dsp(ctx);
20454 TCGv tv0 = tcg_temp_new();
20455 TCGv tv1 = tcg_temp_new();
20456 int16_t imm = extract32(ctx->opcode, 16, 7);
20458 tcg_gen_movi_tl(tv0, rd >> 3);
20459 tcg_gen_movi_tl(tv1, imm);
20460 gen_helper_shilo(tv0, tv1, cpu_env);
20462 break;
20463 case NM_MULEQ_S_W_PHL:
20464 check_dsp(ctx);
20465 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20466 gen_store_gpr(v1_t, ret);
20467 break;
20468 case NM_MULEQ_S_W_PHR:
20469 check_dsp(ctx);
20470 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20471 gen_store_gpr(v1_t, ret);
20472 break;
20473 case NM_MUL_S_PH:
20474 check_dsp_r2(ctx);
20475 switch (extract32(ctx->opcode, 10, 1)) {
20476 case 0:
20477 /* MUL_PH */
20478 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20479 gen_store_gpr(v1_t, ret);
20480 break;
20481 case 1:
20482 /* MUL_S_PH */
20483 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20484 gen_store_gpr(v1_t, ret);
20485 break;
20487 break;
20488 case NM_PRECR_QB_PH:
20489 check_dsp_r2(ctx);
20490 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20491 gen_store_gpr(v1_t, ret);
20492 break;
20493 case NM_PRECRQ_QB_PH:
20494 check_dsp(ctx);
20495 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20496 gen_store_gpr(v1_t, ret);
20497 break;
20498 case NM_PRECRQ_PH_W:
20499 check_dsp(ctx);
20500 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20501 gen_store_gpr(v1_t, ret);
20502 break;
20503 case NM_PRECRQ_RS_PH_W:
20504 check_dsp(ctx);
20505 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20506 gen_store_gpr(v1_t, ret);
20507 break;
20508 case NM_PRECRQU_S_QB_PH:
20509 check_dsp(ctx);
20510 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20511 gen_store_gpr(v1_t, ret);
20512 break;
20513 case NM_SHRA_R_W:
20514 check_dsp(ctx);
20515 tcg_gen_movi_tl(t0, rd);
20516 gen_helper_shra_r_w(v1_t, t0, v1_t);
20517 gen_store_gpr(v1_t, rt);
20518 break;
20519 case NM_SHRA_R_PH:
20520 check_dsp(ctx);
20521 tcg_gen_movi_tl(t0, rd >> 1);
20522 switch (extract32(ctx->opcode, 10, 1)) {
20523 case 0:
20524 /* SHRA_PH */
20525 gen_helper_shra_ph(v1_t, t0, v1_t);
20526 gen_store_gpr(v1_t, rt);
20527 break;
20528 case 1:
20529 /* SHRA_R_PH */
20530 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20531 gen_store_gpr(v1_t, rt);
20532 break;
20534 break;
20535 case NM_SHLL_S_PH:
20536 check_dsp(ctx);
20537 tcg_gen_movi_tl(t0, rd >> 1);
20538 switch (extract32(ctx->opcode, 10, 2)) {
20539 case 0:
20540 /* SHLL_PH */
20541 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20542 gen_store_gpr(v1_t, rt);
20543 break;
20544 case 2:
20545 /* SHLL_S_PH */
20546 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20547 gen_store_gpr(v1_t, rt);
20548 break;
20549 default:
20550 generate_exception_end(ctx, EXCP_RI);
20551 break;
20553 break;
20554 case NM_SHLL_S_W:
20555 check_dsp(ctx);
20556 tcg_gen_movi_tl(t0, rd);
20557 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20558 gen_store_gpr(v1_t, rt);
20559 break;
20560 case NM_REPL_PH:
20561 check_dsp(ctx);
20563 int16_t imm;
20564 imm = sextract32(ctx->opcode, 11, 11);
20565 imm = (int16_t)(imm << 6) >> 6;
20566 if (rt != 0) {
20567 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20570 break;
20571 default:
20572 generate_exception_end(ctx, EXCP_RI);
20573 break;
20577 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20579 uint16_t insn;
20580 uint32_t op;
20581 int rt, rs, rd;
20582 int offset;
20583 int imm;
20585 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20586 ctx->opcode = (ctx->opcode << 16) | insn;
20588 rt = extract32(ctx->opcode, 21, 5);
20589 rs = extract32(ctx->opcode, 16, 5);
20590 rd = extract32(ctx->opcode, 11, 5);
20592 op = extract32(ctx->opcode, 26, 6);
20593 switch (op) {
20594 case NM_P_ADDIU:
20595 if (rt == 0) {
20596 /* P.RI */
20597 switch (extract32(ctx->opcode, 19, 2)) {
20598 case NM_SIGRIE:
20599 default:
20600 generate_exception_end(ctx, EXCP_RI);
20601 break;
20602 case NM_P_SYSCALL:
20603 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20604 generate_exception_end(ctx, EXCP_SYSCALL);
20605 } else {
20606 generate_exception_end(ctx, EXCP_RI);
20608 break;
20609 case NM_BREAK:
20610 generate_exception_end(ctx, EXCP_BREAK);
20611 break;
20612 case NM_SDBBP:
20613 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20614 gen_helper_do_semihosting(cpu_env);
20615 } else {
20616 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20617 generate_exception_end(ctx, EXCP_RI);
20618 } else {
20619 generate_exception_end(ctx, EXCP_DBp);
20622 break;
20624 } else {
20625 /* NM_ADDIU */
20626 imm = extract32(ctx->opcode, 0, 16);
20627 if (rs != 0) {
20628 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20629 } else {
20630 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20632 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20634 break;
20635 case NM_ADDIUPC:
20636 if (rt != 0) {
20637 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20638 extract32(ctx->opcode, 1, 20) << 1;
20639 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20640 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20642 break;
20643 case NM_POOL32A:
20644 switch (ctx->opcode & 0x07) {
20645 case NM_POOL32A0:
20646 gen_pool32a0_nanomips_insn(env, ctx);
20647 break;
20648 case NM_POOL32A5:
20650 int32_t op1 = extract32(ctx->opcode, 3, 7);
20651 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20653 break;
20654 case NM_POOL32A7:
20655 switch (extract32(ctx->opcode, 3, 3)) {
20656 case NM_P_LSX:
20657 gen_p_lsx(ctx, rd, rs, rt);
20658 break;
20659 case NM_LSA:
20660 /* In nanoMIPS, the shift field directly encodes the shift
20661 * amount, meaning that the supported shift values are in
20662 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20663 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20664 extract32(ctx->opcode, 9, 2) - 1);
20665 break;
20666 case NM_EXTW:
20667 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20668 break;
20669 case NM_POOL32AXF:
20670 gen_pool32axf_nanomips_insn(env, ctx);
20671 break;
20672 default:
20673 generate_exception_end(ctx, EXCP_RI);
20674 break;
20676 break;
20677 default:
20678 generate_exception_end(ctx, EXCP_RI);
20679 break;
20681 break;
20682 case NM_P_GP_W:
20683 switch (ctx->opcode & 0x03) {
20684 case NM_ADDIUGP_W:
20685 if (rt != 0) {
20686 offset = extract32(ctx->opcode, 0, 21);
20687 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20689 break;
20690 case NM_LWGP:
20691 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20692 break;
20693 case NM_SWGP:
20694 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20695 break;
20696 default:
20697 generate_exception_end(ctx, EXCP_RI);
20698 break;
20700 break;
20701 case NM_P48I:
20703 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20704 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20705 switch (extract32(ctx->opcode, 16, 5)) {
20706 case NM_LI48:
20707 check_nms(ctx);
20708 if (rt != 0) {
20709 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20711 break;
20712 case NM_ADDIU48:
20713 check_nms(ctx);
20714 if (rt != 0) {
20715 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20716 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20718 break;
20719 case NM_ADDIUGP48:
20720 check_nms(ctx);
20721 if (rt != 0) {
20722 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20724 break;
20725 case NM_ADDIUPC48:
20726 check_nms(ctx);
20727 if (rt != 0) {
20728 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20729 addr_off);
20731 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20733 break;
20734 case NM_LWPC48:
20735 check_nms(ctx);
20736 if (rt != 0) {
20737 TCGv t0;
20738 t0 = tcg_temp_new();
20740 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20741 addr_off);
20743 tcg_gen_movi_tl(t0, addr);
20744 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20745 tcg_temp_free(t0);
20747 break;
20748 case NM_SWPC48:
20749 check_nms(ctx);
20751 TCGv t0, t1;
20752 t0 = tcg_temp_new();
20753 t1 = tcg_temp_new();
20755 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20756 addr_off);
20758 tcg_gen_movi_tl(t0, addr);
20759 gen_load_gpr(t1, rt);
20761 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20763 tcg_temp_free(t0);
20764 tcg_temp_free(t1);
20766 break;
20767 default:
20768 generate_exception_end(ctx, EXCP_RI);
20769 break;
20771 return 6;
20773 case NM_P_U12:
20774 switch (extract32(ctx->opcode, 12, 4)) {
20775 case NM_ORI:
20776 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20777 break;
20778 case NM_XORI:
20779 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20780 break;
20781 case NM_ANDI:
20782 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20783 break;
20784 case NM_P_SR:
20785 switch (extract32(ctx->opcode, 20, 1)) {
20786 case NM_PP_SR:
20787 switch (ctx->opcode & 3) {
20788 case NM_SAVE:
20789 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20790 extract32(ctx->opcode, 2, 1),
20791 extract32(ctx->opcode, 3, 9) << 3);
20792 break;
20793 case NM_RESTORE:
20794 case NM_RESTORE_JRC:
20795 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20796 extract32(ctx->opcode, 2, 1),
20797 extract32(ctx->opcode, 3, 9) << 3);
20798 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20799 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20801 break;
20802 default:
20803 generate_exception_end(ctx, EXCP_RI);
20804 break;
20806 break;
20807 case NM_P_SR_F:
20808 generate_exception_end(ctx, EXCP_RI);
20809 break;
20811 break;
20812 case NM_SLTI:
20813 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20814 break;
20815 case NM_SLTIU:
20816 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20817 break;
20818 case NM_SEQI:
20820 TCGv t0 = tcg_temp_new();
20822 imm = extract32(ctx->opcode, 0, 12);
20823 gen_load_gpr(t0, rs);
20824 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20825 gen_store_gpr(t0, rt);
20827 tcg_temp_free(t0);
20829 break;
20830 case NM_ADDIUNEG:
20831 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20832 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20833 break;
20834 case NM_P_SHIFT:
20836 int shift = extract32(ctx->opcode, 0, 5);
20837 switch (extract32(ctx->opcode, 5, 4)) {
20838 case NM_P_SLL:
20839 if (rt == 0 && shift == 0) {
20840 /* NOP */
20841 } else if (rt == 0 && shift == 3) {
20842 /* EHB - treat as NOP */
20843 } else if (rt == 0 && shift == 5) {
20844 /* PAUSE - treat as NOP */
20845 } else if (rt == 0 && shift == 6) {
20846 /* SYNC */
20847 gen_sync(extract32(ctx->opcode, 16, 5));
20848 } else {
20849 /* SLL */
20850 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20851 extract32(ctx->opcode, 0, 5));
20853 break;
20854 case NM_SRL:
20855 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20856 extract32(ctx->opcode, 0, 5));
20857 break;
20858 case NM_SRA:
20859 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20860 extract32(ctx->opcode, 0, 5));
20861 break;
20862 case NM_ROTR:
20863 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20864 extract32(ctx->opcode, 0, 5));
20865 break;
20868 break;
20869 case NM_P_ROTX:
20870 check_nms(ctx);
20871 if (rt != 0) {
20872 TCGv t0 = tcg_temp_new();
20873 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20874 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20875 << 1);
20876 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20878 gen_load_gpr(t0, rs);
20879 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20880 tcg_temp_free(t0);
20882 tcg_temp_free_i32(shift);
20883 tcg_temp_free_i32(shiftx);
20884 tcg_temp_free_i32(stripe);
20886 break;
20887 case NM_P_INS:
20888 switch (((ctx->opcode >> 10) & 2) |
20889 (extract32(ctx->opcode, 5, 1))) {
20890 case NM_INS:
20891 check_nms(ctx);
20892 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20893 extract32(ctx->opcode, 6, 5));
20894 break;
20895 default:
20896 generate_exception_end(ctx, EXCP_RI);
20897 break;
20899 break;
20900 case NM_P_EXT:
20901 switch (((ctx->opcode >> 10) & 2) |
20902 (extract32(ctx->opcode, 5, 1))) {
20903 case NM_EXT:
20904 check_nms(ctx);
20905 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20906 extract32(ctx->opcode, 6, 5));
20907 break;
20908 default:
20909 generate_exception_end(ctx, EXCP_RI);
20910 break;
20912 break;
20913 default:
20914 generate_exception_end(ctx, EXCP_RI);
20915 break;
20917 break;
20918 case NM_POOL32F:
20919 gen_pool32f_nanomips_insn(ctx);
20920 break;
20921 case NM_POOL32S:
20922 break;
20923 case NM_P_LUI:
20924 switch (extract32(ctx->opcode, 1, 1)) {
20925 case NM_LUI:
20926 if (rt != 0) {
20927 tcg_gen_movi_tl(cpu_gpr[rt],
20928 sextract32(ctx->opcode, 0, 1) << 31 |
20929 extract32(ctx->opcode, 2, 10) << 21 |
20930 extract32(ctx->opcode, 12, 9) << 12);
20932 break;
20933 case NM_ALUIPC:
20934 if (rt != 0) {
20935 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20936 extract32(ctx->opcode, 2, 10) << 21 |
20937 extract32(ctx->opcode, 12, 9) << 12;
20938 target_long addr;
20939 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20940 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20942 break;
20944 break;
20945 case NM_P_GP_BH:
20947 uint32_t u = extract32(ctx->opcode, 0, 18);
20949 switch (extract32(ctx->opcode, 18, 3)) {
20950 case NM_LBGP:
20951 gen_ld(ctx, OPC_LB, rt, 28, u);
20952 break;
20953 case NM_SBGP:
20954 gen_st(ctx, OPC_SB, rt, 28, u);
20955 break;
20956 case NM_LBUGP:
20957 gen_ld(ctx, OPC_LBU, rt, 28, u);
20958 break;
20959 case NM_ADDIUGP_B:
20960 if (rt != 0) {
20961 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20963 break;
20964 case NM_P_GP_LH:
20965 u &= ~1;
20966 switch (ctx->opcode & 1) {
20967 case NM_LHGP:
20968 gen_ld(ctx, OPC_LH, rt, 28, u);
20969 break;
20970 case NM_LHUGP:
20971 gen_ld(ctx, OPC_LHU, rt, 28, u);
20972 break;
20974 break;
20975 case NM_P_GP_SH:
20976 u &= ~1;
20977 switch (ctx->opcode & 1) {
20978 case NM_SHGP:
20979 gen_st(ctx, OPC_SH, rt, 28, u);
20980 break;
20981 default:
20982 generate_exception_end(ctx, EXCP_RI);
20983 break;
20985 break;
20986 case NM_P_GP_CP1:
20987 u &= ~0x3;
20988 switch (ctx->opcode & 0x3) {
20989 case NM_LWC1GP:
20990 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20991 break;
20992 case NM_LDC1GP:
20993 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20994 break;
20995 case NM_SWC1GP:
20996 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20997 break;
20998 case NM_SDC1GP:
20999 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
21000 break;
21002 break;
21003 default:
21004 generate_exception_end(ctx, EXCP_RI);
21005 break;
21008 break;
21009 case NM_P_LS_U12:
21011 uint32_t u = extract32(ctx->opcode, 0, 12);
21013 switch (extract32(ctx->opcode, 12, 4)) {
21014 case NM_P_PREFU12:
21015 if (rt == 31) {
21016 /* SYNCI */
21017 /* Break the TB to be able to sync copied instructions
21018 immediately */
21019 ctx->base.is_jmp = DISAS_STOP;
21020 } else {
21021 /* PREF */
21022 /* Treat as NOP. */
21024 break;
21025 case NM_LB:
21026 gen_ld(ctx, OPC_LB, rt, rs, u);
21027 break;
21028 case NM_LH:
21029 gen_ld(ctx, OPC_LH, rt, rs, u);
21030 break;
21031 case NM_LW:
21032 gen_ld(ctx, OPC_LW, rt, rs, u);
21033 break;
21034 case NM_LBU:
21035 gen_ld(ctx, OPC_LBU, rt, rs, u);
21036 break;
21037 case NM_LHU:
21038 gen_ld(ctx, OPC_LHU, rt, rs, u);
21039 break;
21040 case NM_SB:
21041 gen_st(ctx, OPC_SB, rt, rs, u);
21042 break;
21043 case NM_SH:
21044 gen_st(ctx, OPC_SH, rt, rs, u);
21045 break;
21046 case NM_SW:
21047 gen_st(ctx, OPC_SW, rt, rs, u);
21048 break;
21049 case NM_LWC1:
21050 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
21051 break;
21052 case NM_LDC1:
21053 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
21054 break;
21055 case NM_SWC1:
21056 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
21057 break;
21058 case NM_SDC1:
21059 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
21060 break;
21061 default:
21062 generate_exception_end(ctx, EXCP_RI);
21063 break;
21066 break;
21067 case NM_P_LS_S9:
21069 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
21070 extract32(ctx->opcode, 0, 8);
21072 switch (extract32(ctx->opcode, 8, 3)) {
21073 case NM_P_LS_S0:
21074 switch (extract32(ctx->opcode, 11, 4)) {
21075 case NM_LBS9:
21076 gen_ld(ctx, OPC_LB, rt, rs, s);
21077 break;
21078 case NM_LHS9:
21079 gen_ld(ctx, OPC_LH, rt, rs, s);
21080 break;
21081 case NM_LWS9:
21082 gen_ld(ctx, OPC_LW, rt, rs, s);
21083 break;
21084 case NM_LBUS9:
21085 gen_ld(ctx, OPC_LBU, rt, rs, s);
21086 break;
21087 case NM_LHUS9:
21088 gen_ld(ctx, OPC_LHU, rt, rs, s);
21089 break;
21090 case NM_SBS9:
21091 gen_st(ctx, OPC_SB, rt, rs, s);
21092 break;
21093 case NM_SHS9:
21094 gen_st(ctx, OPC_SH, rt, rs, s);
21095 break;
21096 case NM_SWS9:
21097 gen_st(ctx, OPC_SW, rt, rs, s);
21098 break;
21099 case NM_LWC1S9:
21100 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
21101 break;
21102 case NM_LDC1S9:
21103 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
21104 break;
21105 case NM_SWC1S9:
21106 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
21107 break;
21108 case NM_SDC1S9:
21109 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
21110 break;
21111 case NM_P_PREFS9:
21112 if (rt == 31) {
21113 /* SYNCI */
21114 /* Break the TB to be able to sync copied instructions
21115 immediately */
21116 ctx->base.is_jmp = DISAS_STOP;
21117 } else {
21118 /* PREF */
21119 /* Treat as NOP. */
21121 break;
21122 default:
21123 generate_exception_end(ctx, EXCP_RI);
21124 break;
21126 break;
21127 case NM_P_LS_S1:
21128 switch (extract32(ctx->opcode, 11, 4)) {
21129 case NM_UALH:
21130 case NM_UASH:
21131 check_nms(ctx);
21133 TCGv t0 = tcg_temp_new();
21134 TCGv t1 = tcg_temp_new();
21136 gen_base_offset_addr(ctx, t0, rs, s);
21138 switch (extract32(ctx->opcode, 11, 4)) {
21139 case NM_UALH:
21140 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
21141 MO_UNALN);
21142 gen_store_gpr(t0, rt);
21143 break;
21144 case NM_UASH:
21145 gen_load_gpr(t1, rt);
21146 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
21147 MO_UNALN);
21148 break;
21150 tcg_temp_free(t0);
21151 tcg_temp_free(t1);
21153 break;
21154 case NM_P_LL:
21155 switch (ctx->opcode & 0x03) {
21156 case NM_LL:
21157 gen_ld(ctx, OPC_LL, rt, rs, s);
21158 break;
21159 case NM_LLWP:
21160 check_xnp(ctx);
21161 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21162 break;
21164 break;
21165 case NM_P_SC:
21166 switch (ctx->opcode & 0x03) {
21167 case NM_SC:
21168 gen_st_cond(ctx, OPC_SC, rt, rs, s);
21169 break;
21170 case NM_SCWP:
21171 check_xnp(ctx);
21172 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
21173 break;
21175 break;
21176 case NM_CACHE:
21177 check_cp0_enabled(ctx);
21178 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
21179 gen_cache_operation(ctx, rt, rs, s);
21181 break;
21183 break;
21184 case NM_P_LS_WM:
21185 case NM_P_LS_UAWM:
21186 check_nms(ctx);
21188 int count = extract32(ctx->opcode, 12, 3);
21189 int counter = 0;
21191 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21192 extract32(ctx->opcode, 0, 8);
21193 TCGv va = tcg_temp_new();
21194 TCGv t1 = tcg_temp_new();
21195 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21196 NM_P_LS_UAWM ? MO_UNALN : 0;
21198 count = (count == 0) ? 8 : count;
21199 while (counter != count) {
21200 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21201 int this_offset = offset + (counter << 2);
21203 gen_base_offset_addr(ctx, va, rs, this_offset);
21205 switch (extract32(ctx->opcode, 11, 1)) {
21206 case NM_LWM:
21207 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21208 memop | MO_TESL);
21209 gen_store_gpr(t1, this_rt);
21210 if ((this_rt == rs) &&
21211 (counter != (count - 1))) {
21212 /* UNPREDICTABLE */
21214 break;
21215 case NM_SWM:
21216 this_rt = (rt == 0) ? 0 : this_rt;
21217 gen_load_gpr(t1, this_rt);
21218 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21219 memop | MO_TEUL);
21220 break;
21222 counter++;
21224 tcg_temp_free(va);
21225 tcg_temp_free(t1);
21227 break;
21228 default:
21229 generate_exception_end(ctx, EXCP_RI);
21230 break;
21233 break;
21234 case NM_MOVE_BALC:
21235 check_nms(ctx);
21237 TCGv t0 = tcg_temp_new();
21238 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21239 extract32(ctx->opcode, 1, 20) << 1;
21240 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21241 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21242 extract32(ctx->opcode, 21, 3));
21243 gen_load_gpr(t0, rt);
21244 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21245 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21246 tcg_temp_free(t0);
21248 break;
21249 case NM_P_BAL:
21251 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21252 extract32(ctx->opcode, 1, 24) << 1;
21254 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21255 /* BC */
21256 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21257 } else {
21258 /* BALC */
21259 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21262 break;
21263 case NM_P_J:
21264 switch (extract32(ctx->opcode, 12, 4)) {
21265 case NM_JALRC:
21266 case NM_JALRC_HB:
21267 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21268 break;
21269 case NM_P_BALRSC:
21270 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21271 break;
21272 default:
21273 generate_exception_end(ctx, EXCP_RI);
21274 break;
21276 break;
21277 case NM_P_BR1:
21279 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21280 extract32(ctx->opcode, 1, 13) << 1;
21281 switch (extract32(ctx->opcode, 14, 2)) {
21282 case NM_BEQC:
21283 check_nms(ctx);
21284 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21285 break;
21286 case NM_P_BR3A:
21287 s = sextract32(ctx->opcode, 0, 1) << 14 |
21288 extract32(ctx->opcode, 1, 13) << 1;
21289 check_cp1_enabled(ctx);
21290 switch (extract32(ctx->opcode, 16, 5)) {
21291 case NM_BC1EQZC:
21292 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21293 break;
21294 case NM_BC1NEZC:
21295 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21296 break;
21297 case NM_BPOSGE32C:
21298 check_dsp_r3(ctx);
21300 int32_t imm = extract32(ctx->opcode, 1, 13) |
21301 extract32(ctx->opcode, 0, 1) << 13;
21303 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21304 imm);
21306 break;
21307 default:
21308 generate_exception_end(ctx, EXCP_RI);
21309 break;
21311 break;
21312 case NM_BGEC:
21313 if (rs == rt) {
21314 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21315 } else {
21316 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21318 break;
21319 case NM_BGEUC:
21320 if (rs == rt || rt == 0) {
21321 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21322 } else if (rs == 0) {
21323 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21324 } else {
21325 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21327 break;
21330 break;
21331 case NM_P_BR2:
21333 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21334 extract32(ctx->opcode, 1, 13) << 1;
21335 switch (extract32(ctx->opcode, 14, 2)) {
21336 case NM_BNEC:
21337 check_nms(ctx);
21338 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21339 break;
21340 case NM_BLTC:
21341 if (rs != 0 && rt != 0 && rs == rt) {
21342 /* NOP */
21343 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21344 } else {
21345 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21347 break;
21348 case NM_BLTUC:
21349 if (rs == 0 || rs == rt) {
21350 /* NOP */
21351 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21352 } else {
21353 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21355 break;
21356 default:
21357 generate_exception_end(ctx, EXCP_RI);
21358 break;
21361 break;
21362 case NM_P_BRI:
21364 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21365 extract32(ctx->opcode, 1, 10) << 1;
21366 uint32_t u = extract32(ctx->opcode, 11, 7);
21368 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21369 rt, u, s);
21371 break;
21372 default:
21373 generate_exception_end(ctx, EXCP_RI);
21374 break;
21376 return 4;
21379 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21381 uint32_t op;
21382 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21383 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21384 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21385 int offset;
21386 int imm;
21388 /* make sure instructions are on a halfword boundary */
21389 if (ctx->base.pc_next & 0x1) {
21390 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21391 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21392 tcg_temp_free(tmp);
21393 generate_exception_end(ctx, EXCP_AdEL);
21394 return 2;
21397 op = extract32(ctx->opcode, 10, 6);
21398 switch (op) {
21399 case NM_P16_MV:
21400 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21401 if (rt != 0) {
21402 /* MOVE */
21403 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21404 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21405 } else {
21406 /* P16.RI */
21407 switch (extract32(ctx->opcode, 3, 2)) {
21408 case NM_P16_SYSCALL:
21409 if (extract32(ctx->opcode, 2, 1) == 0) {
21410 generate_exception_end(ctx, EXCP_SYSCALL);
21411 } else {
21412 generate_exception_end(ctx, EXCP_RI);
21414 break;
21415 case NM_BREAK16:
21416 generate_exception_end(ctx, EXCP_BREAK);
21417 break;
21418 case NM_SDBBP16:
21419 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21420 gen_helper_do_semihosting(cpu_env);
21421 } else {
21422 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21423 generate_exception_end(ctx, EXCP_RI);
21424 } else {
21425 generate_exception_end(ctx, EXCP_DBp);
21428 break;
21429 default:
21430 generate_exception_end(ctx, EXCP_RI);
21431 break;
21434 break;
21435 case NM_P16_SHIFT:
21437 int shift = extract32(ctx->opcode, 0, 3);
21438 uint32_t opc = 0;
21439 shift = (shift == 0) ? 8 : shift;
21441 switch (extract32(ctx->opcode, 3, 1)) {
21442 case NM_SLL16:
21443 opc = OPC_SLL;
21444 break;
21445 case NM_SRL16:
21446 opc = OPC_SRL;
21447 break;
21449 gen_shift_imm(ctx, opc, rt, rs, shift);
21451 break;
21452 case NM_P16C:
21453 switch (ctx->opcode & 1) {
21454 case NM_POOL16C_0:
21455 gen_pool16c_nanomips_insn(ctx);
21456 break;
21457 case NM_LWXS16:
21458 gen_ldxs(ctx, rt, rs, rd);
21459 break;
21461 break;
21462 case NM_P16_A1:
21463 switch (extract32(ctx->opcode, 6, 1)) {
21464 case NM_ADDIUR1SP:
21465 imm = extract32(ctx->opcode, 0, 6) << 2;
21466 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21467 break;
21468 default:
21469 generate_exception_end(ctx, EXCP_RI);
21470 break;
21472 break;
21473 case NM_P16_A2:
21474 switch (extract32(ctx->opcode, 3, 1)) {
21475 case NM_ADDIUR2:
21476 imm = extract32(ctx->opcode, 0, 3) << 2;
21477 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21478 break;
21479 case NM_P_ADDIURS5:
21480 rt = extract32(ctx->opcode, 5, 5);
21481 if (rt != 0) {
21482 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21483 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21484 (extract32(ctx->opcode, 0, 3));
21485 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21487 break;
21489 break;
21490 case NM_P16_ADDU:
21491 switch (ctx->opcode & 0x1) {
21492 case NM_ADDU16:
21493 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21494 break;
21495 case NM_SUBU16:
21496 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21497 break;
21499 break;
21500 case NM_P16_4X4:
21501 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21502 extract32(ctx->opcode, 5, 3);
21503 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21504 extract32(ctx->opcode, 0, 3);
21505 rt = decode_gpr_gpr4(rt);
21506 rs = decode_gpr_gpr4(rs);
21507 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21508 (extract32(ctx->opcode, 3, 1))) {
21509 case NM_ADDU4X4:
21510 check_nms(ctx);
21511 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21512 break;
21513 case NM_MUL4X4:
21514 check_nms(ctx);
21515 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21516 break;
21517 default:
21518 generate_exception_end(ctx, EXCP_RI);
21519 break;
21521 break;
21522 case NM_LI16:
21524 int imm = extract32(ctx->opcode, 0, 7);
21525 imm = (imm == 0x7f ? -1 : imm);
21526 if (rt != 0) {
21527 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21530 break;
21531 case NM_ANDI16:
21533 uint32_t u = extract32(ctx->opcode, 0, 4);
21534 u = (u == 12) ? 0xff :
21535 (u == 13) ? 0xffff : u;
21536 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21538 break;
21539 case NM_P16_LB:
21540 offset = extract32(ctx->opcode, 0, 2);
21541 switch (extract32(ctx->opcode, 2, 2)) {
21542 case NM_LB16:
21543 gen_ld(ctx, OPC_LB, rt, rs, offset);
21544 break;
21545 case NM_SB16:
21546 rt = decode_gpr_gpr3_src_store(
21547 NANOMIPS_EXTRACT_RD(ctx->opcode));
21548 gen_st(ctx, OPC_SB, rt, rs, offset);
21549 break;
21550 case NM_LBU16:
21551 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21552 break;
21553 default:
21554 generate_exception_end(ctx, EXCP_RI);
21555 break;
21557 break;
21558 case NM_P16_LH:
21559 offset = extract32(ctx->opcode, 1, 2) << 1;
21560 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21561 case NM_LH16:
21562 gen_ld(ctx, OPC_LH, rt, rs, offset);
21563 break;
21564 case NM_SH16:
21565 rt = decode_gpr_gpr3_src_store(
21566 NANOMIPS_EXTRACT_RD(ctx->opcode));
21567 gen_st(ctx, OPC_SH, rt, rs, offset);
21568 break;
21569 case NM_LHU16:
21570 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21571 break;
21572 default:
21573 generate_exception_end(ctx, EXCP_RI);
21574 break;
21576 break;
21577 case NM_LW16:
21578 offset = extract32(ctx->opcode, 0, 4) << 2;
21579 gen_ld(ctx, OPC_LW, rt, rs, offset);
21580 break;
21581 case NM_LWSP16:
21582 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21583 offset = extract32(ctx->opcode, 0, 5) << 2;
21584 gen_ld(ctx, OPC_LW, rt, 29, offset);
21585 break;
21586 case NM_LW4X4:
21587 check_nms(ctx);
21588 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21589 extract32(ctx->opcode, 5, 3);
21590 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21591 extract32(ctx->opcode, 0, 3);
21592 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21593 (extract32(ctx->opcode, 8, 1) << 2);
21594 rt = decode_gpr_gpr4(rt);
21595 rs = decode_gpr_gpr4(rs);
21596 gen_ld(ctx, OPC_LW, rt, rs, offset);
21597 break;
21598 case NM_SW4X4:
21599 check_nms(ctx);
21600 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21601 extract32(ctx->opcode, 5, 3);
21602 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21603 extract32(ctx->opcode, 0, 3);
21604 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21605 (extract32(ctx->opcode, 8, 1) << 2);
21606 rt = decode_gpr_gpr4_zero(rt);
21607 rs = decode_gpr_gpr4(rs);
21608 gen_st(ctx, OPC_SW, rt, rs, offset);
21609 break;
21610 case NM_LWGP16:
21611 offset = extract32(ctx->opcode, 0, 7) << 2;
21612 gen_ld(ctx, OPC_LW, rt, 28, offset);
21613 break;
21614 case NM_SWSP16:
21615 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21616 offset = extract32(ctx->opcode, 0, 5) << 2;
21617 gen_st(ctx, OPC_SW, rt, 29, offset);
21618 break;
21619 case NM_SW16:
21620 rt = decode_gpr_gpr3_src_store(
21621 NANOMIPS_EXTRACT_RD(ctx->opcode));
21622 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21623 offset = extract32(ctx->opcode, 0, 4) << 2;
21624 gen_st(ctx, OPC_SW, rt, rs, offset);
21625 break;
21626 case NM_SWGP16:
21627 rt = decode_gpr_gpr3_src_store(
21628 NANOMIPS_EXTRACT_RD(ctx->opcode));
21629 offset = extract32(ctx->opcode, 0, 7) << 2;
21630 gen_st(ctx, OPC_SW, rt, 28, offset);
21631 break;
21632 case NM_BC16:
21633 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21634 (sextract32(ctx->opcode, 0, 1) << 10) |
21635 (extract32(ctx->opcode, 1, 9) << 1));
21636 break;
21637 case NM_BALC16:
21638 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21639 (sextract32(ctx->opcode, 0, 1) << 10) |
21640 (extract32(ctx->opcode, 1, 9) << 1));
21641 break;
21642 case NM_BEQZC16:
21643 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21644 (sextract32(ctx->opcode, 0, 1) << 7) |
21645 (extract32(ctx->opcode, 1, 6) << 1));
21646 break;
21647 case NM_BNEZC16:
21648 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21649 (sextract32(ctx->opcode, 0, 1) << 7) |
21650 (extract32(ctx->opcode, 1, 6) << 1));
21651 break;
21652 case NM_P16_BR:
21653 switch (ctx->opcode & 0xf) {
21654 case 0:
21655 /* P16.JRC */
21656 switch (extract32(ctx->opcode, 4, 1)) {
21657 case NM_JRC:
21658 gen_compute_branch_nm(ctx, OPC_JR, 2,
21659 extract32(ctx->opcode, 5, 5), 0, 0);
21660 break;
21661 case NM_JALRC16:
21662 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21663 extract32(ctx->opcode, 5, 5), 31, 0);
21664 break;
21666 break;
21667 default:
21669 /* P16.BRI */
21670 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21671 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21672 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21673 extract32(ctx->opcode, 0, 4) << 1);
21675 break;
21677 break;
21678 case NM_P16_SR:
21680 int count = extract32(ctx->opcode, 0, 4);
21681 int u = extract32(ctx->opcode, 4, 4) << 4;
21683 rt = 30 + extract32(ctx->opcode, 9, 1);
21684 switch (extract32(ctx->opcode, 8, 1)) {
21685 case NM_SAVE16:
21686 gen_save(ctx, rt, count, 0, u);
21687 break;
21688 case NM_RESTORE_JRC16:
21689 gen_restore(ctx, rt, count, 0, u);
21690 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21691 break;
21694 break;
21695 case NM_MOVEP:
21696 case NM_MOVEPREV:
21697 check_nms(ctx);
21699 static const int gpr2reg1[] = {4, 5, 6, 7};
21700 static const int gpr2reg2[] = {5, 6, 7, 8};
21701 int re;
21702 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21703 extract32(ctx->opcode, 8, 1);
21704 int r1 = gpr2reg1[rd2];
21705 int r2 = gpr2reg2[rd2];
21706 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21707 extract32(ctx->opcode, 0, 3);
21708 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21709 extract32(ctx->opcode, 5, 3);
21710 TCGv t0 = tcg_temp_new();
21711 TCGv t1 = tcg_temp_new();
21712 if (op == NM_MOVEP) {
21713 rd = r1;
21714 re = r2;
21715 rs = decode_gpr_gpr4_zero(r3);
21716 rt = decode_gpr_gpr4_zero(r4);
21717 } else {
21718 rd = decode_gpr_gpr4(r3);
21719 re = decode_gpr_gpr4(r4);
21720 rs = r1;
21721 rt = r2;
21723 gen_load_gpr(t0, rs);
21724 gen_load_gpr(t1, rt);
21725 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21726 tcg_gen_mov_tl(cpu_gpr[re], t1);
21727 tcg_temp_free(t0);
21728 tcg_temp_free(t1);
21730 break;
21731 default:
21732 return decode_nanomips_32_48_opc(env, ctx);
21735 return 2;
21739 /* SmartMIPS extension to MIPS32 */
21741 #if defined(TARGET_MIPS64)
21743 /* MDMX extension to MIPS64 */
21745 #endif
21747 /* MIPSDSP functions. */
21748 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21749 int rd, int base, int offset)
21751 TCGv t0;
21753 check_dsp(ctx);
21754 t0 = tcg_temp_new();
21756 if (base == 0) {
21757 gen_load_gpr(t0, offset);
21758 } else if (offset == 0) {
21759 gen_load_gpr(t0, base);
21760 } else {
21761 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21764 switch (opc) {
21765 case OPC_LBUX:
21766 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21767 gen_store_gpr(t0, rd);
21768 break;
21769 case OPC_LHX:
21770 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21771 gen_store_gpr(t0, rd);
21772 break;
21773 case OPC_LWX:
21774 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21775 gen_store_gpr(t0, rd);
21776 break;
21777 #if defined(TARGET_MIPS64)
21778 case OPC_LDX:
21779 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21780 gen_store_gpr(t0, rd);
21781 break;
21782 #endif
21784 tcg_temp_free(t0);
21787 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21788 int ret, int v1, int v2)
21790 TCGv v1_t;
21791 TCGv v2_t;
21793 if (ret == 0) {
21794 /* Treat as NOP. */
21795 return;
21798 v1_t = tcg_temp_new();
21799 v2_t = tcg_temp_new();
21801 gen_load_gpr(v1_t, v1);
21802 gen_load_gpr(v2_t, v2);
21804 switch (op1) {
21805 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21806 case OPC_MULT_G_2E:
21807 check_dsp_r2(ctx);
21808 switch (op2) {
21809 case OPC_ADDUH_QB:
21810 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21811 break;
21812 case OPC_ADDUH_R_QB:
21813 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21814 break;
21815 case OPC_ADDQH_PH:
21816 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21817 break;
21818 case OPC_ADDQH_R_PH:
21819 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21820 break;
21821 case OPC_ADDQH_W:
21822 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21823 break;
21824 case OPC_ADDQH_R_W:
21825 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21826 break;
21827 case OPC_SUBUH_QB:
21828 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21829 break;
21830 case OPC_SUBUH_R_QB:
21831 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21832 break;
21833 case OPC_SUBQH_PH:
21834 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21835 break;
21836 case OPC_SUBQH_R_PH:
21837 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21838 break;
21839 case OPC_SUBQH_W:
21840 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21841 break;
21842 case OPC_SUBQH_R_W:
21843 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21844 break;
21846 break;
21847 case OPC_ABSQ_S_PH_DSP:
21848 switch (op2) {
21849 case OPC_ABSQ_S_QB:
21850 check_dsp_r2(ctx);
21851 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21852 break;
21853 case OPC_ABSQ_S_PH:
21854 check_dsp(ctx);
21855 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21856 break;
21857 case OPC_ABSQ_S_W:
21858 check_dsp(ctx);
21859 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21860 break;
21861 case OPC_PRECEQ_W_PHL:
21862 check_dsp(ctx);
21863 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21864 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21865 break;
21866 case OPC_PRECEQ_W_PHR:
21867 check_dsp(ctx);
21868 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21869 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21870 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21871 break;
21872 case OPC_PRECEQU_PH_QBL:
21873 check_dsp(ctx);
21874 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21875 break;
21876 case OPC_PRECEQU_PH_QBR:
21877 check_dsp(ctx);
21878 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21879 break;
21880 case OPC_PRECEQU_PH_QBLA:
21881 check_dsp(ctx);
21882 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21883 break;
21884 case OPC_PRECEQU_PH_QBRA:
21885 check_dsp(ctx);
21886 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21887 break;
21888 case OPC_PRECEU_PH_QBL:
21889 check_dsp(ctx);
21890 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21891 break;
21892 case OPC_PRECEU_PH_QBR:
21893 check_dsp(ctx);
21894 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21895 break;
21896 case OPC_PRECEU_PH_QBLA:
21897 check_dsp(ctx);
21898 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21899 break;
21900 case OPC_PRECEU_PH_QBRA:
21901 check_dsp(ctx);
21902 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21903 break;
21905 break;
21906 case OPC_ADDU_QB_DSP:
21907 switch (op2) {
21908 case OPC_ADDQ_PH:
21909 check_dsp(ctx);
21910 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21911 break;
21912 case OPC_ADDQ_S_PH:
21913 check_dsp(ctx);
21914 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21915 break;
21916 case OPC_ADDQ_S_W:
21917 check_dsp(ctx);
21918 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21919 break;
21920 case OPC_ADDU_QB:
21921 check_dsp(ctx);
21922 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21923 break;
21924 case OPC_ADDU_S_QB:
21925 check_dsp(ctx);
21926 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21927 break;
21928 case OPC_ADDU_PH:
21929 check_dsp_r2(ctx);
21930 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21931 break;
21932 case OPC_ADDU_S_PH:
21933 check_dsp_r2(ctx);
21934 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21935 break;
21936 case OPC_SUBQ_PH:
21937 check_dsp(ctx);
21938 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21939 break;
21940 case OPC_SUBQ_S_PH:
21941 check_dsp(ctx);
21942 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21943 break;
21944 case OPC_SUBQ_S_W:
21945 check_dsp(ctx);
21946 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21947 break;
21948 case OPC_SUBU_QB:
21949 check_dsp(ctx);
21950 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21951 break;
21952 case OPC_SUBU_S_QB:
21953 check_dsp(ctx);
21954 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21955 break;
21956 case OPC_SUBU_PH:
21957 check_dsp_r2(ctx);
21958 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21959 break;
21960 case OPC_SUBU_S_PH:
21961 check_dsp_r2(ctx);
21962 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21963 break;
21964 case OPC_ADDSC:
21965 check_dsp(ctx);
21966 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21967 break;
21968 case OPC_ADDWC:
21969 check_dsp(ctx);
21970 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21971 break;
21972 case OPC_MODSUB:
21973 check_dsp(ctx);
21974 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21975 break;
21976 case OPC_RADDU_W_QB:
21977 check_dsp(ctx);
21978 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21979 break;
21981 break;
21982 case OPC_CMPU_EQ_QB_DSP:
21983 switch (op2) {
21984 case OPC_PRECR_QB_PH:
21985 check_dsp_r2(ctx);
21986 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21987 break;
21988 case OPC_PRECRQ_QB_PH:
21989 check_dsp(ctx);
21990 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21991 break;
21992 case OPC_PRECR_SRA_PH_W:
21993 check_dsp_r2(ctx);
21995 TCGv_i32 sa_t = tcg_const_i32(v2);
21996 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21997 cpu_gpr[ret]);
21998 tcg_temp_free_i32(sa_t);
21999 break;
22001 case OPC_PRECR_SRA_R_PH_W:
22002 check_dsp_r2(ctx);
22004 TCGv_i32 sa_t = tcg_const_i32(v2);
22005 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
22006 cpu_gpr[ret]);
22007 tcg_temp_free_i32(sa_t);
22008 break;
22010 case OPC_PRECRQ_PH_W:
22011 check_dsp(ctx);
22012 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
22013 break;
22014 case OPC_PRECRQ_RS_PH_W:
22015 check_dsp(ctx);
22016 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22017 break;
22018 case OPC_PRECRQU_S_QB_PH:
22019 check_dsp(ctx);
22020 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22021 break;
22023 break;
22024 #ifdef TARGET_MIPS64
22025 case OPC_ABSQ_S_QH_DSP:
22026 switch (op2) {
22027 case OPC_PRECEQ_L_PWL:
22028 check_dsp(ctx);
22029 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
22030 break;
22031 case OPC_PRECEQ_L_PWR:
22032 check_dsp(ctx);
22033 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
22034 break;
22035 case OPC_PRECEQ_PW_QHL:
22036 check_dsp(ctx);
22037 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
22038 break;
22039 case OPC_PRECEQ_PW_QHR:
22040 check_dsp(ctx);
22041 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
22042 break;
22043 case OPC_PRECEQ_PW_QHLA:
22044 check_dsp(ctx);
22045 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
22046 break;
22047 case OPC_PRECEQ_PW_QHRA:
22048 check_dsp(ctx);
22049 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
22050 break;
22051 case OPC_PRECEQU_QH_OBL:
22052 check_dsp(ctx);
22053 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
22054 break;
22055 case OPC_PRECEQU_QH_OBR:
22056 check_dsp(ctx);
22057 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
22058 break;
22059 case OPC_PRECEQU_QH_OBLA:
22060 check_dsp(ctx);
22061 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
22062 break;
22063 case OPC_PRECEQU_QH_OBRA:
22064 check_dsp(ctx);
22065 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
22066 break;
22067 case OPC_PRECEU_QH_OBL:
22068 check_dsp(ctx);
22069 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
22070 break;
22071 case OPC_PRECEU_QH_OBR:
22072 check_dsp(ctx);
22073 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
22074 break;
22075 case OPC_PRECEU_QH_OBLA:
22076 check_dsp(ctx);
22077 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
22078 break;
22079 case OPC_PRECEU_QH_OBRA:
22080 check_dsp(ctx);
22081 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
22082 break;
22083 case OPC_ABSQ_S_OB:
22084 check_dsp_r2(ctx);
22085 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
22086 break;
22087 case OPC_ABSQ_S_PW:
22088 check_dsp(ctx);
22089 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
22090 break;
22091 case OPC_ABSQ_S_QH:
22092 check_dsp(ctx);
22093 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
22094 break;
22096 break;
22097 case OPC_ADDU_OB_DSP:
22098 switch (op2) {
22099 case OPC_RADDU_L_OB:
22100 check_dsp(ctx);
22101 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
22102 break;
22103 case OPC_SUBQ_PW:
22104 check_dsp(ctx);
22105 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22106 break;
22107 case OPC_SUBQ_S_PW:
22108 check_dsp(ctx);
22109 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22110 break;
22111 case OPC_SUBQ_QH:
22112 check_dsp(ctx);
22113 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22114 break;
22115 case OPC_SUBQ_S_QH:
22116 check_dsp(ctx);
22117 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22118 break;
22119 case OPC_SUBU_OB:
22120 check_dsp(ctx);
22121 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22122 break;
22123 case OPC_SUBU_S_OB:
22124 check_dsp(ctx);
22125 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22126 break;
22127 case OPC_SUBU_QH:
22128 check_dsp_r2(ctx);
22129 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22130 break;
22131 case OPC_SUBU_S_QH:
22132 check_dsp_r2(ctx);
22133 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22134 break;
22135 case OPC_SUBUH_OB:
22136 check_dsp_r2(ctx);
22137 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
22138 break;
22139 case OPC_SUBUH_R_OB:
22140 check_dsp_r2(ctx);
22141 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22142 break;
22143 case OPC_ADDQ_PW:
22144 check_dsp(ctx);
22145 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22146 break;
22147 case OPC_ADDQ_S_PW:
22148 check_dsp(ctx);
22149 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22150 break;
22151 case OPC_ADDQ_QH:
22152 check_dsp(ctx);
22153 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22154 break;
22155 case OPC_ADDQ_S_QH:
22156 check_dsp(ctx);
22157 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22158 break;
22159 case OPC_ADDU_OB:
22160 check_dsp(ctx);
22161 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22162 break;
22163 case OPC_ADDU_S_OB:
22164 check_dsp(ctx);
22165 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22166 break;
22167 case OPC_ADDU_QH:
22168 check_dsp_r2(ctx);
22169 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22170 break;
22171 case OPC_ADDU_S_QH:
22172 check_dsp_r2(ctx);
22173 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22174 break;
22175 case OPC_ADDUH_OB:
22176 check_dsp_r2(ctx);
22177 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22178 break;
22179 case OPC_ADDUH_R_OB:
22180 check_dsp_r2(ctx);
22181 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22182 break;
22184 break;
22185 case OPC_CMPU_EQ_OB_DSP:
22186 switch (op2) {
22187 case OPC_PRECR_OB_QH:
22188 check_dsp_r2(ctx);
22189 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22190 break;
22191 case OPC_PRECR_SRA_QH_PW:
22192 check_dsp_r2(ctx);
22194 TCGv_i32 ret_t = tcg_const_i32(ret);
22195 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22196 tcg_temp_free_i32(ret_t);
22197 break;
22199 case OPC_PRECR_SRA_R_QH_PW:
22200 check_dsp_r2(ctx);
22202 TCGv_i32 sa_v = tcg_const_i32(ret);
22203 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22204 tcg_temp_free_i32(sa_v);
22205 break;
22207 case OPC_PRECRQ_OB_QH:
22208 check_dsp(ctx);
22209 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22210 break;
22211 case OPC_PRECRQ_PW_L:
22212 check_dsp(ctx);
22213 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22214 break;
22215 case OPC_PRECRQ_QH_PW:
22216 check_dsp(ctx);
22217 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22218 break;
22219 case OPC_PRECRQ_RS_QH_PW:
22220 check_dsp(ctx);
22221 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22222 break;
22223 case OPC_PRECRQU_S_OB_QH:
22224 check_dsp(ctx);
22225 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22226 break;
22228 break;
22229 #endif
22232 tcg_temp_free(v1_t);
22233 tcg_temp_free(v2_t);
22236 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22237 int ret, int v1, int v2)
22239 uint32_t op2;
22240 TCGv t0;
22241 TCGv v1_t;
22242 TCGv v2_t;
22244 if (ret == 0) {
22245 /* Treat as NOP. */
22246 return;
22249 t0 = tcg_temp_new();
22250 v1_t = tcg_temp_new();
22251 v2_t = tcg_temp_new();
22253 tcg_gen_movi_tl(t0, v1);
22254 gen_load_gpr(v1_t, v1);
22255 gen_load_gpr(v2_t, v2);
22257 switch (opc) {
22258 case OPC_SHLL_QB_DSP:
22260 op2 = MASK_SHLL_QB(ctx->opcode);
22261 switch (op2) {
22262 case OPC_SHLL_QB:
22263 check_dsp(ctx);
22264 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22265 break;
22266 case OPC_SHLLV_QB:
22267 check_dsp(ctx);
22268 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22269 break;
22270 case OPC_SHLL_PH:
22271 check_dsp(ctx);
22272 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22273 break;
22274 case OPC_SHLLV_PH:
22275 check_dsp(ctx);
22276 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22277 break;
22278 case OPC_SHLL_S_PH:
22279 check_dsp(ctx);
22280 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22281 break;
22282 case OPC_SHLLV_S_PH:
22283 check_dsp(ctx);
22284 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22285 break;
22286 case OPC_SHLL_S_W:
22287 check_dsp(ctx);
22288 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22289 break;
22290 case OPC_SHLLV_S_W:
22291 check_dsp(ctx);
22292 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22293 break;
22294 case OPC_SHRL_QB:
22295 check_dsp(ctx);
22296 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22297 break;
22298 case OPC_SHRLV_QB:
22299 check_dsp(ctx);
22300 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22301 break;
22302 case OPC_SHRL_PH:
22303 check_dsp_r2(ctx);
22304 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22305 break;
22306 case OPC_SHRLV_PH:
22307 check_dsp_r2(ctx);
22308 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22309 break;
22310 case OPC_SHRA_QB:
22311 check_dsp_r2(ctx);
22312 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22313 break;
22314 case OPC_SHRA_R_QB:
22315 check_dsp_r2(ctx);
22316 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22317 break;
22318 case OPC_SHRAV_QB:
22319 check_dsp_r2(ctx);
22320 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22321 break;
22322 case OPC_SHRAV_R_QB:
22323 check_dsp_r2(ctx);
22324 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22325 break;
22326 case OPC_SHRA_PH:
22327 check_dsp(ctx);
22328 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22329 break;
22330 case OPC_SHRA_R_PH:
22331 check_dsp(ctx);
22332 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22333 break;
22334 case OPC_SHRAV_PH:
22335 check_dsp(ctx);
22336 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22337 break;
22338 case OPC_SHRAV_R_PH:
22339 check_dsp(ctx);
22340 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22341 break;
22342 case OPC_SHRA_R_W:
22343 check_dsp(ctx);
22344 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22345 break;
22346 case OPC_SHRAV_R_W:
22347 check_dsp(ctx);
22348 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22349 break;
22350 default: /* Invalid */
22351 MIPS_INVAL("MASK SHLL.QB");
22352 generate_exception_end(ctx, EXCP_RI);
22353 break;
22355 break;
22357 #ifdef TARGET_MIPS64
22358 case OPC_SHLL_OB_DSP:
22359 op2 = MASK_SHLL_OB(ctx->opcode);
22360 switch (op2) {
22361 case OPC_SHLL_PW:
22362 check_dsp(ctx);
22363 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22364 break;
22365 case OPC_SHLLV_PW:
22366 check_dsp(ctx);
22367 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22368 break;
22369 case OPC_SHLL_S_PW:
22370 check_dsp(ctx);
22371 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22372 break;
22373 case OPC_SHLLV_S_PW:
22374 check_dsp(ctx);
22375 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22376 break;
22377 case OPC_SHLL_OB:
22378 check_dsp(ctx);
22379 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22380 break;
22381 case OPC_SHLLV_OB:
22382 check_dsp(ctx);
22383 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22384 break;
22385 case OPC_SHLL_QH:
22386 check_dsp(ctx);
22387 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22388 break;
22389 case OPC_SHLLV_QH:
22390 check_dsp(ctx);
22391 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22392 break;
22393 case OPC_SHLL_S_QH:
22394 check_dsp(ctx);
22395 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22396 break;
22397 case OPC_SHLLV_S_QH:
22398 check_dsp(ctx);
22399 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22400 break;
22401 case OPC_SHRA_OB:
22402 check_dsp_r2(ctx);
22403 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22404 break;
22405 case OPC_SHRAV_OB:
22406 check_dsp_r2(ctx);
22407 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22408 break;
22409 case OPC_SHRA_R_OB:
22410 check_dsp_r2(ctx);
22411 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22412 break;
22413 case OPC_SHRAV_R_OB:
22414 check_dsp_r2(ctx);
22415 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22416 break;
22417 case OPC_SHRA_PW:
22418 check_dsp(ctx);
22419 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22420 break;
22421 case OPC_SHRAV_PW:
22422 check_dsp(ctx);
22423 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22424 break;
22425 case OPC_SHRA_R_PW:
22426 check_dsp(ctx);
22427 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22428 break;
22429 case OPC_SHRAV_R_PW:
22430 check_dsp(ctx);
22431 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22432 break;
22433 case OPC_SHRA_QH:
22434 check_dsp(ctx);
22435 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22436 break;
22437 case OPC_SHRAV_QH:
22438 check_dsp(ctx);
22439 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22440 break;
22441 case OPC_SHRA_R_QH:
22442 check_dsp(ctx);
22443 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22444 break;
22445 case OPC_SHRAV_R_QH:
22446 check_dsp(ctx);
22447 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22448 break;
22449 case OPC_SHRL_OB:
22450 check_dsp(ctx);
22451 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22452 break;
22453 case OPC_SHRLV_OB:
22454 check_dsp(ctx);
22455 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22456 break;
22457 case OPC_SHRL_QH:
22458 check_dsp_r2(ctx);
22459 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22460 break;
22461 case OPC_SHRLV_QH:
22462 check_dsp_r2(ctx);
22463 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22464 break;
22465 default: /* Invalid */
22466 MIPS_INVAL("MASK SHLL.OB");
22467 generate_exception_end(ctx, EXCP_RI);
22468 break;
22470 break;
22471 #endif
22474 tcg_temp_free(t0);
22475 tcg_temp_free(v1_t);
22476 tcg_temp_free(v2_t);
22479 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22480 int ret, int v1, int v2, int check_ret)
22482 TCGv_i32 t0;
22483 TCGv v1_t;
22484 TCGv v2_t;
22486 if ((ret == 0) && (check_ret == 1)) {
22487 /* Treat as NOP. */
22488 return;
22491 t0 = tcg_temp_new_i32();
22492 v1_t = tcg_temp_new();
22493 v2_t = tcg_temp_new();
22495 tcg_gen_movi_i32(t0, ret);
22496 gen_load_gpr(v1_t, v1);
22497 gen_load_gpr(v2_t, v2);
22499 switch (op1) {
22500 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22501 * the same mask and op1. */
22502 case OPC_MULT_G_2E:
22503 check_dsp_r2(ctx);
22504 switch (op2) {
22505 case OPC_MUL_PH:
22506 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22507 break;
22508 case OPC_MUL_S_PH:
22509 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22510 break;
22511 case OPC_MULQ_S_W:
22512 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22513 break;
22514 case OPC_MULQ_RS_W:
22515 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22516 break;
22518 break;
22519 case OPC_DPA_W_PH_DSP:
22520 switch (op2) {
22521 case OPC_DPAU_H_QBL:
22522 check_dsp(ctx);
22523 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22524 break;
22525 case OPC_DPAU_H_QBR:
22526 check_dsp(ctx);
22527 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22528 break;
22529 case OPC_DPSU_H_QBL:
22530 check_dsp(ctx);
22531 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22532 break;
22533 case OPC_DPSU_H_QBR:
22534 check_dsp(ctx);
22535 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22536 break;
22537 case OPC_DPA_W_PH:
22538 check_dsp_r2(ctx);
22539 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22540 break;
22541 case OPC_DPAX_W_PH:
22542 check_dsp_r2(ctx);
22543 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22544 break;
22545 case OPC_DPAQ_S_W_PH:
22546 check_dsp(ctx);
22547 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22548 break;
22549 case OPC_DPAQX_S_W_PH:
22550 check_dsp_r2(ctx);
22551 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22552 break;
22553 case OPC_DPAQX_SA_W_PH:
22554 check_dsp_r2(ctx);
22555 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22556 break;
22557 case OPC_DPS_W_PH:
22558 check_dsp_r2(ctx);
22559 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22560 break;
22561 case OPC_DPSX_W_PH:
22562 check_dsp_r2(ctx);
22563 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22564 break;
22565 case OPC_DPSQ_S_W_PH:
22566 check_dsp(ctx);
22567 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22568 break;
22569 case OPC_DPSQX_S_W_PH:
22570 check_dsp_r2(ctx);
22571 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22572 break;
22573 case OPC_DPSQX_SA_W_PH:
22574 check_dsp_r2(ctx);
22575 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22576 break;
22577 case OPC_MULSAQ_S_W_PH:
22578 check_dsp(ctx);
22579 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22580 break;
22581 case OPC_DPAQ_SA_L_W:
22582 check_dsp(ctx);
22583 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22584 break;
22585 case OPC_DPSQ_SA_L_W:
22586 check_dsp(ctx);
22587 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22588 break;
22589 case OPC_MAQ_S_W_PHL:
22590 check_dsp(ctx);
22591 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22592 break;
22593 case OPC_MAQ_S_W_PHR:
22594 check_dsp(ctx);
22595 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22596 break;
22597 case OPC_MAQ_SA_W_PHL:
22598 check_dsp(ctx);
22599 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22600 break;
22601 case OPC_MAQ_SA_W_PHR:
22602 check_dsp(ctx);
22603 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22604 break;
22605 case OPC_MULSA_W_PH:
22606 check_dsp_r2(ctx);
22607 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22608 break;
22610 break;
22611 #ifdef TARGET_MIPS64
22612 case OPC_DPAQ_W_QH_DSP:
22614 int ac = ret & 0x03;
22615 tcg_gen_movi_i32(t0, ac);
22617 switch (op2) {
22618 case OPC_DMADD:
22619 check_dsp(ctx);
22620 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22621 break;
22622 case OPC_DMADDU:
22623 check_dsp(ctx);
22624 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22625 break;
22626 case OPC_DMSUB:
22627 check_dsp(ctx);
22628 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22629 break;
22630 case OPC_DMSUBU:
22631 check_dsp(ctx);
22632 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22633 break;
22634 case OPC_DPA_W_QH:
22635 check_dsp_r2(ctx);
22636 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22637 break;
22638 case OPC_DPAQ_S_W_QH:
22639 check_dsp(ctx);
22640 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22641 break;
22642 case OPC_DPAQ_SA_L_PW:
22643 check_dsp(ctx);
22644 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22645 break;
22646 case OPC_DPAU_H_OBL:
22647 check_dsp(ctx);
22648 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22649 break;
22650 case OPC_DPAU_H_OBR:
22651 check_dsp(ctx);
22652 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22653 break;
22654 case OPC_DPS_W_QH:
22655 check_dsp_r2(ctx);
22656 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22657 break;
22658 case OPC_DPSQ_S_W_QH:
22659 check_dsp(ctx);
22660 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22661 break;
22662 case OPC_DPSQ_SA_L_PW:
22663 check_dsp(ctx);
22664 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22665 break;
22666 case OPC_DPSU_H_OBL:
22667 check_dsp(ctx);
22668 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22669 break;
22670 case OPC_DPSU_H_OBR:
22671 check_dsp(ctx);
22672 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22673 break;
22674 case OPC_MAQ_S_L_PWL:
22675 check_dsp(ctx);
22676 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22677 break;
22678 case OPC_MAQ_S_L_PWR:
22679 check_dsp(ctx);
22680 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22681 break;
22682 case OPC_MAQ_S_W_QHLL:
22683 check_dsp(ctx);
22684 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22685 break;
22686 case OPC_MAQ_SA_W_QHLL:
22687 check_dsp(ctx);
22688 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22689 break;
22690 case OPC_MAQ_S_W_QHLR:
22691 check_dsp(ctx);
22692 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22693 break;
22694 case OPC_MAQ_SA_W_QHLR:
22695 check_dsp(ctx);
22696 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22697 break;
22698 case OPC_MAQ_S_W_QHRL:
22699 check_dsp(ctx);
22700 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22701 break;
22702 case OPC_MAQ_SA_W_QHRL:
22703 check_dsp(ctx);
22704 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22705 break;
22706 case OPC_MAQ_S_W_QHRR:
22707 check_dsp(ctx);
22708 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22709 break;
22710 case OPC_MAQ_SA_W_QHRR:
22711 check_dsp(ctx);
22712 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22713 break;
22714 case OPC_MULSAQ_S_L_PW:
22715 check_dsp(ctx);
22716 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22717 break;
22718 case OPC_MULSAQ_S_W_QH:
22719 check_dsp(ctx);
22720 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22721 break;
22724 break;
22725 #endif
22726 case OPC_ADDU_QB_DSP:
22727 switch (op2) {
22728 case OPC_MULEU_S_PH_QBL:
22729 check_dsp(ctx);
22730 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22731 break;
22732 case OPC_MULEU_S_PH_QBR:
22733 check_dsp(ctx);
22734 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22735 break;
22736 case OPC_MULQ_RS_PH:
22737 check_dsp(ctx);
22738 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22739 break;
22740 case OPC_MULEQ_S_W_PHL:
22741 check_dsp(ctx);
22742 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22743 break;
22744 case OPC_MULEQ_S_W_PHR:
22745 check_dsp(ctx);
22746 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22747 break;
22748 case OPC_MULQ_S_PH:
22749 check_dsp_r2(ctx);
22750 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22751 break;
22753 break;
22754 #ifdef TARGET_MIPS64
22755 case OPC_ADDU_OB_DSP:
22756 switch (op2) {
22757 case OPC_MULEQ_S_PW_QHL:
22758 check_dsp(ctx);
22759 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22760 break;
22761 case OPC_MULEQ_S_PW_QHR:
22762 check_dsp(ctx);
22763 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22764 break;
22765 case OPC_MULEU_S_QH_OBL:
22766 check_dsp(ctx);
22767 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22768 break;
22769 case OPC_MULEU_S_QH_OBR:
22770 check_dsp(ctx);
22771 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22772 break;
22773 case OPC_MULQ_RS_QH:
22774 check_dsp(ctx);
22775 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22776 break;
22778 break;
22779 #endif
22782 tcg_temp_free_i32(t0);
22783 tcg_temp_free(v1_t);
22784 tcg_temp_free(v2_t);
22787 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22788 int ret, int val)
22790 int16_t imm;
22791 TCGv t0;
22792 TCGv val_t;
22794 if (ret == 0) {
22795 /* Treat as NOP. */
22796 return;
22799 t0 = tcg_temp_new();
22800 val_t = tcg_temp_new();
22801 gen_load_gpr(val_t, val);
22803 switch (op1) {
22804 case OPC_ABSQ_S_PH_DSP:
22805 switch (op2) {
22806 case OPC_BITREV:
22807 check_dsp(ctx);
22808 gen_helper_bitrev(cpu_gpr[ret], val_t);
22809 break;
22810 case OPC_REPL_QB:
22811 check_dsp(ctx);
22813 target_long result;
22814 imm = (ctx->opcode >> 16) & 0xFF;
22815 result = (uint32_t)imm << 24 |
22816 (uint32_t)imm << 16 |
22817 (uint32_t)imm << 8 |
22818 (uint32_t)imm;
22819 result = (int32_t)result;
22820 tcg_gen_movi_tl(cpu_gpr[ret], result);
22822 break;
22823 case OPC_REPLV_QB:
22824 check_dsp(ctx);
22825 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22826 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22827 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22828 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22829 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22830 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22831 break;
22832 case OPC_REPL_PH:
22833 check_dsp(ctx);
22835 imm = (ctx->opcode >> 16) & 0x03FF;
22836 imm = (int16_t)(imm << 6) >> 6;
22837 tcg_gen_movi_tl(cpu_gpr[ret], \
22838 (target_long)((int32_t)imm << 16 | \
22839 (uint16_t)imm));
22841 break;
22842 case OPC_REPLV_PH:
22843 check_dsp(ctx);
22844 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22845 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22846 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22847 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22848 break;
22850 break;
22851 #ifdef TARGET_MIPS64
22852 case OPC_ABSQ_S_QH_DSP:
22853 switch (op2) {
22854 case OPC_REPL_OB:
22855 check_dsp(ctx);
22857 target_long temp;
22859 imm = (ctx->opcode >> 16) & 0xFF;
22860 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22861 temp = (temp << 16) | temp;
22862 temp = (temp << 32) | temp;
22863 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22864 break;
22866 case OPC_REPL_PW:
22867 check_dsp(ctx);
22869 target_long temp;
22871 imm = (ctx->opcode >> 16) & 0x03FF;
22872 imm = (int16_t)(imm << 6) >> 6;
22873 temp = ((target_long)imm << 32) \
22874 | ((target_long)imm & 0xFFFFFFFF);
22875 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22876 break;
22878 case OPC_REPL_QH:
22879 check_dsp(ctx);
22881 target_long temp;
22883 imm = (ctx->opcode >> 16) & 0x03FF;
22884 imm = (int16_t)(imm << 6) >> 6;
22886 temp = ((uint64_t)(uint16_t)imm << 48) |
22887 ((uint64_t)(uint16_t)imm << 32) |
22888 ((uint64_t)(uint16_t)imm << 16) |
22889 (uint64_t)(uint16_t)imm;
22890 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22891 break;
22893 case OPC_REPLV_OB:
22894 check_dsp(ctx);
22895 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22896 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22897 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22898 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22899 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22900 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22901 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22902 break;
22903 case OPC_REPLV_PW:
22904 check_dsp(ctx);
22905 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22906 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22907 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22908 break;
22909 case OPC_REPLV_QH:
22910 check_dsp(ctx);
22911 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22912 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22913 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22914 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22915 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22916 break;
22918 break;
22919 #endif
22921 tcg_temp_free(t0);
22922 tcg_temp_free(val_t);
22925 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22926 uint32_t op1, uint32_t op2,
22927 int ret, int v1, int v2, int check_ret)
22929 TCGv t1;
22930 TCGv v1_t;
22931 TCGv v2_t;
22933 if ((ret == 0) && (check_ret == 1)) {
22934 /* Treat as NOP. */
22935 return;
22938 t1 = tcg_temp_new();
22939 v1_t = tcg_temp_new();
22940 v2_t = tcg_temp_new();
22942 gen_load_gpr(v1_t, v1);
22943 gen_load_gpr(v2_t, v2);
22945 switch (op1) {
22946 case OPC_CMPU_EQ_QB_DSP:
22947 switch (op2) {
22948 case OPC_CMPU_EQ_QB:
22949 check_dsp(ctx);
22950 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22951 break;
22952 case OPC_CMPU_LT_QB:
22953 check_dsp(ctx);
22954 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22955 break;
22956 case OPC_CMPU_LE_QB:
22957 check_dsp(ctx);
22958 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22959 break;
22960 case OPC_CMPGU_EQ_QB:
22961 check_dsp(ctx);
22962 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22963 break;
22964 case OPC_CMPGU_LT_QB:
22965 check_dsp(ctx);
22966 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22967 break;
22968 case OPC_CMPGU_LE_QB:
22969 check_dsp(ctx);
22970 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22971 break;
22972 case OPC_CMPGDU_EQ_QB:
22973 check_dsp_r2(ctx);
22974 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22975 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22976 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22977 tcg_gen_shli_tl(t1, t1, 24);
22978 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22979 break;
22980 case OPC_CMPGDU_LT_QB:
22981 check_dsp_r2(ctx);
22982 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22983 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22984 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22985 tcg_gen_shli_tl(t1, t1, 24);
22986 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22987 break;
22988 case OPC_CMPGDU_LE_QB:
22989 check_dsp_r2(ctx);
22990 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22991 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22992 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22993 tcg_gen_shli_tl(t1, t1, 24);
22994 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22995 break;
22996 case OPC_CMP_EQ_PH:
22997 check_dsp(ctx);
22998 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22999 break;
23000 case OPC_CMP_LT_PH:
23001 check_dsp(ctx);
23002 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
23003 break;
23004 case OPC_CMP_LE_PH:
23005 check_dsp(ctx);
23006 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
23007 break;
23008 case OPC_PICK_QB:
23009 check_dsp(ctx);
23010 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23011 break;
23012 case OPC_PICK_PH:
23013 check_dsp(ctx);
23014 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23015 break;
23016 case OPC_PACKRL_PH:
23017 check_dsp(ctx);
23018 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
23019 break;
23021 break;
23022 #ifdef TARGET_MIPS64
23023 case OPC_CMPU_EQ_OB_DSP:
23024 switch (op2) {
23025 case OPC_CMP_EQ_PW:
23026 check_dsp(ctx);
23027 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
23028 break;
23029 case OPC_CMP_LT_PW:
23030 check_dsp(ctx);
23031 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
23032 break;
23033 case OPC_CMP_LE_PW:
23034 check_dsp(ctx);
23035 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
23036 break;
23037 case OPC_CMP_EQ_QH:
23038 check_dsp(ctx);
23039 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
23040 break;
23041 case OPC_CMP_LT_QH:
23042 check_dsp(ctx);
23043 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
23044 break;
23045 case OPC_CMP_LE_QH:
23046 check_dsp(ctx);
23047 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
23048 break;
23049 case OPC_CMPGDU_EQ_OB:
23050 check_dsp_r2(ctx);
23051 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23052 break;
23053 case OPC_CMPGDU_LT_OB:
23054 check_dsp_r2(ctx);
23055 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23056 break;
23057 case OPC_CMPGDU_LE_OB:
23058 check_dsp_r2(ctx);
23059 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23060 break;
23061 case OPC_CMPGU_EQ_OB:
23062 check_dsp(ctx);
23063 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
23064 break;
23065 case OPC_CMPGU_LT_OB:
23066 check_dsp(ctx);
23067 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
23068 break;
23069 case OPC_CMPGU_LE_OB:
23070 check_dsp(ctx);
23071 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
23072 break;
23073 case OPC_CMPU_EQ_OB:
23074 check_dsp(ctx);
23075 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
23076 break;
23077 case OPC_CMPU_LT_OB:
23078 check_dsp(ctx);
23079 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
23080 break;
23081 case OPC_CMPU_LE_OB:
23082 check_dsp(ctx);
23083 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
23084 break;
23085 case OPC_PACKRL_PW:
23086 check_dsp(ctx);
23087 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
23088 break;
23089 case OPC_PICK_OB:
23090 check_dsp(ctx);
23091 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23092 break;
23093 case OPC_PICK_PW:
23094 check_dsp(ctx);
23095 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23096 break;
23097 case OPC_PICK_QH:
23098 check_dsp(ctx);
23099 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23100 break;
23102 break;
23103 #endif
23106 tcg_temp_free(t1);
23107 tcg_temp_free(v1_t);
23108 tcg_temp_free(v2_t);
23111 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
23112 uint32_t op1, int rt, int rs, int sa)
23114 TCGv t0;
23116 check_dsp_r2(ctx);
23118 if (rt == 0) {
23119 /* Treat as NOP. */
23120 return;
23123 t0 = tcg_temp_new();
23124 gen_load_gpr(t0, rs);
23126 switch (op1) {
23127 case OPC_APPEND_DSP:
23128 switch (MASK_APPEND(ctx->opcode)) {
23129 case OPC_APPEND:
23130 if (sa != 0) {
23131 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
23133 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23134 break;
23135 case OPC_PREPEND:
23136 if (sa != 0) {
23137 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
23138 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23139 tcg_gen_shli_tl(t0, t0, 32 - sa);
23140 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23142 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23143 break;
23144 case OPC_BALIGN:
23145 sa &= 3;
23146 if (sa != 0 && sa != 2) {
23147 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23148 tcg_gen_ext32u_tl(t0, t0);
23149 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
23150 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23152 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
23153 break;
23154 default: /* Invalid */
23155 MIPS_INVAL("MASK APPEND");
23156 generate_exception_end(ctx, EXCP_RI);
23157 break;
23159 break;
23160 #ifdef TARGET_MIPS64
23161 case OPC_DAPPEND_DSP:
23162 switch (MASK_DAPPEND(ctx->opcode)) {
23163 case OPC_DAPPEND:
23164 if (sa != 0) {
23165 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
23167 break;
23168 case OPC_PREPENDD:
23169 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
23170 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23171 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23172 break;
23173 case OPC_PREPENDW:
23174 if (sa != 0) {
23175 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23176 tcg_gen_shli_tl(t0, t0, 64 - sa);
23177 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23179 break;
23180 case OPC_DBALIGN:
23181 sa &= 7;
23182 if (sa != 0 && sa != 2 && sa != 4) {
23183 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23184 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23185 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23187 break;
23188 default: /* Invalid */
23189 MIPS_INVAL("MASK DAPPEND");
23190 generate_exception_end(ctx, EXCP_RI);
23191 break;
23193 break;
23194 #endif
23196 tcg_temp_free(t0);
23199 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23200 int ret, int v1, int v2, int check_ret)
23203 TCGv t0;
23204 TCGv t1;
23205 TCGv v1_t;
23206 TCGv v2_t;
23207 int16_t imm;
23209 if ((ret == 0) && (check_ret == 1)) {
23210 /* Treat as NOP. */
23211 return;
23214 t0 = tcg_temp_new();
23215 t1 = tcg_temp_new();
23216 v1_t = tcg_temp_new();
23217 v2_t = tcg_temp_new();
23219 gen_load_gpr(v1_t, v1);
23220 gen_load_gpr(v2_t, v2);
23222 switch (op1) {
23223 case OPC_EXTR_W_DSP:
23224 check_dsp(ctx);
23225 switch (op2) {
23226 case OPC_EXTR_W:
23227 tcg_gen_movi_tl(t0, v2);
23228 tcg_gen_movi_tl(t1, v1);
23229 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23230 break;
23231 case OPC_EXTR_R_W:
23232 tcg_gen_movi_tl(t0, v2);
23233 tcg_gen_movi_tl(t1, v1);
23234 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23235 break;
23236 case OPC_EXTR_RS_W:
23237 tcg_gen_movi_tl(t0, v2);
23238 tcg_gen_movi_tl(t1, v1);
23239 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23240 break;
23241 case OPC_EXTR_S_H:
23242 tcg_gen_movi_tl(t0, v2);
23243 tcg_gen_movi_tl(t1, v1);
23244 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23245 break;
23246 case OPC_EXTRV_S_H:
23247 tcg_gen_movi_tl(t0, v2);
23248 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23249 break;
23250 case OPC_EXTRV_W:
23251 tcg_gen_movi_tl(t0, v2);
23252 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23253 break;
23254 case OPC_EXTRV_R_W:
23255 tcg_gen_movi_tl(t0, v2);
23256 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23257 break;
23258 case OPC_EXTRV_RS_W:
23259 tcg_gen_movi_tl(t0, v2);
23260 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23261 break;
23262 case OPC_EXTP:
23263 tcg_gen_movi_tl(t0, v2);
23264 tcg_gen_movi_tl(t1, v1);
23265 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23266 break;
23267 case OPC_EXTPV:
23268 tcg_gen_movi_tl(t0, v2);
23269 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23270 break;
23271 case OPC_EXTPDP:
23272 tcg_gen_movi_tl(t0, v2);
23273 tcg_gen_movi_tl(t1, v1);
23274 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23275 break;
23276 case OPC_EXTPDPV:
23277 tcg_gen_movi_tl(t0, v2);
23278 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23279 break;
23280 case OPC_SHILO:
23281 imm = (ctx->opcode >> 20) & 0x3F;
23282 tcg_gen_movi_tl(t0, ret);
23283 tcg_gen_movi_tl(t1, imm);
23284 gen_helper_shilo(t0, t1, cpu_env);
23285 break;
23286 case OPC_SHILOV:
23287 tcg_gen_movi_tl(t0, ret);
23288 gen_helper_shilo(t0, v1_t, cpu_env);
23289 break;
23290 case OPC_MTHLIP:
23291 tcg_gen_movi_tl(t0, ret);
23292 gen_helper_mthlip(t0, v1_t, cpu_env);
23293 break;
23294 case OPC_WRDSP:
23295 imm = (ctx->opcode >> 11) & 0x3FF;
23296 tcg_gen_movi_tl(t0, imm);
23297 gen_helper_wrdsp(v1_t, t0, cpu_env);
23298 break;
23299 case OPC_RDDSP:
23300 imm = (ctx->opcode >> 16) & 0x03FF;
23301 tcg_gen_movi_tl(t0, imm);
23302 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23303 break;
23305 break;
23306 #ifdef TARGET_MIPS64
23307 case OPC_DEXTR_W_DSP:
23308 check_dsp(ctx);
23309 switch (op2) {
23310 case OPC_DMTHLIP:
23311 tcg_gen_movi_tl(t0, ret);
23312 gen_helper_dmthlip(v1_t, t0, cpu_env);
23313 break;
23314 case OPC_DSHILO:
23316 int shift = (ctx->opcode >> 19) & 0x7F;
23317 int ac = (ctx->opcode >> 11) & 0x03;
23318 tcg_gen_movi_tl(t0, shift);
23319 tcg_gen_movi_tl(t1, ac);
23320 gen_helper_dshilo(t0, t1, cpu_env);
23321 break;
23323 case OPC_DSHILOV:
23325 int ac = (ctx->opcode >> 11) & 0x03;
23326 tcg_gen_movi_tl(t0, ac);
23327 gen_helper_dshilo(v1_t, t0, cpu_env);
23328 break;
23330 case OPC_DEXTP:
23331 tcg_gen_movi_tl(t0, v2);
23332 tcg_gen_movi_tl(t1, v1);
23334 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23335 break;
23336 case OPC_DEXTPV:
23337 tcg_gen_movi_tl(t0, v2);
23338 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23339 break;
23340 case OPC_DEXTPDP:
23341 tcg_gen_movi_tl(t0, v2);
23342 tcg_gen_movi_tl(t1, v1);
23343 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23344 break;
23345 case OPC_DEXTPDPV:
23346 tcg_gen_movi_tl(t0, v2);
23347 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23348 break;
23349 case OPC_DEXTR_L:
23350 tcg_gen_movi_tl(t0, v2);
23351 tcg_gen_movi_tl(t1, v1);
23352 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23353 break;
23354 case OPC_DEXTR_R_L:
23355 tcg_gen_movi_tl(t0, v2);
23356 tcg_gen_movi_tl(t1, v1);
23357 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23358 break;
23359 case OPC_DEXTR_RS_L:
23360 tcg_gen_movi_tl(t0, v2);
23361 tcg_gen_movi_tl(t1, v1);
23362 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23363 break;
23364 case OPC_DEXTR_W:
23365 tcg_gen_movi_tl(t0, v2);
23366 tcg_gen_movi_tl(t1, v1);
23367 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23368 break;
23369 case OPC_DEXTR_R_W:
23370 tcg_gen_movi_tl(t0, v2);
23371 tcg_gen_movi_tl(t1, v1);
23372 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23373 break;
23374 case OPC_DEXTR_RS_W:
23375 tcg_gen_movi_tl(t0, v2);
23376 tcg_gen_movi_tl(t1, v1);
23377 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23378 break;
23379 case OPC_DEXTR_S_H:
23380 tcg_gen_movi_tl(t0, v2);
23381 tcg_gen_movi_tl(t1, v1);
23382 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23383 break;
23384 case OPC_DEXTRV_S_H:
23385 tcg_gen_movi_tl(t0, v2);
23386 tcg_gen_movi_tl(t1, v1);
23387 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23388 break;
23389 case OPC_DEXTRV_L:
23390 tcg_gen_movi_tl(t0, v2);
23391 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23392 break;
23393 case OPC_DEXTRV_R_L:
23394 tcg_gen_movi_tl(t0, v2);
23395 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23396 break;
23397 case OPC_DEXTRV_RS_L:
23398 tcg_gen_movi_tl(t0, v2);
23399 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23400 break;
23401 case OPC_DEXTRV_W:
23402 tcg_gen_movi_tl(t0, v2);
23403 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23404 break;
23405 case OPC_DEXTRV_R_W:
23406 tcg_gen_movi_tl(t0, v2);
23407 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23408 break;
23409 case OPC_DEXTRV_RS_W:
23410 tcg_gen_movi_tl(t0, v2);
23411 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23412 break;
23414 break;
23415 #endif
23418 tcg_temp_free(t0);
23419 tcg_temp_free(t1);
23420 tcg_temp_free(v1_t);
23421 tcg_temp_free(v2_t);
23424 /* End MIPSDSP functions. */
23426 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23428 int rs, rt, rd, sa;
23429 uint32_t op1, op2;
23431 rs = (ctx->opcode >> 21) & 0x1f;
23432 rt = (ctx->opcode >> 16) & 0x1f;
23433 rd = (ctx->opcode >> 11) & 0x1f;
23434 sa = (ctx->opcode >> 6) & 0x1f;
23436 op1 = MASK_SPECIAL(ctx->opcode);
23437 switch (op1) {
23438 case OPC_LSA:
23439 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23440 break;
23441 case OPC_MULT:
23442 case OPC_MULTU:
23443 case OPC_DIV:
23444 case OPC_DIVU:
23445 op2 = MASK_R6_MULDIV(ctx->opcode);
23446 switch (op2) {
23447 case R6_OPC_MUL:
23448 case R6_OPC_MUH:
23449 case R6_OPC_MULU:
23450 case R6_OPC_MUHU:
23451 case R6_OPC_DIV:
23452 case R6_OPC_MOD:
23453 case R6_OPC_DIVU:
23454 case R6_OPC_MODU:
23455 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23456 break;
23457 default:
23458 MIPS_INVAL("special_r6 muldiv");
23459 generate_exception_end(ctx, EXCP_RI);
23460 break;
23462 break;
23463 case OPC_SELEQZ:
23464 case OPC_SELNEZ:
23465 gen_cond_move(ctx, op1, rd, rs, rt);
23466 break;
23467 case R6_OPC_CLO:
23468 case R6_OPC_CLZ:
23469 if (rt == 0 && sa == 1) {
23470 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23471 We need additionally to check other fields */
23472 gen_cl(ctx, op1, rd, rs);
23473 } else {
23474 generate_exception_end(ctx, EXCP_RI);
23476 break;
23477 case R6_OPC_SDBBP:
23478 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23479 gen_helper_do_semihosting(cpu_env);
23480 } else {
23481 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23482 generate_exception_end(ctx, EXCP_RI);
23483 } else {
23484 generate_exception_end(ctx, EXCP_DBp);
23487 break;
23488 #if defined(TARGET_MIPS64)
23489 case OPC_DLSA:
23490 check_mips_64(ctx);
23491 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23492 break;
23493 case R6_OPC_DCLO:
23494 case R6_OPC_DCLZ:
23495 if (rt == 0 && sa == 1) {
23496 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23497 We need additionally to check other fields */
23498 check_mips_64(ctx);
23499 gen_cl(ctx, op1, rd, rs);
23500 } else {
23501 generate_exception_end(ctx, EXCP_RI);
23503 break;
23504 case OPC_DMULT:
23505 case OPC_DMULTU:
23506 case OPC_DDIV:
23507 case OPC_DDIVU:
23509 op2 = MASK_R6_MULDIV(ctx->opcode);
23510 switch (op2) {
23511 case R6_OPC_DMUL:
23512 case R6_OPC_DMUH:
23513 case R6_OPC_DMULU:
23514 case R6_OPC_DMUHU:
23515 case R6_OPC_DDIV:
23516 case R6_OPC_DMOD:
23517 case R6_OPC_DDIVU:
23518 case R6_OPC_DMODU:
23519 check_mips_64(ctx);
23520 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23521 break;
23522 default:
23523 MIPS_INVAL("special_r6 muldiv");
23524 generate_exception_end(ctx, EXCP_RI);
23525 break;
23527 break;
23528 #endif
23529 default: /* Invalid */
23530 MIPS_INVAL("special_r6");
23531 generate_exception_end(ctx, EXCP_RI);
23532 break;
23536 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23538 int rs, rt, rd, sa;
23539 uint32_t op1;
23541 rs = (ctx->opcode >> 21) & 0x1f;
23542 rt = (ctx->opcode >> 16) & 0x1f;
23543 rd = (ctx->opcode >> 11) & 0x1f;
23544 sa = (ctx->opcode >> 6) & 0x1f;
23546 op1 = MASK_SPECIAL(ctx->opcode);
23547 switch (op1) {
23548 case OPC_MOVN: /* Conditional move */
23549 case OPC_MOVZ:
23550 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23551 INSN_LOONGSON2E | INSN_LOONGSON2F);
23552 gen_cond_move(ctx, op1, rd, rs, rt);
23553 break;
23554 case OPC_MFHI: /* Move from HI/LO */
23555 case OPC_MFLO:
23556 gen_HILO(ctx, op1, rs & 3, rd);
23557 break;
23558 case OPC_MTHI:
23559 case OPC_MTLO: /* Move to HI/LO */
23560 gen_HILO(ctx, op1, rd & 3, rs);
23561 break;
23562 case OPC_MOVCI:
23563 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23564 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23565 check_cp1_enabled(ctx);
23566 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23567 (ctx->opcode >> 16) & 1);
23568 } else {
23569 generate_exception_err(ctx, EXCP_CpU, 1);
23571 break;
23572 case OPC_MULT:
23573 case OPC_MULTU:
23574 if (sa) {
23575 check_insn(ctx, INSN_VR54XX);
23576 op1 = MASK_MUL_VR54XX(ctx->opcode);
23577 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23578 } else if (ctx->insn_flags & INSN_R5900) {
23579 gen_mul_txx9(ctx, op1, rd, rs, rt);
23580 } else {
23581 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23583 break;
23584 case OPC_DIV:
23585 case OPC_DIVU:
23586 gen_muldiv(ctx, op1, 0, rs, rt);
23587 break;
23588 #if defined(TARGET_MIPS64)
23589 case OPC_DMULT:
23590 case OPC_DMULTU:
23591 case OPC_DDIV:
23592 case OPC_DDIVU:
23593 check_insn(ctx, ISA_MIPS3);
23594 check_mips_64(ctx);
23595 gen_muldiv(ctx, op1, 0, rs, rt);
23596 break;
23597 #endif
23598 case OPC_JR:
23599 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23600 break;
23601 case OPC_SPIM:
23602 #ifdef MIPS_STRICT_STANDARD
23603 MIPS_INVAL("SPIM");
23604 generate_exception_end(ctx, EXCP_RI);
23605 #else
23606 /* Implemented as RI exception for now. */
23607 MIPS_INVAL("spim (unofficial)");
23608 generate_exception_end(ctx, EXCP_RI);
23609 #endif
23610 break;
23611 default: /* Invalid */
23612 MIPS_INVAL("special_legacy");
23613 generate_exception_end(ctx, EXCP_RI);
23614 break;
23618 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23620 int rs, rt, rd, sa;
23621 uint32_t op1;
23623 rs = (ctx->opcode >> 21) & 0x1f;
23624 rt = (ctx->opcode >> 16) & 0x1f;
23625 rd = (ctx->opcode >> 11) & 0x1f;
23626 sa = (ctx->opcode >> 6) & 0x1f;
23628 op1 = MASK_SPECIAL(ctx->opcode);
23629 switch (op1) {
23630 case OPC_SLL: /* Shift with immediate */
23631 if (sa == 5 && rd == 0 &&
23632 rs == 0 && rt == 0) { /* PAUSE */
23633 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23634 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23635 generate_exception_end(ctx, EXCP_RI);
23636 break;
23639 /* Fallthrough */
23640 case OPC_SRA:
23641 gen_shift_imm(ctx, op1, rd, rt, sa);
23642 break;
23643 case OPC_SRL:
23644 switch ((ctx->opcode >> 21) & 0x1f) {
23645 case 1:
23646 /* rotr is decoded as srl on non-R2 CPUs */
23647 if (ctx->insn_flags & ISA_MIPS32R2) {
23648 op1 = OPC_ROTR;
23650 /* Fallthrough */
23651 case 0:
23652 gen_shift_imm(ctx, op1, rd, rt, sa);
23653 break;
23654 default:
23655 generate_exception_end(ctx, EXCP_RI);
23656 break;
23658 break;
23659 case OPC_ADD:
23660 case OPC_ADDU:
23661 case OPC_SUB:
23662 case OPC_SUBU:
23663 gen_arith(ctx, op1, rd, rs, rt);
23664 break;
23665 case OPC_SLLV: /* Shifts */
23666 case OPC_SRAV:
23667 gen_shift(ctx, op1, rd, rs, rt);
23668 break;
23669 case OPC_SRLV:
23670 switch ((ctx->opcode >> 6) & 0x1f) {
23671 case 1:
23672 /* rotrv is decoded as srlv on non-R2 CPUs */
23673 if (ctx->insn_flags & ISA_MIPS32R2) {
23674 op1 = OPC_ROTRV;
23676 /* Fallthrough */
23677 case 0:
23678 gen_shift(ctx, op1, rd, rs, rt);
23679 break;
23680 default:
23681 generate_exception_end(ctx, EXCP_RI);
23682 break;
23684 break;
23685 case OPC_SLT: /* Set on less than */
23686 case OPC_SLTU:
23687 gen_slt(ctx, op1, rd, rs, rt);
23688 break;
23689 case OPC_AND: /* Logic*/
23690 case OPC_OR:
23691 case OPC_NOR:
23692 case OPC_XOR:
23693 gen_logic(ctx, op1, rd, rs, rt);
23694 break;
23695 case OPC_JALR:
23696 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23697 break;
23698 case OPC_TGE: /* Traps */
23699 case OPC_TGEU:
23700 case OPC_TLT:
23701 case OPC_TLTU:
23702 case OPC_TEQ:
23703 case OPC_TNE:
23704 check_insn(ctx, ISA_MIPS2);
23705 gen_trap(ctx, op1, rs, rt, -1);
23706 break;
23707 case OPC_LSA: /* OPC_PMON */
23708 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23709 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23710 decode_opc_special_r6(env, ctx);
23711 } else {
23712 /* Pmon entry point, also R4010 selsl */
23713 #ifdef MIPS_STRICT_STANDARD
23714 MIPS_INVAL("PMON / selsl");
23715 generate_exception_end(ctx, EXCP_RI);
23716 #else
23717 gen_helper_0e0i(pmon, sa);
23718 #endif
23720 break;
23721 case OPC_SYSCALL:
23722 generate_exception_end(ctx, EXCP_SYSCALL);
23723 break;
23724 case OPC_BREAK:
23725 generate_exception_end(ctx, EXCP_BREAK);
23726 break;
23727 case OPC_SYNC:
23728 check_insn(ctx, ISA_MIPS2);
23729 gen_sync(extract32(ctx->opcode, 6, 5));
23730 break;
23732 #if defined(TARGET_MIPS64)
23733 /* MIPS64 specific opcodes */
23734 case OPC_DSLL:
23735 case OPC_DSRA:
23736 case OPC_DSLL32:
23737 case OPC_DSRA32:
23738 check_insn(ctx, ISA_MIPS3);
23739 check_mips_64(ctx);
23740 gen_shift_imm(ctx, op1, rd, rt, sa);
23741 break;
23742 case OPC_DSRL:
23743 switch ((ctx->opcode >> 21) & 0x1f) {
23744 case 1:
23745 /* drotr is decoded as dsrl on non-R2 CPUs */
23746 if (ctx->insn_flags & ISA_MIPS32R2) {
23747 op1 = OPC_DROTR;
23749 /* Fallthrough */
23750 case 0:
23751 check_insn(ctx, ISA_MIPS3);
23752 check_mips_64(ctx);
23753 gen_shift_imm(ctx, op1, rd, rt, sa);
23754 break;
23755 default:
23756 generate_exception_end(ctx, EXCP_RI);
23757 break;
23759 break;
23760 case OPC_DSRL32:
23761 switch ((ctx->opcode >> 21) & 0x1f) {
23762 case 1:
23763 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23764 if (ctx->insn_flags & ISA_MIPS32R2) {
23765 op1 = OPC_DROTR32;
23767 /* Fallthrough */
23768 case 0:
23769 check_insn(ctx, ISA_MIPS3);
23770 check_mips_64(ctx);
23771 gen_shift_imm(ctx, op1, rd, rt, sa);
23772 break;
23773 default:
23774 generate_exception_end(ctx, EXCP_RI);
23775 break;
23777 break;
23778 case OPC_DADD:
23779 case OPC_DADDU:
23780 case OPC_DSUB:
23781 case OPC_DSUBU:
23782 check_insn(ctx, ISA_MIPS3);
23783 check_mips_64(ctx);
23784 gen_arith(ctx, op1, rd, rs, rt);
23785 break;
23786 case OPC_DSLLV:
23787 case OPC_DSRAV:
23788 check_insn(ctx, ISA_MIPS3);
23789 check_mips_64(ctx);
23790 gen_shift(ctx, op1, rd, rs, rt);
23791 break;
23792 case OPC_DSRLV:
23793 switch ((ctx->opcode >> 6) & 0x1f) {
23794 case 1:
23795 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23796 if (ctx->insn_flags & ISA_MIPS32R2) {
23797 op1 = OPC_DROTRV;
23799 /* Fallthrough */
23800 case 0:
23801 check_insn(ctx, ISA_MIPS3);
23802 check_mips_64(ctx);
23803 gen_shift(ctx, op1, rd, rs, rt);
23804 break;
23805 default:
23806 generate_exception_end(ctx, EXCP_RI);
23807 break;
23809 break;
23810 case OPC_DLSA:
23811 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23812 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23813 decode_opc_special_r6(env, ctx);
23815 break;
23816 #endif
23817 default:
23818 if (ctx->insn_flags & ISA_MIPS32R6) {
23819 decode_opc_special_r6(env, ctx);
23820 } else {
23821 decode_opc_special_legacy(env, ctx);
23826 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23828 int rs, rt, rd;
23829 uint32_t op1;
23831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23833 rs = (ctx->opcode >> 21) & 0x1f;
23834 rt = (ctx->opcode >> 16) & 0x1f;
23835 rd = (ctx->opcode >> 11) & 0x1f;
23837 op1 = MASK_SPECIAL2(ctx->opcode);
23838 switch (op1) {
23839 case OPC_MADD: /* Multiply and add/sub */
23840 case OPC_MADDU:
23841 case OPC_MSUB:
23842 case OPC_MSUBU:
23843 check_insn(ctx, ISA_MIPS32);
23844 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23845 break;
23846 case OPC_MUL:
23847 gen_arith(ctx, op1, rd, rs, rt);
23848 break;
23849 case OPC_DIV_G_2F:
23850 case OPC_DIVU_G_2F:
23851 case OPC_MULT_G_2F:
23852 case OPC_MULTU_G_2F:
23853 case OPC_MOD_G_2F:
23854 case OPC_MODU_G_2F:
23855 check_insn(ctx, INSN_LOONGSON2F);
23856 gen_loongson_integer(ctx, op1, rd, rs, rt);
23857 break;
23858 case OPC_CLO:
23859 case OPC_CLZ:
23860 check_insn(ctx, ISA_MIPS32);
23861 gen_cl(ctx, op1, rd, rs);
23862 break;
23863 case OPC_SDBBP:
23864 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23865 gen_helper_do_semihosting(cpu_env);
23866 } else {
23867 /* XXX: not clear which exception should be raised
23868 * when in debug mode...
23870 check_insn(ctx, ISA_MIPS32);
23871 generate_exception_end(ctx, EXCP_DBp);
23873 break;
23874 #if defined(TARGET_MIPS64)
23875 case OPC_DCLO:
23876 case OPC_DCLZ:
23877 check_insn(ctx, ISA_MIPS64);
23878 check_mips_64(ctx);
23879 gen_cl(ctx, op1, rd, rs);
23880 break;
23881 case OPC_DMULT_G_2F:
23882 case OPC_DMULTU_G_2F:
23883 case OPC_DDIV_G_2F:
23884 case OPC_DDIVU_G_2F:
23885 case OPC_DMOD_G_2F:
23886 case OPC_DMODU_G_2F:
23887 check_insn(ctx, INSN_LOONGSON2F);
23888 gen_loongson_integer(ctx, op1, rd, rs, rt);
23889 break;
23890 #endif
23891 default: /* Invalid */
23892 MIPS_INVAL("special2_legacy");
23893 generate_exception_end(ctx, EXCP_RI);
23894 break;
23898 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23900 int rs, rt, rd, sa;
23901 uint32_t op1, op2;
23902 int16_t imm;
23904 rs = (ctx->opcode >> 21) & 0x1f;
23905 rt = (ctx->opcode >> 16) & 0x1f;
23906 rd = (ctx->opcode >> 11) & 0x1f;
23907 sa = (ctx->opcode >> 6) & 0x1f;
23908 imm = (int16_t)ctx->opcode >> 7;
23910 op1 = MASK_SPECIAL3(ctx->opcode);
23911 switch (op1) {
23912 case R6_OPC_PREF:
23913 if (rt >= 24) {
23914 /* hint codes 24-31 are reserved and signal RI */
23915 generate_exception_end(ctx, EXCP_RI);
23917 /* Treat as NOP. */
23918 break;
23919 case R6_OPC_CACHE:
23920 check_cp0_enabled(ctx);
23921 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23922 gen_cache_operation(ctx, rt, rs, imm);
23924 break;
23925 case R6_OPC_SC:
23926 gen_st_cond(ctx, op1, rt, rs, imm);
23927 break;
23928 case R6_OPC_LL:
23929 gen_ld(ctx, op1, rt, rs, imm);
23930 break;
23931 case OPC_BSHFL:
23933 if (rd == 0) {
23934 /* Treat as NOP. */
23935 break;
23937 op2 = MASK_BSHFL(ctx->opcode);
23938 switch (op2) {
23939 case OPC_ALIGN:
23940 case OPC_ALIGN_END:
23941 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23942 break;
23943 case OPC_BITSWAP:
23944 gen_bitswap(ctx, op2, rd, rt);
23945 break;
23948 break;
23949 #if defined(TARGET_MIPS64)
23950 case R6_OPC_SCD:
23951 gen_st_cond(ctx, op1, rt, rs, imm);
23952 break;
23953 case R6_OPC_LLD:
23954 gen_ld(ctx, op1, rt, rs, imm);
23955 break;
23956 case OPC_DBSHFL:
23957 check_mips_64(ctx);
23959 if (rd == 0) {
23960 /* Treat as NOP. */
23961 break;
23963 op2 = MASK_DBSHFL(ctx->opcode);
23964 switch (op2) {
23965 case OPC_DALIGN:
23966 case OPC_DALIGN_END:
23967 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23968 break;
23969 case OPC_DBITSWAP:
23970 gen_bitswap(ctx, op2, rd, rt);
23971 break;
23975 break;
23976 #endif
23977 default: /* Invalid */
23978 MIPS_INVAL("special3_r6");
23979 generate_exception_end(ctx, EXCP_RI);
23980 break;
23984 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23986 int rs, rt, rd;
23987 uint32_t op1, op2;
23989 rs = (ctx->opcode >> 21) & 0x1f;
23990 rt = (ctx->opcode >> 16) & 0x1f;
23991 rd = (ctx->opcode >> 11) & 0x1f;
23993 op1 = MASK_SPECIAL3(ctx->opcode);
23994 switch (op1) {
23995 case OPC_DIV_G_2E:
23996 case OPC_DIVU_G_2E:
23997 case OPC_MOD_G_2E:
23998 case OPC_MODU_G_2E:
23999 case OPC_MULT_G_2E:
24000 case OPC_MULTU_G_2E:
24001 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
24002 * the same mask and op1. */
24003 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
24004 op2 = MASK_ADDUH_QB(ctx->opcode);
24005 switch (op2) {
24006 case OPC_ADDUH_QB:
24007 case OPC_ADDUH_R_QB:
24008 case OPC_ADDQH_PH:
24009 case OPC_ADDQH_R_PH:
24010 case OPC_ADDQH_W:
24011 case OPC_ADDQH_R_W:
24012 case OPC_SUBUH_QB:
24013 case OPC_SUBUH_R_QB:
24014 case OPC_SUBQH_PH:
24015 case OPC_SUBQH_R_PH:
24016 case OPC_SUBQH_W:
24017 case OPC_SUBQH_R_W:
24018 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24019 break;
24020 case OPC_MUL_PH:
24021 case OPC_MUL_S_PH:
24022 case OPC_MULQ_S_W:
24023 case OPC_MULQ_RS_W:
24024 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24025 break;
24026 default:
24027 MIPS_INVAL("MASK ADDUH.QB");
24028 generate_exception_end(ctx, EXCP_RI);
24029 break;
24031 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
24032 gen_loongson_integer(ctx, op1, rd, rs, rt);
24033 } else {
24034 generate_exception_end(ctx, EXCP_RI);
24036 break;
24037 case OPC_LX_DSP:
24038 op2 = MASK_LX(ctx->opcode);
24039 switch (op2) {
24040 #if defined(TARGET_MIPS64)
24041 case OPC_LDX:
24042 #endif
24043 case OPC_LBUX:
24044 case OPC_LHX:
24045 case OPC_LWX:
24046 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
24047 break;
24048 default: /* Invalid */
24049 MIPS_INVAL("MASK LX");
24050 generate_exception_end(ctx, EXCP_RI);
24051 break;
24053 break;
24054 case OPC_ABSQ_S_PH_DSP:
24055 op2 = MASK_ABSQ_S_PH(ctx->opcode);
24056 switch (op2) {
24057 case OPC_ABSQ_S_QB:
24058 case OPC_ABSQ_S_PH:
24059 case OPC_ABSQ_S_W:
24060 case OPC_PRECEQ_W_PHL:
24061 case OPC_PRECEQ_W_PHR:
24062 case OPC_PRECEQU_PH_QBL:
24063 case OPC_PRECEQU_PH_QBR:
24064 case OPC_PRECEQU_PH_QBLA:
24065 case OPC_PRECEQU_PH_QBRA:
24066 case OPC_PRECEU_PH_QBL:
24067 case OPC_PRECEU_PH_QBR:
24068 case OPC_PRECEU_PH_QBLA:
24069 case OPC_PRECEU_PH_QBRA:
24070 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24071 break;
24072 case OPC_BITREV:
24073 case OPC_REPL_QB:
24074 case OPC_REPLV_QB:
24075 case OPC_REPL_PH:
24076 case OPC_REPLV_PH:
24077 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24078 break;
24079 default:
24080 MIPS_INVAL("MASK ABSQ_S.PH");
24081 generate_exception_end(ctx, EXCP_RI);
24082 break;
24084 break;
24085 case OPC_ADDU_QB_DSP:
24086 op2 = MASK_ADDU_QB(ctx->opcode);
24087 switch (op2) {
24088 case OPC_ADDQ_PH:
24089 case OPC_ADDQ_S_PH:
24090 case OPC_ADDQ_S_W:
24091 case OPC_ADDU_QB:
24092 case OPC_ADDU_S_QB:
24093 case OPC_ADDU_PH:
24094 case OPC_ADDU_S_PH:
24095 case OPC_SUBQ_PH:
24096 case OPC_SUBQ_S_PH:
24097 case OPC_SUBQ_S_W:
24098 case OPC_SUBU_QB:
24099 case OPC_SUBU_S_QB:
24100 case OPC_SUBU_PH:
24101 case OPC_SUBU_S_PH:
24102 case OPC_ADDSC:
24103 case OPC_ADDWC:
24104 case OPC_MODSUB:
24105 case OPC_RADDU_W_QB:
24106 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24107 break;
24108 case OPC_MULEU_S_PH_QBL:
24109 case OPC_MULEU_S_PH_QBR:
24110 case OPC_MULQ_RS_PH:
24111 case OPC_MULEQ_S_W_PHL:
24112 case OPC_MULEQ_S_W_PHR:
24113 case OPC_MULQ_S_PH:
24114 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24115 break;
24116 default: /* Invalid */
24117 MIPS_INVAL("MASK ADDU.QB");
24118 generate_exception_end(ctx, EXCP_RI);
24119 break;
24122 break;
24123 case OPC_CMPU_EQ_QB_DSP:
24124 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24125 switch (op2) {
24126 case OPC_PRECR_SRA_PH_W:
24127 case OPC_PRECR_SRA_R_PH_W:
24128 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24129 break;
24130 case OPC_PRECR_QB_PH:
24131 case OPC_PRECRQ_QB_PH:
24132 case OPC_PRECRQ_PH_W:
24133 case OPC_PRECRQ_RS_PH_W:
24134 case OPC_PRECRQU_S_QB_PH:
24135 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24136 break;
24137 case OPC_CMPU_EQ_QB:
24138 case OPC_CMPU_LT_QB:
24139 case OPC_CMPU_LE_QB:
24140 case OPC_CMP_EQ_PH:
24141 case OPC_CMP_LT_PH:
24142 case OPC_CMP_LE_PH:
24143 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24144 break;
24145 case OPC_CMPGU_EQ_QB:
24146 case OPC_CMPGU_LT_QB:
24147 case OPC_CMPGU_LE_QB:
24148 case OPC_CMPGDU_EQ_QB:
24149 case OPC_CMPGDU_LT_QB:
24150 case OPC_CMPGDU_LE_QB:
24151 case OPC_PICK_QB:
24152 case OPC_PICK_PH:
24153 case OPC_PACKRL_PH:
24154 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24155 break;
24156 default: /* Invalid */
24157 MIPS_INVAL("MASK CMPU.EQ.QB");
24158 generate_exception_end(ctx, EXCP_RI);
24159 break;
24161 break;
24162 case OPC_SHLL_QB_DSP:
24163 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24164 break;
24165 case OPC_DPA_W_PH_DSP:
24166 op2 = MASK_DPA_W_PH(ctx->opcode);
24167 switch (op2) {
24168 case OPC_DPAU_H_QBL:
24169 case OPC_DPAU_H_QBR:
24170 case OPC_DPSU_H_QBL:
24171 case OPC_DPSU_H_QBR:
24172 case OPC_DPA_W_PH:
24173 case OPC_DPAX_W_PH:
24174 case OPC_DPAQ_S_W_PH:
24175 case OPC_DPAQX_S_W_PH:
24176 case OPC_DPAQX_SA_W_PH:
24177 case OPC_DPS_W_PH:
24178 case OPC_DPSX_W_PH:
24179 case OPC_DPSQ_S_W_PH:
24180 case OPC_DPSQX_S_W_PH:
24181 case OPC_DPSQX_SA_W_PH:
24182 case OPC_MULSAQ_S_W_PH:
24183 case OPC_DPAQ_SA_L_W:
24184 case OPC_DPSQ_SA_L_W:
24185 case OPC_MAQ_S_W_PHL:
24186 case OPC_MAQ_S_W_PHR:
24187 case OPC_MAQ_SA_W_PHL:
24188 case OPC_MAQ_SA_W_PHR:
24189 case OPC_MULSA_W_PH:
24190 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24191 break;
24192 default: /* Invalid */
24193 MIPS_INVAL("MASK DPAW.PH");
24194 generate_exception_end(ctx, EXCP_RI);
24195 break;
24197 break;
24198 case OPC_INSV_DSP:
24199 op2 = MASK_INSV(ctx->opcode);
24200 switch (op2) {
24201 case OPC_INSV:
24202 check_dsp(ctx);
24204 TCGv t0, t1;
24206 if (rt == 0) {
24207 break;
24210 t0 = tcg_temp_new();
24211 t1 = tcg_temp_new();
24213 gen_load_gpr(t0, rt);
24214 gen_load_gpr(t1, rs);
24216 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24218 tcg_temp_free(t0);
24219 tcg_temp_free(t1);
24220 break;
24222 default: /* Invalid */
24223 MIPS_INVAL("MASK INSV");
24224 generate_exception_end(ctx, EXCP_RI);
24225 break;
24227 break;
24228 case OPC_APPEND_DSP:
24229 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24230 break;
24231 case OPC_EXTR_W_DSP:
24232 op2 = MASK_EXTR_W(ctx->opcode);
24233 switch (op2) {
24234 case OPC_EXTR_W:
24235 case OPC_EXTR_R_W:
24236 case OPC_EXTR_RS_W:
24237 case OPC_EXTR_S_H:
24238 case OPC_EXTRV_S_H:
24239 case OPC_EXTRV_W:
24240 case OPC_EXTRV_R_W:
24241 case OPC_EXTRV_RS_W:
24242 case OPC_EXTP:
24243 case OPC_EXTPV:
24244 case OPC_EXTPDP:
24245 case OPC_EXTPDPV:
24246 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24247 break;
24248 case OPC_RDDSP:
24249 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24250 break;
24251 case OPC_SHILO:
24252 case OPC_SHILOV:
24253 case OPC_MTHLIP:
24254 case OPC_WRDSP:
24255 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24256 break;
24257 default: /* Invalid */
24258 MIPS_INVAL("MASK EXTR.W");
24259 generate_exception_end(ctx, EXCP_RI);
24260 break;
24262 break;
24263 #if defined(TARGET_MIPS64)
24264 case OPC_DDIV_G_2E:
24265 case OPC_DDIVU_G_2E:
24266 case OPC_DMULT_G_2E:
24267 case OPC_DMULTU_G_2E:
24268 case OPC_DMOD_G_2E:
24269 case OPC_DMODU_G_2E:
24270 check_insn(ctx, INSN_LOONGSON2E);
24271 gen_loongson_integer(ctx, op1, rd, rs, rt);
24272 break;
24273 case OPC_ABSQ_S_QH_DSP:
24274 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24275 switch (op2) {
24276 case OPC_PRECEQ_L_PWL:
24277 case OPC_PRECEQ_L_PWR:
24278 case OPC_PRECEQ_PW_QHL:
24279 case OPC_PRECEQ_PW_QHR:
24280 case OPC_PRECEQ_PW_QHLA:
24281 case OPC_PRECEQ_PW_QHRA:
24282 case OPC_PRECEQU_QH_OBL:
24283 case OPC_PRECEQU_QH_OBR:
24284 case OPC_PRECEQU_QH_OBLA:
24285 case OPC_PRECEQU_QH_OBRA:
24286 case OPC_PRECEU_QH_OBL:
24287 case OPC_PRECEU_QH_OBR:
24288 case OPC_PRECEU_QH_OBLA:
24289 case OPC_PRECEU_QH_OBRA:
24290 case OPC_ABSQ_S_OB:
24291 case OPC_ABSQ_S_PW:
24292 case OPC_ABSQ_S_QH:
24293 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24294 break;
24295 case OPC_REPL_OB:
24296 case OPC_REPL_PW:
24297 case OPC_REPL_QH:
24298 case OPC_REPLV_OB:
24299 case OPC_REPLV_PW:
24300 case OPC_REPLV_QH:
24301 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24302 break;
24303 default: /* Invalid */
24304 MIPS_INVAL("MASK ABSQ_S.QH");
24305 generate_exception_end(ctx, EXCP_RI);
24306 break;
24308 break;
24309 case OPC_ADDU_OB_DSP:
24310 op2 = MASK_ADDU_OB(ctx->opcode);
24311 switch (op2) {
24312 case OPC_RADDU_L_OB:
24313 case OPC_SUBQ_PW:
24314 case OPC_SUBQ_S_PW:
24315 case OPC_SUBQ_QH:
24316 case OPC_SUBQ_S_QH:
24317 case OPC_SUBU_OB:
24318 case OPC_SUBU_S_OB:
24319 case OPC_SUBU_QH:
24320 case OPC_SUBU_S_QH:
24321 case OPC_SUBUH_OB:
24322 case OPC_SUBUH_R_OB:
24323 case OPC_ADDQ_PW:
24324 case OPC_ADDQ_S_PW:
24325 case OPC_ADDQ_QH:
24326 case OPC_ADDQ_S_QH:
24327 case OPC_ADDU_OB:
24328 case OPC_ADDU_S_OB:
24329 case OPC_ADDU_QH:
24330 case OPC_ADDU_S_QH:
24331 case OPC_ADDUH_OB:
24332 case OPC_ADDUH_R_OB:
24333 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24334 break;
24335 case OPC_MULEQ_S_PW_QHL:
24336 case OPC_MULEQ_S_PW_QHR:
24337 case OPC_MULEU_S_QH_OBL:
24338 case OPC_MULEU_S_QH_OBR:
24339 case OPC_MULQ_RS_QH:
24340 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24341 break;
24342 default: /* Invalid */
24343 MIPS_INVAL("MASK ADDU.OB");
24344 generate_exception_end(ctx, EXCP_RI);
24345 break;
24347 break;
24348 case OPC_CMPU_EQ_OB_DSP:
24349 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24350 switch (op2) {
24351 case OPC_PRECR_SRA_QH_PW:
24352 case OPC_PRECR_SRA_R_QH_PW:
24353 /* Return value is rt. */
24354 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24355 break;
24356 case OPC_PRECR_OB_QH:
24357 case OPC_PRECRQ_OB_QH:
24358 case OPC_PRECRQ_PW_L:
24359 case OPC_PRECRQ_QH_PW:
24360 case OPC_PRECRQ_RS_QH_PW:
24361 case OPC_PRECRQU_S_OB_QH:
24362 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24363 break;
24364 case OPC_CMPU_EQ_OB:
24365 case OPC_CMPU_LT_OB:
24366 case OPC_CMPU_LE_OB:
24367 case OPC_CMP_EQ_QH:
24368 case OPC_CMP_LT_QH:
24369 case OPC_CMP_LE_QH:
24370 case OPC_CMP_EQ_PW:
24371 case OPC_CMP_LT_PW:
24372 case OPC_CMP_LE_PW:
24373 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24374 break;
24375 case OPC_CMPGDU_EQ_OB:
24376 case OPC_CMPGDU_LT_OB:
24377 case OPC_CMPGDU_LE_OB:
24378 case OPC_CMPGU_EQ_OB:
24379 case OPC_CMPGU_LT_OB:
24380 case OPC_CMPGU_LE_OB:
24381 case OPC_PACKRL_PW:
24382 case OPC_PICK_OB:
24383 case OPC_PICK_PW:
24384 case OPC_PICK_QH:
24385 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24386 break;
24387 default: /* Invalid */
24388 MIPS_INVAL("MASK CMPU_EQ.OB");
24389 generate_exception_end(ctx, EXCP_RI);
24390 break;
24392 break;
24393 case OPC_DAPPEND_DSP:
24394 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24395 break;
24396 case OPC_DEXTR_W_DSP:
24397 op2 = MASK_DEXTR_W(ctx->opcode);
24398 switch (op2) {
24399 case OPC_DEXTP:
24400 case OPC_DEXTPDP:
24401 case OPC_DEXTPDPV:
24402 case OPC_DEXTPV:
24403 case OPC_DEXTR_L:
24404 case OPC_DEXTR_R_L:
24405 case OPC_DEXTR_RS_L:
24406 case OPC_DEXTR_W:
24407 case OPC_DEXTR_R_W:
24408 case OPC_DEXTR_RS_W:
24409 case OPC_DEXTR_S_H:
24410 case OPC_DEXTRV_L:
24411 case OPC_DEXTRV_R_L:
24412 case OPC_DEXTRV_RS_L:
24413 case OPC_DEXTRV_S_H:
24414 case OPC_DEXTRV_W:
24415 case OPC_DEXTRV_R_W:
24416 case OPC_DEXTRV_RS_W:
24417 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24418 break;
24419 case OPC_DMTHLIP:
24420 case OPC_DSHILO:
24421 case OPC_DSHILOV:
24422 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24423 break;
24424 default: /* Invalid */
24425 MIPS_INVAL("MASK EXTR.W");
24426 generate_exception_end(ctx, EXCP_RI);
24427 break;
24429 break;
24430 case OPC_DPAQ_W_QH_DSP:
24431 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24432 switch (op2) {
24433 case OPC_DPAU_H_OBL:
24434 case OPC_DPAU_H_OBR:
24435 case OPC_DPSU_H_OBL:
24436 case OPC_DPSU_H_OBR:
24437 case OPC_DPA_W_QH:
24438 case OPC_DPAQ_S_W_QH:
24439 case OPC_DPS_W_QH:
24440 case OPC_DPSQ_S_W_QH:
24441 case OPC_MULSAQ_S_W_QH:
24442 case OPC_DPAQ_SA_L_PW:
24443 case OPC_DPSQ_SA_L_PW:
24444 case OPC_MULSAQ_S_L_PW:
24445 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24446 break;
24447 case OPC_MAQ_S_W_QHLL:
24448 case OPC_MAQ_S_W_QHLR:
24449 case OPC_MAQ_S_W_QHRL:
24450 case OPC_MAQ_S_W_QHRR:
24451 case OPC_MAQ_SA_W_QHLL:
24452 case OPC_MAQ_SA_W_QHLR:
24453 case OPC_MAQ_SA_W_QHRL:
24454 case OPC_MAQ_SA_W_QHRR:
24455 case OPC_MAQ_S_L_PWL:
24456 case OPC_MAQ_S_L_PWR:
24457 case OPC_DMADD:
24458 case OPC_DMADDU:
24459 case OPC_DMSUB:
24460 case OPC_DMSUBU:
24461 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24462 break;
24463 default: /* Invalid */
24464 MIPS_INVAL("MASK DPAQ.W.QH");
24465 generate_exception_end(ctx, EXCP_RI);
24466 break;
24468 break;
24469 case OPC_DINSV_DSP:
24470 op2 = MASK_INSV(ctx->opcode);
24471 switch (op2) {
24472 case OPC_DINSV:
24474 TCGv t0, t1;
24476 if (rt == 0) {
24477 break;
24479 check_dsp(ctx);
24481 t0 = tcg_temp_new();
24482 t1 = tcg_temp_new();
24484 gen_load_gpr(t0, rt);
24485 gen_load_gpr(t1, rs);
24487 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24489 tcg_temp_free(t0);
24490 tcg_temp_free(t1);
24491 break;
24493 default: /* Invalid */
24494 MIPS_INVAL("MASK DINSV");
24495 generate_exception_end(ctx, EXCP_RI);
24496 break;
24498 break;
24499 case OPC_SHLL_OB_DSP:
24500 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24501 break;
24502 #endif
24503 default: /* Invalid */
24504 MIPS_INVAL("special3_legacy");
24505 generate_exception_end(ctx, EXCP_RI);
24506 break;
24510 static void decode_tx79_mmi0(CPUMIPSState *env, DisasContext *ctx)
24512 uint32_t opc = MASK_TX79_MMI0(ctx->opcode);
24514 switch (opc) {
24515 case TX79_MMI0_PADDW: /* TODO: TX79_MMI0_PADDW */
24516 case TX79_MMI0_PSUBW: /* TODO: TX79_MMI0_PSUBW */
24517 case TX79_MMI0_PCGTW: /* TODO: TX79_MMI0_PCGTW */
24518 case TX79_MMI0_PMAXW: /* TODO: TX79_MMI0_PMAXW */
24519 case TX79_MMI0_PADDH: /* TODO: TX79_MMI0_PADDH */
24520 case TX79_MMI0_PSUBH: /* TODO: TX79_MMI0_PSUBH */
24521 case TX79_MMI0_PCGTH: /* TODO: TX79_MMI0_PCGTH */
24522 case TX79_MMI0_PMAXH: /* TODO: TX79_MMI0_PMAXH */
24523 case TX79_MMI0_PADDB: /* TODO: TX79_MMI0_PADDB */
24524 case TX79_MMI0_PSUBB: /* TODO: TX79_MMI0_PSUBB */
24525 case TX79_MMI0_PCGTB: /* TODO: TX79_MMI0_PCGTB */
24526 case TX79_MMI0_PADDSW: /* TODO: TX79_MMI0_PADDSW */
24527 case TX79_MMI0_PSUBSW: /* TODO: TX79_MMI0_PSUBSW */
24528 case TX79_MMI0_PEXTLW: /* TODO: TX79_MMI0_PEXTLW */
24529 case TX79_MMI0_PPACW: /* TODO: TX79_MMI0_PPACW */
24530 case TX79_MMI0_PADDSH: /* TODO: TX79_MMI0_PADDSH */
24531 case TX79_MMI0_PSUBSH: /* TODO: TX79_MMI0_PSUBSH */
24532 case TX79_MMI0_PEXTLH: /* TODO: TX79_MMI0_PEXTLH */
24533 case TX79_MMI0_PPACH: /* TODO: TX79_MMI0_PPACH */
24534 case TX79_MMI0_PADDSB: /* TODO: TX79_MMI0_PADDSB */
24535 case TX79_MMI0_PSUBSB: /* TODO: TX79_MMI0_PSUBSB */
24536 case TX79_MMI0_PEXTLB: /* TODO: TX79_MMI0_PEXTLB */
24537 case TX79_MMI0_PPACB: /* TODO: TX79_MMI0_PPACB */
24538 case TX79_MMI0_PEXT5: /* TODO: TX79_MMI0_PEXT5 */
24539 case TX79_MMI0_PPAC5: /* TODO: TX79_MMI0_PPAC5 */
24540 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI0 */
24541 break;
24542 default:
24543 MIPS_INVAL("TX79 MMI class MMI0");
24544 generate_exception_end(ctx, EXCP_RI);
24545 break;
24549 static void decode_tx79_mmi1(CPUMIPSState *env, DisasContext *ctx)
24551 uint32_t opc = MASK_TX79_MMI1(ctx->opcode);
24553 switch (opc) {
24554 case TX79_MMI1_PABSW: /* TODO: TX79_MMI1_PABSW */
24555 case TX79_MMI1_PCEQW: /* TODO: TX79_MMI1_PCEQW */
24556 case TX79_MMI1_PMINW: /* TODO: TX79_MMI1_PMINW */
24557 case TX79_MMI1_PADSBH: /* TODO: TX79_MMI1_PADSBH */
24558 case TX79_MMI1_PABSH: /* TODO: TX79_MMI1_PABSH */
24559 case TX79_MMI1_PCEQH: /* TODO: TX79_MMI1_PCEQH */
24560 case TX79_MMI1_PMINH: /* TODO: TX79_MMI1_PMINH */
24561 case TX79_MMI1_PCEQB: /* TODO: TX79_MMI1_PCEQB */
24562 case TX79_MMI1_PADDUW: /* TODO: TX79_MMI1_PADDUW */
24563 case TX79_MMI1_PSUBUW: /* TODO: TX79_MMI1_PSUBUW */
24564 case TX79_MMI1_PEXTUW: /* TODO: TX79_MMI1_PEXTUW */
24565 case TX79_MMI1_PADDUH: /* TODO: TX79_MMI1_PADDUH */
24566 case TX79_MMI1_PSUBUH: /* TODO: TX79_MMI1_PSUBUH */
24567 case TX79_MMI1_PEXTUH: /* TODO: TX79_MMI1_PEXTUH */
24568 case TX79_MMI1_PADDUB: /* TODO: TX79_MMI1_PADDUB */
24569 case TX79_MMI1_PSUBUB: /* TODO: TX79_MMI1_PSUBUB */
24570 case TX79_MMI1_PEXTUB: /* TODO: TX79_MMI1_PEXTUB */
24571 case TX79_MMI1_QFSRV: /* TODO: TX79_MMI1_QFSRV */
24572 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI1 */
24573 break;
24574 default:
24575 MIPS_INVAL("TX79 MMI class MMI1");
24576 generate_exception_end(ctx, EXCP_RI);
24577 break;
24581 static void decode_tx79_mmi2(CPUMIPSState *env, DisasContext *ctx)
24583 uint32_t opc = MASK_TX79_MMI2(ctx->opcode);
24585 switch (opc) {
24586 case TX79_MMI2_PMADDW: /* TODO: TX79_MMI2_PMADDW */
24587 case TX79_MMI2_PSLLVW: /* TODO: TX79_MMI2_PSLLVW */
24588 case TX79_MMI2_PSRLVW: /* TODO: TX79_MMI2_PSRLVW */
24589 case TX79_MMI2_PMSUBW: /* TODO: TX79_MMI2_PMSUBW */
24590 case TX79_MMI2_PMFHI: /* TODO: TX79_MMI2_PMFHI */
24591 case TX79_MMI2_PMFLO: /* TODO: TX79_MMI2_PMFLO */
24592 case TX79_MMI2_PINTH: /* TODO: TX79_MMI2_PINTH */
24593 case TX79_MMI2_PMULTW: /* TODO: TX79_MMI2_PMULTW */
24594 case TX79_MMI2_PDIVW: /* TODO: TX79_MMI2_PDIVW */
24595 case TX79_MMI2_PCPYLD: /* TODO: TX79_MMI2_PCPYLD */
24596 case TX79_MMI2_PMADDH: /* TODO: TX79_MMI2_PMADDH */
24597 case TX79_MMI2_PHMADH: /* TODO: TX79_MMI2_PHMADH */
24598 case TX79_MMI2_PAND: /* TODO: TX79_MMI2_PAND */
24599 case TX79_MMI2_PXOR: /* TODO: TX79_MMI2_PXOR */
24600 case TX79_MMI2_PMSUBH: /* TODO: TX79_MMI2_PMSUBH */
24601 case TX79_MMI2_PHMSBH: /* TODO: TX79_MMI2_PHMSBH */
24602 case TX79_MMI2_PEXEH: /* TODO: TX79_MMI2_PEXEH */
24603 case TX79_MMI2_PREVH: /* TODO: TX79_MMI2_PREVH */
24604 case TX79_MMI2_PMULTH: /* TODO: TX79_MMI2_PMULTH */
24605 case TX79_MMI2_PDIVBW: /* TODO: TX79_MMI2_PDIVBW */
24606 case TX79_MMI2_PEXEW: /* TODO: TX79_MMI2_PEXEW */
24607 case TX79_MMI2_PROT3W: /* TODO: TX79_MMI2_PROT3W */
24608 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI2 */
24609 break;
24610 default:
24611 MIPS_INVAL("TX79 MMI class MMI2");
24612 generate_exception_end(ctx, EXCP_RI);
24613 break;
24617 static void decode_tx79_mmi3(CPUMIPSState *env, DisasContext *ctx)
24619 uint32_t opc = MASK_TX79_MMI3(ctx->opcode);
24621 switch (opc) {
24622 case TX79_MMI3_PMADDUW: /* TODO: TX79_MMI3_PMADDUW */
24623 case TX79_MMI3_PSRAVW: /* TODO: TX79_MMI3_PSRAVW */
24624 case TX79_MMI3_PMTHI: /* TODO: TX79_MMI3_PMTHI */
24625 case TX79_MMI3_PMTLO: /* TODO: TX79_MMI3_PMTLO */
24626 case TX79_MMI3_PINTEH: /* TODO: TX79_MMI3_PINTEH */
24627 case TX79_MMI3_PMULTUW: /* TODO: TX79_MMI3_PMULTUW */
24628 case TX79_MMI3_PDIVUW: /* TODO: TX79_MMI3_PDIVUW */
24629 case TX79_MMI3_PCPYUD: /* TODO: TX79_MMI3_PCPYUD */
24630 case TX79_MMI3_POR: /* TODO: TX79_MMI3_POR */
24631 case TX79_MMI3_PNOR: /* TODO: TX79_MMI3_PNOR */
24632 case TX79_MMI3_PEXCH: /* TODO: TX79_MMI3_PEXCH */
24633 case TX79_MMI3_PCPYH: /* TODO: TX79_MMI3_PCPYH */
24634 case TX79_MMI3_PEXCW: /* TODO: TX79_MMI3_PEXCW */
24635 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_MMI_CLASS_MMI3 */
24636 break;
24637 default:
24638 MIPS_INVAL("TX79 MMI class MMI3");
24639 generate_exception_end(ctx, EXCP_RI);
24640 break;
24644 static void decode_tx79_mmi(CPUMIPSState *env, DisasContext *ctx)
24646 uint32_t opc = MASK_TX79_MMI(ctx->opcode);
24647 int rs = extract32(ctx->opcode, 21, 5);
24648 int rt = extract32(ctx->opcode, 16, 5);
24649 int rd = extract32(ctx->opcode, 11, 5);
24651 switch (opc) {
24652 case TX79_MMI_CLASS_MMI0:
24653 decode_tx79_mmi0(env, ctx);
24654 break;
24655 case TX79_MMI_CLASS_MMI1:
24656 decode_tx79_mmi1(env, ctx);
24657 break;
24658 case TX79_MMI_CLASS_MMI2:
24659 decode_tx79_mmi2(env, ctx);
24660 break;
24661 case TX79_MMI_CLASS_MMI3:
24662 decode_tx79_mmi3(env, ctx);
24663 break;
24664 case TX79_MMI_MULT1:
24665 case TX79_MMI_MULTU1:
24666 gen_mul_txx9(ctx, opc, rd, rs, rt);
24667 break;
24668 case TX79_MMI_MTLO1:
24669 case TX79_MMI_MTHI1:
24670 gen_HILO(ctx, opc, 1, rs);
24671 break;
24672 case TX79_MMI_MFLO1:
24673 case TX79_MMI_MFHI1:
24674 gen_HILO(ctx, opc, 1, rd);
24675 break;
24676 case TX79_MMI_MADD: /* TODO: TX79_MMI_MADD */
24677 case TX79_MMI_MADDU: /* TODO: TX79_MMI_MADDU */
24678 case TX79_MMI_PLZCW: /* TODO: TX79_MMI_PLZCW */
24679 case TX79_MMI_DIV1: /* TODO: TX79_MMI_DIV1 */
24680 case TX79_MMI_DIVU1: /* TODO: TX79_MMI_DIVU1 */
24681 case TX79_MMI_MADD1: /* TODO: TX79_MMI_MADD1 */
24682 case TX79_MMI_MADDU1: /* TODO: TX79_MMI_MADDU1 */
24683 case TX79_MMI_PMFHL: /* TODO: TX79_MMI_PMFHL */
24684 case TX79_MMI_PMTHL: /* TODO: TX79_MMI_PMTHL */
24685 case TX79_MMI_PSLLH: /* TODO: TX79_MMI_PSLLH */
24686 case TX79_MMI_PSRLH: /* TODO: TX79_MMI_PSRLH */
24687 case TX79_MMI_PSRAH: /* TODO: TX79_MMI_PSRAH */
24688 case TX79_MMI_PSLLW: /* TODO: TX79_MMI_PSLLW */
24689 case TX79_MMI_PSRLW: /* TODO: TX79_MMI_PSRLW */
24690 case TX79_MMI_PSRAW: /* TODO: TX79_MMI_PSRAW */
24691 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_CLASS_MMI */
24692 break;
24693 default:
24694 MIPS_INVAL("TX79 MMI class");
24695 generate_exception_end(ctx, EXCP_RI);
24696 break;
24700 static void decode_tx79_lq(CPUMIPSState *env, DisasContext *ctx)
24702 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_LQ */
24705 static void gen_tx79_sq(DisasContext *ctx, int base, int rt, int offset)
24707 generate_exception_end(ctx, EXCP_RI); /* TODO: TX79_SQ */
24711 * The TX79-specific instruction Store Quadword
24713 * +--------+-------+-------+------------------------+
24714 * | 011111 | base | rt | offset | SQ
24715 * +--------+-------+-------+------------------------+
24716 * 6 5 5 16
24718 * has the same opcode as the Read Hardware Register instruction
24720 * +--------+-------+-------+-------+-------+--------+
24721 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24722 * +--------+-------+-------+-------+-------+--------+
24723 * 6 5 5 5 5 6
24725 * that is required, trapped and emulated by the Linux kernel. However, all
24726 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24727 * offset is odd. Therefore all valid SQ instructions can execute normally.
24728 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24729 * between SQ and RDHWR, as the Linux kernel does.
24731 static void decode_tx79_sq(CPUMIPSState *env, DisasContext *ctx)
24733 int base = extract32(ctx->opcode, 21, 5);
24734 int rt = extract32(ctx->opcode, 16, 5);
24735 int offset = extract32(ctx->opcode, 0, 16);
24737 #ifdef CONFIG_USER_ONLY
24738 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24739 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24741 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24742 int rd = extract32(ctx->opcode, 11, 5);
24744 gen_rdhwr(ctx, rt, rd, 0);
24745 return;
24747 #endif
24749 gen_tx79_sq(ctx, base, rt, offset);
24752 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24754 int rs, rt, rd, sa;
24755 uint32_t op1, op2;
24756 int16_t imm;
24758 rs = (ctx->opcode >> 21) & 0x1f;
24759 rt = (ctx->opcode >> 16) & 0x1f;
24760 rd = (ctx->opcode >> 11) & 0x1f;
24761 sa = (ctx->opcode >> 6) & 0x1f;
24762 imm = sextract32(ctx->opcode, 7, 9);
24764 op1 = MASK_SPECIAL3(ctx->opcode);
24767 * EVA loads and stores overlap Loongson 2E instructions decoded by
24768 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24769 * EVA is absent.
24771 if (ctx->eva) {
24772 switch (op1) {
24773 case OPC_LWLE:
24774 case OPC_LWRE:
24775 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24776 /* fall through */
24777 case OPC_LBUE:
24778 case OPC_LHUE:
24779 case OPC_LBE:
24780 case OPC_LHE:
24781 case OPC_LLE:
24782 case OPC_LWE:
24783 check_cp0_enabled(ctx);
24784 gen_ld(ctx, op1, rt, rs, imm);
24785 return;
24786 case OPC_SWLE:
24787 case OPC_SWRE:
24788 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24789 /* fall through */
24790 case OPC_SBE:
24791 case OPC_SHE:
24792 case OPC_SWE:
24793 check_cp0_enabled(ctx);
24794 gen_st(ctx, op1, rt, rs, imm);
24795 return;
24796 case OPC_SCE:
24797 check_cp0_enabled(ctx);
24798 gen_st_cond(ctx, op1, rt, rs, imm);
24799 return;
24800 case OPC_CACHEE:
24801 check_cp0_enabled(ctx);
24802 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24803 gen_cache_operation(ctx, rt, rs, imm);
24805 /* Treat as NOP. */
24806 return;
24807 case OPC_PREFE:
24808 check_cp0_enabled(ctx);
24809 /* Treat as NOP. */
24810 return;
24814 switch (op1) {
24815 case OPC_EXT:
24816 case OPC_INS:
24817 check_insn(ctx, ISA_MIPS32R2);
24818 gen_bitops(ctx, op1, rt, rs, sa, rd);
24819 break;
24820 case OPC_BSHFL:
24821 op2 = MASK_BSHFL(ctx->opcode);
24822 switch (op2) {
24823 case OPC_ALIGN:
24824 case OPC_ALIGN_END:
24825 case OPC_BITSWAP:
24826 check_insn(ctx, ISA_MIPS32R6);
24827 decode_opc_special3_r6(env, ctx);
24828 break;
24829 default:
24830 check_insn(ctx, ISA_MIPS32R2);
24831 gen_bshfl(ctx, op2, rt, rd);
24832 break;
24834 break;
24835 #if defined(TARGET_MIPS64)
24836 case OPC_DEXTM:
24837 case OPC_DEXTU:
24838 case OPC_DEXT:
24839 case OPC_DINSM:
24840 case OPC_DINSU:
24841 case OPC_DINS:
24842 check_insn(ctx, ISA_MIPS64R2);
24843 check_mips_64(ctx);
24844 gen_bitops(ctx, op1, rt, rs, sa, rd);
24845 break;
24846 case OPC_DBSHFL:
24847 op2 = MASK_DBSHFL(ctx->opcode);
24848 switch (op2) {
24849 case OPC_DALIGN:
24850 case OPC_DALIGN_END:
24851 case OPC_DBITSWAP:
24852 check_insn(ctx, ISA_MIPS32R6);
24853 decode_opc_special3_r6(env, ctx);
24854 break;
24855 default:
24856 check_insn(ctx, ISA_MIPS64R2);
24857 check_mips_64(ctx);
24858 op2 = MASK_DBSHFL(ctx->opcode);
24859 gen_bshfl(ctx, op2, rt, rd);
24860 break;
24862 break;
24863 #endif
24864 case OPC_RDHWR:
24865 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24866 break;
24867 case OPC_FORK:
24868 check_mt(ctx);
24870 TCGv t0 = tcg_temp_new();
24871 TCGv t1 = tcg_temp_new();
24873 gen_load_gpr(t0, rt);
24874 gen_load_gpr(t1, rs);
24875 gen_helper_fork(t0, t1);
24876 tcg_temp_free(t0);
24877 tcg_temp_free(t1);
24879 break;
24880 case OPC_YIELD:
24881 check_mt(ctx);
24883 TCGv t0 = tcg_temp_new();
24885 gen_load_gpr(t0, rs);
24886 gen_helper_yield(t0, cpu_env, t0);
24887 gen_store_gpr(t0, rd);
24888 tcg_temp_free(t0);
24890 break;
24891 default:
24892 if (ctx->insn_flags & ISA_MIPS32R6) {
24893 decode_opc_special3_r6(env, ctx);
24894 } else {
24895 decode_opc_special3_legacy(env, ctx);
24900 /* MIPS SIMD Architecture (MSA) */
24901 static inline int check_msa_access(DisasContext *ctx)
24903 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
24904 !(ctx->hflags & MIPS_HFLAG_F64))) {
24905 generate_exception_end(ctx, EXCP_RI);
24906 return 0;
24909 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
24910 if (ctx->insn_flags & ASE_MSA) {
24911 generate_exception_end(ctx, EXCP_MSADIS);
24912 return 0;
24913 } else {
24914 generate_exception_end(ctx, EXCP_RI);
24915 return 0;
24918 return 1;
24921 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
24923 /* generates tcg ops to check if any element is 0 */
24924 /* Note this function only works with MSA_WRLEN = 128 */
24925 uint64_t eval_zero_or_big = 0;
24926 uint64_t eval_big = 0;
24927 TCGv_i64 t0 = tcg_temp_new_i64();
24928 TCGv_i64 t1 = tcg_temp_new_i64();
24929 switch (df) {
24930 case DF_BYTE:
24931 eval_zero_or_big = 0x0101010101010101ULL;
24932 eval_big = 0x8080808080808080ULL;
24933 break;
24934 case DF_HALF:
24935 eval_zero_or_big = 0x0001000100010001ULL;
24936 eval_big = 0x8000800080008000ULL;
24937 break;
24938 case DF_WORD:
24939 eval_zero_or_big = 0x0000000100000001ULL;
24940 eval_big = 0x8000000080000000ULL;
24941 break;
24942 case DF_DOUBLE:
24943 eval_zero_or_big = 0x0000000000000001ULL;
24944 eval_big = 0x8000000000000000ULL;
24945 break;
24947 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
24948 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
24949 tcg_gen_andi_i64(t0, t0, eval_big);
24950 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
24951 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
24952 tcg_gen_andi_i64(t1, t1, eval_big);
24953 tcg_gen_or_i64(t0, t0, t1);
24954 /* if all bits are zero then all elements are not zero */
24955 /* if some bit is non-zero then some element is zero */
24956 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
24957 tcg_gen_trunc_i64_tl(tresult, t0);
24958 tcg_temp_free_i64(t0);
24959 tcg_temp_free_i64(t1);
24962 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
24964 uint8_t df = (ctx->opcode >> 21) & 0x3;
24965 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24966 int64_t s16 = (int16_t)ctx->opcode;
24968 check_msa_access(ctx);
24970 if (ctx->hflags & MIPS_HFLAG_BMASK) {
24971 generate_exception_end(ctx, EXCP_RI);
24972 return;
24974 switch (op1) {
24975 case OPC_BZ_V:
24976 case OPC_BNZ_V:
24978 TCGv_i64 t0 = tcg_temp_new_i64();
24979 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
24980 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
24981 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
24982 tcg_gen_trunc_i64_tl(bcond, t0);
24983 tcg_temp_free_i64(t0);
24985 break;
24986 case OPC_BZ_B:
24987 case OPC_BZ_H:
24988 case OPC_BZ_W:
24989 case OPC_BZ_D:
24990 gen_check_zero_element(bcond, df, wt);
24991 break;
24992 case OPC_BNZ_B:
24993 case OPC_BNZ_H:
24994 case OPC_BNZ_W:
24995 case OPC_BNZ_D:
24996 gen_check_zero_element(bcond, df, wt);
24997 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
24998 break;
25001 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
25003 ctx->hflags |= MIPS_HFLAG_BC;
25004 ctx->hflags |= MIPS_HFLAG_BDS32;
25007 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
25009 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
25010 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
25011 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25012 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25014 TCGv_i32 twd = tcg_const_i32(wd);
25015 TCGv_i32 tws = tcg_const_i32(ws);
25016 TCGv_i32 ti8 = tcg_const_i32(i8);
25018 switch (MASK_MSA_I8(ctx->opcode)) {
25019 case OPC_ANDI_B:
25020 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
25021 break;
25022 case OPC_ORI_B:
25023 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
25024 break;
25025 case OPC_NORI_B:
25026 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
25027 break;
25028 case OPC_XORI_B:
25029 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
25030 break;
25031 case OPC_BMNZI_B:
25032 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
25033 break;
25034 case OPC_BMZI_B:
25035 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
25036 break;
25037 case OPC_BSELI_B:
25038 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
25039 break;
25040 case OPC_SHF_B:
25041 case OPC_SHF_H:
25042 case OPC_SHF_W:
25044 uint8_t df = (ctx->opcode >> 24) & 0x3;
25045 if (df == DF_DOUBLE) {
25046 generate_exception_end(ctx, EXCP_RI);
25047 } else {
25048 TCGv_i32 tdf = tcg_const_i32(df);
25049 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
25050 tcg_temp_free_i32(tdf);
25053 break;
25054 default:
25055 MIPS_INVAL("MSA instruction");
25056 generate_exception_end(ctx, EXCP_RI);
25057 break;
25060 tcg_temp_free_i32(twd);
25061 tcg_temp_free_i32(tws);
25062 tcg_temp_free_i32(ti8);
25065 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
25067 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25068 uint8_t df = (ctx->opcode >> 21) & 0x3;
25069 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
25070 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
25071 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25072 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25074 TCGv_i32 tdf = tcg_const_i32(df);
25075 TCGv_i32 twd = tcg_const_i32(wd);
25076 TCGv_i32 tws = tcg_const_i32(ws);
25077 TCGv_i32 timm = tcg_temp_new_i32();
25078 tcg_gen_movi_i32(timm, u5);
25080 switch (MASK_MSA_I5(ctx->opcode)) {
25081 case OPC_ADDVI_df:
25082 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
25083 break;
25084 case OPC_SUBVI_df:
25085 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
25086 break;
25087 case OPC_MAXI_S_df:
25088 tcg_gen_movi_i32(timm, s5);
25089 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
25090 break;
25091 case OPC_MAXI_U_df:
25092 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
25093 break;
25094 case OPC_MINI_S_df:
25095 tcg_gen_movi_i32(timm, s5);
25096 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
25097 break;
25098 case OPC_MINI_U_df:
25099 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
25100 break;
25101 case OPC_CEQI_df:
25102 tcg_gen_movi_i32(timm, s5);
25103 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
25104 break;
25105 case OPC_CLTI_S_df:
25106 tcg_gen_movi_i32(timm, s5);
25107 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
25108 break;
25109 case OPC_CLTI_U_df:
25110 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
25111 break;
25112 case OPC_CLEI_S_df:
25113 tcg_gen_movi_i32(timm, s5);
25114 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
25115 break;
25116 case OPC_CLEI_U_df:
25117 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
25118 break;
25119 case OPC_LDI_df:
25121 int32_t s10 = sextract32(ctx->opcode, 11, 10);
25122 tcg_gen_movi_i32(timm, s10);
25123 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
25125 break;
25126 default:
25127 MIPS_INVAL("MSA instruction");
25128 generate_exception_end(ctx, EXCP_RI);
25129 break;
25132 tcg_temp_free_i32(tdf);
25133 tcg_temp_free_i32(twd);
25134 tcg_temp_free_i32(tws);
25135 tcg_temp_free_i32(timm);
25138 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
25140 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25141 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
25142 uint32_t df = 0, m = 0;
25143 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25144 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25146 TCGv_i32 tdf;
25147 TCGv_i32 tm;
25148 TCGv_i32 twd;
25149 TCGv_i32 tws;
25151 if ((dfm & 0x40) == 0x00) {
25152 m = dfm & 0x3f;
25153 df = DF_DOUBLE;
25154 } else if ((dfm & 0x60) == 0x40) {
25155 m = dfm & 0x1f;
25156 df = DF_WORD;
25157 } else if ((dfm & 0x70) == 0x60) {
25158 m = dfm & 0x0f;
25159 df = DF_HALF;
25160 } else if ((dfm & 0x78) == 0x70) {
25161 m = dfm & 0x7;
25162 df = DF_BYTE;
25163 } else {
25164 generate_exception_end(ctx, EXCP_RI);
25165 return;
25168 tdf = tcg_const_i32(df);
25169 tm = tcg_const_i32(m);
25170 twd = tcg_const_i32(wd);
25171 tws = tcg_const_i32(ws);
25173 switch (MASK_MSA_BIT(ctx->opcode)) {
25174 case OPC_SLLI_df:
25175 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
25176 break;
25177 case OPC_SRAI_df:
25178 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
25179 break;
25180 case OPC_SRLI_df:
25181 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
25182 break;
25183 case OPC_BCLRI_df:
25184 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
25185 break;
25186 case OPC_BSETI_df:
25187 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
25188 break;
25189 case OPC_BNEGI_df:
25190 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
25191 break;
25192 case OPC_BINSLI_df:
25193 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
25194 break;
25195 case OPC_BINSRI_df:
25196 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
25197 break;
25198 case OPC_SAT_S_df:
25199 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
25200 break;
25201 case OPC_SAT_U_df:
25202 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
25203 break;
25204 case OPC_SRARI_df:
25205 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
25206 break;
25207 case OPC_SRLRI_df:
25208 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
25209 break;
25210 default:
25211 MIPS_INVAL("MSA instruction");
25212 generate_exception_end(ctx, EXCP_RI);
25213 break;
25216 tcg_temp_free_i32(tdf);
25217 tcg_temp_free_i32(tm);
25218 tcg_temp_free_i32(twd);
25219 tcg_temp_free_i32(tws);
25222 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
25224 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
25225 uint8_t df = (ctx->opcode >> 21) & 0x3;
25226 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25227 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25228 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25230 TCGv_i32 tdf = tcg_const_i32(df);
25231 TCGv_i32 twd = tcg_const_i32(wd);
25232 TCGv_i32 tws = tcg_const_i32(ws);
25233 TCGv_i32 twt = tcg_const_i32(wt);
25235 switch (MASK_MSA_3R(ctx->opcode)) {
25236 case OPC_SLL_df:
25237 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
25238 break;
25239 case OPC_ADDV_df:
25240 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
25241 break;
25242 case OPC_CEQ_df:
25243 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
25244 break;
25245 case OPC_ADD_A_df:
25246 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
25247 break;
25248 case OPC_SUBS_S_df:
25249 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
25250 break;
25251 case OPC_MULV_df:
25252 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
25253 break;
25254 case OPC_SLD_df:
25255 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
25256 break;
25257 case OPC_VSHF_df:
25258 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
25259 break;
25260 case OPC_SRA_df:
25261 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
25262 break;
25263 case OPC_SUBV_df:
25264 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
25265 break;
25266 case OPC_ADDS_A_df:
25267 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
25268 break;
25269 case OPC_SUBS_U_df:
25270 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
25271 break;
25272 case OPC_MADDV_df:
25273 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
25274 break;
25275 case OPC_SPLAT_df:
25276 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
25277 break;
25278 case OPC_SRAR_df:
25279 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
25280 break;
25281 case OPC_SRL_df:
25282 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
25283 break;
25284 case OPC_MAX_S_df:
25285 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
25286 break;
25287 case OPC_CLT_S_df:
25288 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
25289 break;
25290 case OPC_ADDS_S_df:
25291 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
25292 break;
25293 case OPC_SUBSUS_U_df:
25294 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
25295 break;
25296 case OPC_MSUBV_df:
25297 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
25298 break;
25299 case OPC_PCKEV_df:
25300 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
25301 break;
25302 case OPC_SRLR_df:
25303 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
25304 break;
25305 case OPC_BCLR_df:
25306 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
25307 break;
25308 case OPC_MAX_U_df:
25309 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
25310 break;
25311 case OPC_CLT_U_df:
25312 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
25313 break;
25314 case OPC_ADDS_U_df:
25315 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
25316 break;
25317 case OPC_SUBSUU_S_df:
25318 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
25319 break;
25320 case OPC_PCKOD_df:
25321 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
25322 break;
25323 case OPC_BSET_df:
25324 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
25325 break;
25326 case OPC_MIN_S_df:
25327 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
25328 break;
25329 case OPC_CLE_S_df:
25330 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
25331 break;
25332 case OPC_AVE_S_df:
25333 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
25334 break;
25335 case OPC_ASUB_S_df:
25336 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
25337 break;
25338 case OPC_DIV_S_df:
25339 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
25340 break;
25341 case OPC_ILVL_df:
25342 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
25343 break;
25344 case OPC_BNEG_df:
25345 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
25346 break;
25347 case OPC_MIN_U_df:
25348 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
25349 break;
25350 case OPC_CLE_U_df:
25351 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
25352 break;
25353 case OPC_AVE_U_df:
25354 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
25355 break;
25356 case OPC_ASUB_U_df:
25357 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
25358 break;
25359 case OPC_DIV_U_df:
25360 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
25361 break;
25362 case OPC_ILVR_df:
25363 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
25364 break;
25365 case OPC_BINSL_df:
25366 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
25367 break;
25368 case OPC_MAX_A_df:
25369 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
25370 break;
25371 case OPC_AVER_S_df:
25372 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
25373 break;
25374 case OPC_MOD_S_df:
25375 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
25376 break;
25377 case OPC_ILVEV_df:
25378 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
25379 break;
25380 case OPC_BINSR_df:
25381 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
25382 break;
25383 case OPC_MIN_A_df:
25384 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
25385 break;
25386 case OPC_AVER_U_df:
25387 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
25388 break;
25389 case OPC_MOD_U_df:
25390 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
25391 break;
25392 case OPC_ILVOD_df:
25393 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
25394 break;
25396 case OPC_DOTP_S_df:
25397 case OPC_DOTP_U_df:
25398 case OPC_DPADD_S_df:
25399 case OPC_DPADD_U_df:
25400 case OPC_DPSUB_S_df:
25401 case OPC_HADD_S_df:
25402 case OPC_DPSUB_U_df:
25403 case OPC_HADD_U_df:
25404 case OPC_HSUB_S_df:
25405 case OPC_HSUB_U_df:
25406 if (df == DF_BYTE) {
25407 generate_exception_end(ctx, EXCP_RI);
25408 break;
25410 switch (MASK_MSA_3R(ctx->opcode)) {
25411 case OPC_DOTP_S_df:
25412 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
25413 break;
25414 case OPC_DOTP_U_df:
25415 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
25416 break;
25417 case OPC_DPADD_S_df:
25418 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
25419 break;
25420 case OPC_DPADD_U_df:
25421 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
25422 break;
25423 case OPC_DPSUB_S_df:
25424 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
25425 break;
25426 case OPC_HADD_S_df:
25427 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
25428 break;
25429 case OPC_DPSUB_U_df:
25430 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
25431 break;
25432 case OPC_HADD_U_df:
25433 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
25434 break;
25435 case OPC_HSUB_S_df:
25436 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
25437 break;
25438 case OPC_HSUB_U_df:
25439 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
25440 break;
25442 break;
25443 default:
25444 MIPS_INVAL("MSA instruction");
25445 generate_exception_end(ctx, EXCP_RI);
25446 break;
25448 tcg_temp_free_i32(twd);
25449 tcg_temp_free_i32(tws);
25450 tcg_temp_free_i32(twt);
25451 tcg_temp_free_i32(tdf);
25454 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
25456 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
25457 uint8_t source = (ctx->opcode >> 11) & 0x1f;
25458 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
25459 TCGv telm = tcg_temp_new();
25460 TCGv_i32 tsr = tcg_const_i32(source);
25461 TCGv_i32 tdt = tcg_const_i32(dest);
25463 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
25464 case OPC_CTCMSA:
25465 gen_load_gpr(telm, source);
25466 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
25467 break;
25468 case OPC_CFCMSA:
25469 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
25470 gen_store_gpr(telm, dest);
25471 break;
25472 case OPC_MOVE_V:
25473 gen_helper_msa_move_v(cpu_env, tdt, tsr);
25474 break;
25475 default:
25476 MIPS_INVAL("MSA instruction");
25477 generate_exception_end(ctx, EXCP_RI);
25478 break;
25481 tcg_temp_free(telm);
25482 tcg_temp_free_i32(tdt);
25483 tcg_temp_free_i32(tsr);
25486 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
25487 uint32_t n)
25489 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25490 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25491 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25493 TCGv_i32 tws = tcg_const_i32(ws);
25494 TCGv_i32 twd = tcg_const_i32(wd);
25495 TCGv_i32 tn = tcg_const_i32(n);
25496 TCGv_i32 tdf = tcg_const_i32(df);
25498 switch (MASK_MSA_ELM(ctx->opcode)) {
25499 case OPC_SLDI_df:
25500 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
25501 break;
25502 case OPC_SPLATI_df:
25503 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
25504 break;
25505 case OPC_INSVE_df:
25506 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
25507 break;
25508 case OPC_COPY_S_df:
25509 case OPC_COPY_U_df:
25510 case OPC_INSERT_df:
25511 #if !defined(TARGET_MIPS64)
25512 /* Double format valid only for MIPS64 */
25513 if (df == DF_DOUBLE) {
25514 generate_exception_end(ctx, EXCP_RI);
25515 break;
25517 #endif
25518 switch (MASK_MSA_ELM(ctx->opcode)) {
25519 case OPC_COPY_S_df:
25520 if (likely(wd != 0)) {
25521 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
25523 break;
25524 case OPC_COPY_U_df:
25525 if (likely(wd != 0)) {
25526 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
25528 break;
25529 case OPC_INSERT_df:
25530 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
25531 break;
25533 break;
25534 default:
25535 MIPS_INVAL("MSA instruction");
25536 generate_exception_end(ctx, EXCP_RI);
25538 tcg_temp_free_i32(twd);
25539 tcg_temp_free_i32(tws);
25540 tcg_temp_free_i32(tn);
25541 tcg_temp_free_i32(tdf);
25544 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
25546 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
25547 uint32_t df = 0, n = 0;
25549 if ((dfn & 0x30) == 0x00) {
25550 n = dfn & 0x0f;
25551 df = DF_BYTE;
25552 } else if ((dfn & 0x38) == 0x20) {
25553 n = dfn & 0x07;
25554 df = DF_HALF;
25555 } else if ((dfn & 0x3c) == 0x30) {
25556 n = dfn & 0x03;
25557 df = DF_WORD;
25558 } else if ((dfn & 0x3e) == 0x38) {
25559 n = dfn & 0x01;
25560 df = DF_DOUBLE;
25561 } else if (dfn == 0x3E) {
25562 /* CTCMSA, CFCMSA, MOVE.V */
25563 gen_msa_elm_3e(env, ctx);
25564 return;
25565 } else {
25566 generate_exception_end(ctx, EXCP_RI);
25567 return;
25570 gen_msa_elm_df(env, ctx, df, n);
25573 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
25575 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25576 uint8_t df = (ctx->opcode >> 21) & 0x1;
25577 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25578 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25579 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25581 TCGv_i32 twd = tcg_const_i32(wd);
25582 TCGv_i32 tws = tcg_const_i32(ws);
25583 TCGv_i32 twt = tcg_const_i32(wt);
25584 TCGv_i32 tdf = tcg_temp_new_i32();
25586 /* adjust df value for floating-point instruction */
25587 tcg_gen_movi_i32(tdf, df + 2);
25589 switch (MASK_MSA_3RF(ctx->opcode)) {
25590 case OPC_FCAF_df:
25591 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
25592 break;
25593 case OPC_FADD_df:
25594 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
25595 break;
25596 case OPC_FCUN_df:
25597 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
25598 break;
25599 case OPC_FSUB_df:
25600 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
25601 break;
25602 case OPC_FCOR_df:
25603 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
25604 break;
25605 case OPC_FCEQ_df:
25606 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
25607 break;
25608 case OPC_FMUL_df:
25609 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
25610 break;
25611 case OPC_FCUNE_df:
25612 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
25613 break;
25614 case OPC_FCUEQ_df:
25615 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
25616 break;
25617 case OPC_FDIV_df:
25618 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
25619 break;
25620 case OPC_FCNE_df:
25621 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
25622 break;
25623 case OPC_FCLT_df:
25624 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
25625 break;
25626 case OPC_FMADD_df:
25627 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
25628 break;
25629 case OPC_MUL_Q_df:
25630 tcg_gen_movi_i32(tdf, df + 1);
25631 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
25632 break;
25633 case OPC_FCULT_df:
25634 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
25635 break;
25636 case OPC_FMSUB_df:
25637 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
25638 break;
25639 case OPC_MADD_Q_df:
25640 tcg_gen_movi_i32(tdf, df + 1);
25641 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
25642 break;
25643 case OPC_FCLE_df:
25644 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
25645 break;
25646 case OPC_MSUB_Q_df:
25647 tcg_gen_movi_i32(tdf, df + 1);
25648 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
25649 break;
25650 case OPC_FCULE_df:
25651 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
25652 break;
25653 case OPC_FEXP2_df:
25654 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
25655 break;
25656 case OPC_FSAF_df:
25657 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
25658 break;
25659 case OPC_FEXDO_df:
25660 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
25661 break;
25662 case OPC_FSUN_df:
25663 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
25664 break;
25665 case OPC_FSOR_df:
25666 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
25667 break;
25668 case OPC_FSEQ_df:
25669 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
25670 break;
25671 case OPC_FTQ_df:
25672 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
25673 break;
25674 case OPC_FSUNE_df:
25675 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
25676 break;
25677 case OPC_FSUEQ_df:
25678 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
25679 break;
25680 case OPC_FSNE_df:
25681 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
25682 break;
25683 case OPC_FSLT_df:
25684 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
25685 break;
25686 case OPC_FMIN_df:
25687 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
25688 break;
25689 case OPC_MULR_Q_df:
25690 tcg_gen_movi_i32(tdf, df + 1);
25691 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
25692 break;
25693 case OPC_FSULT_df:
25694 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
25695 break;
25696 case OPC_FMIN_A_df:
25697 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
25698 break;
25699 case OPC_MADDR_Q_df:
25700 tcg_gen_movi_i32(tdf, df + 1);
25701 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
25702 break;
25703 case OPC_FSLE_df:
25704 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
25705 break;
25706 case OPC_FMAX_df:
25707 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
25708 break;
25709 case OPC_MSUBR_Q_df:
25710 tcg_gen_movi_i32(tdf, df + 1);
25711 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
25712 break;
25713 case OPC_FSULE_df:
25714 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
25715 break;
25716 case OPC_FMAX_A_df:
25717 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
25718 break;
25719 default:
25720 MIPS_INVAL("MSA instruction");
25721 generate_exception_end(ctx, EXCP_RI);
25722 break;
25725 tcg_temp_free_i32(twd);
25726 tcg_temp_free_i32(tws);
25727 tcg_temp_free_i32(twt);
25728 tcg_temp_free_i32(tdf);
25731 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
25733 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25734 (op & (0x7 << 18)))
25735 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25736 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25737 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25738 uint8_t df = (ctx->opcode >> 16) & 0x3;
25739 TCGv_i32 twd = tcg_const_i32(wd);
25740 TCGv_i32 tws = tcg_const_i32(ws);
25741 TCGv_i32 twt = tcg_const_i32(wt);
25742 TCGv_i32 tdf = tcg_const_i32(df);
25744 switch (MASK_MSA_2R(ctx->opcode)) {
25745 case OPC_FILL_df:
25746 #if !defined(TARGET_MIPS64)
25747 /* Double format valid only for MIPS64 */
25748 if (df == DF_DOUBLE) {
25749 generate_exception_end(ctx, EXCP_RI);
25750 break;
25752 #endif
25753 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
25754 break;
25755 case OPC_PCNT_df:
25756 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
25757 break;
25758 case OPC_NLOC_df:
25759 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
25760 break;
25761 case OPC_NLZC_df:
25762 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25763 break;
25764 default:
25765 MIPS_INVAL("MSA instruction");
25766 generate_exception_end(ctx, EXCP_RI);
25767 break;
25770 tcg_temp_free_i32(twd);
25771 tcg_temp_free_i32(tws);
25772 tcg_temp_free_i32(twt);
25773 tcg_temp_free_i32(tdf);
25776 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25778 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25779 (op & (0xf << 17)))
25780 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25781 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25782 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25783 uint8_t df = (ctx->opcode >> 16) & 0x1;
25784 TCGv_i32 twd = tcg_const_i32(wd);
25785 TCGv_i32 tws = tcg_const_i32(ws);
25786 TCGv_i32 twt = tcg_const_i32(wt);
25787 /* adjust df value for floating-point instruction */
25788 TCGv_i32 tdf = tcg_const_i32(df + 2);
25790 switch (MASK_MSA_2RF(ctx->opcode)) {
25791 case OPC_FCLASS_df:
25792 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25793 break;
25794 case OPC_FTRUNC_S_df:
25795 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25796 break;
25797 case OPC_FTRUNC_U_df:
25798 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25799 break;
25800 case OPC_FSQRT_df:
25801 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25802 break;
25803 case OPC_FRSQRT_df:
25804 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25805 break;
25806 case OPC_FRCP_df:
25807 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25808 break;
25809 case OPC_FRINT_df:
25810 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25811 break;
25812 case OPC_FLOG2_df:
25813 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
25814 break;
25815 case OPC_FEXUPL_df:
25816 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
25817 break;
25818 case OPC_FEXUPR_df:
25819 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
25820 break;
25821 case OPC_FFQL_df:
25822 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
25823 break;
25824 case OPC_FFQR_df:
25825 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
25826 break;
25827 case OPC_FTINT_S_df:
25828 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
25829 break;
25830 case OPC_FTINT_U_df:
25831 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
25832 break;
25833 case OPC_FFINT_S_df:
25834 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
25835 break;
25836 case OPC_FFINT_U_df:
25837 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
25838 break;
25841 tcg_temp_free_i32(twd);
25842 tcg_temp_free_i32(tws);
25843 tcg_temp_free_i32(twt);
25844 tcg_temp_free_i32(tdf);
25847 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
25849 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
25850 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25851 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25852 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25853 TCGv_i32 twd = tcg_const_i32(wd);
25854 TCGv_i32 tws = tcg_const_i32(ws);
25855 TCGv_i32 twt = tcg_const_i32(wt);
25857 switch (MASK_MSA_VEC(ctx->opcode)) {
25858 case OPC_AND_V:
25859 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
25860 break;
25861 case OPC_OR_V:
25862 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
25863 break;
25864 case OPC_NOR_V:
25865 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
25866 break;
25867 case OPC_XOR_V:
25868 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
25869 break;
25870 case OPC_BMNZ_V:
25871 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
25872 break;
25873 case OPC_BMZ_V:
25874 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
25875 break;
25876 case OPC_BSEL_V:
25877 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
25878 break;
25879 default:
25880 MIPS_INVAL("MSA instruction");
25881 generate_exception_end(ctx, EXCP_RI);
25882 break;
25885 tcg_temp_free_i32(twd);
25886 tcg_temp_free_i32(tws);
25887 tcg_temp_free_i32(twt);
25890 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
25892 switch (MASK_MSA_VEC(ctx->opcode)) {
25893 case OPC_AND_V:
25894 case OPC_OR_V:
25895 case OPC_NOR_V:
25896 case OPC_XOR_V:
25897 case OPC_BMNZ_V:
25898 case OPC_BMZ_V:
25899 case OPC_BSEL_V:
25900 gen_msa_vec_v(env, ctx);
25901 break;
25902 case OPC_MSA_2R:
25903 gen_msa_2r(env, ctx);
25904 break;
25905 case OPC_MSA_2RF:
25906 gen_msa_2rf(env, ctx);
25907 break;
25908 default:
25909 MIPS_INVAL("MSA instruction");
25910 generate_exception_end(ctx, EXCP_RI);
25911 break;
25915 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
25917 uint32_t opcode = ctx->opcode;
25918 check_insn(ctx, ASE_MSA);
25919 check_msa_access(ctx);
25921 switch (MASK_MSA_MINOR(opcode)) {
25922 case OPC_MSA_I8_00:
25923 case OPC_MSA_I8_01:
25924 case OPC_MSA_I8_02:
25925 gen_msa_i8(env, ctx);
25926 break;
25927 case OPC_MSA_I5_06:
25928 case OPC_MSA_I5_07:
25929 gen_msa_i5(env, ctx);
25930 break;
25931 case OPC_MSA_BIT_09:
25932 case OPC_MSA_BIT_0A:
25933 gen_msa_bit(env, ctx);
25934 break;
25935 case OPC_MSA_3R_0D:
25936 case OPC_MSA_3R_0E:
25937 case OPC_MSA_3R_0F:
25938 case OPC_MSA_3R_10:
25939 case OPC_MSA_3R_11:
25940 case OPC_MSA_3R_12:
25941 case OPC_MSA_3R_13:
25942 case OPC_MSA_3R_14:
25943 case OPC_MSA_3R_15:
25944 gen_msa_3r(env, ctx);
25945 break;
25946 case OPC_MSA_ELM:
25947 gen_msa_elm(env, ctx);
25948 break;
25949 case OPC_MSA_3RF_1A:
25950 case OPC_MSA_3RF_1B:
25951 case OPC_MSA_3RF_1C:
25952 gen_msa_3rf(env, ctx);
25953 break;
25954 case OPC_MSA_VEC:
25955 gen_msa_vec(env, ctx);
25956 break;
25957 case OPC_LD_B:
25958 case OPC_LD_H:
25959 case OPC_LD_W:
25960 case OPC_LD_D:
25961 case OPC_ST_B:
25962 case OPC_ST_H:
25963 case OPC_ST_W:
25964 case OPC_ST_D:
25966 int32_t s10 = sextract32(ctx->opcode, 16, 10);
25967 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
25968 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25969 uint8_t df = (ctx->opcode >> 0) & 0x3;
25971 TCGv_i32 twd = tcg_const_i32(wd);
25972 TCGv taddr = tcg_temp_new();
25973 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
25975 switch (MASK_MSA_MINOR(opcode)) {
25976 case OPC_LD_B:
25977 gen_helper_msa_ld_b(cpu_env, twd, taddr);
25978 break;
25979 case OPC_LD_H:
25980 gen_helper_msa_ld_h(cpu_env, twd, taddr);
25981 break;
25982 case OPC_LD_W:
25983 gen_helper_msa_ld_w(cpu_env, twd, taddr);
25984 break;
25985 case OPC_LD_D:
25986 gen_helper_msa_ld_d(cpu_env, twd, taddr);
25987 break;
25988 case OPC_ST_B:
25989 gen_helper_msa_st_b(cpu_env, twd, taddr);
25990 break;
25991 case OPC_ST_H:
25992 gen_helper_msa_st_h(cpu_env, twd, taddr);
25993 break;
25994 case OPC_ST_W:
25995 gen_helper_msa_st_w(cpu_env, twd, taddr);
25996 break;
25997 case OPC_ST_D:
25998 gen_helper_msa_st_d(cpu_env, twd, taddr);
25999 break;
26002 tcg_temp_free_i32(twd);
26003 tcg_temp_free(taddr);
26005 break;
26006 default:
26007 MIPS_INVAL("MSA instruction");
26008 generate_exception_end(ctx, EXCP_RI);
26009 break;
26014 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
26016 int32_t offset;
26017 int rs, rt, rd, sa;
26018 uint32_t op, op1;
26019 int16_t imm;
26021 /* make sure instructions are on a word boundary */
26022 if (ctx->base.pc_next & 0x3) {
26023 env->CP0_BadVAddr = ctx->base.pc_next;
26024 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
26025 return;
26028 /* Handle blikely not taken case */
26029 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
26030 TCGLabel *l1 = gen_new_label();
26032 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
26033 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
26034 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
26035 gen_set_label(l1);
26038 op = MASK_OP_MAJOR(ctx->opcode);
26039 rs = (ctx->opcode >> 21) & 0x1f;
26040 rt = (ctx->opcode >> 16) & 0x1f;
26041 rd = (ctx->opcode >> 11) & 0x1f;
26042 sa = (ctx->opcode >> 6) & 0x1f;
26043 imm = (int16_t)ctx->opcode;
26044 switch (op) {
26045 case OPC_SPECIAL:
26046 decode_opc_special(env, ctx);
26047 break;
26048 case OPC_SPECIAL2:
26049 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
26050 decode_tx79_mmi(env, ctx);
26051 } else {
26052 decode_opc_special2_legacy(env, ctx);
26054 break;
26055 case OPC_SPECIAL3:
26056 if (ctx->insn_flags & INSN_R5900) {
26057 decode_tx79_sq(env, ctx); /* TX79_SQ */
26058 } else {
26059 decode_opc_special3(env, ctx);
26061 break;
26062 case OPC_REGIMM:
26063 op1 = MASK_REGIMM(ctx->opcode);
26064 switch (op1) {
26065 case OPC_BLTZL: /* REGIMM branches */
26066 case OPC_BGEZL:
26067 case OPC_BLTZALL:
26068 case OPC_BGEZALL:
26069 check_insn(ctx, ISA_MIPS2);
26070 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26071 /* Fallthrough */
26072 case OPC_BLTZ:
26073 case OPC_BGEZ:
26074 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26075 break;
26076 case OPC_BLTZAL:
26077 case OPC_BGEZAL:
26078 if (ctx->insn_flags & ISA_MIPS32R6) {
26079 if (rs == 0) {
26080 /* OPC_NAL, OPC_BAL */
26081 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
26082 } else {
26083 generate_exception_end(ctx, EXCP_RI);
26085 } else {
26086 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
26088 break;
26089 case OPC_TGEI: /* REGIMM traps */
26090 case OPC_TGEIU:
26091 case OPC_TLTI:
26092 case OPC_TLTIU:
26093 case OPC_TEQI:
26095 case OPC_TNEI:
26096 check_insn(ctx, ISA_MIPS2);
26097 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26098 gen_trap(ctx, op1, rs, -1, imm);
26099 break;
26100 case OPC_SIGRIE:
26101 check_insn(ctx, ISA_MIPS32R6);
26102 generate_exception_end(ctx, EXCP_RI);
26103 break;
26104 case OPC_SYNCI:
26105 check_insn(ctx, ISA_MIPS32R2);
26106 /* Break the TB to be able to sync copied instructions
26107 immediately */
26108 ctx->base.is_jmp = DISAS_STOP;
26109 break;
26110 case OPC_BPOSGE32: /* MIPS DSP branch */
26111 #if defined(TARGET_MIPS64)
26112 case OPC_BPOSGE64:
26113 #endif
26114 check_dsp(ctx);
26115 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
26116 break;
26117 #if defined(TARGET_MIPS64)
26118 case OPC_DAHI:
26119 check_insn(ctx, ISA_MIPS32R6);
26120 check_mips_64(ctx);
26121 if (rs != 0) {
26122 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
26124 break;
26125 case OPC_DATI:
26126 check_insn(ctx, ISA_MIPS32R6);
26127 check_mips_64(ctx);
26128 if (rs != 0) {
26129 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
26131 break;
26132 #endif
26133 default: /* Invalid */
26134 MIPS_INVAL("regimm");
26135 generate_exception_end(ctx, EXCP_RI);
26136 break;
26138 break;
26139 case OPC_CP0:
26140 check_cp0_enabled(ctx);
26141 op1 = MASK_CP0(ctx->opcode);
26142 switch (op1) {
26143 case OPC_MFC0:
26144 case OPC_MTC0:
26145 case OPC_MFTR:
26146 case OPC_MTTR:
26147 case OPC_MFHC0:
26148 case OPC_MTHC0:
26149 #if defined(TARGET_MIPS64)
26150 case OPC_DMFC0:
26151 case OPC_DMTC0:
26152 #endif
26153 #ifndef CONFIG_USER_ONLY
26154 gen_cp0(env, ctx, op1, rt, rd);
26155 #endif /* !CONFIG_USER_ONLY */
26156 break;
26157 case OPC_C0:
26158 case OPC_C0_1:
26159 case OPC_C0_2:
26160 case OPC_C0_3:
26161 case OPC_C0_4:
26162 case OPC_C0_5:
26163 case OPC_C0_6:
26164 case OPC_C0_7:
26165 case OPC_C0_8:
26166 case OPC_C0_9:
26167 case OPC_C0_A:
26168 case OPC_C0_B:
26169 case OPC_C0_C:
26170 case OPC_C0_D:
26171 case OPC_C0_E:
26172 case OPC_C0_F:
26173 #ifndef CONFIG_USER_ONLY
26174 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
26175 #endif /* !CONFIG_USER_ONLY */
26176 break;
26177 case OPC_MFMC0:
26178 #ifndef CONFIG_USER_ONLY
26180 uint32_t op2;
26181 TCGv t0 = tcg_temp_new();
26183 op2 = MASK_MFMC0(ctx->opcode);
26184 switch (op2) {
26185 case OPC_DMT:
26186 check_cp0_mt(ctx);
26187 gen_helper_dmt(t0);
26188 gen_store_gpr(t0, rt);
26189 break;
26190 case OPC_EMT:
26191 check_cp0_mt(ctx);
26192 gen_helper_emt(t0);
26193 gen_store_gpr(t0, rt);
26194 break;
26195 case OPC_DVPE:
26196 check_cp0_mt(ctx);
26197 gen_helper_dvpe(t0, cpu_env);
26198 gen_store_gpr(t0, rt);
26199 break;
26200 case OPC_EVPE:
26201 check_cp0_mt(ctx);
26202 gen_helper_evpe(t0, cpu_env);
26203 gen_store_gpr(t0, rt);
26204 break;
26205 case OPC_DVP:
26206 check_insn(ctx, ISA_MIPS32R6);
26207 if (ctx->vp) {
26208 gen_helper_dvp(t0, cpu_env);
26209 gen_store_gpr(t0, rt);
26211 break;
26212 case OPC_EVP:
26213 check_insn(ctx, ISA_MIPS32R6);
26214 if (ctx->vp) {
26215 gen_helper_evp(t0, cpu_env);
26216 gen_store_gpr(t0, rt);
26218 break;
26219 case OPC_DI:
26220 check_insn(ctx, ISA_MIPS32R2);
26221 save_cpu_state(ctx, 1);
26222 gen_helper_di(t0, cpu_env);
26223 gen_store_gpr(t0, rt);
26224 /* Stop translation as we may have switched
26225 the execution mode. */
26226 ctx->base.is_jmp = DISAS_STOP;
26227 break;
26228 case OPC_EI:
26229 check_insn(ctx, ISA_MIPS32R2);
26230 save_cpu_state(ctx, 1);
26231 gen_helper_ei(t0, cpu_env);
26232 gen_store_gpr(t0, rt);
26233 /* DISAS_STOP isn't sufficient, we need to ensure we break
26234 out of translated code to check for pending interrupts */
26235 gen_save_pc(ctx->base.pc_next + 4);
26236 ctx->base.is_jmp = DISAS_EXIT;
26237 break;
26238 default: /* Invalid */
26239 MIPS_INVAL("mfmc0");
26240 generate_exception_end(ctx, EXCP_RI);
26241 break;
26243 tcg_temp_free(t0);
26245 #endif /* !CONFIG_USER_ONLY */
26246 break;
26247 case OPC_RDPGPR:
26248 check_insn(ctx, ISA_MIPS32R2);
26249 gen_load_srsgpr(rt, rd);
26250 break;
26251 case OPC_WRPGPR:
26252 check_insn(ctx, ISA_MIPS32R2);
26253 gen_store_srsgpr(rt, rd);
26254 break;
26255 default:
26256 MIPS_INVAL("cp0");
26257 generate_exception_end(ctx, EXCP_RI);
26258 break;
26260 break;
26261 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
26262 if (ctx->insn_flags & ISA_MIPS32R6) {
26263 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
26264 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26265 } else {
26266 /* OPC_ADDI */
26267 /* Arithmetic with immediate opcode */
26268 gen_arith_imm(ctx, op, rt, rs, imm);
26270 break;
26271 case OPC_ADDIU:
26272 gen_arith_imm(ctx, op, rt, rs, imm);
26273 break;
26274 case OPC_SLTI: /* Set on less than with immediate opcode */
26275 case OPC_SLTIU:
26276 gen_slt_imm(ctx, op, rt, rs, imm);
26277 break;
26278 case OPC_ANDI: /* Arithmetic with immediate opcode */
26279 case OPC_LUI: /* OPC_AUI */
26280 case OPC_ORI:
26281 case OPC_XORI:
26282 gen_logic_imm(ctx, op, rt, rs, imm);
26283 break;
26284 case OPC_J: /* Jump */
26285 case OPC_JAL:
26286 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26287 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26288 break;
26289 /* Branch */
26290 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
26291 if (ctx->insn_flags & ISA_MIPS32R6) {
26292 if (rt == 0) {
26293 generate_exception_end(ctx, EXCP_RI);
26294 break;
26296 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
26297 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26298 } else {
26299 /* OPC_BLEZL */
26300 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26302 break;
26303 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
26304 if (ctx->insn_flags & ISA_MIPS32R6) {
26305 if (rt == 0) {
26306 generate_exception_end(ctx, EXCP_RI);
26307 break;
26309 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
26310 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26311 } else {
26312 /* OPC_BGTZL */
26313 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26315 break;
26316 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
26317 if (rt == 0) {
26318 /* OPC_BLEZ */
26319 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26320 } else {
26321 check_insn(ctx, ISA_MIPS32R6);
26322 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
26323 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26325 break;
26326 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
26327 if (rt == 0) {
26328 /* OPC_BGTZ */
26329 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26330 } else {
26331 check_insn(ctx, ISA_MIPS32R6);
26332 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
26333 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26335 break;
26336 case OPC_BEQL:
26337 case OPC_BNEL:
26338 check_insn(ctx, ISA_MIPS2);
26339 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26340 /* Fallthrough */
26341 case OPC_BEQ:
26342 case OPC_BNE:
26343 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
26344 break;
26345 case OPC_LL: /* Load and stores */
26346 check_insn(ctx, ISA_MIPS2);
26347 /* Fallthrough */
26348 case OPC_LWL:
26349 case OPC_LWR:
26350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26351 /* Fallthrough */
26352 case OPC_LB:
26353 case OPC_LH:
26354 case OPC_LW:
26355 case OPC_LWPC:
26356 case OPC_LBU:
26357 case OPC_LHU:
26358 gen_ld(ctx, op, rt, rs, imm);
26359 break;
26360 case OPC_SWL:
26361 case OPC_SWR:
26362 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26363 /* fall through */
26364 case OPC_SB:
26365 case OPC_SH:
26366 case OPC_SW:
26367 gen_st(ctx, op, rt, rs, imm);
26368 break;
26369 case OPC_SC:
26370 check_insn(ctx, ISA_MIPS2);
26371 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26372 gen_st_cond(ctx, op, rt, rs, imm);
26373 break;
26374 case OPC_CACHE:
26375 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26376 check_cp0_enabled(ctx);
26377 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
26378 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
26379 gen_cache_operation(ctx, rt, rs, imm);
26381 /* Treat as NOP. */
26382 break;
26383 case OPC_PREF:
26384 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26385 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
26386 /* Treat as NOP. */
26387 break;
26389 /* Floating point (COP1). */
26390 case OPC_LWC1:
26391 case OPC_LDC1:
26392 case OPC_SWC1:
26393 case OPC_SDC1:
26394 gen_cop1_ldst(ctx, op, rt, rs, imm);
26395 break;
26397 case OPC_CP1:
26398 op1 = MASK_CP1(ctx->opcode);
26400 switch (op1) {
26401 case OPC_MFHC1:
26402 case OPC_MTHC1:
26403 check_cp1_enabled(ctx);
26404 check_insn(ctx, ISA_MIPS32R2);
26405 /* fall through */
26406 case OPC_MFC1:
26407 case OPC_CFC1:
26408 case OPC_MTC1:
26409 case OPC_CTC1:
26410 check_cp1_enabled(ctx);
26411 gen_cp1(ctx, op1, rt, rd);
26412 break;
26413 #if defined(TARGET_MIPS64)
26414 case OPC_DMFC1:
26415 case OPC_DMTC1:
26416 check_cp1_enabled(ctx);
26417 check_insn(ctx, ISA_MIPS3);
26418 check_mips_64(ctx);
26419 gen_cp1(ctx, op1, rt, rd);
26420 break;
26421 #endif
26422 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
26423 check_cp1_enabled(ctx);
26424 if (ctx->insn_flags & ISA_MIPS32R6) {
26425 /* OPC_BC1EQZ */
26426 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26427 rt, imm << 2, 4);
26428 } else {
26429 /* OPC_BC1ANY2 */
26430 check_cop1x(ctx);
26431 check_insn(ctx, ASE_MIPS3D);
26432 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26433 (rt >> 2) & 0x7, imm << 2);
26435 break;
26436 case OPC_BC1NEZ:
26437 check_cp1_enabled(ctx);
26438 check_insn(ctx, ISA_MIPS32R6);
26439 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
26440 rt, imm << 2, 4);
26441 break;
26442 case OPC_BC1ANY4:
26443 check_cp1_enabled(ctx);
26444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26445 check_cop1x(ctx);
26446 check_insn(ctx, ASE_MIPS3D);
26447 /* fall through */
26448 case OPC_BC1:
26449 check_cp1_enabled(ctx);
26450 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26451 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
26452 (rt >> 2) & 0x7, imm << 2);
26453 break;
26454 case OPC_PS_FMT:
26455 check_ps(ctx);
26456 /* fall through */
26457 case OPC_S_FMT:
26458 case OPC_D_FMT:
26459 check_cp1_enabled(ctx);
26460 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26461 (imm >> 8) & 0x7);
26462 break;
26463 case OPC_W_FMT:
26464 case OPC_L_FMT:
26466 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
26467 check_cp1_enabled(ctx);
26468 if (ctx->insn_flags & ISA_MIPS32R6) {
26469 switch (r6_op) {
26470 case R6_OPC_CMP_AF_S:
26471 case R6_OPC_CMP_UN_S:
26472 case R6_OPC_CMP_EQ_S:
26473 case R6_OPC_CMP_UEQ_S:
26474 case R6_OPC_CMP_LT_S:
26475 case R6_OPC_CMP_ULT_S:
26476 case R6_OPC_CMP_LE_S:
26477 case R6_OPC_CMP_ULE_S:
26478 case R6_OPC_CMP_SAF_S:
26479 case R6_OPC_CMP_SUN_S:
26480 case R6_OPC_CMP_SEQ_S:
26481 case R6_OPC_CMP_SEUQ_S:
26482 case R6_OPC_CMP_SLT_S:
26483 case R6_OPC_CMP_SULT_S:
26484 case R6_OPC_CMP_SLE_S:
26485 case R6_OPC_CMP_SULE_S:
26486 case R6_OPC_CMP_OR_S:
26487 case R6_OPC_CMP_UNE_S:
26488 case R6_OPC_CMP_NE_S:
26489 case R6_OPC_CMP_SOR_S:
26490 case R6_OPC_CMP_SUNE_S:
26491 case R6_OPC_CMP_SNE_S:
26492 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26493 break;
26494 case R6_OPC_CMP_AF_D:
26495 case R6_OPC_CMP_UN_D:
26496 case R6_OPC_CMP_EQ_D:
26497 case R6_OPC_CMP_UEQ_D:
26498 case R6_OPC_CMP_LT_D:
26499 case R6_OPC_CMP_ULT_D:
26500 case R6_OPC_CMP_LE_D:
26501 case R6_OPC_CMP_ULE_D:
26502 case R6_OPC_CMP_SAF_D:
26503 case R6_OPC_CMP_SUN_D:
26504 case R6_OPC_CMP_SEQ_D:
26505 case R6_OPC_CMP_SEUQ_D:
26506 case R6_OPC_CMP_SLT_D:
26507 case R6_OPC_CMP_SULT_D:
26508 case R6_OPC_CMP_SLE_D:
26509 case R6_OPC_CMP_SULE_D:
26510 case R6_OPC_CMP_OR_D:
26511 case R6_OPC_CMP_UNE_D:
26512 case R6_OPC_CMP_NE_D:
26513 case R6_OPC_CMP_SOR_D:
26514 case R6_OPC_CMP_SUNE_D:
26515 case R6_OPC_CMP_SNE_D:
26516 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
26517 break;
26518 default:
26519 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
26520 rt, rd, sa, (imm >> 8) & 0x7);
26522 break;
26524 } else {
26525 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26526 (imm >> 8) & 0x7);
26528 break;
26530 case OPC_BZ_V:
26531 case OPC_BNZ_V:
26532 case OPC_BZ_B:
26533 case OPC_BZ_H:
26534 case OPC_BZ_W:
26535 case OPC_BZ_D:
26536 case OPC_BNZ_B:
26537 case OPC_BNZ_H:
26538 case OPC_BNZ_W:
26539 case OPC_BNZ_D:
26540 check_insn(ctx, ASE_MSA);
26541 gen_msa_branch(env, ctx, op1);
26542 break;
26543 default:
26544 MIPS_INVAL("cp1");
26545 generate_exception_end(ctx, EXCP_RI);
26546 break;
26548 break;
26550 /* Compact branches [R6] and COP2 [non-R6] */
26551 case OPC_BC: /* OPC_LWC2 */
26552 case OPC_BALC: /* OPC_SWC2 */
26553 if (ctx->insn_flags & ISA_MIPS32R6) {
26554 /* OPC_BC, OPC_BALC */
26555 gen_compute_compact_branch(ctx, op, 0, 0,
26556 sextract32(ctx->opcode << 2, 0, 28));
26557 } else {
26558 /* OPC_LWC2, OPC_SWC2 */
26559 /* COP2: Not implemented. */
26560 generate_exception_err(ctx, EXCP_CpU, 2);
26562 break;
26563 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
26564 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
26565 if (ctx->insn_flags & ISA_MIPS32R6) {
26566 if (rs != 0) {
26567 /* OPC_BEQZC, OPC_BNEZC */
26568 gen_compute_compact_branch(ctx, op, rs, 0,
26569 sextract32(ctx->opcode << 2, 0, 23));
26570 } else {
26571 /* OPC_JIC, OPC_JIALC */
26572 gen_compute_compact_branch(ctx, op, 0, rt, imm);
26574 } else {
26575 /* OPC_LWC2, OPC_SWC2 */
26576 /* COP2: Not implemented. */
26577 generate_exception_err(ctx, EXCP_CpU, 2);
26579 break;
26580 case OPC_CP2:
26581 check_insn(ctx, INSN_LOONGSON2F);
26582 /* Note that these instructions use different fields. */
26583 gen_loongson_multimedia(ctx, sa, rd, rt);
26584 break;
26586 case OPC_CP3:
26587 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26588 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26589 check_cp1_enabled(ctx);
26590 op1 = MASK_CP3(ctx->opcode);
26591 switch (op1) {
26592 case OPC_LUXC1:
26593 case OPC_SUXC1:
26594 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26595 /* Fallthrough */
26596 case OPC_LWXC1:
26597 case OPC_LDXC1:
26598 case OPC_SWXC1:
26599 case OPC_SDXC1:
26600 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26601 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
26602 break;
26603 case OPC_PREFX:
26604 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26605 /* Treat as NOP. */
26606 break;
26607 case OPC_ALNV_PS:
26608 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26609 /* Fallthrough */
26610 case OPC_MADD_S:
26611 case OPC_MADD_D:
26612 case OPC_MADD_PS:
26613 case OPC_MSUB_S:
26614 case OPC_MSUB_D:
26615 case OPC_MSUB_PS:
26616 case OPC_NMADD_S:
26617 case OPC_NMADD_D:
26618 case OPC_NMADD_PS:
26619 case OPC_NMSUB_S:
26620 case OPC_NMSUB_D:
26621 case OPC_NMSUB_PS:
26622 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26623 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
26624 break;
26625 default:
26626 MIPS_INVAL("cp3");
26627 generate_exception_end(ctx, EXCP_RI);
26628 break;
26630 } else {
26631 generate_exception_err(ctx, EXCP_CpU, 1);
26633 break;
26635 #if defined(TARGET_MIPS64)
26636 /* MIPS64 opcodes */
26637 case OPC_LDL:
26638 case OPC_LDR:
26639 case OPC_LLD:
26640 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26641 /* fall through */
26642 case OPC_LWU:
26643 case OPC_LD:
26644 check_insn(ctx, ISA_MIPS3);
26645 check_mips_64(ctx);
26646 gen_ld(ctx, op, rt, rs, imm);
26647 break;
26648 case OPC_SDL:
26649 case OPC_SDR:
26650 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26651 /* fall through */
26652 case OPC_SD:
26653 check_insn(ctx, ISA_MIPS3);
26654 check_mips_64(ctx);
26655 gen_st(ctx, op, rt, rs, imm);
26656 break;
26657 case OPC_SCD:
26658 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26659 check_insn(ctx, ISA_MIPS3);
26660 check_mips_64(ctx);
26661 gen_st_cond(ctx, op, rt, rs, imm);
26662 break;
26663 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
26664 if (ctx->insn_flags & ISA_MIPS32R6) {
26665 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
26666 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26667 } else {
26668 /* OPC_DADDI */
26669 check_insn(ctx, ISA_MIPS3);
26670 check_mips_64(ctx);
26671 gen_arith_imm(ctx, op, rt, rs, imm);
26673 break;
26674 case OPC_DADDIU:
26675 check_insn(ctx, ISA_MIPS3);
26676 check_mips_64(ctx);
26677 gen_arith_imm(ctx, op, rt, rs, imm);
26678 break;
26679 #else
26680 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
26681 if (ctx->insn_flags & ISA_MIPS32R6) {
26682 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26683 } else {
26684 MIPS_INVAL("major opcode");
26685 generate_exception_end(ctx, EXCP_RI);
26687 break;
26688 #endif
26689 case OPC_DAUI: /* OPC_JALX */
26690 if (ctx->insn_flags & ISA_MIPS32R6) {
26691 #if defined(TARGET_MIPS64)
26692 /* OPC_DAUI */
26693 check_mips_64(ctx);
26694 if (rs == 0) {
26695 generate_exception(ctx, EXCP_RI);
26696 } else if (rt != 0) {
26697 TCGv t0 = tcg_temp_new();
26698 gen_load_gpr(t0, rs);
26699 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
26700 tcg_temp_free(t0);
26702 #else
26703 generate_exception_end(ctx, EXCP_RI);
26704 MIPS_INVAL("major opcode");
26705 #endif
26706 } else {
26707 /* OPC_JALX */
26708 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26709 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26710 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26712 break;
26713 case OPC_MSA: /* OPC_MDMX */
26714 if (ctx->insn_flags & INSN_R5900) {
26715 decode_tx79_lq(env, ctx); /* TX79_LQ */
26716 } else {
26717 /* MDMX: Not implemented. */
26718 gen_msa(env, ctx);
26720 break;
26721 case OPC_PCREL:
26722 check_insn(ctx, ISA_MIPS32R6);
26723 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
26724 break;
26725 default: /* Invalid */
26726 MIPS_INVAL("major opcode");
26727 generate_exception_end(ctx, EXCP_RI);
26728 break;
26732 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
26734 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26735 CPUMIPSState *env = cs->env_ptr;
26737 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
26738 ctx->saved_pc = -1;
26739 ctx->insn_flags = env->insn_flags;
26740 ctx->CP0_Config1 = env->CP0_Config1;
26741 ctx->CP0_Config2 = env->CP0_Config2;
26742 ctx->CP0_Config3 = env->CP0_Config3;
26743 ctx->CP0_Config5 = env->CP0_Config5;
26744 ctx->btarget = 0;
26745 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26746 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26747 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26748 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26749 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26750 ctx->PAMask = env->PAMask;
26751 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26752 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26753 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26754 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26755 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
26756 /* Restore delay slot state from the tb context. */
26757 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26758 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26759 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
26760 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
26761 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26762 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26763 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26764 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26765 restore_cpu_state(env, ctx);
26766 #ifdef CONFIG_USER_ONLY
26767 ctx->mem_idx = MIPS_HFLAG_UM;
26768 #else
26769 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
26770 #endif
26771 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
26772 MO_UNALN : MO_ALIGN;
26774 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26775 ctx->hflags);
26778 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26782 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26784 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26786 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26787 ctx->btarget);
26790 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26791 const CPUBreakpoint *bp)
26793 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26795 save_cpu_state(ctx, 1);
26796 ctx->base.is_jmp = DISAS_NORETURN;
26797 gen_helper_raise_exception_debug(cpu_env);
26798 /* The address covered by the breakpoint must be included in
26799 [tb->pc, tb->pc + tb->size) in order to for it to be
26800 properly cleared -- thus we increment the PC here so that
26801 the logic setting tb->size below does the right thing. */
26802 ctx->base.pc_next += 4;
26803 return true;
26806 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26808 CPUMIPSState *env = cs->env_ptr;
26809 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26810 int insn_bytes;
26811 int is_slot;
26813 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26814 if (ctx->insn_flags & ISA_NANOMIPS32) {
26815 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26816 insn_bytes = decode_nanomips_opc(env, ctx);
26817 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26818 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
26819 insn_bytes = 4;
26820 decode_opc(env, ctx);
26821 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26822 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26823 insn_bytes = decode_micromips_opc(env, ctx);
26824 } else if (ctx->insn_flags & ASE_MIPS16) {
26825 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26826 insn_bytes = decode_mips16_opc(env, ctx);
26827 } else {
26828 generate_exception_end(ctx, EXCP_RI);
26829 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26830 return;
26833 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26834 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26835 MIPS_HFLAG_FBNSLOT))) {
26836 /* force to generate branch as there is neither delay nor
26837 forbidden slot */
26838 is_slot = 1;
26840 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26841 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26842 /* Force to generate branch as microMIPS R6 doesn't restrict
26843 branches in the forbidden slot. */
26844 is_slot = 1;
26847 if (is_slot) {
26848 gen_branch(ctx, insn_bytes);
26850 ctx->base.pc_next += insn_bytes;
26852 if (ctx->base.is_jmp != DISAS_NEXT) {
26853 return;
26855 /* Execute a branch and its delay slot as a single instruction.
26856 This is what GDB expects and is consistent with what the
26857 hardware does (e.g. if a delay slot instruction faults, the
26858 reported PC is the PC of the branch). */
26859 if (ctx->base.singlestep_enabled &&
26860 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26861 ctx->base.is_jmp = DISAS_TOO_MANY;
26863 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26864 ctx->base.is_jmp = DISAS_TOO_MANY;
26868 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26870 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26872 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26873 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26874 gen_helper_raise_exception_debug(cpu_env);
26875 } else {
26876 switch (ctx->base.is_jmp) {
26877 case DISAS_STOP:
26878 gen_save_pc(ctx->base.pc_next);
26879 tcg_gen_lookup_and_goto_ptr();
26880 break;
26881 case DISAS_NEXT:
26882 case DISAS_TOO_MANY:
26883 save_cpu_state(ctx, 0);
26884 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26885 break;
26886 case DISAS_EXIT:
26887 tcg_gen_exit_tb(NULL, 0);
26888 break;
26889 case DISAS_NORETURN:
26890 break;
26891 default:
26892 g_assert_not_reached();
26897 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26899 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26900 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26903 static const TranslatorOps mips_tr_ops = {
26904 .init_disas_context = mips_tr_init_disas_context,
26905 .tb_start = mips_tr_tb_start,
26906 .insn_start = mips_tr_insn_start,
26907 .breakpoint_check = mips_tr_breakpoint_check,
26908 .translate_insn = mips_tr_translate_insn,
26909 .tb_stop = mips_tr_tb_stop,
26910 .disas_log = mips_tr_disas_log,
26913 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
26915 DisasContext ctx;
26917 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
26920 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
26921 int flags)
26923 int i;
26924 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26926 #define printfpr(fp) \
26927 do { \
26928 if (is_fpu64) \
26929 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26930 " fd:%13g fs:%13g psu: %13g\n", \
26931 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26932 (double)(fp)->fd, \
26933 (double)(fp)->fs[FP_ENDIAN_IDX], \
26934 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26935 else { \
26936 fpr_t tmp; \
26937 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
26938 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
26939 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26940 " fd:%13g fs:%13g psu:%13g\n", \
26941 tmp.w[FP_ENDIAN_IDX], tmp.d, \
26942 (double)tmp.fd, \
26943 (double)tmp.fs[FP_ENDIAN_IDX], \
26944 (double)tmp.fs[!FP_ENDIAN_IDX]); \
26946 } while(0)
26949 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
26950 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
26951 get_float_exception_flags(&env->active_fpu.fp_status));
26952 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
26953 fpu_fprintf(f, "%3s: ", fregnames[i]);
26954 printfpr(&env->active_fpu.fpr[i]);
26957 #undef printfpr
26960 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
26961 int flags)
26963 MIPSCPU *cpu = MIPS_CPU(cs);
26964 CPUMIPSState *env = &cpu->env;
26965 int i;
26967 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
26968 " LO=0x" TARGET_FMT_lx " ds %04x "
26969 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
26970 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
26971 env->hflags, env->btarget, env->bcond);
26972 for (i = 0; i < 32; i++) {
26973 if ((i & 3) == 0)
26974 cpu_fprintf(f, "GPR%02d:", i);
26975 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
26976 if ((i & 3) == 3)
26977 cpu_fprintf(f, "\n");
26980 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
26981 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
26982 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
26983 PRIx64 "\n",
26984 env->CP0_Config0, env->CP0_Config1, env->lladdr);
26985 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
26986 env->CP0_Config2, env->CP0_Config3);
26987 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
26988 env->CP0_Config4, env->CP0_Config5);
26989 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
26990 fpu_dump_state(env, f, cpu_fprintf, flags);
26994 void mips_tcg_init(void)
26996 int i;
26998 cpu_gpr[0] = NULL;
26999 for (i = 1; i < 32; i++)
27000 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
27001 offsetof(CPUMIPSState, active_tc.gpr[i]),
27002 regnames[i]);
27004 for (i = 0; i < 32; i++) {
27005 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
27006 msa_wr_d[i * 2] =
27007 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
27008 /* The scalar floating-point unit (FPU) registers are mapped on
27009 * the MSA vector registers. */
27010 fpu_f64[i] = msa_wr_d[i * 2];
27011 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
27012 msa_wr_d[i * 2 + 1] =
27013 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
27016 cpu_PC = tcg_global_mem_new(cpu_env,
27017 offsetof(CPUMIPSState, active_tc.PC), "PC");
27018 for (i = 0; i < MIPS_DSP_ACC; i++) {
27019 cpu_HI[i] = tcg_global_mem_new(cpu_env,
27020 offsetof(CPUMIPSState, active_tc.HI[i]),
27021 regnames_HI[i]);
27022 cpu_LO[i] = tcg_global_mem_new(cpu_env,
27023 offsetof(CPUMIPSState, active_tc.LO[i]),
27024 regnames_LO[i]);
27026 cpu_dspctrl = tcg_global_mem_new(cpu_env,
27027 offsetof(CPUMIPSState, active_tc.DSPControl),
27028 "DSPControl");
27029 bcond = tcg_global_mem_new(cpu_env,
27030 offsetof(CPUMIPSState, bcond), "bcond");
27031 btarget = tcg_global_mem_new(cpu_env,
27032 offsetof(CPUMIPSState, btarget), "btarget");
27033 hflags = tcg_global_mem_new_i32(cpu_env,
27034 offsetof(CPUMIPSState, hflags), "hflags");
27036 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
27037 offsetof(CPUMIPSState, active_fpu.fcr0),
27038 "fcr0");
27039 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
27040 offsetof(CPUMIPSState, active_fpu.fcr31),
27041 "fcr31");
27044 #include "translate_init.inc.c"
27046 void cpu_mips_realize_env(CPUMIPSState *env)
27048 env->exception_base = (int32_t)0xBFC00000;
27050 #ifndef CONFIG_USER_ONLY
27051 mmu_init(env, env->cpu_model);
27052 #endif
27053 fpu_init(env, env->cpu_model);
27054 mvp_init(env, env->cpu_model);
27057 bool cpu_supports_cps_smp(const char *cpu_type)
27059 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27060 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
27063 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
27065 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
27066 return (mcc->cpu_def->insn_flags & isa) != 0;
27069 void cpu_set_exception_base(int vp_index, target_ulong address)
27071 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
27072 vp->env.exception_base = address;
27075 void cpu_state_reset(CPUMIPSState *env)
27077 MIPSCPU *cpu = mips_env_get_cpu(env);
27078 CPUState *cs = CPU(cpu);
27080 /* Reset registers to their default values */
27081 env->CP0_PRid = env->cpu_model->CP0_PRid;
27082 env->CP0_Config0 = env->cpu_model->CP0_Config0;
27083 #ifdef TARGET_WORDS_BIGENDIAN
27084 env->CP0_Config0 |= (1 << CP0C0_BE);
27085 #endif
27086 env->CP0_Config1 = env->cpu_model->CP0_Config1;
27087 env->CP0_Config2 = env->cpu_model->CP0_Config2;
27088 env->CP0_Config3 = env->cpu_model->CP0_Config3;
27089 env->CP0_Config4 = env->cpu_model->CP0_Config4;
27090 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
27091 env->CP0_Config5 = env->cpu_model->CP0_Config5;
27092 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
27093 env->CP0_Config6 = env->cpu_model->CP0_Config6;
27094 env->CP0_Config7 = env->cpu_model->CP0_Config7;
27095 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
27096 << env->cpu_model->CP0_LLAddr_shift;
27097 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
27098 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
27099 env->CCRes = env->cpu_model->CCRes;
27100 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
27101 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
27102 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
27103 env->current_tc = 0;
27104 env->SEGBITS = env->cpu_model->SEGBITS;
27105 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
27106 #if defined(TARGET_MIPS64)
27107 if (env->cpu_model->insn_flags & ISA_MIPS3) {
27108 env->SEGMask |= 3ULL << 62;
27110 #endif
27111 env->PABITS = env->cpu_model->PABITS;
27112 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
27113 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
27114 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
27115 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
27116 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
27117 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
27118 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
27119 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
27120 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
27121 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
27122 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
27123 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
27124 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
27125 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
27126 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
27127 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
27128 env->msair = env->cpu_model->MSAIR;
27129 env->insn_flags = env->cpu_model->insn_flags;
27131 #if defined(CONFIG_USER_ONLY)
27132 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
27133 # ifdef TARGET_MIPS64
27134 /* Enable 64-bit register mode. */
27135 env->CP0_Status |= (1 << CP0St_PX);
27136 # endif
27137 # ifdef TARGET_ABI_MIPSN64
27138 /* Enable 64-bit address mode. */
27139 env->CP0_Status |= (1 << CP0St_UX);
27140 # endif
27141 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
27142 hardware registers. */
27143 env->CP0_HWREna |= 0x0000000F;
27144 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
27145 env->CP0_Status |= (1 << CP0St_CU1);
27147 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
27148 env->CP0_Status |= (1 << CP0St_MX);
27150 # if defined(TARGET_MIPS64)
27151 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
27152 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
27153 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
27154 env->CP0_Status |= (1 << CP0St_FR);
27156 # endif
27157 #else
27158 if (env->hflags & MIPS_HFLAG_BMASK) {
27159 /* If the exception was raised from a delay slot,
27160 come back to the jump. */
27161 env->CP0_ErrorEPC = (env->active_tc.PC
27162 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
27163 } else {
27164 env->CP0_ErrorEPC = env->active_tc.PC;
27166 env->active_tc.PC = env->exception_base;
27167 env->CP0_Random = env->tlb->nb_tlb - 1;
27168 env->tlb->tlb_in_use = env->tlb->nb_tlb;
27169 env->CP0_Wired = 0;
27170 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
27171 env->CP0_EBase = (cs->cpu_index & 0x3FF);
27172 if (mips_um_ksegs_enabled()) {
27173 env->CP0_EBase |= 0x40000000;
27174 } else {
27175 env->CP0_EBase |= (int32_t)0x80000000;
27177 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
27178 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
27180 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
27181 0x3ff : 0xff;
27182 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
27183 /* vectored interrupts not implemented, timer on int 7,
27184 no performance counters. */
27185 env->CP0_IntCtl = 0xe0000000;
27187 int i;
27189 for (i = 0; i < 7; i++) {
27190 env->CP0_WatchLo[i] = 0;
27191 env->CP0_WatchHi[i] = 0x80000000;
27193 env->CP0_WatchLo[7] = 0;
27194 env->CP0_WatchHi[7] = 0;
27196 /* Count register increments in debug mode, EJTAG version 1 */
27197 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
27199 cpu_mips_store_count(env, 1);
27201 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
27202 int i;
27204 /* Only TC0 on VPE 0 starts as active. */
27205 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
27206 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
27207 env->tcs[i].CP0_TCHalt = 1;
27209 env->active_tc.CP0_TCHalt = 1;
27210 cs->halted = 1;
27212 if (cs->cpu_index == 0) {
27213 /* VPE0 starts up enabled. */
27214 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
27215 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
27217 /* TC0 starts up unhalted. */
27218 cs->halted = 0;
27219 env->active_tc.CP0_TCHalt = 0;
27220 env->tcs[0].CP0_TCHalt = 0;
27221 /* With thread 0 active. */
27222 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
27223 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
27228 * Configure default legacy segmentation control. We use this regardless of
27229 * whether segmentation control is presented to the guest.
27231 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
27232 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
27233 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
27234 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
27235 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
27236 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27237 (2 << CP0SC_C);
27238 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
27239 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
27240 (3 << CP0SC_C)) << 16;
27241 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
27242 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27243 (1 << CP0SC_EU) | (2 << CP0SC_C);
27244 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
27245 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
27246 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
27247 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
27248 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
27249 #endif
27250 if ((env->insn_flags & ISA_MIPS32R6) &&
27251 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
27252 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
27253 env->CP0_Status |= (1 << CP0St_FR);
27256 if (env->insn_flags & ISA_MIPS32R6) {
27257 /* PTW = 1 */
27258 env->CP0_PWSize = 0x40;
27259 /* GDI = 12 */
27260 /* UDI = 12 */
27261 /* MDI = 12 */
27262 /* PRI = 12 */
27263 /* PTEI = 2 */
27264 env->CP0_PWField = 0x0C30C302;
27265 } else {
27266 /* GDI = 0 */
27267 /* UDI = 0 */
27268 /* MDI = 0 */
27269 /* PRI = 0 */
27270 /* PTEI = 2 */
27271 env->CP0_PWField = 0x02;
27274 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
27275 /* microMIPS on reset when Config3.ISA is 3 */
27276 env->hflags |= MIPS_HFLAG_M16;
27279 /* MSA */
27280 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
27281 msa_reset(env);
27284 compute_hflags(env);
27285 restore_fp_status(env);
27286 restore_pamask(env);
27287 cs->exception_index = EXCP_NONE;
27289 if (semihosting_get_argc()) {
27290 /* UHI interface can be used to obtain argc and argv */
27291 env->active_tc.gpr[4] = -1;
27295 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
27296 target_ulong *data)
27298 env->active_tc.PC = data[0];
27299 env->hflags &= ~MIPS_HFLAG_BMASK;
27300 env->hflags |= data[1];
27301 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
27302 case MIPS_HFLAG_BR:
27303 break;
27304 case MIPS_HFLAG_BC:
27305 case MIPS_HFLAG_BL:
27306 case MIPS_HFLAG_B:
27307 env->btarget = data[2];
27308 break;