target/mips: Define R5900 MMI<0|1|2|3> subclasses and opcode constants
[qemu/ar7.git] / target / mips / translate.c
blobae988177a1deda70f89af3c1f54c82a1adb1a7cb
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,
2183 /* global register indices */
2184 static TCGv cpu_gpr[32], cpu_PC;
2185 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2186 static TCGv cpu_dspctrl, btarget, bcond;
2187 static TCGv_i32 hflags;
2188 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2189 static TCGv_i64 fpu_f64[32];
2190 static TCGv_i64 msa_wr_d[64];
2192 #include "exec/gen-icount.h"
2194 #define gen_helper_0e0i(name, arg) do { \
2195 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2196 gen_helper_##name(cpu_env, helper_tmp); \
2197 tcg_temp_free_i32(helper_tmp); \
2198 } while(0)
2200 #define gen_helper_0e1i(name, arg1, arg2) do { \
2201 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2202 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2203 tcg_temp_free_i32(helper_tmp); \
2204 } while(0)
2206 #define gen_helper_1e0i(name, ret, arg1) do { \
2207 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2208 gen_helper_##name(ret, cpu_env, helper_tmp); \
2209 tcg_temp_free_i32(helper_tmp); \
2210 } while(0)
2212 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2213 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2214 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2215 tcg_temp_free_i32(helper_tmp); \
2216 } while(0)
2218 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2219 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2220 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2221 tcg_temp_free_i32(helper_tmp); \
2222 } while(0)
2224 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2225 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2226 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2227 tcg_temp_free_i32(helper_tmp); \
2228 } while(0)
2230 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2231 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2232 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2233 tcg_temp_free_i32(helper_tmp); \
2234 } while(0)
2236 typedef struct DisasContext {
2237 DisasContextBase base;
2238 target_ulong saved_pc;
2239 target_ulong page_start;
2240 uint32_t opcode;
2241 uint64_t insn_flags;
2242 int32_t CP0_Config1;
2243 int32_t CP0_Config2;
2244 int32_t CP0_Config3;
2245 int32_t CP0_Config5;
2246 /* Routine used to access memory */
2247 int mem_idx;
2248 TCGMemOp default_tcg_memop_mask;
2249 uint32_t hflags, saved_hflags;
2250 target_ulong btarget;
2251 bool ulri;
2252 int kscrexist;
2253 bool rxi;
2254 int ie;
2255 bool bi;
2256 bool bp;
2257 uint64_t PAMask;
2258 bool mvh;
2259 bool eva;
2260 bool sc;
2261 int CP0_LLAddr_shift;
2262 bool ps;
2263 bool vp;
2264 bool cmgcr;
2265 bool mrp;
2266 bool nan2008;
2267 bool abs2008;
2268 } DisasContext;
2270 #define DISAS_STOP DISAS_TARGET_0
2271 #define DISAS_EXIT DISAS_TARGET_1
2273 static const char * const regnames[] = {
2274 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2275 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2276 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2277 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2280 static const char * const regnames_HI[] = {
2281 "HI0", "HI1", "HI2", "HI3",
2284 static const char * const regnames_LO[] = {
2285 "LO0", "LO1", "LO2", "LO3",
2288 static const char * const fregnames[] = {
2289 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2290 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2291 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2292 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2295 static const char * const msaregnames[] = {
2296 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2297 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2298 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2299 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2300 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2301 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2302 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2303 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2304 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2305 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2306 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2307 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2308 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2309 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2310 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2311 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2314 #define LOG_DISAS(...) \
2315 do { \
2316 if (MIPS_DEBUG_DISAS) { \
2317 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2319 } while (0)
2321 #define MIPS_INVAL(op) \
2322 do { \
2323 if (MIPS_DEBUG_DISAS) { \
2324 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2325 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2326 ctx->base.pc_next, ctx->opcode, op, \
2327 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2328 ((ctx->opcode >> 16) & 0x1F)); \
2330 } while (0)
2332 /* General purpose registers moves. */
2333 static inline void gen_load_gpr (TCGv t, int reg)
2335 if (reg == 0)
2336 tcg_gen_movi_tl(t, 0);
2337 else
2338 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2341 static inline void gen_store_gpr (TCGv t, int reg)
2343 if (reg != 0)
2344 tcg_gen_mov_tl(cpu_gpr[reg], t);
2347 /* Moves to/from shadow registers. */
2348 static inline void gen_load_srsgpr (int from, int to)
2350 TCGv t0 = tcg_temp_new();
2352 if (from == 0)
2353 tcg_gen_movi_tl(t0, 0);
2354 else {
2355 TCGv_i32 t2 = tcg_temp_new_i32();
2356 TCGv_ptr addr = tcg_temp_new_ptr();
2358 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2359 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2360 tcg_gen_andi_i32(t2, t2, 0xf);
2361 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2362 tcg_gen_ext_i32_ptr(addr, t2);
2363 tcg_gen_add_ptr(addr, cpu_env, addr);
2365 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2366 tcg_temp_free_ptr(addr);
2367 tcg_temp_free_i32(t2);
2369 gen_store_gpr(t0, to);
2370 tcg_temp_free(t0);
2373 static inline void gen_store_srsgpr (int from, int to)
2375 if (to != 0) {
2376 TCGv t0 = tcg_temp_new();
2377 TCGv_i32 t2 = tcg_temp_new_i32();
2378 TCGv_ptr addr = tcg_temp_new_ptr();
2380 gen_load_gpr(t0, from);
2381 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2382 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2383 tcg_gen_andi_i32(t2, t2, 0xf);
2384 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2385 tcg_gen_ext_i32_ptr(addr, t2);
2386 tcg_gen_add_ptr(addr, cpu_env, addr);
2388 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2389 tcg_temp_free_ptr(addr);
2390 tcg_temp_free_i32(t2);
2391 tcg_temp_free(t0);
2395 /* Tests */
2396 static inline void gen_save_pc(target_ulong pc)
2398 tcg_gen_movi_tl(cpu_PC, pc);
2401 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2403 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2404 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2405 gen_save_pc(ctx->base.pc_next);
2406 ctx->saved_pc = ctx->base.pc_next;
2408 if (ctx->hflags != ctx->saved_hflags) {
2409 tcg_gen_movi_i32(hflags, ctx->hflags);
2410 ctx->saved_hflags = ctx->hflags;
2411 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2412 case MIPS_HFLAG_BR:
2413 break;
2414 case MIPS_HFLAG_BC:
2415 case MIPS_HFLAG_BL:
2416 case MIPS_HFLAG_B:
2417 tcg_gen_movi_tl(btarget, ctx->btarget);
2418 break;
2423 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2425 ctx->saved_hflags = ctx->hflags;
2426 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2427 case MIPS_HFLAG_BR:
2428 break;
2429 case MIPS_HFLAG_BC:
2430 case MIPS_HFLAG_BL:
2431 case MIPS_HFLAG_B:
2432 ctx->btarget = env->btarget;
2433 break;
2437 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2439 TCGv_i32 texcp = tcg_const_i32(excp);
2440 TCGv_i32 terr = tcg_const_i32(err);
2441 save_cpu_state(ctx, 1);
2442 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2443 tcg_temp_free_i32(terr);
2444 tcg_temp_free_i32(texcp);
2445 ctx->base.is_jmp = DISAS_NORETURN;
2448 static inline void generate_exception(DisasContext *ctx, int excp)
2450 gen_helper_0e0i(raise_exception, excp);
2453 static inline void generate_exception_end(DisasContext *ctx, int excp)
2455 generate_exception_err(ctx, excp, 0);
2458 /* Floating point register moves. */
2459 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2461 if (ctx->hflags & MIPS_HFLAG_FRE) {
2462 generate_exception(ctx, EXCP_RI);
2464 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2467 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2469 TCGv_i64 t64;
2470 if (ctx->hflags & MIPS_HFLAG_FRE) {
2471 generate_exception(ctx, EXCP_RI);
2473 t64 = tcg_temp_new_i64();
2474 tcg_gen_extu_i32_i64(t64, t);
2475 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2476 tcg_temp_free_i64(t64);
2479 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2481 if (ctx->hflags & MIPS_HFLAG_F64) {
2482 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2483 } else {
2484 gen_load_fpr32(ctx, t, reg | 1);
2488 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2490 if (ctx->hflags & MIPS_HFLAG_F64) {
2491 TCGv_i64 t64 = tcg_temp_new_i64();
2492 tcg_gen_extu_i32_i64(t64, t);
2493 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2494 tcg_temp_free_i64(t64);
2495 } else {
2496 gen_store_fpr32(ctx, t, reg | 1);
2500 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2502 if (ctx->hflags & MIPS_HFLAG_F64) {
2503 tcg_gen_mov_i64(t, fpu_f64[reg]);
2504 } else {
2505 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2509 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2511 if (ctx->hflags & MIPS_HFLAG_F64) {
2512 tcg_gen_mov_i64(fpu_f64[reg], t);
2513 } else {
2514 TCGv_i64 t0;
2515 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2516 t0 = tcg_temp_new_i64();
2517 tcg_gen_shri_i64(t0, t, 32);
2518 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2519 tcg_temp_free_i64(t0);
2523 static inline int get_fp_bit (int cc)
2525 if (cc)
2526 return 24 + cc;
2527 else
2528 return 23;
2531 /* Addresses computation */
2532 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2534 tcg_gen_add_tl(ret, arg0, arg1);
2536 #if defined(TARGET_MIPS64)
2537 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2538 tcg_gen_ext32s_i64(ret, ret);
2540 #endif
2543 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2544 target_long ofs)
2546 tcg_gen_addi_tl(ret, base, ofs);
2548 #if defined(TARGET_MIPS64)
2549 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2550 tcg_gen_ext32s_i64(ret, ret);
2552 #endif
2555 /* Addresses computation (translation time) */
2556 static target_long addr_add(DisasContext *ctx, target_long base,
2557 target_long offset)
2559 target_long sum = base + offset;
2561 #if defined(TARGET_MIPS64)
2562 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2563 sum = (int32_t)sum;
2565 #endif
2566 return sum;
2569 /* Sign-extract the low 32-bits to a target_long. */
2570 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2572 #if defined(TARGET_MIPS64)
2573 tcg_gen_ext32s_i64(ret, arg);
2574 #else
2575 tcg_gen_extrl_i64_i32(ret, arg);
2576 #endif
2579 /* Sign-extract the high 32-bits to a target_long. */
2580 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2582 #if defined(TARGET_MIPS64)
2583 tcg_gen_sari_i64(ret, arg, 32);
2584 #else
2585 tcg_gen_extrh_i64_i32(ret, arg);
2586 #endif
2589 static inline void check_cp0_enabled(DisasContext *ctx)
2591 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
2592 generate_exception_err(ctx, EXCP_CpU, 0);
2595 static inline void check_cp1_enabled(DisasContext *ctx)
2597 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
2598 generate_exception_err(ctx, EXCP_CpU, 1);
2601 /* Verify that the processor is running with COP1X instructions enabled.
2602 This is associated with the nabla symbol in the MIPS32 and MIPS64
2603 opcode tables. */
2605 static inline void check_cop1x(DisasContext *ctx)
2607 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
2608 generate_exception_end(ctx, EXCP_RI);
2611 /* Verify that the processor is running with 64-bit floating-point
2612 operations enabled. */
2614 static inline void check_cp1_64bitmode(DisasContext *ctx)
2616 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
2617 generate_exception_end(ctx, EXCP_RI);
2621 * Verify if floating point register is valid; an operation is not defined
2622 * if bit 0 of any register specification is set and the FR bit in the
2623 * Status register equals zero, since the register numbers specify an
2624 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2625 * in the Status register equals one, both even and odd register numbers
2626 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2628 * Multiple 64 bit wide registers can be checked by calling
2629 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2631 static inline void check_cp1_registers(DisasContext *ctx, int regs)
2633 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
2634 generate_exception_end(ctx, EXCP_RI);
2637 /* Verify that the processor is running with DSP instructions enabled.
2638 This is enabled by CP0 Status register MX(24) bit.
2641 static inline void check_dsp(DisasContext *ctx)
2643 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2644 if (ctx->insn_flags & ASE_DSP) {
2645 generate_exception_end(ctx, EXCP_DSPDIS);
2646 } else {
2647 generate_exception_end(ctx, EXCP_RI);
2652 static inline void check_dsp_r2(DisasContext *ctx)
2654 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2655 if (ctx->insn_flags & ASE_DSP) {
2656 generate_exception_end(ctx, EXCP_DSPDIS);
2657 } else {
2658 generate_exception_end(ctx, EXCP_RI);
2663 static inline void check_dsp_r3(DisasContext *ctx)
2665 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2666 if (ctx->insn_flags & ASE_DSP) {
2667 generate_exception_end(ctx, EXCP_DSPDIS);
2668 } else {
2669 generate_exception_end(ctx, EXCP_RI);
2674 /* This code generates a "reserved instruction" exception if the
2675 CPU does not support the instruction set corresponding to flags. */
2676 static inline void check_insn(DisasContext *ctx, uint64_t flags)
2678 if (unlikely(!(ctx->insn_flags & flags))) {
2679 generate_exception_end(ctx, EXCP_RI);
2683 /* This code generates a "reserved instruction" exception if the
2684 CPU has corresponding flag set which indicates that the instruction
2685 has been removed. */
2686 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2688 if (unlikely(ctx->insn_flags & flags)) {
2689 generate_exception_end(ctx, EXCP_RI);
2693 /* This code generates a "reserved instruction" exception if the
2694 CPU does not support 64-bit paired-single (PS) floating point data type */
2695 static inline void check_ps(DisasContext *ctx)
2697 if (unlikely(!ctx->ps)) {
2698 generate_exception(ctx, EXCP_RI);
2700 check_cp1_64bitmode(ctx);
2703 #ifdef TARGET_MIPS64
2704 /* This code generates a "reserved instruction" exception if 64-bit
2705 instructions are not enabled. */
2706 static inline void check_mips_64(DisasContext *ctx)
2708 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
2709 generate_exception_end(ctx, EXCP_RI);
2711 #endif
2713 #ifndef CONFIG_USER_ONLY
2714 static inline void check_mvh(DisasContext *ctx)
2716 if (unlikely(!ctx->mvh)) {
2717 generate_exception(ctx, EXCP_RI);
2720 #endif
2723 * This code generates a "reserved instruction" exception if the
2724 * Config5 XNP bit is set.
2726 static inline void check_xnp(DisasContext *ctx)
2728 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
2729 generate_exception_end(ctx, EXCP_RI);
2733 #ifndef CONFIG_USER_ONLY
2735 * This code generates a "reserved instruction" exception if the
2736 * Config3 PW bit is NOT set.
2738 static inline void check_pw(DisasContext *ctx)
2740 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
2741 generate_exception_end(ctx, EXCP_RI);
2744 #endif
2747 * This code generates a "reserved instruction" exception if the
2748 * Config3 MT bit is NOT set.
2750 static inline void check_mt(DisasContext *ctx)
2752 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2753 generate_exception_end(ctx, EXCP_RI);
2757 #ifndef CONFIG_USER_ONLY
2759 * This code generates a "coprocessor unusable" exception if CP0 is not
2760 * available, and, if that is not the case, generates a "reserved instruction"
2761 * exception if the Config5 MT bit is NOT set. This is needed for availability
2762 * control of some of MT ASE instructions.
2764 static inline void check_cp0_mt(DisasContext *ctx)
2766 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2767 generate_exception_err(ctx, EXCP_CpU, 0);
2768 } else {
2769 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
2770 generate_exception_err(ctx, EXCP_RI, 0);
2774 #endif
2777 * This code generates a "reserved instruction" exception if the
2778 * Config5 NMS bit is set.
2780 static inline void check_nms(DisasContext *ctx)
2782 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
2783 generate_exception_end(ctx, EXCP_RI);
2788 /* Define small wrappers for gen_load_fpr* so that we have a uniform
2789 calling interface for 32 and 64-bit FPRs. No sense in changing
2790 all callers for gen_load_fpr32 when we need the CTX parameter for
2791 this one use. */
2792 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
2793 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
2794 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
2795 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
2796 int ft, int fs, int cc) \
2798 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
2799 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
2800 switch (ifmt) { \
2801 case FMT_PS: \
2802 check_ps(ctx); \
2803 break; \
2804 case FMT_D: \
2805 if (abs) { \
2806 check_cop1x(ctx); \
2808 check_cp1_registers(ctx, fs | ft); \
2809 break; \
2810 case FMT_S: \
2811 if (abs) { \
2812 check_cop1x(ctx); \
2814 break; \
2816 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
2817 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
2818 switch (n) { \
2819 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
2820 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
2821 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
2822 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
2823 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
2824 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
2825 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
2826 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
2827 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
2828 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
2829 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
2830 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
2831 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
2832 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
2833 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
2834 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
2835 default: abort(); \
2837 tcg_temp_free_i##bits (fp0); \
2838 tcg_temp_free_i##bits (fp1); \
2841 FOP_CONDS(, 0, d, FMT_D, 64)
2842 FOP_CONDS(abs, 1, d, FMT_D, 64)
2843 FOP_CONDS(, 0, s, FMT_S, 32)
2844 FOP_CONDS(abs, 1, s, FMT_S, 32)
2845 FOP_CONDS(, 0, ps, FMT_PS, 64)
2846 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
2847 #undef FOP_CONDS
2849 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
2850 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
2851 int ft, int fs, int fd) \
2853 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
2854 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
2855 if (ifmt == FMT_D) { \
2856 check_cp1_registers(ctx, fs | ft | fd); \
2858 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
2859 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
2860 switch (n) { \
2861 case 0: \
2862 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
2863 break; \
2864 case 1: \
2865 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
2866 break; \
2867 case 2: \
2868 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
2869 break; \
2870 case 3: \
2871 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
2872 break; \
2873 case 4: \
2874 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
2875 break; \
2876 case 5: \
2877 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
2878 break; \
2879 case 6: \
2880 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
2881 break; \
2882 case 7: \
2883 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
2884 break; \
2885 case 8: \
2886 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
2887 break; \
2888 case 9: \
2889 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
2890 break; \
2891 case 10: \
2892 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2893 break; \
2894 case 11: \
2895 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2896 break; \
2897 case 12: \
2898 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2899 break; \
2900 case 13: \
2901 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2902 break; \
2903 case 14: \
2904 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2905 break; \
2906 case 15: \
2907 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2908 break; \
2909 case 17: \
2910 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2911 break; \
2912 case 18: \
2913 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2914 break; \
2915 case 19: \
2916 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2917 break; \
2918 case 25: \
2919 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2920 break; \
2921 case 26: \
2922 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2923 break; \
2924 case 27: \
2925 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2926 break; \
2927 default: \
2928 abort(); \
2930 STORE; \
2931 tcg_temp_free_i ## bits (fp0); \
2932 tcg_temp_free_i ## bits (fp1); \
2935 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2936 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2937 #undef FOP_CONDNS
2938 #undef gen_ldcmp_fpr32
2939 #undef gen_ldcmp_fpr64
2941 /* load/store instructions. */
2942 #ifdef CONFIG_USER_ONLY
2943 #define OP_LD_ATOMIC(insn,fname) \
2944 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2945 DisasContext *ctx) \
2947 TCGv t0 = tcg_temp_new(); \
2948 tcg_gen_mov_tl(t0, arg1); \
2949 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2950 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2951 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2952 tcg_temp_free(t0); \
2954 #else
2955 #define OP_LD_ATOMIC(insn,fname) \
2956 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2957 DisasContext *ctx) \
2959 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2961 #endif
2962 OP_LD_ATOMIC(ll,ld32s);
2963 #if defined(TARGET_MIPS64)
2964 OP_LD_ATOMIC(lld,ld64);
2965 #endif
2966 #undef OP_LD_ATOMIC
2968 #ifdef CONFIG_USER_ONLY
2969 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2970 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2971 DisasContext *ctx) \
2973 TCGv t0 = tcg_temp_new(); \
2974 TCGLabel *l1 = gen_new_label(); \
2975 TCGLabel *l2 = gen_new_label(); \
2977 tcg_gen_andi_tl(t0, arg2, almask); \
2978 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2979 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2980 generate_exception(ctx, EXCP_AdES); \
2981 gen_set_label(l1); \
2982 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2983 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2984 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2985 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2986 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2987 generate_exception_end(ctx, EXCP_SC); \
2988 gen_set_label(l2); \
2989 tcg_gen_movi_tl(t0, 0); \
2990 gen_store_gpr(t0, rt); \
2991 tcg_temp_free(t0); \
2993 #else
2994 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2995 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2996 DisasContext *ctx) \
2998 TCGv t0 = tcg_temp_new(); \
2999 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
3000 gen_store_gpr(t0, rt); \
3001 tcg_temp_free(t0); \
3003 #endif
3004 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
3005 #if defined(TARGET_MIPS64)
3006 OP_ST_ATOMIC(scd,st64,ld64,0x7);
3007 #endif
3008 #undef OP_ST_ATOMIC
3010 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
3011 int base, int offset)
3013 if (base == 0) {
3014 tcg_gen_movi_tl(addr, offset);
3015 } else if (offset == 0) {
3016 gen_load_gpr(addr, base);
3017 } else {
3018 tcg_gen_movi_tl(addr, offset);
3019 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3023 static target_ulong pc_relative_pc (DisasContext *ctx)
3025 target_ulong pc = ctx->base.pc_next;
3027 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3028 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3030 pc -= branch_bytes;
3033 pc &= ~(target_ulong)3;
3034 return pc;
3037 /* Load */
3038 static void gen_ld(DisasContext *ctx, uint32_t opc,
3039 int rt, int base, int offset)
3041 TCGv t0, t1, t2;
3042 int mem_idx = ctx->mem_idx;
3044 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
3045 /* Loongson CPU uses a load to zero register for prefetch.
3046 We emulate it as a NOP. On other CPU we must perform the
3047 actual memory access. */
3048 return;
3051 t0 = tcg_temp_new();
3052 gen_base_offset_addr(ctx, t0, base, offset);
3054 switch (opc) {
3055 #if defined(TARGET_MIPS64)
3056 case OPC_LWU:
3057 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3058 ctx->default_tcg_memop_mask);
3059 gen_store_gpr(t0, rt);
3060 break;
3061 case OPC_LD:
3062 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3063 ctx->default_tcg_memop_mask);
3064 gen_store_gpr(t0, rt);
3065 break;
3066 case OPC_LLD:
3067 case R6_OPC_LLD:
3068 op_ld_lld(t0, t0, mem_idx, ctx);
3069 gen_store_gpr(t0, rt);
3070 break;
3071 case OPC_LDL:
3072 t1 = tcg_temp_new();
3073 /* Do a byte access to possibly trigger a page
3074 fault with the unaligned address. */
3075 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3076 tcg_gen_andi_tl(t1, t0, 7);
3077 #ifndef TARGET_WORDS_BIGENDIAN
3078 tcg_gen_xori_tl(t1, t1, 7);
3079 #endif
3080 tcg_gen_shli_tl(t1, t1, 3);
3081 tcg_gen_andi_tl(t0, t0, ~7);
3082 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3083 tcg_gen_shl_tl(t0, t0, t1);
3084 t2 = tcg_const_tl(-1);
3085 tcg_gen_shl_tl(t2, t2, t1);
3086 gen_load_gpr(t1, rt);
3087 tcg_gen_andc_tl(t1, t1, t2);
3088 tcg_temp_free(t2);
3089 tcg_gen_or_tl(t0, t0, t1);
3090 tcg_temp_free(t1);
3091 gen_store_gpr(t0, rt);
3092 break;
3093 case OPC_LDR:
3094 t1 = tcg_temp_new();
3095 /* Do a byte access to possibly trigger a page
3096 fault with the unaligned address. */
3097 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3098 tcg_gen_andi_tl(t1, t0, 7);
3099 #ifdef TARGET_WORDS_BIGENDIAN
3100 tcg_gen_xori_tl(t1, t1, 7);
3101 #endif
3102 tcg_gen_shli_tl(t1, t1, 3);
3103 tcg_gen_andi_tl(t0, t0, ~7);
3104 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3105 tcg_gen_shr_tl(t0, t0, t1);
3106 tcg_gen_xori_tl(t1, t1, 63);
3107 t2 = tcg_const_tl(0xfffffffffffffffeull);
3108 tcg_gen_shl_tl(t2, t2, t1);
3109 gen_load_gpr(t1, rt);
3110 tcg_gen_and_tl(t1, t1, t2);
3111 tcg_temp_free(t2);
3112 tcg_gen_or_tl(t0, t0, t1);
3113 tcg_temp_free(t1);
3114 gen_store_gpr(t0, rt);
3115 break;
3116 case OPC_LDPC:
3117 t1 = tcg_const_tl(pc_relative_pc(ctx));
3118 gen_op_addr_add(ctx, t0, t0, t1);
3119 tcg_temp_free(t1);
3120 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3121 gen_store_gpr(t0, rt);
3122 break;
3123 #endif
3124 case OPC_LWPC:
3125 t1 = tcg_const_tl(pc_relative_pc(ctx));
3126 gen_op_addr_add(ctx, t0, t0, t1);
3127 tcg_temp_free(t1);
3128 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3129 gen_store_gpr(t0, rt);
3130 break;
3131 case OPC_LWE:
3132 mem_idx = MIPS_HFLAG_UM;
3133 /* fall through */
3134 case OPC_LW:
3135 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3136 ctx->default_tcg_memop_mask);
3137 gen_store_gpr(t0, rt);
3138 break;
3139 case OPC_LHE:
3140 mem_idx = MIPS_HFLAG_UM;
3141 /* fall through */
3142 case OPC_LH:
3143 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3144 ctx->default_tcg_memop_mask);
3145 gen_store_gpr(t0, rt);
3146 break;
3147 case OPC_LHUE:
3148 mem_idx = MIPS_HFLAG_UM;
3149 /* fall through */
3150 case OPC_LHU:
3151 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3152 ctx->default_tcg_memop_mask);
3153 gen_store_gpr(t0, rt);
3154 break;
3155 case OPC_LBE:
3156 mem_idx = MIPS_HFLAG_UM;
3157 /* fall through */
3158 case OPC_LB:
3159 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3160 gen_store_gpr(t0, rt);
3161 break;
3162 case OPC_LBUE:
3163 mem_idx = MIPS_HFLAG_UM;
3164 /* fall through */
3165 case OPC_LBU:
3166 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3167 gen_store_gpr(t0, rt);
3168 break;
3169 case OPC_LWLE:
3170 mem_idx = MIPS_HFLAG_UM;
3171 /* fall through */
3172 case OPC_LWL:
3173 t1 = tcg_temp_new();
3174 /* Do a byte access to possibly trigger a page
3175 fault with the unaligned address. */
3176 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3177 tcg_gen_andi_tl(t1, t0, 3);
3178 #ifndef TARGET_WORDS_BIGENDIAN
3179 tcg_gen_xori_tl(t1, t1, 3);
3180 #endif
3181 tcg_gen_shli_tl(t1, t1, 3);
3182 tcg_gen_andi_tl(t0, t0, ~3);
3183 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3184 tcg_gen_shl_tl(t0, t0, t1);
3185 t2 = tcg_const_tl(-1);
3186 tcg_gen_shl_tl(t2, t2, t1);
3187 gen_load_gpr(t1, rt);
3188 tcg_gen_andc_tl(t1, t1, t2);
3189 tcg_temp_free(t2);
3190 tcg_gen_or_tl(t0, t0, t1);
3191 tcg_temp_free(t1);
3192 tcg_gen_ext32s_tl(t0, t0);
3193 gen_store_gpr(t0, rt);
3194 break;
3195 case OPC_LWRE:
3196 mem_idx = MIPS_HFLAG_UM;
3197 /* fall through */
3198 case OPC_LWR:
3199 t1 = tcg_temp_new();
3200 /* Do a byte access to possibly trigger a page
3201 fault with the unaligned address. */
3202 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3203 tcg_gen_andi_tl(t1, t0, 3);
3204 #ifdef TARGET_WORDS_BIGENDIAN
3205 tcg_gen_xori_tl(t1, t1, 3);
3206 #endif
3207 tcg_gen_shli_tl(t1, t1, 3);
3208 tcg_gen_andi_tl(t0, t0, ~3);
3209 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3210 tcg_gen_shr_tl(t0, t0, t1);
3211 tcg_gen_xori_tl(t1, t1, 31);
3212 t2 = tcg_const_tl(0xfffffffeull);
3213 tcg_gen_shl_tl(t2, t2, t1);
3214 gen_load_gpr(t1, rt);
3215 tcg_gen_and_tl(t1, t1, t2);
3216 tcg_temp_free(t2);
3217 tcg_gen_or_tl(t0, t0, t1);
3218 tcg_temp_free(t1);
3219 tcg_gen_ext32s_tl(t0, t0);
3220 gen_store_gpr(t0, rt);
3221 break;
3222 case OPC_LLE:
3223 mem_idx = MIPS_HFLAG_UM;
3224 /* fall through */
3225 case OPC_LL:
3226 case R6_OPC_LL:
3227 op_ld_ll(t0, t0, mem_idx, ctx);
3228 gen_store_gpr(t0, rt);
3229 break;
3231 tcg_temp_free(t0);
3234 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3235 uint32_t reg1, uint32_t reg2)
3237 TCGv taddr = tcg_temp_new();
3238 TCGv_i64 tval = tcg_temp_new_i64();
3239 TCGv tmp1 = tcg_temp_new();
3240 TCGv tmp2 = tcg_temp_new();
3242 gen_base_offset_addr(ctx, taddr, base, offset);
3243 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3244 #ifdef TARGET_WORDS_BIGENDIAN
3245 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3246 #else
3247 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3248 #endif
3249 gen_store_gpr(tmp1, reg1);
3250 tcg_temp_free(tmp1);
3251 gen_store_gpr(tmp2, reg2);
3252 tcg_temp_free(tmp2);
3253 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3254 tcg_temp_free_i64(tval);
3255 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3256 tcg_temp_free(taddr);
3259 /* Store */
3260 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
3261 int base, int offset)
3263 TCGv t0 = tcg_temp_new();
3264 TCGv t1 = tcg_temp_new();
3265 int mem_idx = ctx->mem_idx;
3267 gen_base_offset_addr(ctx, t0, base, offset);
3268 gen_load_gpr(t1, rt);
3269 switch (opc) {
3270 #if defined(TARGET_MIPS64)
3271 case OPC_SD:
3272 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3273 ctx->default_tcg_memop_mask);
3274 break;
3275 case OPC_SDL:
3276 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3277 break;
3278 case OPC_SDR:
3279 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3280 break;
3281 #endif
3282 case OPC_SWE:
3283 mem_idx = MIPS_HFLAG_UM;
3284 /* fall through */
3285 case OPC_SW:
3286 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3287 ctx->default_tcg_memop_mask);
3288 break;
3289 case OPC_SHE:
3290 mem_idx = MIPS_HFLAG_UM;
3291 /* fall through */
3292 case OPC_SH:
3293 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3294 ctx->default_tcg_memop_mask);
3295 break;
3296 case OPC_SBE:
3297 mem_idx = MIPS_HFLAG_UM;
3298 /* fall through */
3299 case OPC_SB:
3300 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3301 break;
3302 case OPC_SWLE:
3303 mem_idx = MIPS_HFLAG_UM;
3304 /* fall through */
3305 case OPC_SWL:
3306 gen_helper_0e2i(swl, t1, t0, mem_idx);
3307 break;
3308 case OPC_SWRE:
3309 mem_idx = MIPS_HFLAG_UM;
3310 /* fall through */
3311 case OPC_SWR:
3312 gen_helper_0e2i(swr, t1, t0, mem_idx);
3313 break;
3315 tcg_temp_free(t0);
3316 tcg_temp_free(t1);
3320 /* Store conditional */
3321 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
3322 int base, int16_t offset)
3324 TCGv t0, t1;
3325 int mem_idx = ctx->mem_idx;
3327 #ifdef CONFIG_USER_ONLY
3328 t0 = tcg_temp_local_new();
3329 t1 = tcg_temp_local_new();
3330 #else
3331 t0 = tcg_temp_new();
3332 t1 = tcg_temp_new();
3333 #endif
3334 gen_base_offset_addr(ctx, t0, base, offset);
3335 gen_load_gpr(t1, rt);
3336 switch (opc) {
3337 #if defined(TARGET_MIPS64)
3338 case OPC_SCD:
3339 case R6_OPC_SCD:
3340 op_st_scd(t1, t0, rt, mem_idx, ctx);
3341 break;
3342 #endif
3343 case OPC_SCE:
3344 mem_idx = MIPS_HFLAG_UM;
3345 /* fall through */
3346 case OPC_SC:
3347 case R6_OPC_SC:
3348 op_st_sc(t1, t0, rt, mem_idx, ctx);
3349 break;
3351 tcg_temp_free(t1);
3352 tcg_temp_free(t0);
3355 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3356 uint32_t reg1, uint32_t reg2)
3358 TCGv taddr = tcg_temp_local_new();
3359 TCGv lladdr = tcg_temp_local_new();
3360 TCGv_i64 tval = tcg_temp_new_i64();
3361 TCGv_i64 llval = tcg_temp_new_i64();
3362 TCGv_i64 val = tcg_temp_new_i64();
3363 TCGv tmp1 = tcg_temp_new();
3364 TCGv tmp2 = tcg_temp_new();
3365 TCGLabel *lab_fail = gen_new_label();
3366 TCGLabel *lab_done = gen_new_label();
3368 gen_base_offset_addr(ctx, taddr, base, offset);
3370 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3371 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3373 gen_load_gpr(tmp1, reg1);
3374 gen_load_gpr(tmp2, reg2);
3376 #ifdef TARGET_WORDS_BIGENDIAN
3377 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3378 #else
3379 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3380 #endif
3382 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3383 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3384 ctx->mem_idx, MO_64);
3385 if (reg1 != 0) {
3386 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3388 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3390 gen_set_label(lab_fail);
3392 if (reg1 != 0) {
3393 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3395 gen_set_label(lab_done);
3396 tcg_gen_movi_tl(lladdr, -1);
3397 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3400 /* Load and store */
3401 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
3402 TCGv t0)
3404 /* Don't do NOP if destination is zero: we must perform the actual
3405 memory access. */
3406 switch (opc) {
3407 case OPC_LWC1:
3409 TCGv_i32 fp0 = tcg_temp_new_i32();
3410 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3411 ctx->default_tcg_memop_mask);
3412 gen_store_fpr32(ctx, fp0, ft);
3413 tcg_temp_free_i32(fp0);
3415 break;
3416 case OPC_SWC1:
3418 TCGv_i32 fp0 = tcg_temp_new_i32();
3419 gen_load_fpr32(ctx, fp0, ft);
3420 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3421 ctx->default_tcg_memop_mask);
3422 tcg_temp_free_i32(fp0);
3424 break;
3425 case OPC_LDC1:
3427 TCGv_i64 fp0 = tcg_temp_new_i64();
3428 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3429 ctx->default_tcg_memop_mask);
3430 gen_store_fpr64(ctx, fp0, ft);
3431 tcg_temp_free_i64(fp0);
3433 break;
3434 case OPC_SDC1:
3436 TCGv_i64 fp0 = tcg_temp_new_i64();
3437 gen_load_fpr64(ctx, fp0, ft);
3438 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3439 ctx->default_tcg_memop_mask);
3440 tcg_temp_free_i64(fp0);
3442 break;
3443 default:
3444 MIPS_INVAL("flt_ldst");
3445 generate_exception_end(ctx, EXCP_RI);
3446 break;
3450 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3451 int rs, int16_t imm)
3453 TCGv t0 = tcg_temp_new();
3455 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3456 check_cp1_enabled(ctx);
3457 switch (op) {
3458 case OPC_LDC1:
3459 case OPC_SDC1:
3460 check_insn(ctx, ISA_MIPS2);
3461 /* Fallthrough */
3462 default:
3463 gen_base_offset_addr(ctx, t0, rs, imm);
3464 gen_flt_ldst(ctx, op, rt, t0);
3466 } else {
3467 generate_exception_err(ctx, EXCP_CpU, 1);
3469 tcg_temp_free(t0);
3472 /* Arithmetic with immediate operand */
3473 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3474 int rt, int rs, int imm)
3476 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3478 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3479 /* If no destination, treat it as a NOP.
3480 For addi, we must generate the overflow exception when needed. */
3481 return;
3483 switch (opc) {
3484 case OPC_ADDI:
3486 TCGv t0 = tcg_temp_local_new();
3487 TCGv t1 = tcg_temp_new();
3488 TCGv t2 = tcg_temp_new();
3489 TCGLabel *l1 = gen_new_label();
3491 gen_load_gpr(t1, rs);
3492 tcg_gen_addi_tl(t0, t1, uimm);
3493 tcg_gen_ext32s_tl(t0, t0);
3495 tcg_gen_xori_tl(t1, t1, ~uimm);
3496 tcg_gen_xori_tl(t2, t0, uimm);
3497 tcg_gen_and_tl(t1, t1, t2);
3498 tcg_temp_free(t2);
3499 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3500 tcg_temp_free(t1);
3501 /* operands of same sign, result different sign */
3502 generate_exception(ctx, EXCP_OVERFLOW);
3503 gen_set_label(l1);
3504 tcg_gen_ext32s_tl(t0, t0);
3505 gen_store_gpr(t0, rt);
3506 tcg_temp_free(t0);
3508 break;
3509 case OPC_ADDIU:
3510 if (rs != 0) {
3511 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3512 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3513 } else {
3514 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3516 break;
3517 #if defined(TARGET_MIPS64)
3518 case OPC_DADDI:
3520 TCGv t0 = tcg_temp_local_new();
3521 TCGv t1 = tcg_temp_new();
3522 TCGv t2 = tcg_temp_new();
3523 TCGLabel *l1 = gen_new_label();
3525 gen_load_gpr(t1, rs);
3526 tcg_gen_addi_tl(t0, t1, uimm);
3528 tcg_gen_xori_tl(t1, t1, ~uimm);
3529 tcg_gen_xori_tl(t2, t0, uimm);
3530 tcg_gen_and_tl(t1, t1, t2);
3531 tcg_temp_free(t2);
3532 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3533 tcg_temp_free(t1);
3534 /* operands of same sign, result different sign */
3535 generate_exception(ctx, EXCP_OVERFLOW);
3536 gen_set_label(l1);
3537 gen_store_gpr(t0, rt);
3538 tcg_temp_free(t0);
3540 break;
3541 case OPC_DADDIU:
3542 if (rs != 0) {
3543 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3544 } else {
3545 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3547 break;
3548 #endif
3552 /* Logic with immediate operand */
3553 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3554 int rt, int rs, int16_t imm)
3556 target_ulong uimm;
3558 if (rt == 0) {
3559 /* If no destination, treat it as a NOP. */
3560 return;
3562 uimm = (uint16_t)imm;
3563 switch (opc) {
3564 case OPC_ANDI:
3565 if (likely(rs != 0))
3566 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3567 else
3568 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3569 break;
3570 case OPC_ORI:
3571 if (rs != 0)
3572 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3573 else
3574 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3575 break;
3576 case OPC_XORI:
3577 if (likely(rs != 0))
3578 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3579 else
3580 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3581 break;
3582 case OPC_LUI:
3583 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
3584 /* OPC_AUI */
3585 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3586 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3587 } else {
3588 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3590 break;
3592 default:
3593 break;
3597 /* Set on less than with immediate operand */
3598 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3599 int rt, int rs, int16_t imm)
3601 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3602 TCGv t0;
3604 if (rt == 0) {
3605 /* If no destination, treat it as a NOP. */
3606 return;
3608 t0 = tcg_temp_new();
3609 gen_load_gpr(t0, rs);
3610 switch (opc) {
3611 case OPC_SLTI:
3612 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3613 break;
3614 case OPC_SLTIU:
3615 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3616 break;
3618 tcg_temp_free(t0);
3621 /* Shifts with immediate operand */
3622 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3623 int rt, int rs, int16_t imm)
3625 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3626 TCGv t0;
3628 if (rt == 0) {
3629 /* If no destination, treat it as a NOP. */
3630 return;
3633 t0 = tcg_temp_new();
3634 gen_load_gpr(t0, rs);
3635 switch (opc) {
3636 case OPC_SLL:
3637 tcg_gen_shli_tl(t0, t0, uimm);
3638 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3639 break;
3640 case OPC_SRA:
3641 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3642 break;
3643 case OPC_SRL:
3644 if (uimm != 0) {
3645 tcg_gen_ext32u_tl(t0, t0);
3646 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3647 } else {
3648 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3650 break;
3651 case OPC_ROTR:
3652 if (uimm != 0) {
3653 TCGv_i32 t1 = tcg_temp_new_i32();
3655 tcg_gen_trunc_tl_i32(t1, t0);
3656 tcg_gen_rotri_i32(t1, t1, uimm);
3657 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3658 tcg_temp_free_i32(t1);
3659 } else {
3660 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3662 break;
3663 #if defined(TARGET_MIPS64)
3664 case OPC_DSLL:
3665 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3666 break;
3667 case OPC_DSRA:
3668 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3669 break;
3670 case OPC_DSRL:
3671 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3672 break;
3673 case OPC_DROTR:
3674 if (uimm != 0) {
3675 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3676 } else {
3677 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3679 break;
3680 case OPC_DSLL32:
3681 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3682 break;
3683 case OPC_DSRA32:
3684 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3685 break;
3686 case OPC_DSRL32:
3687 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3688 break;
3689 case OPC_DROTR32:
3690 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3691 break;
3692 #endif
3694 tcg_temp_free(t0);
3697 /* Arithmetic */
3698 static void gen_arith(DisasContext *ctx, uint32_t opc,
3699 int rd, int rs, int rt)
3701 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
3702 && opc != OPC_DADD && opc != OPC_DSUB) {
3703 /* If no destination, treat it as a NOP.
3704 For add & sub, we must generate the overflow exception when needed. */
3705 return;
3708 switch (opc) {
3709 case OPC_ADD:
3711 TCGv t0 = tcg_temp_local_new();
3712 TCGv t1 = tcg_temp_new();
3713 TCGv t2 = tcg_temp_new();
3714 TCGLabel *l1 = gen_new_label();
3716 gen_load_gpr(t1, rs);
3717 gen_load_gpr(t2, rt);
3718 tcg_gen_add_tl(t0, t1, t2);
3719 tcg_gen_ext32s_tl(t0, t0);
3720 tcg_gen_xor_tl(t1, t1, t2);
3721 tcg_gen_xor_tl(t2, t0, t2);
3722 tcg_gen_andc_tl(t1, t2, t1);
3723 tcg_temp_free(t2);
3724 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3725 tcg_temp_free(t1);
3726 /* operands of same sign, result different sign */
3727 generate_exception(ctx, EXCP_OVERFLOW);
3728 gen_set_label(l1);
3729 gen_store_gpr(t0, rd);
3730 tcg_temp_free(t0);
3732 break;
3733 case OPC_ADDU:
3734 if (rs != 0 && rt != 0) {
3735 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3736 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3737 } else if (rs == 0 && rt != 0) {
3738 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3739 } else if (rs != 0 && rt == 0) {
3740 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3741 } else {
3742 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3744 break;
3745 case OPC_SUB:
3747 TCGv t0 = tcg_temp_local_new();
3748 TCGv t1 = tcg_temp_new();
3749 TCGv t2 = tcg_temp_new();
3750 TCGLabel *l1 = gen_new_label();
3752 gen_load_gpr(t1, rs);
3753 gen_load_gpr(t2, rt);
3754 tcg_gen_sub_tl(t0, t1, t2);
3755 tcg_gen_ext32s_tl(t0, t0);
3756 tcg_gen_xor_tl(t2, t1, t2);
3757 tcg_gen_xor_tl(t1, t0, t1);
3758 tcg_gen_and_tl(t1, t1, t2);
3759 tcg_temp_free(t2);
3760 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3761 tcg_temp_free(t1);
3762 /* operands of different sign, first operand and result different sign */
3763 generate_exception(ctx, EXCP_OVERFLOW);
3764 gen_set_label(l1);
3765 gen_store_gpr(t0, rd);
3766 tcg_temp_free(t0);
3768 break;
3769 case OPC_SUBU:
3770 if (rs != 0 && rt != 0) {
3771 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3772 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3773 } else if (rs == 0 && rt != 0) {
3774 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3775 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3776 } else if (rs != 0 && rt == 0) {
3777 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3778 } else {
3779 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3781 break;
3782 #if defined(TARGET_MIPS64)
3783 case OPC_DADD:
3785 TCGv t0 = tcg_temp_local_new();
3786 TCGv t1 = tcg_temp_new();
3787 TCGv t2 = tcg_temp_new();
3788 TCGLabel *l1 = gen_new_label();
3790 gen_load_gpr(t1, rs);
3791 gen_load_gpr(t2, rt);
3792 tcg_gen_add_tl(t0, t1, t2);
3793 tcg_gen_xor_tl(t1, t1, t2);
3794 tcg_gen_xor_tl(t2, t0, t2);
3795 tcg_gen_andc_tl(t1, t2, t1);
3796 tcg_temp_free(t2);
3797 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3798 tcg_temp_free(t1);
3799 /* operands of same sign, result different sign */
3800 generate_exception(ctx, EXCP_OVERFLOW);
3801 gen_set_label(l1);
3802 gen_store_gpr(t0, rd);
3803 tcg_temp_free(t0);
3805 break;
3806 case OPC_DADDU:
3807 if (rs != 0 && rt != 0) {
3808 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3809 } else if (rs == 0 && rt != 0) {
3810 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3811 } else if (rs != 0 && rt == 0) {
3812 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3813 } else {
3814 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3816 break;
3817 case OPC_DSUB:
3819 TCGv t0 = tcg_temp_local_new();
3820 TCGv t1 = tcg_temp_new();
3821 TCGv t2 = tcg_temp_new();
3822 TCGLabel *l1 = gen_new_label();
3824 gen_load_gpr(t1, rs);
3825 gen_load_gpr(t2, rt);
3826 tcg_gen_sub_tl(t0, t1, t2);
3827 tcg_gen_xor_tl(t2, t1, t2);
3828 tcg_gen_xor_tl(t1, t0, t1);
3829 tcg_gen_and_tl(t1, t1, t2);
3830 tcg_temp_free(t2);
3831 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3832 tcg_temp_free(t1);
3833 /* operands of different sign, first operand and result different sign */
3834 generate_exception(ctx, EXCP_OVERFLOW);
3835 gen_set_label(l1);
3836 gen_store_gpr(t0, rd);
3837 tcg_temp_free(t0);
3839 break;
3840 case OPC_DSUBU:
3841 if (rs != 0 && rt != 0) {
3842 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3843 } else if (rs == 0 && rt != 0) {
3844 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
3845 } else if (rs != 0 && rt == 0) {
3846 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3847 } else {
3848 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3850 break;
3851 #endif
3852 case OPC_MUL:
3853 if (likely(rs != 0 && rt != 0)) {
3854 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3855 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3856 } else {
3857 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3859 break;
3863 /* Conditional move */
3864 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
3865 int rd, int rs, int rt)
3867 TCGv t0, t1, t2;
3869 if (rd == 0) {
3870 /* If no destination, treat it as a NOP. */
3871 return;
3874 t0 = tcg_temp_new();
3875 gen_load_gpr(t0, rt);
3876 t1 = tcg_const_tl(0);
3877 t2 = tcg_temp_new();
3878 gen_load_gpr(t2, rs);
3879 switch (opc) {
3880 case OPC_MOVN:
3881 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3882 break;
3883 case OPC_MOVZ:
3884 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
3885 break;
3886 case OPC_SELNEZ:
3887 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
3888 break;
3889 case OPC_SELEQZ:
3890 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
3891 break;
3893 tcg_temp_free(t2);
3894 tcg_temp_free(t1);
3895 tcg_temp_free(t0);
3898 /* Logic */
3899 static void gen_logic(DisasContext *ctx, uint32_t opc,
3900 int rd, int rs, int rt)
3902 if (rd == 0) {
3903 /* If no destination, treat it as a NOP. */
3904 return;
3907 switch (opc) {
3908 case OPC_AND:
3909 if (likely(rs != 0 && rt != 0)) {
3910 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3911 } else {
3912 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3914 break;
3915 case OPC_NOR:
3916 if (rs != 0 && rt != 0) {
3917 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3918 } else if (rs == 0 && rt != 0) {
3919 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
3920 } else if (rs != 0 && rt == 0) {
3921 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
3922 } else {
3923 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
3925 break;
3926 case OPC_OR:
3927 if (likely(rs != 0 && rt != 0)) {
3928 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3929 } else if (rs == 0 && rt != 0) {
3930 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3931 } else if (rs != 0 && rt == 0) {
3932 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3933 } else {
3934 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3936 break;
3937 case OPC_XOR:
3938 if (likely(rs != 0 && rt != 0)) {
3939 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3940 } else if (rs == 0 && rt != 0) {
3941 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3942 } else if (rs != 0 && rt == 0) {
3943 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3944 } else {
3945 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3947 break;
3951 /* Set on lower than */
3952 static void gen_slt(DisasContext *ctx, uint32_t opc,
3953 int rd, int rs, int rt)
3955 TCGv t0, t1;
3957 if (rd == 0) {
3958 /* If no destination, treat it as a NOP. */
3959 return;
3962 t0 = tcg_temp_new();
3963 t1 = tcg_temp_new();
3964 gen_load_gpr(t0, rs);
3965 gen_load_gpr(t1, rt);
3966 switch (opc) {
3967 case OPC_SLT:
3968 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3969 break;
3970 case OPC_SLTU:
3971 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3972 break;
3974 tcg_temp_free(t0);
3975 tcg_temp_free(t1);
3978 /* Shifts */
3979 static void gen_shift(DisasContext *ctx, uint32_t opc,
3980 int rd, int rs, int rt)
3982 TCGv t0, t1;
3984 if (rd == 0) {
3985 /* If no destination, treat it as a NOP.
3986 For add & sub, we must generate the overflow exception when needed. */
3987 return;
3990 t0 = tcg_temp_new();
3991 t1 = tcg_temp_new();
3992 gen_load_gpr(t0, rs);
3993 gen_load_gpr(t1, rt);
3994 switch (opc) {
3995 case OPC_SLLV:
3996 tcg_gen_andi_tl(t0, t0, 0x1f);
3997 tcg_gen_shl_tl(t0, t1, t0);
3998 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3999 break;
4000 case OPC_SRAV:
4001 tcg_gen_andi_tl(t0, t0, 0x1f);
4002 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4003 break;
4004 case OPC_SRLV:
4005 tcg_gen_ext32u_tl(t1, t1);
4006 tcg_gen_andi_tl(t0, t0, 0x1f);
4007 tcg_gen_shr_tl(t0, t1, t0);
4008 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4009 break;
4010 case OPC_ROTRV:
4012 TCGv_i32 t2 = tcg_temp_new_i32();
4013 TCGv_i32 t3 = tcg_temp_new_i32();
4015 tcg_gen_trunc_tl_i32(t2, t0);
4016 tcg_gen_trunc_tl_i32(t3, t1);
4017 tcg_gen_andi_i32(t2, t2, 0x1f);
4018 tcg_gen_rotr_i32(t2, t3, t2);
4019 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4020 tcg_temp_free_i32(t2);
4021 tcg_temp_free_i32(t3);
4023 break;
4024 #if defined(TARGET_MIPS64)
4025 case OPC_DSLLV:
4026 tcg_gen_andi_tl(t0, t0, 0x3f);
4027 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4028 break;
4029 case OPC_DSRAV:
4030 tcg_gen_andi_tl(t0, t0, 0x3f);
4031 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4032 break;
4033 case OPC_DSRLV:
4034 tcg_gen_andi_tl(t0, t0, 0x3f);
4035 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4036 break;
4037 case OPC_DROTRV:
4038 tcg_gen_andi_tl(t0, t0, 0x3f);
4039 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4040 break;
4041 #endif
4043 tcg_temp_free(t0);
4044 tcg_temp_free(t1);
4047 /* Arithmetic on HI/LO registers */
4048 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4050 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4051 /* Treat as NOP. */
4052 return;
4055 if (acc != 0) {
4056 check_dsp(ctx);
4059 switch (opc) {
4060 case OPC_MFHI:
4061 #if defined(TARGET_MIPS64)
4062 if (acc != 0) {
4063 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4064 } else
4065 #endif
4067 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4069 break;
4070 case OPC_MFLO:
4071 #if defined(TARGET_MIPS64)
4072 if (acc != 0) {
4073 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4074 } else
4075 #endif
4077 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4079 break;
4080 case OPC_MTHI:
4081 if (reg != 0) {
4082 #if defined(TARGET_MIPS64)
4083 if (acc != 0) {
4084 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4085 } else
4086 #endif
4088 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4090 } else {
4091 tcg_gen_movi_tl(cpu_HI[acc], 0);
4093 break;
4094 case OPC_MTLO:
4095 if (reg != 0) {
4096 #if defined(TARGET_MIPS64)
4097 if (acc != 0) {
4098 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4099 } else
4100 #endif
4102 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4104 } else {
4105 tcg_gen_movi_tl(cpu_LO[acc], 0);
4107 break;
4111 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4112 TCGMemOp memop)
4114 TCGv t0 = tcg_const_tl(addr);
4115 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4116 gen_store_gpr(t0, reg);
4117 tcg_temp_free(t0);
4120 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4121 int rs)
4123 target_long offset;
4124 target_long addr;
4126 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4127 case OPC_ADDIUPC:
4128 if (rs != 0) {
4129 offset = sextract32(ctx->opcode << 2, 0, 21);
4130 addr = addr_add(ctx, pc, offset);
4131 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4133 break;
4134 case R6_OPC_LWPC:
4135 offset = sextract32(ctx->opcode << 2, 0, 21);
4136 addr = addr_add(ctx, pc, offset);
4137 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4138 break;
4139 #if defined(TARGET_MIPS64)
4140 case OPC_LWUPC:
4141 check_mips_64(ctx);
4142 offset = sextract32(ctx->opcode << 2, 0, 21);
4143 addr = addr_add(ctx, pc, offset);
4144 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4145 break;
4146 #endif
4147 default:
4148 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4149 case OPC_AUIPC:
4150 if (rs != 0) {
4151 offset = sextract32(ctx->opcode, 0, 16) << 16;
4152 addr = addr_add(ctx, pc, offset);
4153 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4155 break;
4156 case OPC_ALUIPC:
4157 if (rs != 0) {
4158 offset = sextract32(ctx->opcode, 0, 16) << 16;
4159 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4160 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4162 break;
4163 #if defined(TARGET_MIPS64)
4164 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4165 case R6_OPC_LDPC + (1 << 16):
4166 case R6_OPC_LDPC + (2 << 16):
4167 case R6_OPC_LDPC + (3 << 16):
4168 check_mips_64(ctx);
4169 offset = sextract32(ctx->opcode << 3, 0, 21);
4170 addr = addr_add(ctx, (pc & ~0x7), offset);
4171 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4172 break;
4173 #endif
4174 default:
4175 MIPS_INVAL("OPC_PCREL");
4176 generate_exception_end(ctx, EXCP_RI);
4177 break;
4179 break;
4183 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4185 TCGv t0, t1;
4187 if (rd == 0) {
4188 /* Treat as NOP. */
4189 return;
4192 t0 = tcg_temp_new();
4193 t1 = tcg_temp_new();
4195 gen_load_gpr(t0, rs);
4196 gen_load_gpr(t1, rt);
4198 switch (opc) {
4199 case R6_OPC_DIV:
4201 TCGv t2 = tcg_temp_new();
4202 TCGv t3 = tcg_temp_new();
4203 tcg_gen_ext32s_tl(t0, t0);
4204 tcg_gen_ext32s_tl(t1, t1);
4205 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4206 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4207 tcg_gen_and_tl(t2, t2, t3);
4208 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4209 tcg_gen_or_tl(t2, t2, t3);
4210 tcg_gen_movi_tl(t3, 0);
4211 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4212 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4213 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4214 tcg_temp_free(t3);
4215 tcg_temp_free(t2);
4217 break;
4218 case R6_OPC_MOD:
4220 TCGv t2 = tcg_temp_new();
4221 TCGv t3 = tcg_temp_new();
4222 tcg_gen_ext32s_tl(t0, t0);
4223 tcg_gen_ext32s_tl(t1, t1);
4224 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4225 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4226 tcg_gen_and_tl(t2, t2, t3);
4227 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4228 tcg_gen_or_tl(t2, t2, t3);
4229 tcg_gen_movi_tl(t3, 0);
4230 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4231 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4232 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4233 tcg_temp_free(t3);
4234 tcg_temp_free(t2);
4236 break;
4237 case R6_OPC_DIVU:
4239 TCGv t2 = tcg_const_tl(0);
4240 TCGv t3 = tcg_const_tl(1);
4241 tcg_gen_ext32u_tl(t0, t0);
4242 tcg_gen_ext32u_tl(t1, t1);
4243 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4244 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4245 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4246 tcg_temp_free(t3);
4247 tcg_temp_free(t2);
4249 break;
4250 case R6_OPC_MODU:
4252 TCGv t2 = tcg_const_tl(0);
4253 TCGv t3 = tcg_const_tl(1);
4254 tcg_gen_ext32u_tl(t0, t0);
4255 tcg_gen_ext32u_tl(t1, t1);
4256 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4257 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4258 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4259 tcg_temp_free(t3);
4260 tcg_temp_free(t2);
4262 break;
4263 case R6_OPC_MUL:
4265 TCGv_i32 t2 = tcg_temp_new_i32();
4266 TCGv_i32 t3 = tcg_temp_new_i32();
4267 tcg_gen_trunc_tl_i32(t2, t0);
4268 tcg_gen_trunc_tl_i32(t3, t1);
4269 tcg_gen_mul_i32(t2, t2, t3);
4270 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4271 tcg_temp_free_i32(t2);
4272 tcg_temp_free_i32(t3);
4274 break;
4275 case R6_OPC_MUH:
4277 TCGv_i32 t2 = tcg_temp_new_i32();
4278 TCGv_i32 t3 = tcg_temp_new_i32();
4279 tcg_gen_trunc_tl_i32(t2, t0);
4280 tcg_gen_trunc_tl_i32(t3, t1);
4281 tcg_gen_muls2_i32(t2, t3, t2, t3);
4282 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4283 tcg_temp_free_i32(t2);
4284 tcg_temp_free_i32(t3);
4286 break;
4287 case R6_OPC_MULU:
4289 TCGv_i32 t2 = tcg_temp_new_i32();
4290 TCGv_i32 t3 = tcg_temp_new_i32();
4291 tcg_gen_trunc_tl_i32(t2, t0);
4292 tcg_gen_trunc_tl_i32(t3, t1);
4293 tcg_gen_mul_i32(t2, t2, t3);
4294 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4295 tcg_temp_free_i32(t2);
4296 tcg_temp_free_i32(t3);
4298 break;
4299 case R6_OPC_MUHU:
4301 TCGv_i32 t2 = tcg_temp_new_i32();
4302 TCGv_i32 t3 = tcg_temp_new_i32();
4303 tcg_gen_trunc_tl_i32(t2, t0);
4304 tcg_gen_trunc_tl_i32(t3, t1);
4305 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4306 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4307 tcg_temp_free_i32(t2);
4308 tcg_temp_free_i32(t3);
4310 break;
4311 #if defined(TARGET_MIPS64)
4312 case R6_OPC_DDIV:
4314 TCGv t2 = tcg_temp_new();
4315 TCGv t3 = tcg_temp_new();
4316 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4317 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4318 tcg_gen_and_tl(t2, t2, t3);
4319 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4320 tcg_gen_or_tl(t2, t2, t3);
4321 tcg_gen_movi_tl(t3, 0);
4322 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4323 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4324 tcg_temp_free(t3);
4325 tcg_temp_free(t2);
4327 break;
4328 case R6_OPC_DMOD:
4330 TCGv t2 = tcg_temp_new();
4331 TCGv t3 = tcg_temp_new();
4332 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4333 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4334 tcg_gen_and_tl(t2, t2, t3);
4335 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4336 tcg_gen_or_tl(t2, t2, t3);
4337 tcg_gen_movi_tl(t3, 0);
4338 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4339 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4340 tcg_temp_free(t3);
4341 tcg_temp_free(t2);
4343 break;
4344 case R6_OPC_DDIVU:
4346 TCGv t2 = tcg_const_tl(0);
4347 TCGv t3 = tcg_const_tl(1);
4348 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4349 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4350 tcg_temp_free(t3);
4351 tcg_temp_free(t2);
4353 break;
4354 case R6_OPC_DMODU:
4356 TCGv t2 = tcg_const_tl(0);
4357 TCGv t3 = tcg_const_tl(1);
4358 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4359 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4360 tcg_temp_free(t3);
4361 tcg_temp_free(t2);
4363 break;
4364 case R6_OPC_DMUL:
4365 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4366 break;
4367 case R6_OPC_DMUH:
4369 TCGv t2 = tcg_temp_new();
4370 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4371 tcg_temp_free(t2);
4373 break;
4374 case R6_OPC_DMULU:
4375 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4376 break;
4377 case R6_OPC_DMUHU:
4379 TCGv t2 = tcg_temp_new();
4380 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4381 tcg_temp_free(t2);
4383 break;
4384 #endif
4385 default:
4386 MIPS_INVAL("r6 mul/div");
4387 generate_exception_end(ctx, EXCP_RI);
4388 goto out;
4390 out:
4391 tcg_temp_free(t0);
4392 tcg_temp_free(t1);
4395 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4396 int acc, int rs, int rt)
4398 TCGv t0, t1;
4400 t0 = tcg_temp_new();
4401 t1 = tcg_temp_new();
4403 gen_load_gpr(t0, rs);
4404 gen_load_gpr(t1, rt);
4406 if (acc != 0) {
4407 check_dsp(ctx);
4410 switch (opc) {
4411 case OPC_DIV:
4413 TCGv t2 = tcg_temp_new();
4414 TCGv t3 = tcg_temp_new();
4415 tcg_gen_ext32s_tl(t0, t0);
4416 tcg_gen_ext32s_tl(t1, t1);
4417 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4418 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4419 tcg_gen_and_tl(t2, t2, t3);
4420 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4421 tcg_gen_or_tl(t2, t2, t3);
4422 tcg_gen_movi_tl(t3, 0);
4423 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4424 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4425 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4426 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4427 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4428 tcg_temp_free(t3);
4429 tcg_temp_free(t2);
4431 break;
4432 case OPC_DIVU:
4434 TCGv t2 = tcg_const_tl(0);
4435 TCGv t3 = tcg_const_tl(1);
4436 tcg_gen_ext32u_tl(t0, t0);
4437 tcg_gen_ext32u_tl(t1, t1);
4438 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4439 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4440 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4441 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4442 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4443 tcg_temp_free(t3);
4444 tcg_temp_free(t2);
4446 break;
4447 case OPC_MULT:
4449 TCGv_i32 t2 = tcg_temp_new_i32();
4450 TCGv_i32 t3 = tcg_temp_new_i32();
4451 tcg_gen_trunc_tl_i32(t2, t0);
4452 tcg_gen_trunc_tl_i32(t3, t1);
4453 tcg_gen_muls2_i32(t2, t3, t2, t3);
4454 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4455 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4456 tcg_temp_free_i32(t2);
4457 tcg_temp_free_i32(t3);
4459 break;
4460 case OPC_MULTU:
4462 TCGv_i32 t2 = tcg_temp_new_i32();
4463 TCGv_i32 t3 = tcg_temp_new_i32();
4464 tcg_gen_trunc_tl_i32(t2, t0);
4465 tcg_gen_trunc_tl_i32(t3, t1);
4466 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4467 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4468 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4469 tcg_temp_free_i32(t2);
4470 tcg_temp_free_i32(t3);
4472 break;
4473 #if defined(TARGET_MIPS64)
4474 case OPC_DDIV:
4476 TCGv t2 = tcg_temp_new();
4477 TCGv t3 = tcg_temp_new();
4478 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4479 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4480 tcg_gen_and_tl(t2, t2, t3);
4481 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4482 tcg_gen_or_tl(t2, t2, t3);
4483 tcg_gen_movi_tl(t3, 0);
4484 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4485 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4486 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4487 tcg_temp_free(t3);
4488 tcg_temp_free(t2);
4490 break;
4491 case OPC_DDIVU:
4493 TCGv t2 = tcg_const_tl(0);
4494 TCGv t3 = tcg_const_tl(1);
4495 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4496 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4497 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4498 tcg_temp_free(t3);
4499 tcg_temp_free(t2);
4501 break;
4502 case OPC_DMULT:
4503 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4504 break;
4505 case OPC_DMULTU:
4506 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4507 break;
4508 #endif
4509 case OPC_MADD:
4511 TCGv_i64 t2 = tcg_temp_new_i64();
4512 TCGv_i64 t3 = tcg_temp_new_i64();
4514 tcg_gen_ext_tl_i64(t2, t0);
4515 tcg_gen_ext_tl_i64(t3, t1);
4516 tcg_gen_mul_i64(t2, t2, t3);
4517 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4518 tcg_gen_add_i64(t2, t2, t3);
4519 tcg_temp_free_i64(t3);
4520 gen_move_low32(cpu_LO[acc], t2);
4521 gen_move_high32(cpu_HI[acc], t2);
4522 tcg_temp_free_i64(t2);
4524 break;
4525 case OPC_MADDU:
4527 TCGv_i64 t2 = tcg_temp_new_i64();
4528 TCGv_i64 t3 = tcg_temp_new_i64();
4530 tcg_gen_ext32u_tl(t0, t0);
4531 tcg_gen_ext32u_tl(t1, t1);
4532 tcg_gen_extu_tl_i64(t2, t0);
4533 tcg_gen_extu_tl_i64(t3, t1);
4534 tcg_gen_mul_i64(t2, t2, t3);
4535 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4536 tcg_gen_add_i64(t2, t2, t3);
4537 tcg_temp_free_i64(t3);
4538 gen_move_low32(cpu_LO[acc], t2);
4539 gen_move_high32(cpu_HI[acc], t2);
4540 tcg_temp_free_i64(t2);
4542 break;
4543 case OPC_MSUB:
4545 TCGv_i64 t2 = tcg_temp_new_i64();
4546 TCGv_i64 t3 = tcg_temp_new_i64();
4548 tcg_gen_ext_tl_i64(t2, t0);
4549 tcg_gen_ext_tl_i64(t3, t1);
4550 tcg_gen_mul_i64(t2, t2, t3);
4551 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4552 tcg_gen_sub_i64(t2, t3, t2);
4553 tcg_temp_free_i64(t3);
4554 gen_move_low32(cpu_LO[acc], t2);
4555 gen_move_high32(cpu_HI[acc], t2);
4556 tcg_temp_free_i64(t2);
4558 break;
4559 case OPC_MSUBU:
4561 TCGv_i64 t2 = tcg_temp_new_i64();
4562 TCGv_i64 t3 = tcg_temp_new_i64();
4564 tcg_gen_ext32u_tl(t0, t0);
4565 tcg_gen_ext32u_tl(t1, t1);
4566 tcg_gen_extu_tl_i64(t2, t0);
4567 tcg_gen_extu_tl_i64(t3, t1);
4568 tcg_gen_mul_i64(t2, t2, t3);
4569 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4570 tcg_gen_sub_i64(t2, t3, t2);
4571 tcg_temp_free_i64(t3);
4572 gen_move_low32(cpu_LO[acc], t2);
4573 gen_move_high32(cpu_HI[acc], t2);
4574 tcg_temp_free_i64(t2);
4576 break;
4577 default:
4578 MIPS_INVAL("mul/div");
4579 generate_exception_end(ctx, EXCP_RI);
4580 goto out;
4582 out:
4583 tcg_temp_free(t0);
4584 tcg_temp_free(t1);
4587 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
4588 int rd, int rs, int rt)
4590 TCGv t0 = tcg_temp_new();
4591 TCGv t1 = tcg_temp_new();
4593 gen_load_gpr(t0, rs);
4594 gen_load_gpr(t1, rt);
4596 switch (opc) {
4597 case OPC_VR54XX_MULS:
4598 gen_helper_muls(t0, cpu_env, t0, t1);
4599 break;
4600 case OPC_VR54XX_MULSU:
4601 gen_helper_mulsu(t0, cpu_env, t0, t1);
4602 break;
4603 case OPC_VR54XX_MACC:
4604 gen_helper_macc(t0, cpu_env, t0, t1);
4605 break;
4606 case OPC_VR54XX_MACCU:
4607 gen_helper_maccu(t0, cpu_env, t0, t1);
4608 break;
4609 case OPC_VR54XX_MSAC:
4610 gen_helper_msac(t0, cpu_env, t0, t1);
4611 break;
4612 case OPC_VR54XX_MSACU:
4613 gen_helper_msacu(t0, cpu_env, t0, t1);
4614 break;
4615 case OPC_VR54XX_MULHI:
4616 gen_helper_mulhi(t0, cpu_env, t0, t1);
4617 break;
4618 case OPC_VR54XX_MULHIU:
4619 gen_helper_mulhiu(t0, cpu_env, t0, t1);
4620 break;
4621 case OPC_VR54XX_MULSHI:
4622 gen_helper_mulshi(t0, cpu_env, t0, t1);
4623 break;
4624 case OPC_VR54XX_MULSHIU:
4625 gen_helper_mulshiu(t0, cpu_env, t0, t1);
4626 break;
4627 case OPC_VR54XX_MACCHI:
4628 gen_helper_macchi(t0, cpu_env, t0, t1);
4629 break;
4630 case OPC_VR54XX_MACCHIU:
4631 gen_helper_macchiu(t0, cpu_env, t0, t1);
4632 break;
4633 case OPC_VR54XX_MSACHI:
4634 gen_helper_msachi(t0, cpu_env, t0, t1);
4635 break;
4636 case OPC_VR54XX_MSACHIU:
4637 gen_helper_msachiu(t0, cpu_env, t0, t1);
4638 break;
4639 default:
4640 MIPS_INVAL("mul vr54xx");
4641 generate_exception_end(ctx, EXCP_RI);
4642 goto out;
4644 gen_store_gpr(t0, rd);
4646 out:
4647 tcg_temp_free(t0);
4648 tcg_temp_free(t1);
4651 static void gen_cl (DisasContext *ctx, uint32_t opc,
4652 int rd, int rs)
4654 TCGv t0;
4656 if (rd == 0) {
4657 /* Treat as NOP. */
4658 return;
4660 t0 = cpu_gpr[rd];
4661 gen_load_gpr(t0, rs);
4663 switch (opc) {
4664 case OPC_CLO:
4665 case R6_OPC_CLO:
4666 #if defined(TARGET_MIPS64)
4667 case OPC_DCLO:
4668 case R6_OPC_DCLO:
4669 #endif
4670 tcg_gen_not_tl(t0, t0);
4671 break;
4674 switch (opc) {
4675 case OPC_CLO:
4676 case R6_OPC_CLO:
4677 case OPC_CLZ:
4678 case R6_OPC_CLZ:
4679 tcg_gen_ext32u_tl(t0, t0);
4680 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
4681 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
4682 break;
4683 #if defined(TARGET_MIPS64)
4684 case OPC_DCLO:
4685 case R6_OPC_DCLO:
4686 case OPC_DCLZ:
4687 case R6_OPC_DCLZ:
4688 tcg_gen_clzi_i64(t0, t0, 64);
4689 break;
4690 #endif
4694 /* Godson integer instructions */
4695 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
4696 int rd, int rs, int rt)
4698 TCGv t0, t1;
4700 if (rd == 0) {
4701 /* Treat as NOP. */
4702 return;
4705 switch (opc) {
4706 case OPC_MULT_G_2E:
4707 case OPC_MULT_G_2F:
4708 case OPC_MULTU_G_2E:
4709 case OPC_MULTU_G_2F:
4710 #if defined(TARGET_MIPS64)
4711 case OPC_DMULT_G_2E:
4712 case OPC_DMULT_G_2F:
4713 case OPC_DMULTU_G_2E:
4714 case OPC_DMULTU_G_2F:
4715 #endif
4716 t0 = tcg_temp_new();
4717 t1 = tcg_temp_new();
4718 break;
4719 default:
4720 t0 = tcg_temp_local_new();
4721 t1 = tcg_temp_local_new();
4722 break;
4725 gen_load_gpr(t0, rs);
4726 gen_load_gpr(t1, rt);
4728 switch (opc) {
4729 case OPC_MULT_G_2E:
4730 case OPC_MULT_G_2F:
4731 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4732 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4733 break;
4734 case OPC_MULTU_G_2E:
4735 case OPC_MULTU_G_2F:
4736 tcg_gen_ext32u_tl(t0, t0);
4737 tcg_gen_ext32u_tl(t1, t1);
4738 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4739 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4740 break;
4741 case OPC_DIV_G_2E:
4742 case OPC_DIV_G_2F:
4744 TCGLabel *l1 = gen_new_label();
4745 TCGLabel *l2 = gen_new_label();
4746 TCGLabel *l3 = gen_new_label();
4747 tcg_gen_ext32s_tl(t0, t0);
4748 tcg_gen_ext32s_tl(t1, t1);
4749 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4750 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4751 tcg_gen_br(l3);
4752 gen_set_label(l1);
4753 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4754 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4755 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4756 tcg_gen_br(l3);
4757 gen_set_label(l2);
4758 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4759 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4760 gen_set_label(l3);
4762 break;
4763 case OPC_DIVU_G_2E:
4764 case OPC_DIVU_G_2F:
4766 TCGLabel *l1 = gen_new_label();
4767 TCGLabel *l2 = gen_new_label();
4768 tcg_gen_ext32u_tl(t0, t0);
4769 tcg_gen_ext32u_tl(t1, t1);
4770 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4771 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4772 tcg_gen_br(l2);
4773 gen_set_label(l1);
4774 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4775 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4776 gen_set_label(l2);
4778 break;
4779 case OPC_MOD_G_2E:
4780 case OPC_MOD_G_2F:
4782 TCGLabel *l1 = gen_new_label();
4783 TCGLabel *l2 = gen_new_label();
4784 TCGLabel *l3 = gen_new_label();
4785 tcg_gen_ext32u_tl(t0, t0);
4786 tcg_gen_ext32u_tl(t1, t1);
4787 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4788 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4789 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4790 gen_set_label(l1);
4791 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4792 tcg_gen_br(l3);
4793 gen_set_label(l2);
4794 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4795 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4796 gen_set_label(l3);
4798 break;
4799 case OPC_MODU_G_2E:
4800 case OPC_MODU_G_2F:
4802 TCGLabel *l1 = gen_new_label();
4803 TCGLabel *l2 = gen_new_label();
4804 tcg_gen_ext32u_tl(t0, t0);
4805 tcg_gen_ext32u_tl(t1, t1);
4806 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4807 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4808 tcg_gen_br(l2);
4809 gen_set_label(l1);
4810 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4811 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4812 gen_set_label(l2);
4814 break;
4815 #if defined(TARGET_MIPS64)
4816 case OPC_DMULT_G_2E:
4817 case OPC_DMULT_G_2F:
4818 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4819 break;
4820 case OPC_DMULTU_G_2E:
4821 case OPC_DMULTU_G_2F:
4822 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4823 break;
4824 case OPC_DDIV_G_2E:
4825 case OPC_DDIV_G_2F:
4827 TCGLabel *l1 = gen_new_label();
4828 TCGLabel *l2 = gen_new_label();
4829 TCGLabel *l3 = gen_new_label();
4830 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4831 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4832 tcg_gen_br(l3);
4833 gen_set_label(l1);
4834 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4835 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4836 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4837 tcg_gen_br(l3);
4838 gen_set_label(l2);
4839 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4840 gen_set_label(l3);
4842 break;
4843 case OPC_DDIVU_G_2E:
4844 case OPC_DDIVU_G_2F:
4846 TCGLabel *l1 = gen_new_label();
4847 TCGLabel *l2 = gen_new_label();
4848 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4849 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4850 tcg_gen_br(l2);
4851 gen_set_label(l1);
4852 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4853 gen_set_label(l2);
4855 break;
4856 case OPC_DMOD_G_2E:
4857 case OPC_DMOD_G_2F:
4859 TCGLabel *l1 = gen_new_label();
4860 TCGLabel *l2 = gen_new_label();
4861 TCGLabel *l3 = gen_new_label();
4862 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4863 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4864 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4865 gen_set_label(l1);
4866 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4867 tcg_gen_br(l3);
4868 gen_set_label(l2);
4869 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4870 gen_set_label(l3);
4872 break;
4873 case OPC_DMODU_G_2E:
4874 case OPC_DMODU_G_2F:
4876 TCGLabel *l1 = gen_new_label();
4877 TCGLabel *l2 = gen_new_label();
4878 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4879 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4880 tcg_gen_br(l2);
4881 gen_set_label(l1);
4882 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4883 gen_set_label(l2);
4885 break;
4886 #endif
4889 tcg_temp_free(t0);
4890 tcg_temp_free(t1);
4893 /* Loongson multimedia instructions */
4894 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4896 uint32_t opc, shift_max;
4897 TCGv_i64 t0, t1;
4899 opc = MASK_LMI(ctx->opcode);
4900 switch (opc) {
4901 case OPC_ADD_CP2:
4902 case OPC_SUB_CP2:
4903 case OPC_DADD_CP2:
4904 case OPC_DSUB_CP2:
4905 t0 = tcg_temp_local_new_i64();
4906 t1 = tcg_temp_local_new_i64();
4907 break;
4908 default:
4909 t0 = tcg_temp_new_i64();
4910 t1 = tcg_temp_new_i64();
4911 break;
4914 check_cp1_enabled(ctx);
4915 gen_load_fpr64(ctx, t0, rs);
4916 gen_load_fpr64(ctx, t1, rt);
4918 #define LMI_HELPER(UP, LO) \
4919 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
4920 #define LMI_HELPER_1(UP, LO) \
4921 case OPC_##UP: gen_helper_##LO(t0, t0); break
4922 #define LMI_DIRECT(UP, LO, OP) \
4923 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
4925 switch (opc) {
4926 LMI_HELPER(PADDSH, paddsh);
4927 LMI_HELPER(PADDUSH, paddush);
4928 LMI_HELPER(PADDH, paddh);
4929 LMI_HELPER(PADDW, paddw);
4930 LMI_HELPER(PADDSB, paddsb);
4931 LMI_HELPER(PADDUSB, paddusb);
4932 LMI_HELPER(PADDB, paddb);
4934 LMI_HELPER(PSUBSH, psubsh);
4935 LMI_HELPER(PSUBUSH, psubush);
4936 LMI_HELPER(PSUBH, psubh);
4937 LMI_HELPER(PSUBW, psubw);
4938 LMI_HELPER(PSUBSB, psubsb);
4939 LMI_HELPER(PSUBUSB, psubusb);
4940 LMI_HELPER(PSUBB, psubb);
4942 LMI_HELPER(PSHUFH, pshufh);
4943 LMI_HELPER(PACKSSWH, packsswh);
4944 LMI_HELPER(PACKSSHB, packsshb);
4945 LMI_HELPER(PACKUSHB, packushb);
4947 LMI_HELPER(PUNPCKLHW, punpcklhw);
4948 LMI_HELPER(PUNPCKHHW, punpckhhw);
4949 LMI_HELPER(PUNPCKLBH, punpcklbh);
4950 LMI_HELPER(PUNPCKHBH, punpckhbh);
4951 LMI_HELPER(PUNPCKLWD, punpcklwd);
4952 LMI_HELPER(PUNPCKHWD, punpckhwd);
4954 LMI_HELPER(PAVGH, pavgh);
4955 LMI_HELPER(PAVGB, pavgb);
4956 LMI_HELPER(PMAXSH, pmaxsh);
4957 LMI_HELPER(PMINSH, pminsh);
4958 LMI_HELPER(PMAXUB, pmaxub);
4959 LMI_HELPER(PMINUB, pminub);
4961 LMI_HELPER(PCMPEQW, pcmpeqw);
4962 LMI_HELPER(PCMPGTW, pcmpgtw);
4963 LMI_HELPER(PCMPEQH, pcmpeqh);
4964 LMI_HELPER(PCMPGTH, pcmpgth);
4965 LMI_HELPER(PCMPEQB, pcmpeqb);
4966 LMI_HELPER(PCMPGTB, pcmpgtb);
4968 LMI_HELPER(PSLLW, psllw);
4969 LMI_HELPER(PSLLH, psllh);
4970 LMI_HELPER(PSRLW, psrlw);
4971 LMI_HELPER(PSRLH, psrlh);
4972 LMI_HELPER(PSRAW, psraw);
4973 LMI_HELPER(PSRAH, psrah);
4975 LMI_HELPER(PMULLH, pmullh);
4976 LMI_HELPER(PMULHH, pmulhh);
4977 LMI_HELPER(PMULHUH, pmulhuh);
4978 LMI_HELPER(PMADDHW, pmaddhw);
4980 LMI_HELPER(PASUBUB, pasubub);
4981 LMI_HELPER_1(BIADD, biadd);
4982 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4984 LMI_DIRECT(PADDD, paddd, add);
4985 LMI_DIRECT(PSUBD, psubd, sub);
4986 LMI_DIRECT(XOR_CP2, xor, xor);
4987 LMI_DIRECT(NOR_CP2, nor, nor);
4988 LMI_DIRECT(AND_CP2, and, and);
4989 LMI_DIRECT(OR_CP2, or, or);
4991 case OPC_PANDN:
4992 tcg_gen_andc_i64(t0, t1, t0);
4993 break;
4995 case OPC_PINSRH_0:
4996 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4997 break;
4998 case OPC_PINSRH_1:
4999 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5000 break;
5001 case OPC_PINSRH_2:
5002 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5003 break;
5004 case OPC_PINSRH_3:
5005 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5006 break;
5008 case OPC_PEXTRH:
5009 tcg_gen_andi_i64(t1, t1, 3);
5010 tcg_gen_shli_i64(t1, t1, 4);
5011 tcg_gen_shr_i64(t0, t0, t1);
5012 tcg_gen_ext16u_i64(t0, t0);
5013 break;
5015 case OPC_ADDU_CP2:
5016 tcg_gen_add_i64(t0, t0, t1);
5017 tcg_gen_ext32s_i64(t0, t0);
5018 break;
5019 case OPC_SUBU_CP2:
5020 tcg_gen_sub_i64(t0, t0, t1);
5021 tcg_gen_ext32s_i64(t0, t0);
5022 break;
5024 case OPC_SLL_CP2:
5025 shift_max = 32;
5026 goto do_shift;
5027 case OPC_SRL_CP2:
5028 shift_max = 32;
5029 goto do_shift;
5030 case OPC_SRA_CP2:
5031 shift_max = 32;
5032 goto do_shift;
5033 case OPC_DSLL_CP2:
5034 shift_max = 64;
5035 goto do_shift;
5036 case OPC_DSRL_CP2:
5037 shift_max = 64;
5038 goto do_shift;
5039 case OPC_DSRA_CP2:
5040 shift_max = 64;
5041 goto do_shift;
5042 do_shift:
5043 /* Make sure shift count isn't TCG undefined behaviour. */
5044 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5046 switch (opc) {
5047 case OPC_SLL_CP2:
5048 case OPC_DSLL_CP2:
5049 tcg_gen_shl_i64(t0, t0, t1);
5050 break;
5051 case OPC_SRA_CP2:
5052 case OPC_DSRA_CP2:
5053 /* Since SRA is UndefinedResult without sign-extended inputs,
5054 we can treat SRA and DSRA the same. */
5055 tcg_gen_sar_i64(t0, t0, t1);
5056 break;
5057 case OPC_SRL_CP2:
5058 /* We want to shift in zeros for SRL; zero-extend first. */
5059 tcg_gen_ext32u_i64(t0, t0);
5060 /* FALLTHRU */
5061 case OPC_DSRL_CP2:
5062 tcg_gen_shr_i64(t0, t0, t1);
5063 break;
5066 if (shift_max == 32) {
5067 tcg_gen_ext32s_i64(t0, t0);
5070 /* Shifts larger than MAX produce zero. */
5071 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5072 tcg_gen_neg_i64(t1, t1);
5073 tcg_gen_and_i64(t0, t0, t1);
5074 break;
5076 case OPC_ADD_CP2:
5077 case OPC_DADD_CP2:
5079 TCGv_i64 t2 = tcg_temp_new_i64();
5080 TCGLabel *lab = gen_new_label();
5082 tcg_gen_mov_i64(t2, t0);
5083 tcg_gen_add_i64(t0, t1, t2);
5084 if (opc == OPC_ADD_CP2) {
5085 tcg_gen_ext32s_i64(t0, t0);
5087 tcg_gen_xor_i64(t1, t1, t2);
5088 tcg_gen_xor_i64(t2, t2, t0);
5089 tcg_gen_andc_i64(t1, t2, t1);
5090 tcg_temp_free_i64(t2);
5091 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5092 generate_exception(ctx, EXCP_OVERFLOW);
5093 gen_set_label(lab);
5094 break;
5097 case OPC_SUB_CP2:
5098 case OPC_DSUB_CP2:
5100 TCGv_i64 t2 = tcg_temp_new_i64();
5101 TCGLabel *lab = gen_new_label();
5103 tcg_gen_mov_i64(t2, t0);
5104 tcg_gen_sub_i64(t0, t1, t2);
5105 if (opc == OPC_SUB_CP2) {
5106 tcg_gen_ext32s_i64(t0, t0);
5108 tcg_gen_xor_i64(t1, t1, t2);
5109 tcg_gen_xor_i64(t2, t2, t0);
5110 tcg_gen_and_i64(t1, t1, t2);
5111 tcg_temp_free_i64(t2);
5112 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5113 generate_exception(ctx, EXCP_OVERFLOW);
5114 gen_set_label(lab);
5115 break;
5118 case OPC_PMULUW:
5119 tcg_gen_ext32u_i64(t0, t0);
5120 tcg_gen_ext32u_i64(t1, t1);
5121 tcg_gen_mul_i64(t0, t0, t1);
5122 break;
5124 case OPC_SEQU_CP2:
5125 case OPC_SEQ_CP2:
5126 case OPC_SLTU_CP2:
5127 case OPC_SLT_CP2:
5128 case OPC_SLEU_CP2:
5129 case OPC_SLE_CP2:
5130 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
5131 FD field is the CC field? */
5132 default:
5133 MIPS_INVAL("loongson_cp2");
5134 generate_exception_end(ctx, EXCP_RI);
5135 return;
5138 #undef LMI_HELPER
5139 #undef LMI_DIRECT
5141 gen_store_fpr64(ctx, t0, rd);
5143 tcg_temp_free_i64(t0);
5144 tcg_temp_free_i64(t1);
5147 /* Traps */
5148 static void gen_trap (DisasContext *ctx, uint32_t opc,
5149 int rs, int rt, int16_t imm)
5151 int cond;
5152 TCGv t0 = tcg_temp_new();
5153 TCGv t1 = tcg_temp_new();
5155 cond = 0;
5156 /* Load needed operands */
5157 switch (opc) {
5158 case OPC_TEQ:
5159 case OPC_TGE:
5160 case OPC_TGEU:
5161 case OPC_TLT:
5162 case OPC_TLTU:
5163 case OPC_TNE:
5164 /* Compare two registers */
5165 if (rs != rt) {
5166 gen_load_gpr(t0, rs);
5167 gen_load_gpr(t1, rt);
5168 cond = 1;
5170 break;
5171 case OPC_TEQI:
5172 case OPC_TGEI:
5173 case OPC_TGEIU:
5174 case OPC_TLTI:
5175 case OPC_TLTIU:
5176 case OPC_TNEI:
5177 /* Compare register to immediate */
5178 if (rs != 0 || imm != 0) {
5179 gen_load_gpr(t0, rs);
5180 tcg_gen_movi_tl(t1, (int32_t)imm);
5181 cond = 1;
5183 break;
5185 if (cond == 0) {
5186 switch (opc) {
5187 case OPC_TEQ: /* rs == rs */
5188 case OPC_TEQI: /* r0 == 0 */
5189 case OPC_TGE: /* rs >= rs */
5190 case OPC_TGEI: /* r0 >= 0 */
5191 case OPC_TGEU: /* rs >= rs unsigned */
5192 case OPC_TGEIU: /* r0 >= 0 unsigned */
5193 /* Always trap */
5194 generate_exception_end(ctx, EXCP_TRAP);
5195 break;
5196 case OPC_TLT: /* rs < rs */
5197 case OPC_TLTI: /* r0 < 0 */
5198 case OPC_TLTU: /* rs < rs unsigned */
5199 case OPC_TLTIU: /* r0 < 0 unsigned */
5200 case OPC_TNE: /* rs != rs */
5201 case OPC_TNEI: /* r0 != 0 */
5202 /* Never trap: treat as NOP. */
5203 break;
5205 } else {
5206 TCGLabel *l1 = gen_new_label();
5208 switch (opc) {
5209 case OPC_TEQ:
5210 case OPC_TEQI:
5211 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
5212 break;
5213 case OPC_TGE:
5214 case OPC_TGEI:
5215 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
5216 break;
5217 case OPC_TGEU:
5218 case OPC_TGEIU:
5219 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5220 break;
5221 case OPC_TLT:
5222 case OPC_TLTI:
5223 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5224 break;
5225 case OPC_TLTU:
5226 case OPC_TLTIU:
5227 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5228 break;
5229 case OPC_TNE:
5230 case OPC_TNEI:
5231 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5232 break;
5234 generate_exception(ctx, EXCP_TRAP);
5235 gen_set_label(l1);
5237 tcg_temp_free(t0);
5238 tcg_temp_free(t1);
5241 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5243 if (unlikely(ctx->base.singlestep_enabled)) {
5244 return false;
5247 #ifndef CONFIG_USER_ONLY
5248 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5249 #else
5250 return true;
5251 #endif
5254 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5256 if (use_goto_tb(ctx, dest)) {
5257 tcg_gen_goto_tb(n);
5258 gen_save_pc(dest);
5259 tcg_gen_exit_tb(ctx->base.tb, n);
5260 } else {
5261 gen_save_pc(dest);
5262 if (ctx->base.singlestep_enabled) {
5263 save_cpu_state(ctx, 0);
5264 gen_helper_raise_exception_debug(cpu_env);
5266 tcg_gen_lookup_and_goto_ptr();
5270 /* Branches (before delay slot) */
5271 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
5272 int insn_bytes,
5273 int rs, int rt, int32_t offset,
5274 int delayslot_size)
5276 target_ulong btgt = -1;
5277 int blink = 0;
5278 int bcond_compute = 0;
5279 TCGv t0 = tcg_temp_new();
5280 TCGv t1 = tcg_temp_new();
5282 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5283 #ifdef MIPS_DEBUG_DISAS
5284 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5285 TARGET_FMT_lx "\n", ctx->base.pc_next);
5286 #endif
5287 generate_exception_end(ctx, EXCP_RI);
5288 goto out;
5291 /* Load needed operands */
5292 switch (opc) {
5293 case OPC_BEQ:
5294 case OPC_BEQL:
5295 case OPC_BNE:
5296 case OPC_BNEL:
5297 /* Compare two registers */
5298 if (rs != rt) {
5299 gen_load_gpr(t0, rs);
5300 gen_load_gpr(t1, rt);
5301 bcond_compute = 1;
5303 btgt = ctx->base.pc_next + insn_bytes + offset;
5304 break;
5305 case OPC_BGEZ:
5306 case OPC_BGEZAL:
5307 case OPC_BGEZALL:
5308 case OPC_BGEZL:
5309 case OPC_BGTZ:
5310 case OPC_BGTZL:
5311 case OPC_BLEZ:
5312 case OPC_BLEZL:
5313 case OPC_BLTZ:
5314 case OPC_BLTZAL:
5315 case OPC_BLTZALL:
5316 case OPC_BLTZL:
5317 /* Compare to zero */
5318 if (rs != 0) {
5319 gen_load_gpr(t0, rs);
5320 bcond_compute = 1;
5322 btgt = ctx->base.pc_next + insn_bytes + offset;
5323 break;
5324 case OPC_BPOSGE32:
5325 #if defined(TARGET_MIPS64)
5326 case OPC_BPOSGE64:
5327 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5328 #else
5329 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5330 #endif
5331 bcond_compute = 1;
5332 btgt = ctx->base.pc_next + insn_bytes + offset;
5333 break;
5334 case OPC_J:
5335 case OPC_JAL:
5336 case OPC_JALX:
5337 /* Jump to immediate */
5338 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5339 (uint32_t)offset;
5340 break;
5341 case OPC_JR:
5342 case OPC_JALR:
5343 /* Jump to register */
5344 if (offset != 0 && offset != 16) {
5345 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5346 others are reserved. */
5347 MIPS_INVAL("jump hint");
5348 generate_exception_end(ctx, EXCP_RI);
5349 goto out;
5351 gen_load_gpr(btarget, rs);
5352 break;
5353 default:
5354 MIPS_INVAL("branch/jump");
5355 generate_exception_end(ctx, EXCP_RI);
5356 goto out;
5358 if (bcond_compute == 0) {
5359 /* No condition to be computed */
5360 switch (opc) {
5361 case OPC_BEQ: /* rx == rx */
5362 case OPC_BEQL: /* rx == rx likely */
5363 case OPC_BGEZ: /* 0 >= 0 */
5364 case OPC_BGEZL: /* 0 >= 0 likely */
5365 case OPC_BLEZ: /* 0 <= 0 */
5366 case OPC_BLEZL: /* 0 <= 0 likely */
5367 /* Always take */
5368 ctx->hflags |= MIPS_HFLAG_B;
5369 break;
5370 case OPC_BGEZAL: /* 0 >= 0 */
5371 case OPC_BGEZALL: /* 0 >= 0 likely */
5372 /* Always take and link */
5373 blink = 31;
5374 ctx->hflags |= MIPS_HFLAG_B;
5375 break;
5376 case OPC_BNE: /* rx != rx */
5377 case OPC_BGTZ: /* 0 > 0 */
5378 case OPC_BLTZ: /* 0 < 0 */
5379 /* Treat as NOP. */
5380 goto out;
5381 case OPC_BLTZAL: /* 0 < 0 */
5382 /* Handle as an unconditional branch to get correct delay
5383 slot checking. */
5384 blink = 31;
5385 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5386 ctx->hflags |= MIPS_HFLAG_B;
5387 break;
5388 case OPC_BLTZALL: /* 0 < 0 likely */
5389 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5390 /* Skip the instruction in the delay slot */
5391 ctx->base.pc_next += 4;
5392 goto out;
5393 case OPC_BNEL: /* rx != rx likely */
5394 case OPC_BGTZL: /* 0 > 0 likely */
5395 case OPC_BLTZL: /* 0 < 0 likely */
5396 /* Skip the instruction in the delay slot */
5397 ctx->base.pc_next += 4;
5398 goto out;
5399 case OPC_J:
5400 ctx->hflags |= MIPS_HFLAG_B;
5401 break;
5402 case OPC_JALX:
5403 ctx->hflags |= MIPS_HFLAG_BX;
5404 /* Fallthrough */
5405 case OPC_JAL:
5406 blink = 31;
5407 ctx->hflags |= MIPS_HFLAG_B;
5408 break;
5409 case OPC_JR:
5410 ctx->hflags |= MIPS_HFLAG_BR;
5411 break;
5412 case OPC_JALR:
5413 blink = rt;
5414 ctx->hflags |= MIPS_HFLAG_BR;
5415 break;
5416 default:
5417 MIPS_INVAL("branch/jump");
5418 generate_exception_end(ctx, EXCP_RI);
5419 goto out;
5421 } else {
5422 switch (opc) {
5423 case OPC_BEQ:
5424 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5425 goto not_likely;
5426 case OPC_BEQL:
5427 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5428 goto likely;
5429 case OPC_BNE:
5430 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5431 goto not_likely;
5432 case OPC_BNEL:
5433 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5434 goto likely;
5435 case OPC_BGEZ:
5436 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5437 goto not_likely;
5438 case OPC_BGEZL:
5439 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5440 goto likely;
5441 case OPC_BGEZAL:
5442 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5443 blink = 31;
5444 goto not_likely;
5445 case OPC_BGEZALL:
5446 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5447 blink = 31;
5448 goto likely;
5449 case OPC_BGTZ:
5450 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5451 goto not_likely;
5452 case OPC_BGTZL:
5453 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5454 goto likely;
5455 case OPC_BLEZ:
5456 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5457 goto not_likely;
5458 case OPC_BLEZL:
5459 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5460 goto likely;
5461 case OPC_BLTZ:
5462 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5463 goto not_likely;
5464 case OPC_BLTZL:
5465 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5466 goto likely;
5467 case OPC_BPOSGE32:
5468 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5469 goto not_likely;
5470 #if defined(TARGET_MIPS64)
5471 case OPC_BPOSGE64:
5472 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5473 goto not_likely;
5474 #endif
5475 case OPC_BLTZAL:
5476 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5477 blink = 31;
5478 not_likely:
5479 ctx->hflags |= MIPS_HFLAG_BC;
5480 break;
5481 case OPC_BLTZALL:
5482 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5483 blink = 31;
5484 likely:
5485 ctx->hflags |= MIPS_HFLAG_BL;
5486 break;
5487 default:
5488 MIPS_INVAL("conditional branch/jump");
5489 generate_exception_end(ctx, EXCP_RI);
5490 goto out;
5494 ctx->btarget = btgt;
5496 switch (delayslot_size) {
5497 case 2:
5498 ctx->hflags |= MIPS_HFLAG_BDS16;
5499 break;
5500 case 4:
5501 ctx->hflags |= MIPS_HFLAG_BDS32;
5502 break;
5505 if (blink > 0) {
5506 int post_delay = insn_bytes + delayslot_size;
5507 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5509 tcg_gen_movi_tl(cpu_gpr[blink],
5510 ctx->base.pc_next + post_delay + lowbit);
5513 out:
5514 if (insn_bytes == 2)
5515 ctx->hflags |= MIPS_HFLAG_B16;
5516 tcg_temp_free(t0);
5517 tcg_temp_free(t1);
5521 /* nanoMIPS Branches */
5522 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5523 int insn_bytes,
5524 int rs, int rt, int32_t offset)
5526 target_ulong btgt = -1;
5527 int bcond_compute = 0;
5528 TCGv t0 = tcg_temp_new();
5529 TCGv t1 = tcg_temp_new();
5531 /* Load needed operands */
5532 switch (opc) {
5533 case OPC_BEQ:
5534 case OPC_BNE:
5535 /* Compare two registers */
5536 if (rs != rt) {
5537 gen_load_gpr(t0, rs);
5538 gen_load_gpr(t1, rt);
5539 bcond_compute = 1;
5541 btgt = ctx->base.pc_next + insn_bytes + offset;
5542 break;
5543 case OPC_BGEZAL:
5544 /* Compare to zero */
5545 if (rs != 0) {
5546 gen_load_gpr(t0, rs);
5547 bcond_compute = 1;
5549 btgt = ctx->base.pc_next + insn_bytes + offset;
5550 break;
5551 case OPC_BPOSGE32:
5552 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5553 bcond_compute = 1;
5554 btgt = ctx->base.pc_next + insn_bytes + offset;
5555 break;
5556 case OPC_JR:
5557 case OPC_JALR:
5558 /* Jump to register */
5559 if (offset != 0 && offset != 16) {
5560 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5561 others are reserved. */
5562 MIPS_INVAL("jump hint");
5563 generate_exception_end(ctx, EXCP_RI);
5564 goto out;
5566 gen_load_gpr(btarget, rs);
5567 break;
5568 default:
5569 MIPS_INVAL("branch/jump");
5570 generate_exception_end(ctx, EXCP_RI);
5571 goto out;
5573 if (bcond_compute == 0) {
5574 /* No condition to be computed */
5575 switch (opc) {
5576 case OPC_BEQ: /* rx == rx */
5577 /* Always take */
5578 ctx->hflags |= MIPS_HFLAG_B;
5579 break;
5580 case OPC_BGEZAL: /* 0 >= 0 */
5581 /* Always take and link */
5582 tcg_gen_movi_tl(cpu_gpr[31],
5583 ctx->base.pc_next + insn_bytes);
5584 ctx->hflags |= MIPS_HFLAG_B;
5585 break;
5586 case OPC_BNE: /* rx != rx */
5587 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5588 /* Skip the instruction in the delay slot */
5589 ctx->base.pc_next += 4;
5590 goto out;
5591 case OPC_JR:
5592 ctx->hflags |= MIPS_HFLAG_BR;
5593 break;
5594 case OPC_JALR:
5595 if (rt > 0) {
5596 tcg_gen_movi_tl(cpu_gpr[rt],
5597 ctx->base.pc_next + insn_bytes);
5599 ctx->hflags |= MIPS_HFLAG_BR;
5600 break;
5601 default:
5602 MIPS_INVAL("branch/jump");
5603 generate_exception_end(ctx, EXCP_RI);
5604 goto out;
5606 } else {
5607 switch (opc) {
5608 case OPC_BEQ:
5609 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5610 goto not_likely;
5611 case OPC_BNE:
5612 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5613 goto not_likely;
5614 case OPC_BGEZAL:
5615 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5616 tcg_gen_movi_tl(cpu_gpr[31],
5617 ctx->base.pc_next + insn_bytes);
5618 goto not_likely;
5619 case OPC_BPOSGE32:
5620 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5621 not_likely:
5622 ctx->hflags |= MIPS_HFLAG_BC;
5623 break;
5624 default:
5625 MIPS_INVAL("conditional branch/jump");
5626 generate_exception_end(ctx, EXCP_RI);
5627 goto out;
5631 ctx->btarget = btgt;
5633 out:
5634 if (insn_bytes == 2) {
5635 ctx->hflags |= MIPS_HFLAG_B16;
5637 tcg_temp_free(t0);
5638 tcg_temp_free(t1);
5642 /* special3 bitfield operations */
5643 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
5644 int rs, int lsb, int msb)
5646 TCGv t0 = tcg_temp_new();
5647 TCGv t1 = tcg_temp_new();
5649 gen_load_gpr(t1, rs);
5650 switch (opc) {
5651 case OPC_EXT:
5652 if (lsb + msb > 31) {
5653 goto fail;
5655 if (msb != 31) {
5656 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5657 } else {
5658 /* The two checks together imply that lsb == 0,
5659 so this is a simple sign-extension. */
5660 tcg_gen_ext32s_tl(t0, t1);
5662 break;
5663 #if defined(TARGET_MIPS64)
5664 case OPC_DEXTU:
5665 lsb += 32;
5666 goto do_dext;
5667 case OPC_DEXTM:
5668 msb += 32;
5669 goto do_dext;
5670 case OPC_DEXT:
5671 do_dext:
5672 if (lsb + msb > 63) {
5673 goto fail;
5675 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5676 break;
5677 #endif
5678 case OPC_INS:
5679 if (lsb > msb) {
5680 goto fail;
5682 gen_load_gpr(t0, rt);
5683 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5684 tcg_gen_ext32s_tl(t0, t0);
5685 break;
5686 #if defined(TARGET_MIPS64)
5687 case OPC_DINSU:
5688 lsb += 32;
5689 /* FALLTHRU */
5690 case OPC_DINSM:
5691 msb += 32;
5692 /* FALLTHRU */
5693 case OPC_DINS:
5694 if (lsb > msb) {
5695 goto fail;
5697 gen_load_gpr(t0, rt);
5698 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5699 break;
5700 #endif
5701 default:
5702 fail:
5703 MIPS_INVAL("bitops");
5704 generate_exception_end(ctx, EXCP_RI);
5705 tcg_temp_free(t0);
5706 tcg_temp_free(t1);
5707 return;
5709 gen_store_gpr(t0, rt);
5710 tcg_temp_free(t0);
5711 tcg_temp_free(t1);
5714 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
5716 TCGv t0;
5718 if (rd == 0) {
5719 /* If no destination, treat it as a NOP. */
5720 return;
5723 t0 = tcg_temp_new();
5724 gen_load_gpr(t0, rt);
5725 switch (op2) {
5726 case OPC_WSBH:
5728 TCGv t1 = tcg_temp_new();
5729 TCGv t2 = tcg_const_tl(0x00FF00FF);
5731 tcg_gen_shri_tl(t1, t0, 8);
5732 tcg_gen_and_tl(t1, t1, t2);
5733 tcg_gen_and_tl(t0, t0, t2);
5734 tcg_gen_shli_tl(t0, t0, 8);
5735 tcg_gen_or_tl(t0, t0, t1);
5736 tcg_temp_free(t2);
5737 tcg_temp_free(t1);
5738 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5740 break;
5741 case OPC_SEB:
5742 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5743 break;
5744 case OPC_SEH:
5745 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5746 break;
5747 #if defined(TARGET_MIPS64)
5748 case OPC_DSBH:
5750 TCGv t1 = tcg_temp_new();
5751 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5753 tcg_gen_shri_tl(t1, t0, 8);
5754 tcg_gen_and_tl(t1, t1, t2);
5755 tcg_gen_and_tl(t0, t0, t2);
5756 tcg_gen_shli_tl(t0, t0, 8);
5757 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5758 tcg_temp_free(t2);
5759 tcg_temp_free(t1);
5761 break;
5762 case OPC_DSHD:
5764 TCGv t1 = tcg_temp_new();
5765 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5767 tcg_gen_shri_tl(t1, t0, 16);
5768 tcg_gen_and_tl(t1, t1, t2);
5769 tcg_gen_and_tl(t0, t0, t2);
5770 tcg_gen_shli_tl(t0, t0, 16);
5771 tcg_gen_or_tl(t0, t0, t1);
5772 tcg_gen_shri_tl(t1, t0, 32);
5773 tcg_gen_shli_tl(t0, t0, 32);
5774 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5775 tcg_temp_free(t2);
5776 tcg_temp_free(t1);
5778 break;
5779 #endif
5780 default:
5781 MIPS_INVAL("bsfhl");
5782 generate_exception_end(ctx, EXCP_RI);
5783 tcg_temp_free(t0);
5784 return;
5786 tcg_temp_free(t0);
5789 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
5790 int imm2)
5792 TCGv t0;
5793 TCGv t1;
5794 if (rd == 0) {
5795 /* Treat as NOP. */
5796 return;
5798 t0 = tcg_temp_new();
5799 t1 = tcg_temp_new();
5800 gen_load_gpr(t0, rs);
5801 gen_load_gpr(t1, rt);
5802 tcg_gen_shli_tl(t0, t0, imm2 + 1);
5803 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
5804 if (opc == OPC_LSA) {
5805 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5808 tcg_temp_free(t1);
5809 tcg_temp_free(t0);
5811 return;
5814 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5815 int rt, int bits)
5817 TCGv t0;
5818 if (rd == 0) {
5819 /* Treat as NOP. */
5820 return;
5822 t0 = tcg_temp_new();
5823 if (bits == 0 || bits == wordsz) {
5824 if (bits == 0) {
5825 gen_load_gpr(t0, rt);
5826 } else {
5827 gen_load_gpr(t0, rs);
5829 switch (wordsz) {
5830 case 32:
5831 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5832 break;
5833 #if defined(TARGET_MIPS64)
5834 case 64:
5835 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5836 break;
5837 #endif
5839 } else {
5840 TCGv t1 = tcg_temp_new();
5841 gen_load_gpr(t0, rt);
5842 gen_load_gpr(t1, rs);
5843 switch (wordsz) {
5844 case 32:
5846 TCGv_i64 t2 = tcg_temp_new_i64();
5847 tcg_gen_concat_tl_i64(t2, t1, t0);
5848 tcg_gen_shri_i64(t2, t2, 32 - bits);
5849 gen_move_low32(cpu_gpr[rd], t2);
5850 tcg_temp_free_i64(t2);
5852 break;
5853 #if defined(TARGET_MIPS64)
5854 case 64:
5855 tcg_gen_shli_tl(t0, t0, bits);
5856 tcg_gen_shri_tl(t1, t1, 64 - bits);
5857 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5858 break;
5859 #endif
5861 tcg_temp_free(t1);
5864 tcg_temp_free(t0);
5867 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5868 int bp)
5870 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5873 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5874 int shift)
5876 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5879 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5881 TCGv t0;
5882 if (rd == 0) {
5883 /* Treat as NOP. */
5884 return;
5886 t0 = tcg_temp_new();
5887 gen_load_gpr(t0, rt);
5888 switch (opc) {
5889 case OPC_BITSWAP:
5890 gen_helper_bitswap(cpu_gpr[rd], t0);
5891 break;
5892 #if defined(TARGET_MIPS64)
5893 case OPC_DBITSWAP:
5894 gen_helper_dbitswap(cpu_gpr[rd], t0);
5895 break;
5896 #endif
5898 tcg_temp_free(t0);
5901 #ifndef CONFIG_USER_ONLY
5902 /* CP0 (MMU and control) */
5903 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5905 TCGv_i64 t0 = tcg_temp_new_i64();
5906 TCGv_i64 t1 = tcg_temp_new_i64();
5908 tcg_gen_ext_tl_i64(t0, arg);
5909 tcg_gen_ld_i64(t1, cpu_env, off);
5910 #if defined(TARGET_MIPS64)
5911 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5912 #else
5913 tcg_gen_concat32_i64(t1, t1, t0);
5914 #endif
5915 tcg_gen_st_i64(t1, cpu_env, off);
5916 tcg_temp_free_i64(t1);
5917 tcg_temp_free_i64(t0);
5920 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5922 TCGv_i64 t0 = tcg_temp_new_i64();
5923 TCGv_i64 t1 = tcg_temp_new_i64();
5925 tcg_gen_ext_tl_i64(t0, arg);
5926 tcg_gen_ld_i64(t1, cpu_env, off);
5927 tcg_gen_concat32_i64(t1, t1, t0);
5928 tcg_gen_st_i64(t1, cpu_env, off);
5929 tcg_temp_free_i64(t1);
5930 tcg_temp_free_i64(t0);
5933 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5935 TCGv_i64 t0 = tcg_temp_new_i64();
5937 tcg_gen_ld_i64(t0, cpu_env, off);
5938 #if defined(TARGET_MIPS64)
5939 tcg_gen_shri_i64(t0, t0, 30);
5940 #else
5941 tcg_gen_shri_i64(t0, t0, 32);
5942 #endif
5943 gen_move_low32(arg, t0);
5944 tcg_temp_free_i64(t0);
5947 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5949 TCGv_i64 t0 = tcg_temp_new_i64();
5951 tcg_gen_ld_i64(t0, cpu_env, off);
5952 tcg_gen_shri_i64(t0, t0, 32 + shift);
5953 gen_move_low32(arg, t0);
5954 tcg_temp_free_i64(t0);
5957 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
5959 TCGv_i32 t0 = tcg_temp_new_i32();
5961 tcg_gen_ld_i32(t0, cpu_env, off);
5962 tcg_gen_ext_i32_tl(arg, t0);
5963 tcg_temp_free_i32(t0);
5966 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
5968 tcg_gen_ld_tl(arg, cpu_env, off);
5969 tcg_gen_ext32s_tl(arg, arg);
5972 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
5974 TCGv_i32 t0 = tcg_temp_new_i32();
5976 tcg_gen_trunc_tl_i32(t0, arg);
5977 tcg_gen_st_i32(t0, cpu_env, off);
5978 tcg_temp_free_i32(t0);
5981 #define CP0_CHECK(c) \
5982 do { \
5983 if (!(c)) { \
5984 goto cp0_unimplemented; \
5986 } while (0)
5988 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5990 const char *rn = "invalid";
5992 switch (reg) {
5993 case 2:
5994 switch (sel) {
5995 case 0:
5996 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5997 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5998 rn = "EntryLo0";
5999 break;
6000 default:
6001 goto cp0_unimplemented;
6003 break;
6004 case 3:
6005 switch (sel) {
6006 case 0:
6007 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6008 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6009 rn = "EntryLo1";
6010 break;
6011 default:
6012 goto cp0_unimplemented;
6014 break;
6015 case 17:
6016 switch (sel) {
6017 case 0:
6018 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
6019 ctx->CP0_LLAddr_shift);
6020 rn = "LLAddr";
6021 break;
6022 case 1:
6023 CP0_CHECK(ctx->mrp);
6024 gen_helper_mfhc0_maar(arg, cpu_env);
6025 rn = "MAAR";
6026 break;
6027 default:
6028 goto cp0_unimplemented;
6030 break;
6031 case 28:
6032 switch (sel) {
6033 case 0:
6034 case 2:
6035 case 4:
6036 case 6:
6037 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
6038 rn = "TagLo";
6039 break;
6040 default:
6041 goto cp0_unimplemented;
6043 break;
6044 default:
6045 goto cp0_unimplemented;
6047 trace_mips_translate_c0("mfhc0", rn, reg, sel);
6048 return;
6050 cp0_unimplemented:
6051 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
6052 tcg_gen_movi_tl(arg, 0);
6055 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6057 const char *rn = "invalid";
6058 uint64_t mask = ctx->PAMask >> 36;
6060 switch (reg) {
6061 case 2:
6062 switch (sel) {
6063 case 0:
6064 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6065 tcg_gen_andi_tl(arg, arg, mask);
6066 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
6067 rn = "EntryLo0";
6068 break;
6069 default:
6070 goto cp0_unimplemented;
6072 break;
6073 case 3:
6074 switch (sel) {
6075 case 0:
6076 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
6077 tcg_gen_andi_tl(arg, arg, mask);
6078 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
6079 rn = "EntryLo1";
6080 break;
6081 default:
6082 goto cp0_unimplemented;
6084 break;
6085 case 17:
6086 switch (sel) {
6087 case 0:
6088 /* LLAddr is read-only (the only exception is bit 0 if LLB is
6089 supported); the CP0_LLAddr_rw_bitmask does not seem to be
6090 relevant for modern MIPS cores supporting MTHC0, therefore
6091 treating MTHC0 to LLAddr as NOP. */
6092 rn = "LLAddr";
6093 break;
6094 case 1:
6095 CP0_CHECK(ctx->mrp);
6096 gen_helper_mthc0_maar(cpu_env, arg);
6097 rn = "MAAR";
6098 break;
6099 default:
6100 goto cp0_unimplemented;
6102 break;
6103 case 28:
6104 switch (sel) {
6105 case 0:
6106 case 2:
6107 case 4:
6108 case 6:
6109 tcg_gen_andi_tl(arg, arg, mask);
6110 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
6111 rn = "TagLo";
6112 break;
6113 default:
6114 goto cp0_unimplemented;
6116 break;
6117 default:
6118 goto cp0_unimplemented;
6120 trace_mips_translate_c0("mthc0", rn, reg, sel);
6122 cp0_unimplemented:
6123 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
6126 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
6128 if (ctx->insn_flags & ISA_MIPS32R6) {
6129 tcg_gen_movi_tl(arg, 0);
6130 } else {
6131 tcg_gen_movi_tl(arg, ~0);
6135 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6137 const char *rn = "invalid";
6139 if (sel != 0)
6140 check_insn(ctx, ISA_MIPS32);
6142 switch (reg) {
6143 case 0:
6144 switch (sel) {
6145 case 0:
6146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6147 rn = "Index";
6148 break;
6149 case 1:
6150 CP0_CHECK(ctx->insn_flags & ASE_MT);
6151 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6152 rn = "MVPControl";
6153 break;
6154 case 2:
6155 CP0_CHECK(ctx->insn_flags & ASE_MT);
6156 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6157 rn = "MVPConf0";
6158 break;
6159 case 3:
6160 CP0_CHECK(ctx->insn_flags & ASE_MT);
6161 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6162 rn = "MVPConf1";
6163 break;
6164 case 4:
6165 CP0_CHECK(ctx->vp);
6166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6167 rn = "VPControl";
6168 break;
6169 default:
6170 goto cp0_unimplemented;
6172 break;
6173 case 1:
6174 switch (sel) {
6175 case 0:
6176 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6177 gen_helper_mfc0_random(arg, cpu_env);
6178 rn = "Random";
6179 break;
6180 case 1:
6181 CP0_CHECK(ctx->insn_flags & ASE_MT);
6182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6183 rn = "VPEControl";
6184 break;
6185 case 2:
6186 CP0_CHECK(ctx->insn_flags & ASE_MT);
6187 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6188 rn = "VPEConf0";
6189 break;
6190 case 3:
6191 CP0_CHECK(ctx->insn_flags & ASE_MT);
6192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6193 rn = "VPEConf1";
6194 break;
6195 case 4:
6196 CP0_CHECK(ctx->insn_flags & ASE_MT);
6197 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6198 rn = "YQMask";
6199 break;
6200 case 5:
6201 CP0_CHECK(ctx->insn_flags & ASE_MT);
6202 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6203 rn = "VPESchedule";
6204 break;
6205 case 6:
6206 CP0_CHECK(ctx->insn_flags & ASE_MT);
6207 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6208 rn = "VPEScheFBack";
6209 break;
6210 case 7:
6211 CP0_CHECK(ctx->insn_flags & ASE_MT);
6212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6213 rn = "VPEOpt";
6214 break;
6215 default:
6216 goto cp0_unimplemented;
6218 break;
6219 case 2:
6220 switch (sel) {
6221 case 0:
6223 TCGv_i64 tmp = tcg_temp_new_i64();
6224 tcg_gen_ld_i64(tmp, cpu_env,
6225 offsetof(CPUMIPSState, CP0_EntryLo0));
6226 #if defined(TARGET_MIPS64)
6227 if (ctx->rxi) {
6228 /* Move RI/XI fields to bits 31:30 */
6229 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6230 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6232 #endif
6233 gen_move_low32(arg, tmp);
6234 tcg_temp_free_i64(tmp);
6236 rn = "EntryLo0";
6237 break;
6238 case 1:
6239 CP0_CHECK(ctx->insn_flags & ASE_MT);
6240 gen_helper_mfc0_tcstatus(arg, cpu_env);
6241 rn = "TCStatus";
6242 break;
6243 case 2:
6244 CP0_CHECK(ctx->insn_flags & ASE_MT);
6245 gen_helper_mfc0_tcbind(arg, cpu_env);
6246 rn = "TCBind";
6247 break;
6248 case 3:
6249 CP0_CHECK(ctx->insn_flags & ASE_MT);
6250 gen_helper_mfc0_tcrestart(arg, cpu_env);
6251 rn = "TCRestart";
6252 break;
6253 case 4:
6254 CP0_CHECK(ctx->insn_flags & ASE_MT);
6255 gen_helper_mfc0_tchalt(arg, cpu_env);
6256 rn = "TCHalt";
6257 break;
6258 case 5:
6259 CP0_CHECK(ctx->insn_flags & ASE_MT);
6260 gen_helper_mfc0_tccontext(arg, cpu_env);
6261 rn = "TCContext";
6262 break;
6263 case 6:
6264 CP0_CHECK(ctx->insn_flags & ASE_MT);
6265 gen_helper_mfc0_tcschedule(arg, cpu_env);
6266 rn = "TCSchedule";
6267 break;
6268 case 7:
6269 CP0_CHECK(ctx->insn_flags & ASE_MT);
6270 gen_helper_mfc0_tcschefback(arg, cpu_env);
6271 rn = "TCScheFBack";
6272 break;
6273 default:
6274 goto cp0_unimplemented;
6276 break;
6277 case 3:
6278 switch (sel) {
6279 case 0:
6281 TCGv_i64 tmp = tcg_temp_new_i64();
6282 tcg_gen_ld_i64(tmp, cpu_env,
6283 offsetof(CPUMIPSState, CP0_EntryLo1));
6284 #if defined(TARGET_MIPS64)
6285 if (ctx->rxi) {
6286 /* Move RI/XI fields to bits 31:30 */
6287 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6288 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6290 #endif
6291 gen_move_low32(arg, tmp);
6292 tcg_temp_free_i64(tmp);
6294 rn = "EntryLo1";
6295 break;
6296 case 1:
6297 CP0_CHECK(ctx->vp);
6298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6299 rn = "GlobalNumber";
6300 break;
6301 default:
6302 goto cp0_unimplemented;
6304 break;
6305 case 4:
6306 switch (sel) {
6307 case 0:
6308 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6309 tcg_gen_ext32s_tl(arg, arg);
6310 rn = "Context";
6311 break;
6312 case 1:
6313 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
6314 rn = "ContextConfig";
6315 goto cp0_unimplemented;
6316 case 2:
6317 CP0_CHECK(ctx->ulri);
6318 tcg_gen_ld_tl(arg, cpu_env,
6319 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6320 tcg_gen_ext32s_tl(arg, arg);
6321 rn = "UserLocal";
6322 break;
6323 default:
6324 goto cp0_unimplemented;
6326 break;
6327 case 5:
6328 switch (sel) {
6329 case 0:
6330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6331 rn = "PageMask";
6332 break;
6333 case 1:
6334 check_insn(ctx, ISA_MIPS32R2);
6335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6336 rn = "PageGrain";
6337 break;
6338 case 2:
6339 CP0_CHECK(ctx->sc);
6340 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6341 tcg_gen_ext32s_tl(arg, arg);
6342 rn = "SegCtl0";
6343 break;
6344 case 3:
6345 CP0_CHECK(ctx->sc);
6346 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6347 tcg_gen_ext32s_tl(arg, arg);
6348 rn = "SegCtl1";
6349 break;
6350 case 4:
6351 CP0_CHECK(ctx->sc);
6352 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6353 tcg_gen_ext32s_tl(arg, arg);
6354 rn = "SegCtl2";
6355 break;
6356 case 5:
6357 check_pw(ctx);
6358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6359 rn = "PWBase";
6360 break;
6361 case 6:
6362 check_pw(ctx);
6363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6364 rn = "PWField";
6365 break;
6366 case 7:
6367 check_pw(ctx);
6368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6369 rn = "PWSize";
6370 break;
6371 default:
6372 goto cp0_unimplemented;
6374 break;
6375 case 6:
6376 switch (sel) {
6377 case 0:
6378 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6379 rn = "Wired";
6380 break;
6381 case 1:
6382 check_insn(ctx, ISA_MIPS32R2);
6383 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6384 rn = "SRSConf0";
6385 break;
6386 case 2:
6387 check_insn(ctx, ISA_MIPS32R2);
6388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6389 rn = "SRSConf1";
6390 break;
6391 case 3:
6392 check_insn(ctx, ISA_MIPS32R2);
6393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6394 rn = "SRSConf2";
6395 break;
6396 case 4:
6397 check_insn(ctx, ISA_MIPS32R2);
6398 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6399 rn = "SRSConf3";
6400 break;
6401 case 5:
6402 check_insn(ctx, ISA_MIPS32R2);
6403 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6404 rn = "SRSConf4";
6405 break;
6406 case 6:
6407 check_pw(ctx);
6408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6409 rn = "PWCtl";
6410 break;
6411 default:
6412 goto cp0_unimplemented;
6414 break;
6415 case 7:
6416 switch (sel) {
6417 case 0:
6418 check_insn(ctx, ISA_MIPS32R2);
6419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6420 rn = "HWREna";
6421 break;
6422 default:
6423 goto cp0_unimplemented;
6425 break;
6426 case 8:
6427 switch (sel) {
6428 case 0:
6429 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6430 tcg_gen_ext32s_tl(arg, arg);
6431 rn = "BadVAddr";
6432 break;
6433 case 1:
6434 CP0_CHECK(ctx->bi);
6435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6436 rn = "BadInstr";
6437 break;
6438 case 2:
6439 CP0_CHECK(ctx->bp);
6440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6441 rn = "BadInstrP";
6442 break;
6443 case 3:
6444 CP0_CHECK(ctx->bi);
6445 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6446 tcg_gen_andi_tl(arg, arg, ~0xffff);
6447 rn = "BadInstrX";
6448 break;
6449 default:
6450 goto cp0_unimplemented;
6452 break;
6453 case 9:
6454 switch (sel) {
6455 case 0:
6456 /* Mark as an IO operation because we read the time. */
6457 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6458 gen_io_start();
6460 gen_helper_mfc0_count(arg, cpu_env);
6461 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6462 gen_io_end();
6464 /* Break the TB to be able to take timer interrupts immediately
6465 after reading count. DISAS_STOP isn't sufficient, we need to
6466 ensure we break completely out of translated code. */
6467 gen_save_pc(ctx->base.pc_next + 4);
6468 ctx->base.is_jmp = DISAS_EXIT;
6469 rn = "Count";
6470 break;
6471 /* 6,7 are implementation dependent */
6472 default:
6473 goto cp0_unimplemented;
6475 break;
6476 case 10:
6477 switch (sel) {
6478 case 0:
6479 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6480 tcg_gen_ext32s_tl(arg, arg);
6481 rn = "EntryHi";
6482 break;
6483 default:
6484 goto cp0_unimplemented;
6486 break;
6487 case 11:
6488 switch (sel) {
6489 case 0:
6490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6491 rn = "Compare";
6492 break;
6493 /* 6,7 are implementation dependent */
6494 default:
6495 goto cp0_unimplemented;
6497 break;
6498 case 12:
6499 switch (sel) {
6500 case 0:
6501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6502 rn = "Status";
6503 break;
6504 case 1:
6505 check_insn(ctx, ISA_MIPS32R2);
6506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6507 rn = "IntCtl";
6508 break;
6509 case 2:
6510 check_insn(ctx, ISA_MIPS32R2);
6511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6512 rn = "SRSCtl";
6513 break;
6514 case 3:
6515 check_insn(ctx, ISA_MIPS32R2);
6516 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6517 rn = "SRSMap";
6518 break;
6519 default:
6520 goto cp0_unimplemented;
6522 break;
6523 case 13:
6524 switch (sel) {
6525 case 0:
6526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6527 rn = "Cause";
6528 break;
6529 default:
6530 goto cp0_unimplemented;
6532 break;
6533 case 14:
6534 switch (sel) {
6535 case 0:
6536 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6537 tcg_gen_ext32s_tl(arg, arg);
6538 rn = "EPC";
6539 break;
6540 default:
6541 goto cp0_unimplemented;
6543 break;
6544 case 15:
6545 switch (sel) {
6546 case 0:
6547 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6548 rn = "PRid";
6549 break;
6550 case 1:
6551 check_insn(ctx, ISA_MIPS32R2);
6552 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6553 tcg_gen_ext32s_tl(arg, arg);
6554 rn = "EBase";
6555 break;
6556 case 3:
6557 check_insn(ctx, ISA_MIPS32R2);
6558 CP0_CHECK(ctx->cmgcr);
6559 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6560 tcg_gen_ext32s_tl(arg, arg);
6561 rn = "CMGCRBase";
6562 break;
6563 default:
6564 goto cp0_unimplemented;
6566 break;
6567 case 16:
6568 switch (sel) {
6569 case 0:
6570 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6571 rn = "Config";
6572 break;
6573 case 1:
6574 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6575 rn = "Config1";
6576 break;
6577 case 2:
6578 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6579 rn = "Config2";
6580 break;
6581 case 3:
6582 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6583 rn = "Config3";
6584 break;
6585 case 4:
6586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6587 rn = "Config4";
6588 break;
6589 case 5:
6590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6591 rn = "Config5";
6592 break;
6593 /* 6,7 are implementation dependent */
6594 case 6:
6595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6596 rn = "Config6";
6597 break;
6598 case 7:
6599 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6600 rn = "Config7";
6601 break;
6602 default:
6603 goto cp0_unimplemented;
6605 break;
6606 case 17:
6607 switch (sel) {
6608 case 0:
6609 gen_helper_mfc0_lladdr(arg, cpu_env);
6610 rn = "LLAddr";
6611 break;
6612 case 1:
6613 CP0_CHECK(ctx->mrp);
6614 gen_helper_mfc0_maar(arg, cpu_env);
6615 rn = "MAAR";
6616 break;
6617 case 2:
6618 CP0_CHECK(ctx->mrp);
6619 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6620 rn = "MAARI";
6621 break;
6622 default:
6623 goto cp0_unimplemented;
6625 break;
6626 case 18:
6627 switch (sel) {
6628 case 0:
6629 case 1:
6630 case 2:
6631 case 3:
6632 case 4:
6633 case 5:
6634 case 6:
6635 case 7:
6636 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6637 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6638 rn = "WatchLo";
6639 break;
6640 default:
6641 goto cp0_unimplemented;
6643 break;
6644 case 19:
6645 switch (sel) {
6646 case 0:
6647 case 1:
6648 case 2:
6649 case 3:
6650 case 4:
6651 case 5:
6652 case 6:
6653 case 7:
6654 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6655 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6656 rn = "WatchHi";
6657 break;
6658 default:
6659 goto cp0_unimplemented;
6661 break;
6662 case 20:
6663 switch (sel) {
6664 case 0:
6665 #if defined(TARGET_MIPS64)
6666 check_insn(ctx, ISA_MIPS3);
6667 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6668 tcg_gen_ext32s_tl(arg, arg);
6669 rn = "XContext";
6670 break;
6671 #endif
6672 default:
6673 goto cp0_unimplemented;
6675 break;
6676 case 21:
6677 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6678 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6679 switch (sel) {
6680 case 0:
6681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6682 rn = "Framemask";
6683 break;
6684 default:
6685 goto cp0_unimplemented;
6687 break;
6688 case 22:
6689 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6690 rn = "'Diagnostic"; /* implementation dependent */
6691 break;
6692 case 23:
6693 switch (sel) {
6694 case 0:
6695 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6696 rn = "Debug";
6697 break;
6698 case 1:
6699 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
6700 rn = "TraceControl";
6701 goto cp0_unimplemented;
6702 case 2:
6703 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
6704 rn = "TraceControl2";
6705 goto cp0_unimplemented;
6706 case 3:
6707 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
6708 rn = "UserTraceData";
6709 goto cp0_unimplemented;
6710 case 4:
6711 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
6712 rn = "TraceBPC";
6713 goto cp0_unimplemented;
6714 default:
6715 goto cp0_unimplemented;
6717 break;
6718 case 24:
6719 switch (sel) {
6720 case 0:
6721 /* EJTAG support */
6722 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6723 tcg_gen_ext32s_tl(arg, arg);
6724 rn = "DEPC";
6725 break;
6726 default:
6727 goto cp0_unimplemented;
6729 break;
6730 case 25:
6731 switch (sel) {
6732 case 0:
6733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6734 rn = "Performance0";
6735 break;
6736 case 1:
6737 // gen_helper_mfc0_performance1(arg);
6738 rn = "Performance1";
6739 goto cp0_unimplemented;
6740 case 2:
6741 // gen_helper_mfc0_performance2(arg);
6742 rn = "Performance2";
6743 goto cp0_unimplemented;
6744 case 3:
6745 // gen_helper_mfc0_performance3(arg);
6746 rn = "Performance3";
6747 goto cp0_unimplemented;
6748 case 4:
6749 // gen_helper_mfc0_performance4(arg);
6750 rn = "Performance4";
6751 goto cp0_unimplemented;
6752 case 5:
6753 // gen_helper_mfc0_performance5(arg);
6754 rn = "Performance5";
6755 goto cp0_unimplemented;
6756 case 6:
6757 // gen_helper_mfc0_performance6(arg);
6758 rn = "Performance6";
6759 goto cp0_unimplemented;
6760 case 7:
6761 // gen_helper_mfc0_performance7(arg);
6762 rn = "Performance7";
6763 goto cp0_unimplemented;
6764 default:
6765 goto cp0_unimplemented;
6767 break;
6768 case 26:
6769 switch (sel) {
6770 case 0:
6771 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6772 rn = "ErrCtl";
6773 break;
6774 default:
6775 goto cp0_unimplemented;
6777 break;
6778 case 27:
6779 switch (sel) {
6780 case 0:
6781 case 1:
6782 case 2:
6783 case 3:
6784 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6785 rn = "CacheErr";
6786 break;
6787 default:
6788 goto cp0_unimplemented;
6790 break;
6791 case 28:
6792 switch (sel) {
6793 case 0:
6794 case 2:
6795 case 4:
6796 case 6:
6798 TCGv_i64 tmp = tcg_temp_new_i64();
6799 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6800 gen_move_low32(arg, tmp);
6801 tcg_temp_free_i64(tmp);
6803 rn = "TagLo";
6804 break;
6805 case 1:
6806 case 3:
6807 case 5:
6808 case 7:
6809 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6810 rn = "DataLo";
6811 break;
6812 default:
6813 goto cp0_unimplemented;
6815 break;
6816 case 29:
6817 switch (sel) {
6818 case 0:
6819 case 2:
6820 case 4:
6821 case 6:
6822 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6823 rn = "TagHi";
6824 break;
6825 case 1:
6826 case 3:
6827 case 5:
6828 case 7:
6829 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6830 rn = "DataHi";
6831 break;
6832 default:
6833 goto cp0_unimplemented;
6835 break;
6836 case 30:
6837 switch (sel) {
6838 case 0:
6839 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6840 tcg_gen_ext32s_tl(arg, arg);
6841 rn = "ErrorEPC";
6842 break;
6843 default:
6844 goto cp0_unimplemented;
6846 break;
6847 case 31:
6848 switch (sel) {
6849 case 0:
6850 /* EJTAG support */
6851 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6852 rn = "DESAVE";
6853 break;
6854 case 2:
6855 case 3:
6856 case 4:
6857 case 5:
6858 case 6:
6859 case 7:
6860 CP0_CHECK(ctx->kscrexist & (1 << sel));
6861 tcg_gen_ld_tl(arg, cpu_env,
6862 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6863 tcg_gen_ext32s_tl(arg, arg);
6864 rn = "KScratch";
6865 break;
6866 default:
6867 goto cp0_unimplemented;
6869 break;
6870 default:
6871 goto cp0_unimplemented;
6873 trace_mips_translate_c0("mfc0", rn, reg, sel);
6874 return;
6876 cp0_unimplemented:
6877 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6878 gen_mfc0_unimplemented(ctx, arg);
6881 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6883 const char *rn = "invalid";
6885 if (sel != 0)
6886 check_insn(ctx, ISA_MIPS32);
6888 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6889 gen_io_start();
6892 switch (reg) {
6893 case 0:
6894 switch (sel) {
6895 case 0:
6896 gen_helper_mtc0_index(cpu_env, arg);
6897 rn = "Index";
6898 break;
6899 case 1:
6900 CP0_CHECK(ctx->insn_flags & ASE_MT);
6901 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6902 rn = "MVPControl";
6903 break;
6904 case 2:
6905 CP0_CHECK(ctx->insn_flags & ASE_MT);
6906 /* ignored */
6907 rn = "MVPConf0";
6908 break;
6909 case 3:
6910 CP0_CHECK(ctx->insn_flags & ASE_MT);
6911 /* ignored */
6912 rn = "MVPConf1";
6913 break;
6914 case 4:
6915 CP0_CHECK(ctx->vp);
6916 /* ignored */
6917 rn = "VPControl";
6918 break;
6919 default:
6920 goto cp0_unimplemented;
6922 break;
6923 case 1:
6924 switch (sel) {
6925 case 0:
6926 /* ignored */
6927 rn = "Random";
6928 break;
6929 case 1:
6930 CP0_CHECK(ctx->insn_flags & ASE_MT);
6931 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6932 rn = "VPEControl";
6933 break;
6934 case 2:
6935 CP0_CHECK(ctx->insn_flags & ASE_MT);
6936 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6937 rn = "VPEConf0";
6938 break;
6939 case 3:
6940 CP0_CHECK(ctx->insn_flags & ASE_MT);
6941 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6942 rn = "VPEConf1";
6943 break;
6944 case 4:
6945 CP0_CHECK(ctx->insn_flags & ASE_MT);
6946 gen_helper_mtc0_yqmask(cpu_env, arg);
6947 rn = "YQMask";
6948 break;
6949 case 5:
6950 CP0_CHECK(ctx->insn_flags & ASE_MT);
6951 tcg_gen_st_tl(arg, cpu_env,
6952 offsetof(CPUMIPSState, CP0_VPESchedule));
6953 rn = "VPESchedule";
6954 break;
6955 case 6:
6956 CP0_CHECK(ctx->insn_flags & ASE_MT);
6957 tcg_gen_st_tl(arg, cpu_env,
6958 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6959 rn = "VPEScheFBack";
6960 break;
6961 case 7:
6962 CP0_CHECK(ctx->insn_flags & ASE_MT);
6963 gen_helper_mtc0_vpeopt(cpu_env, arg);
6964 rn = "VPEOpt";
6965 break;
6966 default:
6967 goto cp0_unimplemented;
6969 break;
6970 case 2:
6971 switch (sel) {
6972 case 0:
6973 gen_helper_mtc0_entrylo0(cpu_env, arg);
6974 rn = "EntryLo0";
6975 break;
6976 case 1:
6977 CP0_CHECK(ctx->insn_flags & ASE_MT);
6978 gen_helper_mtc0_tcstatus(cpu_env, arg);
6979 rn = "TCStatus";
6980 break;
6981 case 2:
6982 CP0_CHECK(ctx->insn_flags & ASE_MT);
6983 gen_helper_mtc0_tcbind(cpu_env, arg);
6984 rn = "TCBind";
6985 break;
6986 case 3:
6987 CP0_CHECK(ctx->insn_flags & ASE_MT);
6988 gen_helper_mtc0_tcrestart(cpu_env, arg);
6989 rn = "TCRestart";
6990 break;
6991 case 4:
6992 CP0_CHECK(ctx->insn_flags & ASE_MT);
6993 gen_helper_mtc0_tchalt(cpu_env, arg);
6994 rn = "TCHalt";
6995 break;
6996 case 5:
6997 CP0_CHECK(ctx->insn_flags & ASE_MT);
6998 gen_helper_mtc0_tccontext(cpu_env, arg);
6999 rn = "TCContext";
7000 break;
7001 case 6:
7002 CP0_CHECK(ctx->insn_flags & ASE_MT);
7003 gen_helper_mtc0_tcschedule(cpu_env, arg);
7004 rn = "TCSchedule";
7005 break;
7006 case 7:
7007 CP0_CHECK(ctx->insn_flags & ASE_MT);
7008 gen_helper_mtc0_tcschefback(cpu_env, arg);
7009 rn = "TCScheFBack";
7010 break;
7011 default:
7012 goto cp0_unimplemented;
7014 break;
7015 case 3:
7016 switch (sel) {
7017 case 0:
7018 gen_helper_mtc0_entrylo1(cpu_env, arg);
7019 rn = "EntryLo1";
7020 break;
7021 case 1:
7022 CP0_CHECK(ctx->vp);
7023 /* ignored */
7024 rn = "GlobalNumber";
7025 break;
7026 default:
7027 goto cp0_unimplemented;
7029 break;
7030 case 4:
7031 switch (sel) {
7032 case 0:
7033 gen_helper_mtc0_context(cpu_env, arg);
7034 rn = "Context";
7035 break;
7036 case 1:
7037 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7038 rn = "ContextConfig";
7039 goto cp0_unimplemented;
7040 case 2:
7041 CP0_CHECK(ctx->ulri);
7042 tcg_gen_st_tl(arg, cpu_env,
7043 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7044 rn = "UserLocal";
7045 break;
7046 default:
7047 goto cp0_unimplemented;
7049 break;
7050 case 5:
7051 switch (sel) {
7052 case 0:
7053 gen_helper_mtc0_pagemask(cpu_env, arg);
7054 rn = "PageMask";
7055 break;
7056 case 1:
7057 check_insn(ctx, ISA_MIPS32R2);
7058 gen_helper_mtc0_pagegrain(cpu_env, arg);
7059 rn = "PageGrain";
7060 ctx->base.is_jmp = DISAS_STOP;
7061 break;
7062 case 2:
7063 CP0_CHECK(ctx->sc);
7064 gen_helper_mtc0_segctl0(cpu_env, arg);
7065 rn = "SegCtl0";
7066 break;
7067 case 3:
7068 CP0_CHECK(ctx->sc);
7069 gen_helper_mtc0_segctl1(cpu_env, arg);
7070 rn = "SegCtl1";
7071 break;
7072 case 4:
7073 CP0_CHECK(ctx->sc);
7074 gen_helper_mtc0_segctl2(cpu_env, arg);
7075 rn = "SegCtl2";
7076 break;
7077 case 5:
7078 check_pw(ctx);
7079 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7080 rn = "PWBase";
7081 break;
7082 case 6:
7083 check_pw(ctx);
7084 gen_helper_mtc0_pwfield(cpu_env, arg);
7085 rn = "PWField";
7086 break;
7087 case 7:
7088 check_pw(ctx);
7089 gen_helper_mtc0_pwsize(cpu_env, arg);
7090 rn = "PWSize";
7091 break;
7092 default:
7093 goto cp0_unimplemented;
7095 break;
7096 case 6:
7097 switch (sel) {
7098 case 0:
7099 gen_helper_mtc0_wired(cpu_env, arg);
7100 rn = "Wired";
7101 break;
7102 case 1:
7103 check_insn(ctx, ISA_MIPS32R2);
7104 gen_helper_mtc0_srsconf0(cpu_env, arg);
7105 rn = "SRSConf0";
7106 break;
7107 case 2:
7108 check_insn(ctx, ISA_MIPS32R2);
7109 gen_helper_mtc0_srsconf1(cpu_env, arg);
7110 rn = "SRSConf1";
7111 break;
7112 case 3:
7113 check_insn(ctx, ISA_MIPS32R2);
7114 gen_helper_mtc0_srsconf2(cpu_env, arg);
7115 rn = "SRSConf2";
7116 break;
7117 case 4:
7118 check_insn(ctx, ISA_MIPS32R2);
7119 gen_helper_mtc0_srsconf3(cpu_env, arg);
7120 rn = "SRSConf3";
7121 break;
7122 case 5:
7123 check_insn(ctx, ISA_MIPS32R2);
7124 gen_helper_mtc0_srsconf4(cpu_env, arg);
7125 rn = "SRSConf4";
7126 break;
7127 case 6:
7128 check_pw(ctx);
7129 gen_helper_mtc0_pwctl(cpu_env, arg);
7130 rn = "PWCtl";
7131 break;
7132 default:
7133 goto cp0_unimplemented;
7135 break;
7136 case 7:
7137 switch (sel) {
7138 case 0:
7139 check_insn(ctx, ISA_MIPS32R2);
7140 gen_helper_mtc0_hwrena(cpu_env, arg);
7141 ctx->base.is_jmp = DISAS_STOP;
7142 rn = "HWREna";
7143 break;
7144 default:
7145 goto cp0_unimplemented;
7147 break;
7148 case 8:
7149 switch (sel) {
7150 case 0:
7151 /* ignored */
7152 rn = "BadVAddr";
7153 break;
7154 case 1:
7155 /* ignored */
7156 rn = "BadInstr";
7157 break;
7158 case 2:
7159 /* ignored */
7160 rn = "BadInstrP";
7161 break;
7162 case 3:
7163 /* ignored */
7164 rn = "BadInstrX";
7165 break;
7166 default:
7167 goto cp0_unimplemented;
7169 break;
7170 case 9:
7171 switch (sel) {
7172 case 0:
7173 gen_helper_mtc0_count(cpu_env, arg);
7174 rn = "Count";
7175 break;
7176 /* 6,7 are implementation dependent */
7177 default:
7178 goto cp0_unimplemented;
7180 break;
7181 case 10:
7182 switch (sel) {
7183 case 0:
7184 gen_helper_mtc0_entryhi(cpu_env, arg);
7185 rn = "EntryHi";
7186 break;
7187 default:
7188 goto cp0_unimplemented;
7190 break;
7191 case 11:
7192 switch (sel) {
7193 case 0:
7194 gen_helper_mtc0_compare(cpu_env, arg);
7195 rn = "Compare";
7196 break;
7197 /* 6,7 are implementation dependent */
7198 default:
7199 goto cp0_unimplemented;
7201 break;
7202 case 12:
7203 switch (sel) {
7204 case 0:
7205 save_cpu_state(ctx, 1);
7206 gen_helper_mtc0_status(cpu_env, arg);
7207 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7208 gen_save_pc(ctx->base.pc_next + 4);
7209 ctx->base.is_jmp = DISAS_EXIT;
7210 rn = "Status";
7211 break;
7212 case 1:
7213 check_insn(ctx, ISA_MIPS32R2);
7214 gen_helper_mtc0_intctl(cpu_env, arg);
7215 /* Stop translation as we may have switched the execution mode */
7216 ctx->base.is_jmp = DISAS_STOP;
7217 rn = "IntCtl";
7218 break;
7219 case 2:
7220 check_insn(ctx, ISA_MIPS32R2);
7221 gen_helper_mtc0_srsctl(cpu_env, arg);
7222 /* Stop translation as we may have switched the execution mode */
7223 ctx->base.is_jmp = DISAS_STOP;
7224 rn = "SRSCtl";
7225 break;
7226 case 3:
7227 check_insn(ctx, ISA_MIPS32R2);
7228 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7229 /* Stop translation as we may have switched the execution mode */
7230 ctx->base.is_jmp = DISAS_STOP;
7231 rn = "SRSMap";
7232 break;
7233 default:
7234 goto cp0_unimplemented;
7236 break;
7237 case 13:
7238 switch (sel) {
7239 case 0:
7240 save_cpu_state(ctx, 1);
7241 gen_helper_mtc0_cause(cpu_env, arg);
7242 /* Stop translation as we may have triggered an interrupt.
7243 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7244 * translated code to check for pending interrupts. */
7245 gen_save_pc(ctx->base.pc_next + 4);
7246 ctx->base.is_jmp = DISAS_EXIT;
7247 rn = "Cause";
7248 break;
7249 default:
7250 goto cp0_unimplemented;
7252 break;
7253 case 14:
7254 switch (sel) {
7255 case 0:
7256 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7257 rn = "EPC";
7258 break;
7259 default:
7260 goto cp0_unimplemented;
7262 break;
7263 case 15:
7264 switch (sel) {
7265 case 0:
7266 /* ignored */
7267 rn = "PRid";
7268 break;
7269 case 1:
7270 check_insn(ctx, ISA_MIPS32R2);
7271 gen_helper_mtc0_ebase(cpu_env, arg);
7272 rn = "EBase";
7273 break;
7274 default:
7275 goto cp0_unimplemented;
7277 break;
7278 case 16:
7279 switch (sel) {
7280 case 0:
7281 gen_helper_mtc0_config0(cpu_env, arg);
7282 rn = "Config";
7283 /* Stop translation as we may have switched the execution mode */
7284 ctx->base.is_jmp = DISAS_STOP;
7285 break;
7286 case 1:
7287 /* ignored, read only */
7288 rn = "Config1";
7289 break;
7290 case 2:
7291 gen_helper_mtc0_config2(cpu_env, arg);
7292 rn = "Config2";
7293 /* Stop translation as we may have switched the execution mode */
7294 ctx->base.is_jmp = DISAS_STOP;
7295 break;
7296 case 3:
7297 gen_helper_mtc0_config3(cpu_env, arg);
7298 rn = "Config3";
7299 /* Stop translation as we may have switched the execution mode */
7300 ctx->base.is_jmp = DISAS_STOP;
7301 break;
7302 case 4:
7303 gen_helper_mtc0_config4(cpu_env, arg);
7304 rn = "Config4";
7305 ctx->base.is_jmp = DISAS_STOP;
7306 break;
7307 case 5:
7308 gen_helper_mtc0_config5(cpu_env, arg);
7309 rn = "Config5";
7310 /* Stop translation as we may have switched the execution mode */
7311 ctx->base.is_jmp = DISAS_STOP;
7312 break;
7313 /* 6,7 are implementation dependent */
7314 case 6:
7315 /* ignored */
7316 rn = "Config6";
7317 break;
7318 case 7:
7319 /* ignored */
7320 rn = "Config7";
7321 break;
7322 default:
7323 rn = "Invalid config selector";
7324 goto cp0_unimplemented;
7326 break;
7327 case 17:
7328 switch (sel) {
7329 case 0:
7330 gen_helper_mtc0_lladdr(cpu_env, arg);
7331 rn = "LLAddr";
7332 break;
7333 case 1:
7334 CP0_CHECK(ctx->mrp);
7335 gen_helper_mtc0_maar(cpu_env, arg);
7336 rn = "MAAR";
7337 break;
7338 case 2:
7339 CP0_CHECK(ctx->mrp);
7340 gen_helper_mtc0_maari(cpu_env, arg);
7341 rn = "MAARI";
7342 break;
7343 default:
7344 goto cp0_unimplemented;
7346 break;
7347 case 18:
7348 switch (sel) {
7349 case 0:
7350 case 1:
7351 case 2:
7352 case 3:
7353 case 4:
7354 case 5:
7355 case 6:
7356 case 7:
7357 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7358 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7359 rn = "WatchLo";
7360 break;
7361 default:
7362 goto cp0_unimplemented;
7364 break;
7365 case 19:
7366 switch (sel) {
7367 case 0:
7368 case 1:
7369 case 2:
7370 case 3:
7371 case 4:
7372 case 5:
7373 case 6:
7374 case 7:
7375 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7376 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7377 rn = "WatchHi";
7378 break;
7379 default:
7380 goto cp0_unimplemented;
7382 break;
7383 case 20:
7384 switch (sel) {
7385 case 0:
7386 #if defined(TARGET_MIPS64)
7387 check_insn(ctx, ISA_MIPS3);
7388 gen_helper_mtc0_xcontext(cpu_env, arg);
7389 rn = "XContext";
7390 break;
7391 #endif
7392 default:
7393 goto cp0_unimplemented;
7395 break;
7396 case 21:
7397 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7398 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7399 switch (sel) {
7400 case 0:
7401 gen_helper_mtc0_framemask(cpu_env, arg);
7402 rn = "Framemask";
7403 break;
7404 default:
7405 goto cp0_unimplemented;
7407 break;
7408 case 22:
7409 /* ignored */
7410 rn = "Diagnostic"; /* implementation dependent */
7411 break;
7412 case 23:
7413 switch (sel) {
7414 case 0:
7415 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7416 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7417 gen_save_pc(ctx->base.pc_next + 4);
7418 ctx->base.is_jmp = DISAS_EXIT;
7419 rn = "Debug";
7420 break;
7421 case 1:
7422 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7423 rn = "TraceControl";
7424 /* Stop translation as we may have switched the execution mode */
7425 ctx->base.is_jmp = DISAS_STOP;
7426 goto cp0_unimplemented;
7427 case 2:
7428 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7429 rn = "TraceControl2";
7430 /* Stop translation as we may have switched the execution mode */
7431 ctx->base.is_jmp = DISAS_STOP;
7432 goto cp0_unimplemented;
7433 case 3:
7434 /* Stop translation as we may have switched the execution mode */
7435 ctx->base.is_jmp = DISAS_STOP;
7436 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7437 rn = "UserTraceData";
7438 /* Stop translation as we may have switched the execution mode */
7439 ctx->base.is_jmp = DISAS_STOP;
7440 goto cp0_unimplemented;
7441 case 4:
7442 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7443 /* Stop translation as we may have switched the execution mode */
7444 ctx->base.is_jmp = DISAS_STOP;
7445 rn = "TraceBPC";
7446 goto cp0_unimplemented;
7447 default:
7448 goto cp0_unimplemented;
7450 break;
7451 case 24:
7452 switch (sel) {
7453 case 0:
7454 /* EJTAG support */
7455 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7456 rn = "DEPC";
7457 break;
7458 default:
7459 goto cp0_unimplemented;
7461 break;
7462 case 25:
7463 switch (sel) {
7464 case 0:
7465 gen_helper_mtc0_performance0(cpu_env, arg);
7466 rn = "Performance0";
7467 break;
7468 case 1:
7469 // gen_helper_mtc0_performance1(arg);
7470 rn = "Performance1";
7471 goto cp0_unimplemented;
7472 case 2:
7473 // gen_helper_mtc0_performance2(arg);
7474 rn = "Performance2";
7475 goto cp0_unimplemented;
7476 case 3:
7477 // gen_helper_mtc0_performance3(arg);
7478 rn = "Performance3";
7479 goto cp0_unimplemented;
7480 case 4:
7481 // gen_helper_mtc0_performance4(arg);
7482 rn = "Performance4";
7483 goto cp0_unimplemented;
7484 case 5:
7485 // gen_helper_mtc0_performance5(arg);
7486 rn = "Performance5";
7487 goto cp0_unimplemented;
7488 case 6:
7489 // gen_helper_mtc0_performance6(arg);
7490 rn = "Performance6";
7491 goto cp0_unimplemented;
7492 case 7:
7493 // gen_helper_mtc0_performance7(arg);
7494 rn = "Performance7";
7495 goto cp0_unimplemented;
7496 default:
7497 goto cp0_unimplemented;
7499 break;
7500 case 26:
7501 switch (sel) {
7502 case 0:
7503 gen_helper_mtc0_errctl(cpu_env, arg);
7504 ctx->base.is_jmp = DISAS_STOP;
7505 rn = "ErrCtl";
7506 break;
7507 default:
7508 goto cp0_unimplemented;
7510 break;
7511 case 27:
7512 switch (sel) {
7513 case 0:
7514 case 1:
7515 case 2:
7516 case 3:
7517 /* ignored */
7518 rn = "CacheErr";
7519 break;
7520 default:
7521 goto cp0_unimplemented;
7523 break;
7524 case 28:
7525 switch (sel) {
7526 case 0:
7527 case 2:
7528 case 4:
7529 case 6:
7530 gen_helper_mtc0_taglo(cpu_env, arg);
7531 rn = "TagLo";
7532 break;
7533 case 1:
7534 case 3:
7535 case 5:
7536 case 7:
7537 gen_helper_mtc0_datalo(cpu_env, arg);
7538 rn = "DataLo";
7539 break;
7540 default:
7541 goto cp0_unimplemented;
7543 break;
7544 case 29:
7545 switch (sel) {
7546 case 0:
7547 case 2:
7548 case 4:
7549 case 6:
7550 gen_helper_mtc0_taghi(cpu_env, arg);
7551 rn = "TagHi";
7552 break;
7553 case 1:
7554 case 3:
7555 case 5:
7556 case 7:
7557 gen_helper_mtc0_datahi(cpu_env, arg);
7558 rn = "DataHi";
7559 break;
7560 default:
7561 rn = "invalid sel";
7562 goto cp0_unimplemented;
7564 break;
7565 case 30:
7566 switch (sel) {
7567 case 0:
7568 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7569 rn = "ErrorEPC";
7570 break;
7571 default:
7572 goto cp0_unimplemented;
7574 break;
7575 case 31:
7576 switch (sel) {
7577 case 0:
7578 /* EJTAG support */
7579 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7580 rn = "DESAVE";
7581 break;
7582 case 2:
7583 case 3:
7584 case 4:
7585 case 5:
7586 case 6:
7587 case 7:
7588 CP0_CHECK(ctx->kscrexist & (1 << sel));
7589 tcg_gen_st_tl(arg, cpu_env,
7590 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7591 rn = "KScratch";
7592 break;
7593 default:
7594 goto cp0_unimplemented;
7596 break;
7597 default:
7598 goto cp0_unimplemented;
7600 trace_mips_translate_c0("mtc0", rn, reg, sel);
7602 /* For simplicity assume that all writes can cause interrupts. */
7603 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7604 gen_io_end();
7605 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
7606 * translated code to check for pending interrupts. */
7607 gen_save_pc(ctx->base.pc_next + 4);
7608 ctx->base.is_jmp = DISAS_EXIT;
7610 return;
7612 cp0_unimplemented:
7613 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7616 #if defined(TARGET_MIPS64)
7617 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7619 const char *rn = "invalid";
7621 if (sel != 0)
7622 check_insn(ctx, ISA_MIPS64);
7624 switch (reg) {
7625 case 0:
7626 switch (sel) {
7627 case 0:
7628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7629 rn = "Index";
7630 break;
7631 case 1:
7632 CP0_CHECK(ctx->insn_flags & ASE_MT);
7633 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7634 rn = "MVPControl";
7635 break;
7636 case 2:
7637 CP0_CHECK(ctx->insn_flags & ASE_MT);
7638 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7639 rn = "MVPConf0";
7640 break;
7641 case 3:
7642 CP0_CHECK(ctx->insn_flags & ASE_MT);
7643 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7644 rn = "MVPConf1";
7645 break;
7646 case 4:
7647 CP0_CHECK(ctx->vp);
7648 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7649 rn = "VPControl";
7650 break;
7651 default:
7652 goto cp0_unimplemented;
7654 break;
7655 case 1:
7656 switch (sel) {
7657 case 0:
7658 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7659 gen_helper_mfc0_random(arg, cpu_env);
7660 rn = "Random";
7661 break;
7662 case 1:
7663 CP0_CHECK(ctx->insn_flags & ASE_MT);
7664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7665 rn = "VPEControl";
7666 break;
7667 case 2:
7668 CP0_CHECK(ctx->insn_flags & ASE_MT);
7669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7670 rn = "VPEConf0";
7671 break;
7672 case 3:
7673 CP0_CHECK(ctx->insn_flags & ASE_MT);
7674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7675 rn = "VPEConf1";
7676 break;
7677 case 4:
7678 CP0_CHECK(ctx->insn_flags & ASE_MT);
7679 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
7680 rn = "YQMask";
7681 break;
7682 case 5:
7683 CP0_CHECK(ctx->insn_flags & ASE_MT);
7684 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7685 rn = "VPESchedule";
7686 break;
7687 case 6:
7688 CP0_CHECK(ctx->insn_flags & ASE_MT);
7689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7690 rn = "VPEScheFBack";
7691 break;
7692 case 7:
7693 CP0_CHECK(ctx->insn_flags & ASE_MT);
7694 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7695 rn = "VPEOpt";
7696 break;
7697 default:
7698 goto cp0_unimplemented;
7700 break;
7701 case 2:
7702 switch (sel) {
7703 case 0:
7704 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
7705 rn = "EntryLo0";
7706 break;
7707 case 1:
7708 CP0_CHECK(ctx->insn_flags & ASE_MT);
7709 gen_helper_mfc0_tcstatus(arg, cpu_env);
7710 rn = "TCStatus";
7711 break;
7712 case 2:
7713 CP0_CHECK(ctx->insn_flags & ASE_MT);
7714 gen_helper_mfc0_tcbind(arg, cpu_env);
7715 rn = "TCBind";
7716 break;
7717 case 3:
7718 CP0_CHECK(ctx->insn_flags & ASE_MT);
7719 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7720 rn = "TCRestart";
7721 break;
7722 case 4:
7723 CP0_CHECK(ctx->insn_flags & ASE_MT);
7724 gen_helper_dmfc0_tchalt(arg, cpu_env);
7725 rn = "TCHalt";
7726 break;
7727 case 5:
7728 CP0_CHECK(ctx->insn_flags & ASE_MT);
7729 gen_helper_dmfc0_tccontext(arg, cpu_env);
7730 rn = "TCContext";
7731 break;
7732 case 6:
7733 CP0_CHECK(ctx->insn_flags & ASE_MT);
7734 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7735 rn = "TCSchedule";
7736 break;
7737 case 7:
7738 CP0_CHECK(ctx->insn_flags & ASE_MT);
7739 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7740 rn = "TCScheFBack";
7741 break;
7742 default:
7743 goto cp0_unimplemented;
7745 break;
7746 case 3:
7747 switch (sel) {
7748 case 0:
7749 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7750 rn = "EntryLo1";
7751 break;
7752 case 1:
7753 CP0_CHECK(ctx->vp);
7754 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7755 rn = "GlobalNumber";
7756 break;
7757 default:
7758 goto cp0_unimplemented;
7760 break;
7761 case 4:
7762 switch (sel) {
7763 case 0:
7764 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7765 rn = "Context";
7766 break;
7767 case 1:
7768 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
7769 rn = "ContextConfig";
7770 goto cp0_unimplemented;
7771 case 2:
7772 CP0_CHECK(ctx->ulri);
7773 tcg_gen_ld_tl(arg, cpu_env,
7774 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7775 rn = "UserLocal";
7776 break;
7777 default:
7778 goto cp0_unimplemented;
7780 break;
7781 case 5:
7782 switch (sel) {
7783 case 0:
7784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7785 rn = "PageMask";
7786 break;
7787 case 1:
7788 check_insn(ctx, ISA_MIPS32R2);
7789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7790 rn = "PageGrain";
7791 break;
7792 case 2:
7793 CP0_CHECK(ctx->sc);
7794 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7795 rn = "SegCtl0";
7796 break;
7797 case 3:
7798 CP0_CHECK(ctx->sc);
7799 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7800 rn = "SegCtl1";
7801 break;
7802 case 4:
7803 CP0_CHECK(ctx->sc);
7804 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7805 rn = "SegCtl2";
7806 break;
7807 case 5:
7808 check_pw(ctx);
7809 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7810 rn = "PWBase";
7811 break;
7812 case 6:
7813 check_pw(ctx);
7814 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7815 rn = "PWField";
7816 break;
7817 case 7:
7818 check_pw(ctx);
7819 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7820 rn = "PWSize";
7821 break;
7822 default:
7823 goto cp0_unimplemented;
7825 break;
7826 case 6:
7827 switch (sel) {
7828 case 0:
7829 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7830 rn = "Wired";
7831 break;
7832 case 1:
7833 check_insn(ctx, ISA_MIPS32R2);
7834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7835 rn = "SRSConf0";
7836 break;
7837 case 2:
7838 check_insn(ctx, ISA_MIPS32R2);
7839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7840 rn = "SRSConf1";
7841 break;
7842 case 3:
7843 check_insn(ctx, ISA_MIPS32R2);
7844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7845 rn = "SRSConf2";
7846 break;
7847 case 4:
7848 check_insn(ctx, ISA_MIPS32R2);
7849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7850 rn = "SRSConf3";
7851 break;
7852 case 5:
7853 check_insn(ctx, ISA_MIPS32R2);
7854 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7855 rn = "SRSConf4";
7856 break;
7857 case 6:
7858 check_pw(ctx);
7859 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7860 rn = "PWCtl";
7861 break;
7862 default:
7863 goto cp0_unimplemented;
7865 break;
7866 case 7:
7867 switch (sel) {
7868 case 0:
7869 check_insn(ctx, ISA_MIPS32R2);
7870 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7871 rn = "HWREna";
7872 break;
7873 default:
7874 goto cp0_unimplemented;
7876 break;
7877 case 8:
7878 switch (sel) {
7879 case 0:
7880 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7881 rn = "BadVAddr";
7882 break;
7883 case 1:
7884 CP0_CHECK(ctx->bi);
7885 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7886 rn = "BadInstr";
7887 break;
7888 case 2:
7889 CP0_CHECK(ctx->bp);
7890 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7891 rn = "BadInstrP";
7892 break;
7893 case 3:
7894 CP0_CHECK(ctx->bi);
7895 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7896 tcg_gen_andi_tl(arg, arg, ~0xffff);
7897 rn = "BadInstrX";
7898 break;
7899 default:
7900 goto cp0_unimplemented;
7902 break;
7903 case 9:
7904 switch (sel) {
7905 case 0:
7906 /* Mark as an IO operation because we read the time. */
7907 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7908 gen_io_start();
7910 gen_helper_mfc0_count(arg, cpu_env);
7911 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7912 gen_io_end();
7914 /* Break the TB to be able to take timer interrupts immediately
7915 after reading count. DISAS_STOP isn't sufficient, we need to
7916 ensure we break completely out of translated code. */
7917 gen_save_pc(ctx->base.pc_next + 4);
7918 ctx->base.is_jmp = DISAS_EXIT;
7919 rn = "Count";
7920 break;
7921 /* 6,7 are implementation dependent */
7922 default:
7923 goto cp0_unimplemented;
7925 break;
7926 case 10:
7927 switch (sel) {
7928 case 0:
7929 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7930 rn = "EntryHi";
7931 break;
7932 default:
7933 goto cp0_unimplemented;
7935 break;
7936 case 11:
7937 switch (sel) {
7938 case 0:
7939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7940 rn = "Compare";
7941 break;
7942 /* 6,7 are implementation dependent */
7943 default:
7944 goto cp0_unimplemented;
7946 break;
7947 case 12:
7948 switch (sel) {
7949 case 0:
7950 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7951 rn = "Status";
7952 break;
7953 case 1:
7954 check_insn(ctx, ISA_MIPS32R2);
7955 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7956 rn = "IntCtl";
7957 break;
7958 case 2:
7959 check_insn(ctx, ISA_MIPS32R2);
7960 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7961 rn = "SRSCtl";
7962 break;
7963 case 3:
7964 check_insn(ctx, ISA_MIPS32R2);
7965 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7966 rn = "SRSMap";
7967 break;
7968 default:
7969 goto cp0_unimplemented;
7971 break;
7972 case 13:
7973 switch (sel) {
7974 case 0:
7975 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7976 rn = "Cause";
7977 break;
7978 default:
7979 goto cp0_unimplemented;
7981 break;
7982 case 14:
7983 switch (sel) {
7984 case 0:
7985 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7986 rn = "EPC";
7987 break;
7988 default:
7989 goto cp0_unimplemented;
7991 break;
7992 case 15:
7993 switch (sel) {
7994 case 0:
7995 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7996 rn = "PRid";
7997 break;
7998 case 1:
7999 check_insn(ctx, ISA_MIPS32R2);
8000 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
8001 rn = "EBase";
8002 break;
8003 case 3:
8004 check_insn(ctx, ISA_MIPS32R2);
8005 CP0_CHECK(ctx->cmgcr);
8006 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
8007 rn = "CMGCRBase";
8008 break;
8009 default:
8010 goto cp0_unimplemented;
8012 break;
8013 case 16:
8014 switch (sel) {
8015 case 0:
8016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
8017 rn = "Config";
8018 break;
8019 case 1:
8020 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
8021 rn = "Config1";
8022 break;
8023 case 2:
8024 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
8025 rn = "Config2";
8026 break;
8027 case 3:
8028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
8029 rn = "Config3";
8030 break;
8031 case 4:
8032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
8033 rn = "Config4";
8034 break;
8035 case 5:
8036 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
8037 rn = "Config5";
8038 break;
8039 /* 6,7 are implementation dependent */
8040 case 6:
8041 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
8042 rn = "Config6";
8043 break;
8044 case 7:
8045 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
8046 rn = "Config7";
8047 break;
8048 default:
8049 goto cp0_unimplemented;
8051 break;
8052 case 17:
8053 switch (sel) {
8054 case 0:
8055 gen_helper_dmfc0_lladdr(arg, cpu_env);
8056 rn = "LLAddr";
8057 break;
8058 case 1:
8059 CP0_CHECK(ctx->mrp);
8060 gen_helper_dmfc0_maar(arg, cpu_env);
8061 rn = "MAAR";
8062 break;
8063 case 2:
8064 CP0_CHECK(ctx->mrp);
8065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
8066 rn = "MAARI";
8067 break;
8068 default:
8069 goto cp0_unimplemented;
8071 break;
8072 case 18:
8073 switch (sel) {
8074 case 0:
8075 case 1:
8076 case 2:
8077 case 3:
8078 case 4:
8079 case 5:
8080 case 6:
8081 case 7:
8082 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8083 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
8084 rn = "WatchLo";
8085 break;
8086 default:
8087 goto cp0_unimplemented;
8089 break;
8090 case 19:
8091 switch (sel) {
8092 case 0:
8093 case 1:
8094 case 2:
8095 case 3:
8096 case 4:
8097 case 5:
8098 case 6:
8099 case 7:
8100 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8101 gen_helper_1e0i(mfc0_watchhi, arg, sel);
8102 rn = "WatchHi";
8103 break;
8104 default:
8105 goto cp0_unimplemented;
8107 break;
8108 case 20:
8109 switch (sel) {
8110 case 0:
8111 check_insn(ctx, ISA_MIPS3);
8112 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8113 rn = "XContext";
8114 break;
8115 default:
8116 goto cp0_unimplemented;
8118 break;
8119 case 21:
8120 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8121 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8122 switch (sel) {
8123 case 0:
8124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8125 rn = "Framemask";
8126 break;
8127 default:
8128 goto cp0_unimplemented;
8130 break;
8131 case 22:
8132 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8133 rn = "'Diagnostic"; /* implementation dependent */
8134 break;
8135 case 23:
8136 switch (sel) {
8137 case 0:
8138 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8139 rn = "Debug";
8140 break;
8141 case 1:
8142 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
8143 rn = "TraceControl";
8144 goto cp0_unimplemented;
8145 case 2:
8146 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
8147 rn = "TraceControl2";
8148 goto cp0_unimplemented;
8149 case 3:
8150 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
8151 rn = "UserTraceData";
8152 goto cp0_unimplemented;
8153 case 4:
8154 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
8155 rn = "TraceBPC";
8156 goto cp0_unimplemented;
8157 default:
8158 goto cp0_unimplemented;
8160 break;
8161 case 24:
8162 switch (sel) {
8163 case 0:
8164 /* EJTAG support */
8165 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8166 rn = "DEPC";
8167 break;
8168 default:
8169 goto cp0_unimplemented;
8171 break;
8172 case 25:
8173 switch (sel) {
8174 case 0:
8175 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8176 rn = "Performance0";
8177 break;
8178 case 1:
8179 // gen_helper_dmfc0_performance1(arg);
8180 rn = "Performance1";
8181 goto cp0_unimplemented;
8182 case 2:
8183 // gen_helper_dmfc0_performance2(arg);
8184 rn = "Performance2";
8185 goto cp0_unimplemented;
8186 case 3:
8187 // gen_helper_dmfc0_performance3(arg);
8188 rn = "Performance3";
8189 goto cp0_unimplemented;
8190 case 4:
8191 // gen_helper_dmfc0_performance4(arg);
8192 rn = "Performance4";
8193 goto cp0_unimplemented;
8194 case 5:
8195 // gen_helper_dmfc0_performance5(arg);
8196 rn = "Performance5";
8197 goto cp0_unimplemented;
8198 case 6:
8199 // gen_helper_dmfc0_performance6(arg);
8200 rn = "Performance6";
8201 goto cp0_unimplemented;
8202 case 7:
8203 // gen_helper_dmfc0_performance7(arg);
8204 rn = "Performance7";
8205 goto cp0_unimplemented;
8206 default:
8207 goto cp0_unimplemented;
8209 break;
8210 case 26:
8211 switch (sel) {
8212 case 0:
8213 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8214 rn = "ErrCtl";
8215 break;
8216 default:
8217 goto cp0_unimplemented;
8219 break;
8220 case 27:
8221 switch (sel) {
8222 /* ignored */
8223 case 0:
8224 case 1:
8225 case 2:
8226 case 3:
8227 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8228 rn = "CacheErr";
8229 break;
8230 default:
8231 goto cp0_unimplemented;
8233 break;
8234 case 28:
8235 switch (sel) {
8236 case 0:
8237 case 2:
8238 case 4:
8239 case 6:
8240 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8241 rn = "TagLo";
8242 break;
8243 case 1:
8244 case 3:
8245 case 5:
8246 case 7:
8247 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8248 rn = "DataLo";
8249 break;
8250 default:
8251 goto cp0_unimplemented;
8253 break;
8254 case 29:
8255 switch (sel) {
8256 case 0:
8257 case 2:
8258 case 4:
8259 case 6:
8260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8261 rn = "TagHi";
8262 break;
8263 case 1:
8264 case 3:
8265 case 5:
8266 case 7:
8267 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8268 rn = "DataHi";
8269 break;
8270 default:
8271 goto cp0_unimplemented;
8273 break;
8274 case 30:
8275 switch (sel) {
8276 case 0:
8277 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8278 rn = "ErrorEPC";
8279 break;
8280 default:
8281 goto cp0_unimplemented;
8283 break;
8284 case 31:
8285 switch (sel) {
8286 case 0:
8287 /* EJTAG support */
8288 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8289 rn = "DESAVE";
8290 break;
8291 case 2:
8292 case 3:
8293 case 4:
8294 case 5:
8295 case 6:
8296 case 7:
8297 CP0_CHECK(ctx->kscrexist & (1 << sel));
8298 tcg_gen_ld_tl(arg, cpu_env,
8299 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
8300 rn = "KScratch";
8301 break;
8302 default:
8303 goto cp0_unimplemented;
8305 break;
8306 default:
8307 goto cp0_unimplemented;
8309 trace_mips_translate_c0("dmfc0", rn, reg, sel);
8310 return;
8312 cp0_unimplemented:
8313 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
8314 gen_mfc0_unimplemented(ctx, arg);
8317 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8319 const char *rn = "invalid";
8321 if (sel != 0)
8322 check_insn(ctx, ISA_MIPS64);
8324 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8325 gen_io_start();
8328 switch (reg) {
8329 case 0:
8330 switch (sel) {
8331 case 0:
8332 gen_helper_mtc0_index(cpu_env, arg);
8333 rn = "Index";
8334 break;
8335 case 1:
8336 CP0_CHECK(ctx->insn_flags & ASE_MT);
8337 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8338 rn = "MVPControl";
8339 break;
8340 case 2:
8341 CP0_CHECK(ctx->insn_flags & ASE_MT);
8342 /* ignored */
8343 rn = "MVPConf0";
8344 break;
8345 case 3:
8346 CP0_CHECK(ctx->insn_flags & ASE_MT);
8347 /* ignored */
8348 rn = "MVPConf1";
8349 break;
8350 case 4:
8351 CP0_CHECK(ctx->vp);
8352 /* ignored */
8353 rn = "VPControl";
8354 break;
8355 default:
8356 goto cp0_unimplemented;
8358 break;
8359 case 1:
8360 switch (sel) {
8361 case 0:
8362 /* ignored */
8363 rn = "Random";
8364 break;
8365 case 1:
8366 CP0_CHECK(ctx->insn_flags & ASE_MT);
8367 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8368 rn = "VPEControl";
8369 break;
8370 case 2:
8371 CP0_CHECK(ctx->insn_flags & ASE_MT);
8372 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8373 rn = "VPEConf0";
8374 break;
8375 case 3:
8376 CP0_CHECK(ctx->insn_flags & ASE_MT);
8377 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8378 rn = "VPEConf1";
8379 break;
8380 case 4:
8381 CP0_CHECK(ctx->insn_flags & ASE_MT);
8382 gen_helper_mtc0_yqmask(cpu_env, arg);
8383 rn = "YQMask";
8384 break;
8385 case 5:
8386 CP0_CHECK(ctx->insn_flags & ASE_MT);
8387 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
8388 rn = "VPESchedule";
8389 break;
8390 case 6:
8391 CP0_CHECK(ctx->insn_flags & ASE_MT);
8392 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
8393 rn = "VPEScheFBack";
8394 break;
8395 case 7:
8396 CP0_CHECK(ctx->insn_flags & ASE_MT);
8397 gen_helper_mtc0_vpeopt(cpu_env, arg);
8398 rn = "VPEOpt";
8399 break;
8400 default:
8401 goto cp0_unimplemented;
8403 break;
8404 case 2:
8405 switch (sel) {
8406 case 0:
8407 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8408 rn = "EntryLo0";
8409 break;
8410 case 1:
8411 CP0_CHECK(ctx->insn_flags & ASE_MT);
8412 gen_helper_mtc0_tcstatus(cpu_env, arg);
8413 rn = "TCStatus";
8414 break;
8415 case 2:
8416 CP0_CHECK(ctx->insn_flags & ASE_MT);
8417 gen_helper_mtc0_tcbind(cpu_env, arg);
8418 rn = "TCBind";
8419 break;
8420 case 3:
8421 CP0_CHECK(ctx->insn_flags & ASE_MT);
8422 gen_helper_mtc0_tcrestart(cpu_env, arg);
8423 rn = "TCRestart";
8424 break;
8425 case 4:
8426 CP0_CHECK(ctx->insn_flags & ASE_MT);
8427 gen_helper_mtc0_tchalt(cpu_env, arg);
8428 rn = "TCHalt";
8429 break;
8430 case 5:
8431 CP0_CHECK(ctx->insn_flags & ASE_MT);
8432 gen_helper_mtc0_tccontext(cpu_env, arg);
8433 rn = "TCContext";
8434 break;
8435 case 6:
8436 CP0_CHECK(ctx->insn_flags & ASE_MT);
8437 gen_helper_mtc0_tcschedule(cpu_env, arg);
8438 rn = "TCSchedule";
8439 break;
8440 case 7:
8441 CP0_CHECK(ctx->insn_flags & ASE_MT);
8442 gen_helper_mtc0_tcschefback(cpu_env, arg);
8443 rn = "TCScheFBack";
8444 break;
8445 default:
8446 goto cp0_unimplemented;
8448 break;
8449 case 3:
8450 switch (sel) {
8451 case 0:
8452 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8453 rn = "EntryLo1";
8454 break;
8455 case 1:
8456 CP0_CHECK(ctx->vp);
8457 /* ignored */
8458 rn = "GlobalNumber";
8459 break;
8460 default:
8461 goto cp0_unimplemented;
8463 break;
8464 case 4:
8465 switch (sel) {
8466 case 0:
8467 gen_helper_mtc0_context(cpu_env, arg);
8468 rn = "Context";
8469 break;
8470 case 1:
8471 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
8472 rn = "ContextConfig";
8473 goto cp0_unimplemented;
8474 case 2:
8475 CP0_CHECK(ctx->ulri);
8476 tcg_gen_st_tl(arg, cpu_env,
8477 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8478 rn = "UserLocal";
8479 break;
8480 default:
8481 goto cp0_unimplemented;
8483 break;
8484 case 5:
8485 switch (sel) {
8486 case 0:
8487 gen_helper_mtc0_pagemask(cpu_env, arg);
8488 rn = "PageMask";
8489 break;
8490 case 1:
8491 check_insn(ctx, ISA_MIPS32R2);
8492 gen_helper_mtc0_pagegrain(cpu_env, arg);
8493 rn = "PageGrain";
8494 break;
8495 case 2:
8496 CP0_CHECK(ctx->sc);
8497 gen_helper_mtc0_segctl0(cpu_env, arg);
8498 rn = "SegCtl0";
8499 break;
8500 case 3:
8501 CP0_CHECK(ctx->sc);
8502 gen_helper_mtc0_segctl1(cpu_env, arg);
8503 rn = "SegCtl1";
8504 break;
8505 case 4:
8506 CP0_CHECK(ctx->sc);
8507 gen_helper_mtc0_segctl2(cpu_env, arg);
8508 rn = "SegCtl2";
8509 break;
8510 case 5:
8511 check_pw(ctx);
8512 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8513 rn = "PWBase";
8514 break;
8515 case 6:
8516 check_pw(ctx);
8517 gen_helper_mtc0_pwfield(cpu_env, arg);
8518 rn = "PWField";
8519 break;
8520 case 7:
8521 check_pw(ctx);
8522 gen_helper_mtc0_pwsize(cpu_env, arg);
8523 rn = "PWSize";
8524 break;
8525 default:
8526 goto cp0_unimplemented;
8528 break;
8529 case 6:
8530 switch (sel) {
8531 case 0:
8532 gen_helper_mtc0_wired(cpu_env, arg);
8533 rn = "Wired";
8534 break;
8535 case 1:
8536 check_insn(ctx, ISA_MIPS32R2);
8537 gen_helper_mtc0_srsconf0(cpu_env, arg);
8538 rn = "SRSConf0";
8539 break;
8540 case 2:
8541 check_insn(ctx, ISA_MIPS32R2);
8542 gen_helper_mtc0_srsconf1(cpu_env, arg);
8543 rn = "SRSConf1";
8544 break;
8545 case 3:
8546 check_insn(ctx, ISA_MIPS32R2);
8547 gen_helper_mtc0_srsconf2(cpu_env, arg);
8548 rn = "SRSConf2";
8549 break;
8550 case 4:
8551 check_insn(ctx, ISA_MIPS32R2);
8552 gen_helper_mtc0_srsconf3(cpu_env, arg);
8553 rn = "SRSConf3";
8554 break;
8555 case 5:
8556 check_insn(ctx, ISA_MIPS32R2);
8557 gen_helper_mtc0_srsconf4(cpu_env, arg);
8558 rn = "SRSConf4";
8559 break;
8560 case 6:
8561 check_pw(ctx);
8562 gen_helper_mtc0_pwctl(cpu_env, arg);
8563 rn = "PWCtl";
8564 break;
8565 default:
8566 goto cp0_unimplemented;
8568 break;
8569 case 7:
8570 switch (sel) {
8571 case 0:
8572 check_insn(ctx, ISA_MIPS32R2);
8573 gen_helper_mtc0_hwrena(cpu_env, arg);
8574 ctx->base.is_jmp = DISAS_STOP;
8575 rn = "HWREna";
8576 break;
8577 default:
8578 goto cp0_unimplemented;
8580 break;
8581 case 8:
8582 switch (sel) {
8583 case 0:
8584 /* ignored */
8585 rn = "BadVAddr";
8586 break;
8587 case 1:
8588 /* ignored */
8589 rn = "BadInstr";
8590 break;
8591 case 2:
8592 /* ignored */
8593 rn = "BadInstrP";
8594 break;
8595 case 3:
8596 /* ignored */
8597 rn = "BadInstrX";
8598 break;
8599 default:
8600 goto cp0_unimplemented;
8602 break;
8603 case 9:
8604 switch (sel) {
8605 case 0:
8606 gen_helper_mtc0_count(cpu_env, arg);
8607 rn = "Count";
8608 break;
8609 /* 6,7 are implementation dependent */
8610 default:
8611 goto cp0_unimplemented;
8613 /* Stop translation as we may have switched the execution mode */
8614 ctx->base.is_jmp = DISAS_STOP;
8615 break;
8616 case 10:
8617 switch (sel) {
8618 case 0:
8619 gen_helper_mtc0_entryhi(cpu_env, arg);
8620 rn = "EntryHi";
8621 break;
8622 default:
8623 goto cp0_unimplemented;
8625 break;
8626 case 11:
8627 switch (sel) {
8628 case 0:
8629 gen_helper_mtc0_compare(cpu_env, arg);
8630 rn = "Compare";
8631 break;
8632 /* 6,7 are implementation dependent */
8633 default:
8634 goto cp0_unimplemented;
8636 /* Stop translation as we may have switched the execution mode */
8637 ctx->base.is_jmp = DISAS_STOP;
8638 break;
8639 case 12:
8640 switch (sel) {
8641 case 0:
8642 save_cpu_state(ctx, 1);
8643 gen_helper_mtc0_status(cpu_env, arg);
8644 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8645 gen_save_pc(ctx->base.pc_next + 4);
8646 ctx->base.is_jmp = DISAS_EXIT;
8647 rn = "Status";
8648 break;
8649 case 1:
8650 check_insn(ctx, ISA_MIPS32R2);
8651 gen_helper_mtc0_intctl(cpu_env, arg);
8652 /* Stop translation as we may have switched the execution mode */
8653 ctx->base.is_jmp = DISAS_STOP;
8654 rn = "IntCtl";
8655 break;
8656 case 2:
8657 check_insn(ctx, ISA_MIPS32R2);
8658 gen_helper_mtc0_srsctl(cpu_env, arg);
8659 /* Stop translation as we may have switched the execution mode */
8660 ctx->base.is_jmp = DISAS_STOP;
8661 rn = "SRSCtl";
8662 break;
8663 case 3:
8664 check_insn(ctx, ISA_MIPS32R2);
8665 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8666 /* Stop translation as we may have switched the execution mode */
8667 ctx->base.is_jmp = DISAS_STOP;
8668 rn = "SRSMap";
8669 break;
8670 default:
8671 goto cp0_unimplemented;
8673 break;
8674 case 13:
8675 switch (sel) {
8676 case 0:
8677 save_cpu_state(ctx, 1);
8678 gen_helper_mtc0_cause(cpu_env, arg);
8679 /* Stop translation as we may have triggered an interrupt.
8680 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8681 * translated code to check for pending interrupts. */
8682 gen_save_pc(ctx->base.pc_next + 4);
8683 ctx->base.is_jmp = DISAS_EXIT;
8684 rn = "Cause";
8685 break;
8686 default:
8687 goto cp0_unimplemented;
8689 break;
8690 case 14:
8691 switch (sel) {
8692 case 0:
8693 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8694 rn = "EPC";
8695 break;
8696 default:
8697 goto cp0_unimplemented;
8699 break;
8700 case 15:
8701 switch (sel) {
8702 case 0:
8703 /* ignored */
8704 rn = "PRid";
8705 break;
8706 case 1:
8707 check_insn(ctx, ISA_MIPS32R2);
8708 gen_helper_mtc0_ebase(cpu_env, arg);
8709 rn = "EBase";
8710 break;
8711 default:
8712 goto cp0_unimplemented;
8714 break;
8715 case 16:
8716 switch (sel) {
8717 case 0:
8718 gen_helper_mtc0_config0(cpu_env, arg);
8719 rn = "Config";
8720 /* Stop translation as we may have switched the execution mode */
8721 ctx->base.is_jmp = DISAS_STOP;
8722 break;
8723 case 1:
8724 /* ignored, read only */
8725 rn = "Config1";
8726 break;
8727 case 2:
8728 gen_helper_mtc0_config2(cpu_env, arg);
8729 rn = "Config2";
8730 /* Stop translation as we may have switched the execution mode */
8731 ctx->base.is_jmp = DISAS_STOP;
8732 break;
8733 case 3:
8734 gen_helper_mtc0_config3(cpu_env, arg);
8735 rn = "Config3";
8736 /* Stop translation as we may have switched the execution mode */
8737 ctx->base.is_jmp = DISAS_STOP;
8738 break;
8739 case 4:
8740 /* currently ignored */
8741 rn = "Config4";
8742 break;
8743 case 5:
8744 gen_helper_mtc0_config5(cpu_env, arg);
8745 rn = "Config5";
8746 /* Stop translation as we may have switched the execution mode */
8747 ctx->base.is_jmp = DISAS_STOP;
8748 break;
8749 /* 6,7 are implementation dependent */
8750 default:
8751 rn = "Invalid config selector";
8752 goto cp0_unimplemented;
8754 break;
8755 case 17:
8756 switch (sel) {
8757 case 0:
8758 gen_helper_mtc0_lladdr(cpu_env, arg);
8759 rn = "LLAddr";
8760 break;
8761 case 1:
8762 CP0_CHECK(ctx->mrp);
8763 gen_helper_mtc0_maar(cpu_env, arg);
8764 rn = "MAAR";
8765 break;
8766 case 2:
8767 CP0_CHECK(ctx->mrp);
8768 gen_helper_mtc0_maari(cpu_env, arg);
8769 rn = "MAARI";
8770 break;
8771 default:
8772 goto cp0_unimplemented;
8774 break;
8775 case 18:
8776 switch (sel) {
8777 case 0:
8778 case 1:
8779 case 2:
8780 case 3:
8781 case 4:
8782 case 5:
8783 case 6:
8784 case 7:
8785 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8786 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8787 rn = "WatchLo";
8788 break;
8789 default:
8790 goto cp0_unimplemented;
8792 break;
8793 case 19:
8794 switch (sel) {
8795 case 0:
8796 case 1:
8797 case 2:
8798 case 3:
8799 case 4:
8800 case 5:
8801 case 6:
8802 case 7:
8803 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8804 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8805 rn = "WatchHi";
8806 break;
8807 default:
8808 goto cp0_unimplemented;
8810 break;
8811 case 20:
8812 switch (sel) {
8813 case 0:
8814 check_insn(ctx, ISA_MIPS3);
8815 gen_helper_mtc0_xcontext(cpu_env, arg);
8816 rn = "XContext";
8817 break;
8818 default:
8819 goto cp0_unimplemented;
8821 break;
8822 case 21:
8823 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8824 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8825 switch (sel) {
8826 case 0:
8827 gen_helper_mtc0_framemask(cpu_env, arg);
8828 rn = "Framemask";
8829 break;
8830 default:
8831 goto cp0_unimplemented;
8833 break;
8834 case 22:
8835 /* ignored */
8836 rn = "Diagnostic"; /* implementation dependent */
8837 break;
8838 case 23:
8839 switch (sel) {
8840 case 0:
8841 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8842 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8843 gen_save_pc(ctx->base.pc_next + 4);
8844 ctx->base.is_jmp = DISAS_EXIT;
8845 rn = "Debug";
8846 break;
8847 case 1:
8848 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
8849 /* Stop translation as we may have switched the execution mode */
8850 ctx->base.is_jmp = DISAS_STOP;
8851 rn = "TraceControl";
8852 goto cp0_unimplemented;
8853 case 2:
8854 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
8855 /* Stop translation as we may have switched the execution mode */
8856 ctx->base.is_jmp = DISAS_STOP;
8857 rn = "TraceControl2";
8858 goto cp0_unimplemented;
8859 case 3:
8860 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
8861 /* Stop translation as we may have switched the execution mode */
8862 ctx->base.is_jmp = DISAS_STOP;
8863 rn = "UserTraceData";
8864 goto cp0_unimplemented;
8865 case 4:
8866 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
8867 /* Stop translation as we may have switched the execution mode */
8868 ctx->base.is_jmp = DISAS_STOP;
8869 rn = "TraceBPC";
8870 goto cp0_unimplemented;
8871 default:
8872 goto cp0_unimplemented;
8874 break;
8875 case 24:
8876 switch (sel) {
8877 case 0:
8878 /* EJTAG support */
8879 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8880 rn = "DEPC";
8881 break;
8882 default:
8883 goto cp0_unimplemented;
8885 break;
8886 case 25:
8887 switch (sel) {
8888 case 0:
8889 gen_helper_mtc0_performance0(cpu_env, arg);
8890 rn = "Performance0";
8891 break;
8892 case 1:
8893 // gen_helper_mtc0_performance1(cpu_env, arg);
8894 rn = "Performance1";
8895 goto cp0_unimplemented;
8896 case 2:
8897 // gen_helper_mtc0_performance2(cpu_env, arg);
8898 rn = "Performance2";
8899 goto cp0_unimplemented;
8900 case 3:
8901 // gen_helper_mtc0_performance3(cpu_env, arg);
8902 rn = "Performance3";
8903 goto cp0_unimplemented;
8904 case 4:
8905 // gen_helper_mtc0_performance4(cpu_env, arg);
8906 rn = "Performance4";
8907 goto cp0_unimplemented;
8908 case 5:
8909 // gen_helper_mtc0_performance5(cpu_env, arg);
8910 rn = "Performance5";
8911 goto cp0_unimplemented;
8912 case 6:
8913 // gen_helper_mtc0_performance6(cpu_env, arg);
8914 rn = "Performance6";
8915 goto cp0_unimplemented;
8916 case 7:
8917 // gen_helper_mtc0_performance7(cpu_env, arg);
8918 rn = "Performance7";
8919 goto cp0_unimplemented;
8920 default:
8921 goto cp0_unimplemented;
8923 break;
8924 case 26:
8925 switch (sel) {
8926 case 0:
8927 gen_helper_mtc0_errctl(cpu_env, arg);
8928 ctx->base.is_jmp = DISAS_STOP;
8929 rn = "ErrCtl";
8930 break;
8931 default:
8932 goto cp0_unimplemented;
8934 break;
8935 case 27:
8936 switch (sel) {
8937 case 0:
8938 case 1:
8939 case 2:
8940 case 3:
8941 /* ignored */
8942 rn = "CacheErr";
8943 break;
8944 default:
8945 goto cp0_unimplemented;
8947 break;
8948 case 28:
8949 switch (sel) {
8950 case 0:
8951 case 2:
8952 case 4:
8953 case 6:
8954 gen_helper_mtc0_taglo(cpu_env, arg);
8955 rn = "TagLo";
8956 break;
8957 case 1:
8958 case 3:
8959 case 5:
8960 case 7:
8961 gen_helper_mtc0_datalo(cpu_env, arg);
8962 rn = "DataLo";
8963 break;
8964 default:
8965 goto cp0_unimplemented;
8967 break;
8968 case 29:
8969 switch (sel) {
8970 case 0:
8971 case 2:
8972 case 4:
8973 case 6:
8974 gen_helper_mtc0_taghi(cpu_env, arg);
8975 rn = "TagHi";
8976 break;
8977 case 1:
8978 case 3:
8979 case 5:
8980 case 7:
8981 gen_helper_mtc0_datahi(cpu_env, arg);
8982 rn = "DataHi";
8983 break;
8984 default:
8985 rn = "invalid sel";
8986 goto cp0_unimplemented;
8988 break;
8989 case 30:
8990 switch (sel) {
8991 case 0:
8992 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8993 rn = "ErrorEPC";
8994 break;
8995 default:
8996 goto cp0_unimplemented;
8998 break;
8999 case 31:
9000 switch (sel) {
9001 case 0:
9002 /* EJTAG support */
9003 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9004 rn = "DESAVE";
9005 break;
9006 case 2:
9007 case 3:
9008 case 4:
9009 case 5:
9010 case 6:
9011 case 7:
9012 CP0_CHECK(ctx->kscrexist & (1 << sel));
9013 tcg_gen_st_tl(arg, cpu_env,
9014 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
9015 rn = "KScratch";
9016 break;
9017 default:
9018 goto cp0_unimplemented;
9020 break;
9021 default:
9022 goto cp0_unimplemented;
9024 trace_mips_translate_c0("dmtc0", rn, reg, sel);
9026 /* For simplicity assume that all writes can cause interrupts. */
9027 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9028 gen_io_end();
9029 /* DISAS_STOP isn't sufficient, we need to ensure we break out of
9030 * translated code to check for pending interrupts. */
9031 gen_save_pc(ctx->base.pc_next + 4);
9032 ctx->base.is_jmp = DISAS_EXIT;
9034 return;
9036 cp0_unimplemented:
9037 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9039 #endif /* TARGET_MIPS64 */
9041 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
9042 int u, int sel, int h)
9044 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9045 TCGv t0 = tcg_temp_local_new();
9047 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9048 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9049 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9050 tcg_gen_movi_tl(t0, -1);
9051 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9052 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9053 tcg_gen_movi_tl(t0, -1);
9054 else if (u == 0) {
9055 switch (rt) {
9056 case 1:
9057 switch (sel) {
9058 case 1:
9059 gen_helper_mftc0_vpecontrol(t0, cpu_env);
9060 break;
9061 case 2:
9062 gen_helper_mftc0_vpeconf0(t0, cpu_env);
9063 break;
9064 default:
9065 goto die;
9066 break;
9068 break;
9069 case 2:
9070 switch (sel) {
9071 case 1:
9072 gen_helper_mftc0_tcstatus(t0, cpu_env);
9073 break;
9074 case 2:
9075 gen_helper_mftc0_tcbind(t0, cpu_env);
9076 break;
9077 case 3:
9078 gen_helper_mftc0_tcrestart(t0, cpu_env);
9079 break;
9080 case 4:
9081 gen_helper_mftc0_tchalt(t0, cpu_env);
9082 break;
9083 case 5:
9084 gen_helper_mftc0_tccontext(t0, cpu_env);
9085 break;
9086 case 6:
9087 gen_helper_mftc0_tcschedule(t0, cpu_env);
9088 break;
9089 case 7:
9090 gen_helper_mftc0_tcschefback(t0, cpu_env);
9091 break;
9092 default:
9093 gen_mfc0(ctx, t0, rt, sel);
9094 break;
9096 break;
9097 case 10:
9098 switch (sel) {
9099 case 0:
9100 gen_helper_mftc0_entryhi(t0, cpu_env);
9101 break;
9102 default:
9103 gen_mfc0(ctx, t0, rt, sel);
9104 break;
9106 case 12:
9107 switch (sel) {
9108 case 0:
9109 gen_helper_mftc0_status(t0, cpu_env);
9110 break;
9111 default:
9112 gen_mfc0(ctx, t0, rt, sel);
9113 break;
9115 case 13:
9116 switch (sel) {
9117 case 0:
9118 gen_helper_mftc0_cause(t0, cpu_env);
9119 break;
9120 default:
9121 goto die;
9122 break;
9124 break;
9125 case 14:
9126 switch (sel) {
9127 case 0:
9128 gen_helper_mftc0_epc(t0, cpu_env);
9129 break;
9130 default:
9131 goto die;
9132 break;
9134 break;
9135 case 15:
9136 switch (sel) {
9137 case 1:
9138 gen_helper_mftc0_ebase(t0, cpu_env);
9139 break;
9140 default:
9141 goto die;
9142 break;
9144 break;
9145 case 16:
9146 switch (sel) {
9147 case 0:
9148 case 1:
9149 case 2:
9150 case 3:
9151 case 4:
9152 case 5:
9153 case 6:
9154 case 7:
9155 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9156 break;
9157 default:
9158 goto die;
9159 break;
9161 break;
9162 case 23:
9163 switch (sel) {
9164 case 0:
9165 gen_helper_mftc0_debug(t0, cpu_env);
9166 break;
9167 default:
9168 gen_mfc0(ctx, t0, rt, sel);
9169 break;
9171 break;
9172 default:
9173 gen_mfc0(ctx, t0, rt, sel);
9175 } else switch (sel) {
9176 /* GPR registers. */
9177 case 0:
9178 gen_helper_1e0i(mftgpr, t0, rt);
9179 break;
9180 /* Auxiliary CPU registers */
9181 case 1:
9182 switch (rt) {
9183 case 0:
9184 gen_helper_1e0i(mftlo, t0, 0);
9185 break;
9186 case 1:
9187 gen_helper_1e0i(mfthi, t0, 0);
9188 break;
9189 case 2:
9190 gen_helper_1e0i(mftacx, t0, 0);
9191 break;
9192 case 4:
9193 gen_helper_1e0i(mftlo, t0, 1);
9194 break;
9195 case 5:
9196 gen_helper_1e0i(mfthi, t0, 1);
9197 break;
9198 case 6:
9199 gen_helper_1e0i(mftacx, t0, 1);
9200 break;
9201 case 8:
9202 gen_helper_1e0i(mftlo, t0, 2);
9203 break;
9204 case 9:
9205 gen_helper_1e0i(mfthi, t0, 2);
9206 break;
9207 case 10:
9208 gen_helper_1e0i(mftacx, t0, 2);
9209 break;
9210 case 12:
9211 gen_helper_1e0i(mftlo, t0, 3);
9212 break;
9213 case 13:
9214 gen_helper_1e0i(mfthi, t0, 3);
9215 break;
9216 case 14:
9217 gen_helper_1e0i(mftacx, t0, 3);
9218 break;
9219 case 16:
9220 gen_helper_mftdsp(t0, cpu_env);
9221 break;
9222 default:
9223 goto die;
9225 break;
9226 /* Floating point (COP1). */
9227 case 2:
9228 /* XXX: For now we support only a single FPU context. */
9229 if (h == 0) {
9230 TCGv_i32 fp0 = tcg_temp_new_i32();
9232 gen_load_fpr32(ctx, fp0, rt);
9233 tcg_gen_ext_i32_tl(t0, fp0);
9234 tcg_temp_free_i32(fp0);
9235 } else {
9236 TCGv_i32 fp0 = tcg_temp_new_i32();
9238 gen_load_fpr32h(ctx, fp0, rt);
9239 tcg_gen_ext_i32_tl(t0, fp0);
9240 tcg_temp_free_i32(fp0);
9242 break;
9243 case 3:
9244 /* XXX: For now we support only a single FPU context. */
9245 gen_helper_1e0i(cfc1, t0, rt);
9246 break;
9247 /* COP2: Not implemented. */
9248 case 4:
9249 case 5:
9250 /* fall through */
9251 default:
9252 goto die;
9254 trace_mips_translate_tr("mftr", rt, u, sel, h);
9255 gen_store_gpr(t0, rd);
9256 tcg_temp_free(t0);
9257 return;
9259 die:
9260 tcg_temp_free(t0);
9261 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9262 generate_exception_end(ctx, EXCP_RI);
9265 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9266 int u, int sel, int h)
9268 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9269 TCGv t0 = tcg_temp_local_new();
9271 gen_load_gpr(t0, rt);
9272 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9273 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9274 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
9275 /* NOP */ ;
9276 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9277 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
9278 /* NOP */ ;
9279 else if (u == 0) {
9280 switch (rd) {
9281 case 1:
9282 switch (sel) {
9283 case 1:
9284 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9285 break;
9286 case 2:
9287 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9288 break;
9289 default:
9290 goto die;
9291 break;
9293 break;
9294 case 2:
9295 switch (sel) {
9296 case 1:
9297 gen_helper_mttc0_tcstatus(cpu_env, t0);
9298 break;
9299 case 2:
9300 gen_helper_mttc0_tcbind(cpu_env, t0);
9301 break;
9302 case 3:
9303 gen_helper_mttc0_tcrestart(cpu_env, t0);
9304 break;
9305 case 4:
9306 gen_helper_mttc0_tchalt(cpu_env, t0);
9307 break;
9308 case 5:
9309 gen_helper_mttc0_tccontext(cpu_env, t0);
9310 break;
9311 case 6:
9312 gen_helper_mttc0_tcschedule(cpu_env, t0);
9313 break;
9314 case 7:
9315 gen_helper_mttc0_tcschefback(cpu_env, t0);
9316 break;
9317 default:
9318 gen_mtc0(ctx, t0, rd, sel);
9319 break;
9321 break;
9322 case 10:
9323 switch (sel) {
9324 case 0:
9325 gen_helper_mttc0_entryhi(cpu_env, t0);
9326 break;
9327 default:
9328 gen_mtc0(ctx, t0, rd, sel);
9329 break;
9331 case 12:
9332 switch (sel) {
9333 case 0:
9334 gen_helper_mttc0_status(cpu_env, t0);
9335 break;
9336 default:
9337 gen_mtc0(ctx, t0, rd, sel);
9338 break;
9340 case 13:
9341 switch (sel) {
9342 case 0:
9343 gen_helper_mttc0_cause(cpu_env, t0);
9344 break;
9345 default:
9346 goto die;
9347 break;
9349 break;
9350 case 15:
9351 switch (sel) {
9352 case 1:
9353 gen_helper_mttc0_ebase(cpu_env, t0);
9354 break;
9355 default:
9356 goto die;
9357 break;
9359 break;
9360 case 23:
9361 switch (sel) {
9362 case 0:
9363 gen_helper_mttc0_debug(cpu_env, t0);
9364 break;
9365 default:
9366 gen_mtc0(ctx, t0, rd, sel);
9367 break;
9369 break;
9370 default:
9371 gen_mtc0(ctx, t0, rd, sel);
9373 } else switch (sel) {
9374 /* GPR registers. */
9375 case 0:
9376 gen_helper_0e1i(mttgpr, t0, rd);
9377 break;
9378 /* Auxiliary CPU registers */
9379 case 1:
9380 switch (rd) {
9381 case 0:
9382 gen_helper_0e1i(mttlo, t0, 0);
9383 break;
9384 case 1:
9385 gen_helper_0e1i(mtthi, t0, 0);
9386 break;
9387 case 2:
9388 gen_helper_0e1i(mttacx, t0, 0);
9389 break;
9390 case 4:
9391 gen_helper_0e1i(mttlo, t0, 1);
9392 break;
9393 case 5:
9394 gen_helper_0e1i(mtthi, t0, 1);
9395 break;
9396 case 6:
9397 gen_helper_0e1i(mttacx, t0, 1);
9398 break;
9399 case 8:
9400 gen_helper_0e1i(mttlo, t0, 2);
9401 break;
9402 case 9:
9403 gen_helper_0e1i(mtthi, t0, 2);
9404 break;
9405 case 10:
9406 gen_helper_0e1i(mttacx, t0, 2);
9407 break;
9408 case 12:
9409 gen_helper_0e1i(mttlo, t0, 3);
9410 break;
9411 case 13:
9412 gen_helper_0e1i(mtthi, t0, 3);
9413 break;
9414 case 14:
9415 gen_helper_0e1i(mttacx, t0, 3);
9416 break;
9417 case 16:
9418 gen_helper_mttdsp(cpu_env, t0);
9419 break;
9420 default:
9421 goto die;
9423 break;
9424 /* Floating point (COP1). */
9425 case 2:
9426 /* XXX: For now we support only a single FPU context. */
9427 if (h == 0) {
9428 TCGv_i32 fp0 = tcg_temp_new_i32();
9430 tcg_gen_trunc_tl_i32(fp0, t0);
9431 gen_store_fpr32(ctx, fp0, rd);
9432 tcg_temp_free_i32(fp0);
9433 } else {
9434 TCGv_i32 fp0 = tcg_temp_new_i32();
9436 tcg_gen_trunc_tl_i32(fp0, t0);
9437 gen_store_fpr32h(ctx, fp0, rd);
9438 tcg_temp_free_i32(fp0);
9440 break;
9441 case 3:
9442 /* XXX: For now we support only a single FPU context. */
9444 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9446 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9447 tcg_temp_free_i32(fs_tmp);
9449 /* Stop translation as we may have changed hflags */
9450 ctx->base.is_jmp = DISAS_STOP;
9451 break;
9452 /* COP2: Not implemented. */
9453 case 4:
9454 case 5:
9455 /* fall through */
9456 default:
9457 goto die;
9459 trace_mips_translate_tr("mttr", rd, u, sel, h);
9460 tcg_temp_free(t0);
9461 return;
9463 die:
9464 tcg_temp_free(t0);
9465 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9466 generate_exception_end(ctx, EXCP_RI);
9469 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
9471 const char *opn = "ldst";
9473 check_cp0_enabled(ctx);
9474 switch (opc) {
9475 case OPC_MFC0:
9476 if (rt == 0) {
9477 /* Treat as NOP. */
9478 return;
9480 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9481 opn = "mfc0";
9482 break;
9483 case OPC_MTC0:
9485 TCGv t0 = tcg_temp_new();
9487 gen_load_gpr(t0, rt);
9488 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9489 tcg_temp_free(t0);
9491 opn = "mtc0";
9492 break;
9493 #if defined(TARGET_MIPS64)
9494 case OPC_DMFC0:
9495 check_insn(ctx, ISA_MIPS3);
9496 if (rt == 0) {
9497 /* Treat as NOP. */
9498 return;
9500 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9501 opn = "dmfc0";
9502 break;
9503 case OPC_DMTC0:
9504 check_insn(ctx, ISA_MIPS3);
9506 TCGv t0 = tcg_temp_new();
9508 gen_load_gpr(t0, rt);
9509 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9510 tcg_temp_free(t0);
9512 opn = "dmtc0";
9513 break;
9514 #endif
9515 case OPC_MFHC0:
9516 check_mvh(ctx);
9517 if (rt == 0) {
9518 /* Treat as NOP. */
9519 return;
9521 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9522 opn = "mfhc0";
9523 break;
9524 case OPC_MTHC0:
9525 check_mvh(ctx);
9527 TCGv t0 = tcg_temp_new();
9528 gen_load_gpr(t0, rt);
9529 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9530 tcg_temp_free(t0);
9532 opn = "mthc0";
9533 break;
9534 case OPC_MFTR:
9535 check_cp0_enabled(ctx);
9536 if (rd == 0) {
9537 /* Treat as NOP. */
9538 return;
9540 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9541 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9542 opn = "mftr";
9543 break;
9544 case OPC_MTTR:
9545 check_cp0_enabled(ctx);
9546 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9547 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9548 opn = "mttr";
9549 break;
9550 case OPC_TLBWI:
9551 opn = "tlbwi";
9552 if (!env->tlb->helper_tlbwi)
9553 goto die;
9554 gen_helper_tlbwi(cpu_env);
9555 break;
9556 case OPC_TLBINV:
9557 opn = "tlbinv";
9558 if (ctx->ie >= 2) {
9559 if (!env->tlb->helper_tlbinv) {
9560 goto die;
9562 gen_helper_tlbinv(cpu_env);
9563 } /* treat as nop if TLBINV not supported */
9564 break;
9565 case OPC_TLBINVF:
9566 opn = "tlbinvf";
9567 if (ctx->ie >= 2) {
9568 if (!env->tlb->helper_tlbinvf) {
9569 goto die;
9571 gen_helper_tlbinvf(cpu_env);
9572 } /* treat as nop if TLBINV not supported */
9573 break;
9574 case OPC_TLBWR:
9575 opn = "tlbwr";
9576 if (!env->tlb->helper_tlbwr)
9577 goto die;
9578 gen_helper_tlbwr(cpu_env);
9579 break;
9580 case OPC_TLBP:
9581 opn = "tlbp";
9582 if (!env->tlb->helper_tlbp)
9583 goto die;
9584 gen_helper_tlbp(cpu_env);
9585 break;
9586 case OPC_TLBR:
9587 opn = "tlbr";
9588 if (!env->tlb->helper_tlbr)
9589 goto die;
9590 gen_helper_tlbr(cpu_env);
9591 break;
9592 case OPC_ERET: /* OPC_ERETNC */
9593 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9594 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9595 goto die;
9596 } else {
9597 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9598 if (ctx->opcode & (1 << bit_shift)) {
9599 /* OPC_ERETNC */
9600 opn = "eretnc";
9601 check_insn(ctx, ISA_MIPS32R5);
9602 gen_helper_eretnc(cpu_env);
9603 } else {
9604 /* OPC_ERET */
9605 opn = "eret";
9606 check_insn(ctx, ISA_MIPS2);
9607 gen_helper_eret(cpu_env);
9609 ctx->base.is_jmp = DISAS_EXIT;
9611 break;
9612 case OPC_DERET:
9613 opn = "deret";
9614 check_insn(ctx, ISA_MIPS32);
9615 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9616 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9617 goto die;
9619 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9620 MIPS_INVAL(opn);
9621 generate_exception_end(ctx, EXCP_RI);
9622 } else {
9623 gen_helper_deret(cpu_env);
9624 ctx->base.is_jmp = DISAS_EXIT;
9626 break;
9627 case OPC_WAIT:
9628 opn = "wait";
9629 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
9630 if ((ctx->insn_flags & ISA_MIPS32R6) &&
9631 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9632 goto die;
9634 /* If we get an exception, we want to restart at next instruction */
9635 ctx->base.pc_next += 4;
9636 save_cpu_state(ctx, 1);
9637 ctx->base.pc_next -= 4;
9638 gen_helper_wait(cpu_env);
9639 ctx->base.is_jmp = DISAS_NORETURN;
9640 break;
9641 default:
9642 die:
9643 MIPS_INVAL(opn);
9644 generate_exception_end(ctx, EXCP_RI);
9645 return;
9647 (void)opn; /* avoid a compiler warning */
9649 #endif /* !CONFIG_USER_ONLY */
9651 /* CP1 Branches (before delay slot) */
9652 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9653 int32_t cc, int32_t offset)
9655 target_ulong btarget;
9656 TCGv_i32 t0 = tcg_temp_new_i32();
9658 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9659 generate_exception_end(ctx, EXCP_RI);
9660 goto out;
9663 if (cc != 0)
9664 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
9666 btarget = ctx->base.pc_next + 4 + offset;
9668 switch (op) {
9669 case OPC_BC1F:
9670 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9671 tcg_gen_not_i32(t0, t0);
9672 tcg_gen_andi_i32(t0, t0, 1);
9673 tcg_gen_extu_i32_tl(bcond, t0);
9674 goto not_likely;
9675 case OPC_BC1FL:
9676 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9677 tcg_gen_not_i32(t0, t0);
9678 tcg_gen_andi_i32(t0, t0, 1);
9679 tcg_gen_extu_i32_tl(bcond, t0);
9680 goto likely;
9681 case OPC_BC1T:
9682 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9683 tcg_gen_andi_i32(t0, t0, 1);
9684 tcg_gen_extu_i32_tl(bcond, t0);
9685 goto not_likely;
9686 case OPC_BC1TL:
9687 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9688 tcg_gen_andi_i32(t0, t0, 1);
9689 tcg_gen_extu_i32_tl(bcond, t0);
9690 likely:
9691 ctx->hflags |= MIPS_HFLAG_BL;
9692 break;
9693 case OPC_BC1FANY2:
9695 TCGv_i32 t1 = tcg_temp_new_i32();
9696 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9697 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9698 tcg_gen_nand_i32(t0, t0, t1);
9699 tcg_temp_free_i32(t1);
9700 tcg_gen_andi_i32(t0, t0, 1);
9701 tcg_gen_extu_i32_tl(bcond, t0);
9703 goto not_likely;
9704 case OPC_BC1TANY2:
9706 TCGv_i32 t1 = tcg_temp_new_i32();
9707 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9708 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9709 tcg_gen_or_i32(t0, t0, t1);
9710 tcg_temp_free_i32(t1);
9711 tcg_gen_andi_i32(t0, t0, 1);
9712 tcg_gen_extu_i32_tl(bcond, t0);
9714 goto not_likely;
9715 case OPC_BC1FANY4:
9717 TCGv_i32 t1 = tcg_temp_new_i32();
9718 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9719 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9720 tcg_gen_and_i32(t0, t0, t1);
9721 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9722 tcg_gen_and_i32(t0, t0, t1);
9723 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9724 tcg_gen_nand_i32(t0, t0, t1);
9725 tcg_temp_free_i32(t1);
9726 tcg_gen_andi_i32(t0, t0, 1);
9727 tcg_gen_extu_i32_tl(bcond, t0);
9729 goto not_likely;
9730 case OPC_BC1TANY4:
9732 TCGv_i32 t1 = tcg_temp_new_i32();
9733 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9734 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
9735 tcg_gen_or_i32(t0, t0, t1);
9736 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
9737 tcg_gen_or_i32(t0, t0, t1);
9738 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
9739 tcg_gen_or_i32(t0, t0, t1);
9740 tcg_temp_free_i32(t1);
9741 tcg_gen_andi_i32(t0, t0, 1);
9742 tcg_gen_extu_i32_tl(bcond, t0);
9744 not_likely:
9745 ctx->hflags |= MIPS_HFLAG_BC;
9746 break;
9747 default:
9748 MIPS_INVAL("cp1 cond branch");
9749 generate_exception_end(ctx, EXCP_RI);
9750 goto out;
9752 ctx->btarget = btarget;
9753 ctx->hflags |= MIPS_HFLAG_BDS32;
9754 out:
9755 tcg_temp_free_i32(t0);
9758 /* R6 CP1 Branches */
9759 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9760 int32_t ft, int32_t offset,
9761 int delayslot_size)
9763 target_ulong btarget;
9764 TCGv_i64 t0 = tcg_temp_new_i64();
9766 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9767 #ifdef MIPS_DEBUG_DISAS
9768 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9769 "\n", ctx->base.pc_next);
9770 #endif
9771 generate_exception_end(ctx, EXCP_RI);
9772 goto out;
9775 gen_load_fpr64(ctx, t0, ft);
9776 tcg_gen_andi_i64(t0, t0, 1);
9778 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9780 switch (op) {
9781 case OPC_BC1EQZ:
9782 tcg_gen_xori_i64(t0, t0, 1);
9783 ctx->hflags |= MIPS_HFLAG_BC;
9784 break;
9785 case OPC_BC1NEZ:
9786 /* t0 already set */
9787 ctx->hflags |= MIPS_HFLAG_BC;
9788 break;
9789 default:
9790 MIPS_INVAL("cp1 cond branch");
9791 generate_exception_end(ctx, EXCP_RI);
9792 goto out;
9795 tcg_gen_trunc_i64_tl(bcond, t0);
9797 ctx->btarget = btarget;
9799 switch (delayslot_size) {
9800 case 2:
9801 ctx->hflags |= MIPS_HFLAG_BDS16;
9802 break;
9803 case 4:
9804 ctx->hflags |= MIPS_HFLAG_BDS32;
9805 break;
9808 out:
9809 tcg_temp_free_i64(t0);
9812 /* Coprocessor 1 (FPU) */
9814 #define FOP(func, fmt) (((fmt) << 21) | (func))
9816 enum fopcode {
9817 OPC_ADD_S = FOP(0, FMT_S),
9818 OPC_SUB_S = FOP(1, FMT_S),
9819 OPC_MUL_S = FOP(2, FMT_S),
9820 OPC_DIV_S = FOP(3, FMT_S),
9821 OPC_SQRT_S = FOP(4, FMT_S),
9822 OPC_ABS_S = FOP(5, FMT_S),
9823 OPC_MOV_S = FOP(6, FMT_S),
9824 OPC_NEG_S = FOP(7, FMT_S),
9825 OPC_ROUND_L_S = FOP(8, FMT_S),
9826 OPC_TRUNC_L_S = FOP(9, FMT_S),
9827 OPC_CEIL_L_S = FOP(10, FMT_S),
9828 OPC_FLOOR_L_S = FOP(11, FMT_S),
9829 OPC_ROUND_W_S = FOP(12, FMT_S),
9830 OPC_TRUNC_W_S = FOP(13, FMT_S),
9831 OPC_CEIL_W_S = FOP(14, FMT_S),
9832 OPC_FLOOR_W_S = FOP(15, FMT_S),
9833 OPC_SEL_S = FOP(16, FMT_S),
9834 OPC_MOVCF_S = FOP(17, FMT_S),
9835 OPC_MOVZ_S = FOP(18, FMT_S),
9836 OPC_MOVN_S = FOP(19, FMT_S),
9837 OPC_SELEQZ_S = FOP(20, FMT_S),
9838 OPC_RECIP_S = FOP(21, FMT_S),
9839 OPC_RSQRT_S = FOP(22, FMT_S),
9840 OPC_SELNEZ_S = FOP(23, FMT_S),
9841 OPC_MADDF_S = FOP(24, FMT_S),
9842 OPC_MSUBF_S = FOP(25, FMT_S),
9843 OPC_RINT_S = FOP(26, FMT_S),
9844 OPC_CLASS_S = FOP(27, FMT_S),
9845 OPC_MIN_S = FOP(28, FMT_S),
9846 OPC_RECIP2_S = FOP(28, FMT_S),
9847 OPC_MINA_S = FOP(29, FMT_S),
9848 OPC_RECIP1_S = FOP(29, FMT_S),
9849 OPC_MAX_S = FOP(30, FMT_S),
9850 OPC_RSQRT1_S = FOP(30, FMT_S),
9851 OPC_MAXA_S = FOP(31, FMT_S),
9852 OPC_RSQRT2_S = FOP(31, FMT_S),
9853 OPC_CVT_D_S = FOP(33, FMT_S),
9854 OPC_CVT_W_S = FOP(36, FMT_S),
9855 OPC_CVT_L_S = FOP(37, FMT_S),
9856 OPC_CVT_PS_S = FOP(38, FMT_S),
9857 OPC_CMP_F_S = FOP (48, FMT_S),
9858 OPC_CMP_UN_S = FOP (49, FMT_S),
9859 OPC_CMP_EQ_S = FOP (50, FMT_S),
9860 OPC_CMP_UEQ_S = FOP (51, FMT_S),
9861 OPC_CMP_OLT_S = FOP (52, FMT_S),
9862 OPC_CMP_ULT_S = FOP (53, FMT_S),
9863 OPC_CMP_OLE_S = FOP (54, FMT_S),
9864 OPC_CMP_ULE_S = FOP (55, FMT_S),
9865 OPC_CMP_SF_S = FOP (56, FMT_S),
9866 OPC_CMP_NGLE_S = FOP (57, FMT_S),
9867 OPC_CMP_SEQ_S = FOP (58, FMT_S),
9868 OPC_CMP_NGL_S = FOP (59, FMT_S),
9869 OPC_CMP_LT_S = FOP (60, FMT_S),
9870 OPC_CMP_NGE_S = FOP (61, FMT_S),
9871 OPC_CMP_LE_S = FOP (62, FMT_S),
9872 OPC_CMP_NGT_S = FOP (63, FMT_S),
9874 OPC_ADD_D = FOP(0, FMT_D),
9875 OPC_SUB_D = FOP(1, FMT_D),
9876 OPC_MUL_D = FOP(2, FMT_D),
9877 OPC_DIV_D = FOP(3, FMT_D),
9878 OPC_SQRT_D = FOP(4, FMT_D),
9879 OPC_ABS_D = FOP(5, FMT_D),
9880 OPC_MOV_D = FOP(6, FMT_D),
9881 OPC_NEG_D = FOP(7, FMT_D),
9882 OPC_ROUND_L_D = FOP(8, FMT_D),
9883 OPC_TRUNC_L_D = FOP(9, FMT_D),
9884 OPC_CEIL_L_D = FOP(10, FMT_D),
9885 OPC_FLOOR_L_D = FOP(11, FMT_D),
9886 OPC_ROUND_W_D = FOP(12, FMT_D),
9887 OPC_TRUNC_W_D = FOP(13, FMT_D),
9888 OPC_CEIL_W_D = FOP(14, FMT_D),
9889 OPC_FLOOR_W_D = FOP(15, FMT_D),
9890 OPC_SEL_D = FOP(16, FMT_D),
9891 OPC_MOVCF_D = FOP(17, FMT_D),
9892 OPC_MOVZ_D = FOP(18, FMT_D),
9893 OPC_MOVN_D = FOP(19, FMT_D),
9894 OPC_SELEQZ_D = FOP(20, FMT_D),
9895 OPC_RECIP_D = FOP(21, FMT_D),
9896 OPC_RSQRT_D = FOP(22, FMT_D),
9897 OPC_SELNEZ_D = FOP(23, FMT_D),
9898 OPC_MADDF_D = FOP(24, FMT_D),
9899 OPC_MSUBF_D = FOP(25, FMT_D),
9900 OPC_RINT_D = FOP(26, FMT_D),
9901 OPC_CLASS_D = FOP(27, FMT_D),
9902 OPC_MIN_D = FOP(28, FMT_D),
9903 OPC_RECIP2_D = FOP(28, FMT_D),
9904 OPC_MINA_D = FOP(29, FMT_D),
9905 OPC_RECIP1_D = FOP(29, FMT_D),
9906 OPC_MAX_D = FOP(30, FMT_D),
9907 OPC_RSQRT1_D = FOP(30, FMT_D),
9908 OPC_MAXA_D = FOP(31, FMT_D),
9909 OPC_RSQRT2_D = FOP(31, FMT_D),
9910 OPC_CVT_S_D = FOP(32, FMT_D),
9911 OPC_CVT_W_D = FOP(36, FMT_D),
9912 OPC_CVT_L_D = FOP(37, FMT_D),
9913 OPC_CMP_F_D = FOP (48, FMT_D),
9914 OPC_CMP_UN_D = FOP (49, FMT_D),
9915 OPC_CMP_EQ_D = FOP (50, FMT_D),
9916 OPC_CMP_UEQ_D = FOP (51, FMT_D),
9917 OPC_CMP_OLT_D = FOP (52, FMT_D),
9918 OPC_CMP_ULT_D = FOP (53, FMT_D),
9919 OPC_CMP_OLE_D = FOP (54, FMT_D),
9920 OPC_CMP_ULE_D = FOP (55, FMT_D),
9921 OPC_CMP_SF_D = FOP (56, FMT_D),
9922 OPC_CMP_NGLE_D = FOP (57, FMT_D),
9923 OPC_CMP_SEQ_D = FOP (58, FMT_D),
9924 OPC_CMP_NGL_D = FOP (59, FMT_D),
9925 OPC_CMP_LT_D = FOP (60, FMT_D),
9926 OPC_CMP_NGE_D = FOP (61, FMT_D),
9927 OPC_CMP_LE_D = FOP (62, FMT_D),
9928 OPC_CMP_NGT_D = FOP (63, FMT_D),
9930 OPC_CVT_S_W = FOP(32, FMT_W),
9931 OPC_CVT_D_W = FOP(33, FMT_W),
9932 OPC_CVT_S_L = FOP(32, FMT_L),
9933 OPC_CVT_D_L = FOP(33, FMT_L),
9934 OPC_CVT_PS_PW = FOP(38, FMT_W),
9936 OPC_ADD_PS = FOP(0, FMT_PS),
9937 OPC_SUB_PS = FOP(1, FMT_PS),
9938 OPC_MUL_PS = FOP(2, FMT_PS),
9939 OPC_DIV_PS = FOP(3, FMT_PS),
9940 OPC_ABS_PS = FOP(5, FMT_PS),
9941 OPC_MOV_PS = FOP(6, FMT_PS),
9942 OPC_NEG_PS = FOP(7, FMT_PS),
9943 OPC_MOVCF_PS = FOP(17, FMT_PS),
9944 OPC_MOVZ_PS = FOP(18, FMT_PS),
9945 OPC_MOVN_PS = FOP(19, FMT_PS),
9946 OPC_ADDR_PS = FOP(24, FMT_PS),
9947 OPC_MULR_PS = FOP(26, FMT_PS),
9948 OPC_RECIP2_PS = FOP(28, FMT_PS),
9949 OPC_RECIP1_PS = FOP(29, FMT_PS),
9950 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9951 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9953 OPC_CVT_S_PU = FOP(32, FMT_PS),
9954 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9955 OPC_CVT_S_PL = FOP(40, FMT_PS),
9956 OPC_PLL_PS = FOP(44, FMT_PS),
9957 OPC_PLU_PS = FOP(45, FMT_PS),
9958 OPC_PUL_PS = FOP(46, FMT_PS),
9959 OPC_PUU_PS = FOP(47, FMT_PS),
9960 OPC_CMP_F_PS = FOP (48, FMT_PS),
9961 OPC_CMP_UN_PS = FOP (49, FMT_PS),
9962 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
9963 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
9964 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
9965 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
9966 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
9967 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
9968 OPC_CMP_SF_PS = FOP (56, FMT_PS),
9969 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
9970 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
9971 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
9972 OPC_CMP_LT_PS = FOP (60, FMT_PS),
9973 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
9974 OPC_CMP_LE_PS = FOP (62, FMT_PS),
9975 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
9978 enum r6_f_cmp_op {
9979 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9980 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9981 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9982 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9983 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9984 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9985 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9986 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9987 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9988 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9989 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9990 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9991 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9992 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9993 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9994 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9995 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9996 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9997 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9998 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9999 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
10000 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
10002 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
10003 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
10004 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
10005 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
10006 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
10007 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
10008 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
10009 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
10010 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
10011 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
10012 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
10013 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
10014 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
10015 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
10016 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
10017 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
10018 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
10019 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
10020 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
10021 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
10022 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
10023 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
10025 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
10027 TCGv t0 = tcg_temp_new();
10029 switch (opc) {
10030 case OPC_MFC1:
10032 TCGv_i32 fp0 = tcg_temp_new_i32();
10034 gen_load_fpr32(ctx, fp0, fs);
10035 tcg_gen_ext_i32_tl(t0, fp0);
10036 tcg_temp_free_i32(fp0);
10038 gen_store_gpr(t0, rt);
10039 break;
10040 case OPC_MTC1:
10041 gen_load_gpr(t0, rt);
10043 TCGv_i32 fp0 = tcg_temp_new_i32();
10045 tcg_gen_trunc_tl_i32(fp0, t0);
10046 gen_store_fpr32(ctx, fp0, fs);
10047 tcg_temp_free_i32(fp0);
10049 break;
10050 case OPC_CFC1:
10051 gen_helper_1e0i(cfc1, t0, fs);
10052 gen_store_gpr(t0, rt);
10053 break;
10054 case OPC_CTC1:
10055 gen_load_gpr(t0, rt);
10056 save_cpu_state(ctx, 0);
10058 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10060 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10061 tcg_temp_free_i32(fs_tmp);
10063 /* Stop translation as we may have changed hflags */
10064 ctx->base.is_jmp = DISAS_STOP;
10065 break;
10066 #if defined(TARGET_MIPS64)
10067 case OPC_DMFC1:
10068 gen_load_fpr64(ctx, t0, fs);
10069 gen_store_gpr(t0, rt);
10070 break;
10071 case OPC_DMTC1:
10072 gen_load_gpr(t0, rt);
10073 gen_store_fpr64(ctx, t0, fs);
10074 break;
10075 #endif
10076 case OPC_MFHC1:
10078 TCGv_i32 fp0 = tcg_temp_new_i32();
10080 gen_load_fpr32h(ctx, fp0, fs);
10081 tcg_gen_ext_i32_tl(t0, fp0);
10082 tcg_temp_free_i32(fp0);
10084 gen_store_gpr(t0, rt);
10085 break;
10086 case OPC_MTHC1:
10087 gen_load_gpr(t0, rt);
10089 TCGv_i32 fp0 = tcg_temp_new_i32();
10091 tcg_gen_trunc_tl_i32(fp0, t0);
10092 gen_store_fpr32h(ctx, fp0, fs);
10093 tcg_temp_free_i32(fp0);
10095 break;
10096 default:
10097 MIPS_INVAL("cp1 move");
10098 generate_exception_end(ctx, EXCP_RI);
10099 goto out;
10102 out:
10103 tcg_temp_free(t0);
10106 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
10108 TCGLabel *l1;
10109 TCGCond cond;
10110 TCGv_i32 t0;
10112 if (rd == 0) {
10113 /* Treat as NOP. */
10114 return;
10117 if (tf)
10118 cond = TCG_COND_EQ;
10119 else
10120 cond = TCG_COND_NE;
10122 l1 = gen_new_label();
10123 t0 = tcg_temp_new_i32();
10124 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10125 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10126 tcg_temp_free_i32(t0);
10127 if (rs == 0) {
10128 tcg_gen_movi_tl(cpu_gpr[rd], 0);
10129 } else {
10130 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
10132 gen_set_label(l1);
10135 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10136 int tf)
10138 int cond;
10139 TCGv_i32 t0 = tcg_temp_new_i32();
10140 TCGLabel *l1 = gen_new_label();
10142 if (tf)
10143 cond = TCG_COND_EQ;
10144 else
10145 cond = TCG_COND_NE;
10147 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10148 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10149 gen_load_fpr32(ctx, t0, fs);
10150 gen_store_fpr32(ctx, t0, fd);
10151 gen_set_label(l1);
10152 tcg_temp_free_i32(t0);
10155 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
10157 int cond;
10158 TCGv_i32 t0 = tcg_temp_new_i32();
10159 TCGv_i64 fp0;
10160 TCGLabel *l1 = gen_new_label();
10162 if (tf)
10163 cond = TCG_COND_EQ;
10164 else
10165 cond = TCG_COND_NE;
10167 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10168 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10169 tcg_temp_free_i32(t0);
10170 fp0 = tcg_temp_new_i64();
10171 gen_load_fpr64(ctx, fp0, fs);
10172 gen_store_fpr64(ctx, fp0, fd);
10173 tcg_temp_free_i64(fp0);
10174 gen_set_label(l1);
10177 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10178 int cc, int tf)
10180 int cond;
10181 TCGv_i32 t0 = tcg_temp_new_i32();
10182 TCGLabel *l1 = gen_new_label();
10183 TCGLabel *l2 = gen_new_label();
10185 if (tf)
10186 cond = TCG_COND_EQ;
10187 else
10188 cond = TCG_COND_NE;
10190 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10191 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10192 gen_load_fpr32(ctx, t0, fs);
10193 gen_store_fpr32(ctx, t0, fd);
10194 gen_set_label(l1);
10196 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
10197 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10198 gen_load_fpr32h(ctx, t0, fs);
10199 gen_store_fpr32h(ctx, t0, fd);
10200 tcg_temp_free_i32(t0);
10201 gen_set_label(l2);
10204 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10205 int fs)
10207 TCGv_i32 t1 = tcg_const_i32(0);
10208 TCGv_i32 fp0 = tcg_temp_new_i32();
10209 TCGv_i32 fp1 = tcg_temp_new_i32();
10210 TCGv_i32 fp2 = tcg_temp_new_i32();
10211 gen_load_fpr32(ctx, fp0, fd);
10212 gen_load_fpr32(ctx, fp1, ft);
10213 gen_load_fpr32(ctx, fp2, fs);
10215 switch (op1) {
10216 case OPC_SEL_S:
10217 tcg_gen_andi_i32(fp0, fp0, 1);
10218 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10219 break;
10220 case OPC_SELEQZ_S:
10221 tcg_gen_andi_i32(fp1, fp1, 1);
10222 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10223 break;
10224 case OPC_SELNEZ_S:
10225 tcg_gen_andi_i32(fp1, fp1, 1);
10226 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10227 break;
10228 default:
10229 MIPS_INVAL("gen_sel_s");
10230 generate_exception_end(ctx, EXCP_RI);
10231 break;
10234 gen_store_fpr32(ctx, fp0, fd);
10235 tcg_temp_free_i32(fp2);
10236 tcg_temp_free_i32(fp1);
10237 tcg_temp_free_i32(fp0);
10238 tcg_temp_free_i32(t1);
10241 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10242 int fs)
10244 TCGv_i64 t1 = tcg_const_i64(0);
10245 TCGv_i64 fp0 = tcg_temp_new_i64();
10246 TCGv_i64 fp1 = tcg_temp_new_i64();
10247 TCGv_i64 fp2 = tcg_temp_new_i64();
10248 gen_load_fpr64(ctx, fp0, fd);
10249 gen_load_fpr64(ctx, fp1, ft);
10250 gen_load_fpr64(ctx, fp2, fs);
10252 switch (op1) {
10253 case OPC_SEL_D:
10254 tcg_gen_andi_i64(fp0, fp0, 1);
10255 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10256 break;
10257 case OPC_SELEQZ_D:
10258 tcg_gen_andi_i64(fp1, fp1, 1);
10259 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10260 break;
10261 case OPC_SELNEZ_D:
10262 tcg_gen_andi_i64(fp1, fp1, 1);
10263 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10264 break;
10265 default:
10266 MIPS_INVAL("gen_sel_d");
10267 generate_exception_end(ctx, EXCP_RI);
10268 break;
10271 gen_store_fpr64(ctx, fp0, fd);
10272 tcg_temp_free_i64(fp2);
10273 tcg_temp_free_i64(fp1);
10274 tcg_temp_free_i64(fp0);
10275 tcg_temp_free_i64(t1);
10278 static void gen_farith (DisasContext *ctx, enum fopcode op1,
10279 int ft, int fs, int fd, int cc)
10281 uint32_t func = ctx->opcode & 0x3f;
10282 switch (op1) {
10283 case OPC_ADD_S:
10285 TCGv_i32 fp0 = tcg_temp_new_i32();
10286 TCGv_i32 fp1 = tcg_temp_new_i32();
10288 gen_load_fpr32(ctx, fp0, fs);
10289 gen_load_fpr32(ctx, fp1, ft);
10290 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10291 tcg_temp_free_i32(fp1);
10292 gen_store_fpr32(ctx, fp0, fd);
10293 tcg_temp_free_i32(fp0);
10295 break;
10296 case OPC_SUB_S:
10298 TCGv_i32 fp0 = tcg_temp_new_i32();
10299 TCGv_i32 fp1 = tcg_temp_new_i32();
10301 gen_load_fpr32(ctx, fp0, fs);
10302 gen_load_fpr32(ctx, fp1, ft);
10303 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10304 tcg_temp_free_i32(fp1);
10305 gen_store_fpr32(ctx, fp0, fd);
10306 tcg_temp_free_i32(fp0);
10308 break;
10309 case OPC_MUL_S:
10311 TCGv_i32 fp0 = tcg_temp_new_i32();
10312 TCGv_i32 fp1 = tcg_temp_new_i32();
10314 gen_load_fpr32(ctx, fp0, fs);
10315 gen_load_fpr32(ctx, fp1, ft);
10316 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10317 tcg_temp_free_i32(fp1);
10318 gen_store_fpr32(ctx, fp0, fd);
10319 tcg_temp_free_i32(fp0);
10321 break;
10322 case OPC_DIV_S:
10324 TCGv_i32 fp0 = tcg_temp_new_i32();
10325 TCGv_i32 fp1 = tcg_temp_new_i32();
10327 gen_load_fpr32(ctx, fp0, fs);
10328 gen_load_fpr32(ctx, fp1, ft);
10329 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10330 tcg_temp_free_i32(fp1);
10331 gen_store_fpr32(ctx, fp0, fd);
10332 tcg_temp_free_i32(fp0);
10334 break;
10335 case OPC_SQRT_S:
10337 TCGv_i32 fp0 = tcg_temp_new_i32();
10339 gen_load_fpr32(ctx, fp0, fs);
10340 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10341 gen_store_fpr32(ctx, fp0, fd);
10342 tcg_temp_free_i32(fp0);
10344 break;
10345 case OPC_ABS_S:
10347 TCGv_i32 fp0 = tcg_temp_new_i32();
10349 gen_load_fpr32(ctx, fp0, fs);
10350 if (ctx->abs2008) {
10351 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10352 } else {
10353 gen_helper_float_abs_s(fp0, fp0);
10355 gen_store_fpr32(ctx, fp0, fd);
10356 tcg_temp_free_i32(fp0);
10358 break;
10359 case OPC_MOV_S:
10361 TCGv_i32 fp0 = tcg_temp_new_i32();
10363 gen_load_fpr32(ctx, fp0, fs);
10364 gen_store_fpr32(ctx, fp0, fd);
10365 tcg_temp_free_i32(fp0);
10367 break;
10368 case OPC_NEG_S:
10370 TCGv_i32 fp0 = tcg_temp_new_i32();
10372 gen_load_fpr32(ctx, fp0, fs);
10373 if (ctx->abs2008) {
10374 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10375 } else {
10376 gen_helper_float_chs_s(fp0, fp0);
10378 gen_store_fpr32(ctx, fp0, fd);
10379 tcg_temp_free_i32(fp0);
10381 break;
10382 case OPC_ROUND_L_S:
10383 check_cp1_64bitmode(ctx);
10385 TCGv_i32 fp32 = tcg_temp_new_i32();
10386 TCGv_i64 fp64 = tcg_temp_new_i64();
10388 gen_load_fpr32(ctx, fp32, fs);
10389 if (ctx->nan2008) {
10390 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10391 } else {
10392 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10394 tcg_temp_free_i32(fp32);
10395 gen_store_fpr64(ctx, fp64, fd);
10396 tcg_temp_free_i64(fp64);
10398 break;
10399 case OPC_TRUNC_L_S:
10400 check_cp1_64bitmode(ctx);
10402 TCGv_i32 fp32 = tcg_temp_new_i32();
10403 TCGv_i64 fp64 = tcg_temp_new_i64();
10405 gen_load_fpr32(ctx, fp32, fs);
10406 if (ctx->nan2008) {
10407 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10408 } else {
10409 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10411 tcg_temp_free_i32(fp32);
10412 gen_store_fpr64(ctx, fp64, fd);
10413 tcg_temp_free_i64(fp64);
10415 break;
10416 case OPC_CEIL_L_S:
10417 check_cp1_64bitmode(ctx);
10419 TCGv_i32 fp32 = tcg_temp_new_i32();
10420 TCGv_i64 fp64 = tcg_temp_new_i64();
10422 gen_load_fpr32(ctx, fp32, fs);
10423 if (ctx->nan2008) {
10424 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10425 } else {
10426 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10428 tcg_temp_free_i32(fp32);
10429 gen_store_fpr64(ctx, fp64, fd);
10430 tcg_temp_free_i64(fp64);
10432 break;
10433 case OPC_FLOOR_L_S:
10434 check_cp1_64bitmode(ctx);
10436 TCGv_i32 fp32 = tcg_temp_new_i32();
10437 TCGv_i64 fp64 = tcg_temp_new_i64();
10439 gen_load_fpr32(ctx, fp32, fs);
10440 if (ctx->nan2008) {
10441 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10442 } else {
10443 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10445 tcg_temp_free_i32(fp32);
10446 gen_store_fpr64(ctx, fp64, fd);
10447 tcg_temp_free_i64(fp64);
10449 break;
10450 case OPC_ROUND_W_S:
10452 TCGv_i32 fp0 = tcg_temp_new_i32();
10454 gen_load_fpr32(ctx, fp0, fs);
10455 if (ctx->nan2008) {
10456 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10457 } else {
10458 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10460 gen_store_fpr32(ctx, fp0, fd);
10461 tcg_temp_free_i32(fp0);
10463 break;
10464 case OPC_TRUNC_W_S:
10466 TCGv_i32 fp0 = tcg_temp_new_i32();
10468 gen_load_fpr32(ctx, fp0, fs);
10469 if (ctx->nan2008) {
10470 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10471 } else {
10472 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10474 gen_store_fpr32(ctx, fp0, fd);
10475 tcg_temp_free_i32(fp0);
10477 break;
10478 case OPC_CEIL_W_S:
10480 TCGv_i32 fp0 = tcg_temp_new_i32();
10482 gen_load_fpr32(ctx, fp0, fs);
10483 if (ctx->nan2008) {
10484 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10485 } else {
10486 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10488 gen_store_fpr32(ctx, fp0, fd);
10489 tcg_temp_free_i32(fp0);
10491 break;
10492 case OPC_FLOOR_W_S:
10494 TCGv_i32 fp0 = tcg_temp_new_i32();
10496 gen_load_fpr32(ctx, fp0, fs);
10497 if (ctx->nan2008) {
10498 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10499 } else {
10500 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10502 gen_store_fpr32(ctx, fp0, fd);
10503 tcg_temp_free_i32(fp0);
10505 break;
10506 case OPC_SEL_S:
10507 check_insn(ctx, ISA_MIPS32R6);
10508 gen_sel_s(ctx, op1, fd, ft, fs);
10509 break;
10510 case OPC_SELEQZ_S:
10511 check_insn(ctx, ISA_MIPS32R6);
10512 gen_sel_s(ctx, op1, fd, ft, fs);
10513 break;
10514 case OPC_SELNEZ_S:
10515 check_insn(ctx, ISA_MIPS32R6);
10516 gen_sel_s(ctx, op1, fd, ft, fs);
10517 break;
10518 case OPC_MOVCF_S:
10519 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10520 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10521 break;
10522 case OPC_MOVZ_S:
10523 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10525 TCGLabel *l1 = gen_new_label();
10526 TCGv_i32 fp0;
10528 if (ft != 0) {
10529 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10531 fp0 = tcg_temp_new_i32();
10532 gen_load_fpr32(ctx, fp0, fs);
10533 gen_store_fpr32(ctx, fp0, fd);
10534 tcg_temp_free_i32(fp0);
10535 gen_set_label(l1);
10537 break;
10538 case OPC_MOVN_S:
10539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10541 TCGLabel *l1 = gen_new_label();
10542 TCGv_i32 fp0;
10544 if (ft != 0) {
10545 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10546 fp0 = tcg_temp_new_i32();
10547 gen_load_fpr32(ctx, fp0, fs);
10548 gen_store_fpr32(ctx, fp0, fd);
10549 tcg_temp_free_i32(fp0);
10550 gen_set_label(l1);
10553 break;
10554 case OPC_RECIP_S:
10556 TCGv_i32 fp0 = tcg_temp_new_i32();
10558 gen_load_fpr32(ctx, fp0, fs);
10559 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10560 gen_store_fpr32(ctx, fp0, fd);
10561 tcg_temp_free_i32(fp0);
10563 break;
10564 case OPC_RSQRT_S:
10566 TCGv_i32 fp0 = tcg_temp_new_i32();
10568 gen_load_fpr32(ctx, fp0, fs);
10569 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10570 gen_store_fpr32(ctx, fp0, fd);
10571 tcg_temp_free_i32(fp0);
10573 break;
10574 case OPC_MADDF_S:
10575 check_insn(ctx, ISA_MIPS32R6);
10577 TCGv_i32 fp0 = tcg_temp_new_i32();
10578 TCGv_i32 fp1 = tcg_temp_new_i32();
10579 TCGv_i32 fp2 = tcg_temp_new_i32();
10580 gen_load_fpr32(ctx, fp0, fs);
10581 gen_load_fpr32(ctx, fp1, ft);
10582 gen_load_fpr32(ctx, fp2, fd);
10583 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10584 gen_store_fpr32(ctx, fp2, fd);
10585 tcg_temp_free_i32(fp2);
10586 tcg_temp_free_i32(fp1);
10587 tcg_temp_free_i32(fp0);
10589 break;
10590 case OPC_MSUBF_S:
10591 check_insn(ctx, ISA_MIPS32R6);
10593 TCGv_i32 fp0 = tcg_temp_new_i32();
10594 TCGv_i32 fp1 = tcg_temp_new_i32();
10595 TCGv_i32 fp2 = tcg_temp_new_i32();
10596 gen_load_fpr32(ctx, fp0, fs);
10597 gen_load_fpr32(ctx, fp1, ft);
10598 gen_load_fpr32(ctx, fp2, fd);
10599 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10600 gen_store_fpr32(ctx, fp2, fd);
10601 tcg_temp_free_i32(fp2);
10602 tcg_temp_free_i32(fp1);
10603 tcg_temp_free_i32(fp0);
10605 break;
10606 case OPC_RINT_S:
10607 check_insn(ctx, ISA_MIPS32R6);
10609 TCGv_i32 fp0 = tcg_temp_new_i32();
10610 gen_load_fpr32(ctx, fp0, fs);
10611 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10612 gen_store_fpr32(ctx, fp0, fd);
10613 tcg_temp_free_i32(fp0);
10615 break;
10616 case OPC_CLASS_S:
10617 check_insn(ctx, ISA_MIPS32R6);
10619 TCGv_i32 fp0 = tcg_temp_new_i32();
10620 gen_load_fpr32(ctx, fp0, fs);
10621 gen_helper_float_class_s(fp0, cpu_env, fp0);
10622 gen_store_fpr32(ctx, fp0, fd);
10623 tcg_temp_free_i32(fp0);
10625 break;
10626 case OPC_MIN_S: /* OPC_RECIP2_S */
10627 if (ctx->insn_flags & ISA_MIPS32R6) {
10628 /* OPC_MIN_S */
10629 TCGv_i32 fp0 = tcg_temp_new_i32();
10630 TCGv_i32 fp1 = tcg_temp_new_i32();
10631 TCGv_i32 fp2 = tcg_temp_new_i32();
10632 gen_load_fpr32(ctx, fp0, fs);
10633 gen_load_fpr32(ctx, fp1, ft);
10634 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10635 gen_store_fpr32(ctx, fp2, fd);
10636 tcg_temp_free_i32(fp2);
10637 tcg_temp_free_i32(fp1);
10638 tcg_temp_free_i32(fp0);
10639 } else {
10640 /* OPC_RECIP2_S */
10641 check_cp1_64bitmode(ctx);
10643 TCGv_i32 fp0 = tcg_temp_new_i32();
10644 TCGv_i32 fp1 = tcg_temp_new_i32();
10646 gen_load_fpr32(ctx, fp0, fs);
10647 gen_load_fpr32(ctx, fp1, ft);
10648 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10649 tcg_temp_free_i32(fp1);
10650 gen_store_fpr32(ctx, fp0, fd);
10651 tcg_temp_free_i32(fp0);
10654 break;
10655 case OPC_MINA_S: /* OPC_RECIP1_S */
10656 if (ctx->insn_flags & ISA_MIPS32R6) {
10657 /* OPC_MINA_S */
10658 TCGv_i32 fp0 = tcg_temp_new_i32();
10659 TCGv_i32 fp1 = tcg_temp_new_i32();
10660 TCGv_i32 fp2 = tcg_temp_new_i32();
10661 gen_load_fpr32(ctx, fp0, fs);
10662 gen_load_fpr32(ctx, fp1, ft);
10663 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10664 gen_store_fpr32(ctx, fp2, fd);
10665 tcg_temp_free_i32(fp2);
10666 tcg_temp_free_i32(fp1);
10667 tcg_temp_free_i32(fp0);
10668 } else {
10669 /* OPC_RECIP1_S */
10670 check_cp1_64bitmode(ctx);
10672 TCGv_i32 fp0 = tcg_temp_new_i32();
10674 gen_load_fpr32(ctx, fp0, fs);
10675 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10676 gen_store_fpr32(ctx, fp0, fd);
10677 tcg_temp_free_i32(fp0);
10680 break;
10681 case OPC_MAX_S: /* OPC_RSQRT1_S */
10682 if (ctx->insn_flags & ISA_MIPS32R6) {
10683 /* OPC_MAX_S */
10684 TCGv_i32 fp0 = tcg_temp_new_i32();
10685 TCGv_i32 fp1 = tcg_temp_new_i32();
10686 gen_load_fpr32(ctx, fp0, fs);
10687 gen_load_fpr32(ctx, fp1, ft);
10688 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10689 gen_store_fpr32(ctx, fp1, fd);
10690 tcg_temp_free_i32(fp1);
10691 tcg_temp_free_i32(fp0);
10692 } else {
10693 /* OPC_RSQRT1_S */
10694 check_cp1_64bitmode(ctx);
10696 TCGv_i32 fp0 = tcg_temp_new_i32();
10698 gen_load_fpr32(ctx, fp0, fs);
10699 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10700 gen_store_fpr32(ctx, fp0, fd);
10701 tcg_temp_free_i32(fp0);
10704 break;
10705 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10706 if (ctx->insn_flags & ISA_MIPS32R6) {
10707 /* OPC_MAXA_S */
10708 TCGv_i32 fp0 = tcg_temp_new_i32();
10709 TCGv_i32 fp1 = tcg_temp_new_i32();
10710 gen_load_fpr32(ctx, fp0, fs);
10711 gen_load_fpr32(ctx, fp1, ft);
10712 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10713 gen_store_fpr32(ctx, fp1, fd);
10714 tcg_temp_free_i32(fp1);
10715 tcg_temp_free_i32(fp0);
10716 } else {
10717 /* OPC_RSQRT2_S */
10718 check_cp1_64bitmode(ctx);
10720 TCGv_i32 fp0 = tcg_temp_new_i32();
10721 TCGv_i32 fp1 = tcg_temp_new_i32();
10723 gen_load_fpr32(ctx, fp0, fs);
10724 gen_load_fpr32(ctx, fp1, ft);
10725 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10726 tcg_temp_free_i32(fp1);
10727 gen_store_fpr32(ctx, fp0, fd);
10728 tcg_temp_free_i32(fp0);
10731 break;
10732 case OPC_CVT_D_S:
10733 check_cp1_registers(ctx, fd);
10735 TCGv_i32 fp32 = tcg_temp_new_i32();
10736 TCGv_i64 fp64 = tcg_temp_new_i64();
10738 gen_load_fpr32(ctx, fp32, fs);
10739 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10740 tcg_temp_free_i32(fp32);
10741 gen_store_fpr64(ctx, fp64, fd);
10742 tcg_temp_free_i64(fp64);
10744 break;
10745 case OPC_CVT_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_cvt_2008_w_s(fp0, cpu_env, fp0);
10752 } else {
10753 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10755 gen_store_fpr32(ctx, fp0, fd);
10756 tcg_temp_free_i32(fp0);
10758 break;
10759 case OPC_CVT_L_S:
10760 check_cp1_64bitmode(ctx);
10762 TCGv_i32 fp32 = tcg_temp_new_i32();
10763 TCGv_i64 fp64 = tcg_temp_new_i64();
10765 gen_load_fpr32(ctx, fp32, fs);
10766 if (ctx->nan2008) {
10767 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10768 } else {
10769 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10771 tcg_temp_free_i32(fp32);
10772 gen_store_fpr64(ctx, fp64, fd);
10773 tcg_temp_free_i64(fp64);
10775 break;
10776 case OPC_CVT_PS_S:
10777 check_ps(ctx);
10779 TCGv_i64 fp64 = tcg_temp_new_i64();
10780 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10781 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10783 gen_load_fpr32(ctx, fp32_0, fs);
10784 gen_load_fpr32(ctx, fp32_1, ft);
10785 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10786 tcg_temp_free_i32(fp32_1);
10787 tcg_temp_free_i32(fp32_0);
10788 gen_store_fpr64(ctx, fp64, fd);
10789 tcg_temp_free_i64(fp64);
10791 break;
10792 case OPC_CMP_F_S:
10793 case OPC_CMP_UN_S:
10794 case OPC_CMP_EQ_S:
10795 case OPC_CMP_UEQ_S:
10796 case OPC_CMP_OLT_S:
10797 case OPC_CMP_ULT_S:
10798 case OPC_CMP_OLE_S:
10799 case OPC_CMP_ULE_S:
10800 case OPC_CMP_SF_S:
10801 case OPC_CMP_NGLE_S:
10802 case OPC_CMP_SEQ_S:
10803 case OPC_CMP_NGL_S:
10804 case OPC_CMP_LT_S:
10805 case OPC_CMP_NGE_S:
10806 case OPC_CMP_LE_S:
10807 case OPC_CMP_NGT_S:
10808 check_insn_opc_removed(ctx, ISA_MIPS32R6);
10809 if (ctx->opcode & (1 << 6)) {
10810 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
10811 } else {
10812 gen_cmp_s(ctx, func-48, ft, fs, cc);
10814 break;
10815 case OPC_ADD_D:
10816 check_cp1_registers(ctx, fs | ft | fd);
10818 TCGv_i64 fp0 = tcg_temp_new_i64();
10819 TCGv_i64 fp1 = tcg_temp_new_i64();
10821 gen_load_fpr64(ctx, fp0, fs);
10822 gen_load_fpr64(ctx, fp1, ft);
10823 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10824 tcg_temp_free_i64(fp1);
10825 gen_store_fpr64(ctx, fp0, fd);
10826 tcg_temp_free_i64(fp0);
10828 break;
10829 case OPC_SUB_D:
10830 check_cp1_registers(ctx, fs | ft | fd);
10832 TCGv_i64 fp0 = tcg_temp_new_i64();
10833 TCGv_i64 fp1 = tcg_temp_new_i64();
10835 gen_load_fpr64(ctx, fp0, fs);
10836 gen_load_fpr64(ctx, fp1, ft);
10837 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10838 tcg_temp_free_i64(fp1);
10839 gen_store_fpr64(ctx, fp0, fd);
10840 tcg_temp_free_i64(fp0);
10842 break;
10843 case OPC_MUL_D:
10844 check_cp1_registers(ctx, fs | ft | fd);
10846 TCGv_i64 fp0 = tcg_temp_new_i64();
10847 TCGv_i64 fp1 = tcg_temp_new_i64();
10849 gen_load_fpr64(ctx, fp0, fs);
10850 gen_load_fpr64(ctx, fp1, ft);
10851 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10852 tcg_temp_free_i64(fp1);
10853 gen_store_fpr64(ctx, fp0, fd);
10854 tcg_temp_free_i64(fp0);
10856 break;
10857 case OPC_DIV_D:
10858 check_cp1_registers(ctx, fs | ft | fd);
10860 TCGv_i64 fp0 = tcg_temp_new_i64();
10861 TCGv_i64 fp1 = tcg_temp_new_i64();
10863 gen_load_fpr64(ctx, fp0, fs);
10864 gen_load_fpr64(ctx, fp1, ft);
10865 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10866 tcg_temp_free_i64(fp1);
10867 gen_store_fpr64(ctx, fp0, fd);
10868 tcg_temp_free_i64(fp0);
10870 break;
10871 case OPC_SQRT_D:
10872 check_cp1_registers(ctx, fs | fd);
10874 TCGv_i64 fp0 = tcg_temp_new_i64();
10876 gen_load_fpr64(ctx, fp0, fs);
10877 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10878 gen_store_fpr64(ctx, fp0, fd);
10879 tcg_temp_free_i64(fp0);
10881 break;
10882 case OPC_ABS_D:
10883 check_cp1_registers(ctx, fs | fd);
10885 TCGv_i64 fp0 = tcg_temp_new_i64();
10887 gen_load_fpr64(ctx, fp0, fs);
10888 if (ctx->abs2008) {
10889 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10890 } else {
10891 gen_helper_float_abs_d(fp0, fp0);
10893 gen_store_fpr64(ctx, fp0, fd);
10894 tcg_temp_free_i64(fp0);
10896 break;
10897 case OPC_MOV_D:
10898 check_cp1_registers(ctx, fs | fd);
10900 TCGv_i64 fp0 = tcg_temp_new_i64();
10902 gen_load_fpr64(ctx, fp0, fs);
10903 gen_store_fpr64(ctx, fp0, fd);
10904 tcg_temp_free_i64(fp0);
10906 break;
10907 case OPC_NEG_D:
10908 check_cp1_registers(ctx, fs | fd);
10910 TCGv_i64 fp0 = tcg_temp_new_i64();
10912 gen_load_fpr64(ctx, fp0, fs);
10913 if (ctx->abs2008) {
10914 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10915 } else {
10916 gen_helper_float_chs_d(fp0, fp0);
10918 gen_store_fpr64(ctx, fp0, fd);
10919 tcg_temp_free_i64(fp0);
10921 break;
10922 case OPC_ROUND_L_D:
10923 check_cp1_64bitmode(ctx);
10925 TCGv_i64 fp0 = tcg_temp_new_i64();
10927 gen_load_fpr64(ctx, fp0, fs);
10928 if (ctx->nan2008) {
10929 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10930 } else {
10931 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10933 gen_store_fpr64(ctx, fp0, fd);
10934 tcg_temp_free_i64(fp0);
10936 break;
10937 case OPC_TRUNC_L_D:
10938 check_cp1_64bitmode(ctx);
10940 TCGv_i64 fp0 = tcg_temp_new_i64();
10942 gen_load_fpr64(ctx, fp0, fs);
10943 if (ctx->nan2008) {
10944 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10945 } else {
10946 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10948 gen_store_fpr64(ctx, fp0, fd);
10949 tcg_temp_free_i64(fp0);
10951 break;
10952 case OPC_CEIL_L_D:
10953 check_cp1_64bitmode(ctx);
10955 TCGv_i64 fp0 = tcg_temp_new_i64();
10957 gen_load_fpr64(ctx, fp0, fs);
10958 if (ctx->nan2008) {
10959 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10960 } else {
10961 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10963 gen_store_fpr64(ctx, fp0, fd);
10964 tcg_temp_free_i64(fp0);
10966 break;
10967 case OPC_FLOOR_L_D:
10968 check_cp1_64bitmode(ctx);
10970 TCGv_i64 fp0 = tcg_temp_new_i64();
10972 gen_load_fpr64(ctx, fp0, fs);
10973 if (ctx->nan2008) {
10974 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10975 } else {
10976 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10978 gen_store_fpr64(ctx, fp0, fd);
10979 tcg_temp_free_i64(fp0);
10981 break;
10982 case OPC_ROUND_W_D:
10983 check_cp1_registers(ctx, fs);
10985 TCGv_i32 fp32 = tcg_temp_new_i32();
10986 TCGv_i64 fp64 = tcg_temp_new_i64();
10988 gen_load_fpr64(ctx, fp64, fs);
10989 if (ctx->nan2008) {
10990 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10991 } else {
10992 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10994 tcg_temp_free_i64(fp64);
10995 gen_store_fpr32(ctx, fp32, fd);
10996 tcg_temp_free_i32(fp32);
10998 break;
10999 case OPC_TRUNC_W_D:
11000 check_cp1_registers(ctx, fs);
11002 TCGv_i32 fp32 = tcg_temp_new_i32();
11003 TCGv_i64 fp64 = tcg_temp_new_i64();
11005 gen_load_fpr64(ctx, fp64, fs);
11006 if (ctx->nan2008) {
11007 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
11008 } else {
11009 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
11011 tcg_temp_free_i64(fp64);
11012 gen_store_fpr32(ctx, fp32, fd);
11013 tcg_temp_free_i32(fp32);
11015 break;
11016 case OPC_CEIL_W_D:
11017 check_cp1_registers(ctx, fs);
11019 TCGv_i32 fp32 = tcg_temp_new_i32();
11020 TCGv_i64 fp64 = tcg_temp_new_i64();
11022 gen_load_fpr64(ctx, fp64, fs);
11023 if (ctx->nan2008) {
11024 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
11025 } else {
11026 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
11028 tcg_temp_free_i64(fp64);
11029 gen_store_fpr32(ctx, fp32, fd);
11030 tcg_temp_free_i32(fp32);
11032 break;
11033 case OPC_FLOOR_W_D:
11034 check_cp1_registers(ctx, fs);
11036 TCGv_i32 fp32 = tcg_temp_new_i32();
11037 TCGv_i64 fp64 = tcg_temp_new_i64();
11039 gen_load_fpr64(ctx, fp64, fs);
11040 if (ctx->nan2008) {
11041 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
11042 } else {
11043 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
11045 tcg_temp_free_i64(fp64);
11046 gen_store_fpr32(ctx, fp32, fd);
11047 tcg_temp_free_i32(fp32);
11049 break;
11050 case OPC_SEL_D:
11051 check_insn(ctx, ISA_MIPS32R6);
11052 gen_sel_d(ctx, op1, fd, ft, fs);
11053 break;
11054 case OPC_SELEQZ_D:
11055 check_insn(ctx, ISA_MIPS32R6);
11056 gen_sel_d(ctx, op1, fd, ft, fs);
11057 break;
11058 case OPC_SELNEZ_D:
11059 check_insn(ctx, ISA_MIPS32R6);
11060 gen_sel_d(ctx, op1, fd, ft, fs);
11061 break;
11062 case OPC_MOVCF_D:
11063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11064 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11065 break;
11066 case OPC_MOVZ_D:
11067 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11069 TCGLabel *l1 = gen_new_label();
11070 TCGv_i64 fp0;
11072 if (ft != 0) {
11073 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11075 fp0 = tcg_temp_new_i64();
11076 gen_load_fpr64(ctx, fp0, fs);
11077 gen_store_fpr64(ctx, fp0, fd);
11078 tcg_temp_free_i64(fp0);
11079 gen_set_label(l1);
11081 break;
11082 case OPC_MOVN_D:
11083 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11085 TCGLabel *l1 = gen_new_label();
11086 TCGv_i64 fp0;
11088 if (ft != 0) {
11089 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11090 fp0 = tcg_temp_new_i64();
11091 gen_load_fpr64(ctx, fp0, fs);
11092 gen_store_fpr64(ctx, fp0, fd);
11093 tcg_temp_free_i64(fp0);
11094 gen_set_label(l1);
11097 break;
11098 case OPC_RECIP_D:
11099 check_cp1_registers(ctx, fs | fd);
11101 TCGv_i64 fp0 = tcg_temp_new_i64();
11103 gen_load_fpr64(ctx, fp0, fs);
11104 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11105 gen_store_fpr64(ctx, fp0, fd);
11106 tcg_temp_free_i64(fp0);
11108 break;
11109 case OPC_RSQRT_D:
11110 check_cp1_registers(ctx, fs | fd);
11112 TCGv_i64 fp0 = tcg_temp_new_i64();
11114 gen_load_fpr64(ctx, fp0, fs);
11115 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11116 gen_store_fpr64(ctx, fp0, fd);
11117 tcg_temp_free_i64(fp0);
11119 break;
11120 case OPC_MADDF_D:
11121 check_insn(ctx, ISA_MIPS32R6);
11123 TCGv_i64 fp0 = tcg_temp_new_i64();
11124 TCGv_i64 fp1 = tcg_temp_new_i64();
11125 TCGv_i64 fp2 = tcg_temp_new_i64();
11126 gen_load_fpr64(ctx, fp0, fs);
11127 gen_load_fpr64(ctx, fp1, ft);
11128 gen_load_fpr64(ctx, fp2, fd);
11129 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11130 gen_store_fpr64(ctx, fp2, fd);
11131 tcg_temp_free_i64(fp2);
11132 tcg_temp_free_i64(fp1);
11133 tcg_temp_free_i64(fp0);
11135 break;
11136 case OPC_MSUBF_D:
11137 check_insn(ctx, ISA_MIPS32R6);
11139 TCGv_i64 fp0 = tcg_temp_new_i64();
11140 TCGv_i64 fp1 = tcg_temp_new_i64();
11141 TCGv_i64 fp2 = tcg_temp_new_i64();
11142 gen_load_fpr64(ctx, fp0, fs);
11143 gen_load_fpr64(ctx, fp1, ft);
11144 gen_load_fpr64(ctx, fp2, fd);
11145 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11146 gen_store_fpr64(ctx, fp2, fd);
11147 tcg_temp_free_i64(fp2);
11148 tcg_temp_free_i64(fp1);
11149 tcg_temp_free_i64(fp0);
11151 break;
11152 case OPC_RINT_D:
11153 check_insn(ctx, ISA_MIPS32R6);
11155 TCGv_i64 fp0 = tcg_temp_new_i64();
11156 gen_load_fpr64(ctx, fp0, fs);
11157 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11158 gen_store_fpr64(ctx, fp0, fd);
11159 tcg_temp_free_i64(fp0);
11161 break;
11162 case OPC_CLASS_D:
11163 check_insn(ctx, ISA_MIPS32R6);
11165 TCGv_i64 fp0 = tcg_temp_new_i64();
11166 gen_load_fpr64(ctx, fp0, fs);
11167 gen_helper_float_class_d(fp0, cpu_env, fp0);
11168 gen_store_fpr64(ctx, fp0, fd);
11169 tcg_temp_free_i64(fp0);
11171 break;
11172 case OPC_MIN_D: /* OPC_RECIP2_D */
11173 if (ctx->insn_flags & ISA_MIPS32R6) {
11174 /* OPC_MIN_D */
11175 TCGv_i64 fp0 = tcg_temp_new_i64();
11176 TCGv_i64 fp1 = tcg_temp_new_i64();
11177 gen_load_fpr64(ctx, fp0, fs);
11178 gen_load_fpr64(ctx, fp1, ft);
11179 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11180 gen_store_fpr64(ctx, fp1, fd);
11181 tcg_temp_free_i64(fp1);
11182 tcg_temp_free_i64(fp0);
11183 } else {
11184 /* OPC_RECIP2_D */
11185 check_cp1_64bitmode(ctx);
11187 TCGv_i64 fp0 = tcg_temp_new_i64();
11188 TCGv_i64 fp1 = tcg_temp_new_i64();
11190 gen_load_fpr64(ctx, fp0, fs);
11191 gen_load_fpr64(ctx, fp1, ft);
11192 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11193 tcg_temp_free_i64(fp1);
11194 gen_store_fpr64(ctx, fp0, fd);
11195 tcg_temp_free_i64(fp0);
11198 break;
11199 case OPC_MINA_D: /* OPC_RECIP1_D */
11200 if (ctx->insn_flags & ISA_MIPS32R6) {
11201 /* OPC_MINA_D */
11202 TCGv_i64 fp0 = tcg_temp_new_i64();
11203 TCGv_i64 fp1 = tcg_temp_new_i64();
11204 gen_load_fpr64(ctx, fp0, fs);
11205 gen_load_fpr64(ctx, fp1, ft);
11206 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11207 gen_store_fpr64(ctx, fp1, fd);
11208 tcg_temp_free_i64(fp1);
11209 tcg_temp_free_i64(fp0);
11210 } else {
11211 /* OPC_RECIP1_D */
11212 check_cp1_64bitmode(ctx);
11214 TCGv_i64 fp0 = tcg_temp_new_i64();
11216 gen_load_fpr64(ctx, fp0, fs);
11217 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11218 gen_store_fpr64(ctx, fp0, fd);
11219 tcg_temp_free_i64(fp0);
11222 break;
11223 case OPC_MAX_D: /* OPC_RSQRT1_D */
11224 if (ctx->insn_flags & ISA_MIPS32R6) {
11225 /* OPC_MAX_D */
11226 TCGv_i64 fp0 = tcg_temp_new_i64();
11227 TCGv_i64 fp1 = tcg_temp_new_i64();
11228 gen_load_fpr64(ctx, fp0, fs);
11229 gen_load_fpr64(ctx, fp1, ft);
11230 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11231 gen_store_fpr64(ctx, fp1, fd);
11232 tcg_temp_free_i64(fp1);
11233 tcg_temp_free_i64(fp0);
11234 } else {
11235 /* OPC_RSQRT1_D */
11236 check_cp1_64bitmode(ctx);
11238 TCGv_i64 fp0 = tcg_temp_new_i64();
11240 gen_load_fpr64(ctx, fp0, fs);
11241 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11242 gen_store_fpr64(ctx, fp0, fd);
11243 tcg_temp_free_i64(fp0);
11246 break;
11247 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11248 if (ctx->insn_flags & ISA_MIPS32R6) {
11249 /* OPC_MAXA_D */
11250 TCGv_i64 fp0 = tcg_temp_new_i64();
11251 TCGv_i64 fp1 = tcg_temp_new_i64();
11252 gen_load_fpr64(ctx, fp0, fs);
11253 gen_load_fpr64(ctx, fp1, ft);
11254 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11255 gen_store_fpr64(ctx, fp1, fd);
11256 tcg_temp_free_i64(fp1);
11257 tcg_temp_free_i64(fp0);
11258 } else {
11259 /* OPC_RSQRT2_D */
11260 check_cp1_64bitmode(ctx);
11262 TCGv_i64 fp0 = tcg_temp_new_i64();
11263 TCGv_i64 fp1 = tcg_temp_new_i64();
11265 gen_load_fpr64(ctx, fp0, fs);
11266 gen_load_fpr64(ctx, fp1, ft);
11267 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11268 tcg_temp_free_i64(fp1);
11269 gen_store_fpr64(ctx, fp0, fd);
11270 tcg_temp_free_i64(fp0);
11273 break;
11274 case OPC_CMP_F_D:
11275 case OPC_CMP_UN_D:
11276 case OPC_CMP_EQ_D:
11277 case OPC_CMP_UEQ_D:
11278 case OPC_CMP_OLT_D:
11279 case OPC_CMP_ULT_D:
11280 case OPC_CMP_OLE_D:
11281 case OPC_CMP_ULE_D:
11282 case OPC_CMP_SF_D:
11283 case OPC_CMP_NGLE_D:
11284 case OPC_CMP_SEQ_D:
11285 case OPC_CMP_NGL_D:
11286 case OPC_CMP_LT_D:
11287 case OPC_CMP_NGE_D:
11288 case OPC_CMP_LE_D:
11289 case OPC_CMP_NGT_D:
11290 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11291 if (ctx->opcode & (1 << 6)) {
11292 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
11293 } else {
11294 gen_cmp_d(ctx, func-48, ft, fs, cc);
11296 break;
11297 case OPC_CVT_S_D:
11298 check_cp1_registers(ctx, fs);
11300 TCGv_i32 fp32 = tcg_temp_new_i32();
11301 TCGv_i64 fp64 = tcg_temp_new_i64();
11303 gen_load_fpr64(ctx, fp64, fs);
11304 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11305 tcg_temp_free_i64(fp64);
11306 gen_store_fpr32(ctx, fp32, fd);
11307 tcg_temp_free_i32(fp32);
11309 break;
11310 case OPC_CVT_W_D:
11311 check_cp1_registers(ctx, fs);
11313 TCGv_i32 fp32 = tcg_temp_new_i32();
11314 TCGv_i64 fp64 = tcg_temp_new_i64();
11316 gen_load_fpr64(ctx, fp64, fs);
11317 if (ctx->nan2008) {
11318 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11319 } else {
11320 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11322 tcg_temp_free_i64(fp64);
11323 gen_store_fpr32(ctx, fp32, fd);
11324 tcg_temp_free_i32(fp32);
11326 break;
11327 case OPC_CVT_L_D:
11328 check_cp1_64bitmode(ctx);
11330 TCGv_i64 fp0 = tcg_temp_new_i64();
11332 gen_load_fpr64(ctx, fp0, fs);
11333 if (ctx->nan2008) {
11334 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11335 } else {
11336 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11338 gen_store_fpr64(ctx, fp0, fd);
11339 tcg_temp_free_i64(fp0);
11341 break;
11342 case OPC_CVT_S_W:
11344 TCGv_i32 fp0 = tcg_temp_new_i32();
11346 gen_load_fpr32(ctx, fp0, fs);
11347 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11348 gen_store_fpr32(ctx, fp0, fd);
11349 tcg_temp_free_i32(fp0);
11351 break;
11352 case OPC_CVT_D_W:
11353 check_cp1_registers(ctx, fd);
11355 TCGv_i32 fp32 = tcg_temp_new_i32();
11356 TCGv_i64 fp64 = tcg_temp_new_i64();
11358 gen_load_fpr32(ctx, fp32, fs);
11359 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11360 tcg_temp_free_i32(fp32);
11361 gen_store_fpr64(ctx, fp64, fd);
11362 tcg_temp_free_i64(fp64);
11364 break;
11365 case OPC_CVT_S_L:
11366 check_cp1_64bitmode(ctx);
11368 TCGv_i32 fp32 = tcg_temp_new_i32();
11369 TCGv_i64 fp64 = tcg_temp_new_i64();
11371 gen_load_fpr64(ctx, fp64, fs);
11372 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11373 tcg_temp_free_i64(fp64);
11374 gen_store_fpr32(ctx, fp32, fd);
11375 tcg_temp_free_i32(fp32);
11377 break;
11378 case OPC_CVT_D_L:
11379 check_cp1_64bitmode(ctx);
11381 TCGv_i64 fp0 = tcg_temp_new_i64();
11383 gen_load_fpr64(ctx, fp0, fs);
11384 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11385 gen_store_fpr64(ctx, fp0, fd);
11386 tcg_temp_free_i64(fp0);
11388 break;
11389 case OPC_CVT_PS_PW:
11390 check_ps(ctx);
11392 TCGv_i64 fp0 = tcg_temp_new_i64();
11394 gen_load_fpr64(ctx, fp0, fs);
11395 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11396 gen_store_fpr64(ctx, fp0, fd);
11397 tcg_temp_free_i64(fp0);
11399 break;
11400 case OPC_ADD_PS:
11401 check_ps(ctx);
11403 TCGv_i64 fp0 = tcg_temp_new_i64();
11404 TCGv_i64 fp1 = tcg_temp_new_i64();
11406 gen_load_fpr64(ctx, fp0, fs);
11407 gen_load_fpr64(ctx, fp1, ft);
11408 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11409 tcg_temp_free_i64(fp1);
11410 gen_store_fpr64(ctx, fp0, fd);
11411 tcg_temp_free_i64(fp0);
11413 break;
11414 case OPC_SUB_PS:
11415 check_ps(ctx);
11417 TCGv_i64 fp0 = tcg_temp_new_i64();
11418 TCGv_i64 fp1 = tcg_temp_new_i64();
11420 gen_load_fpr64(ctx, fp0, fs);
11421 gen_load_fpr64(ctx, fp1, ft);
11422 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11423 tcg_temp_free_i64(fp1);
11424 gen_store_fpr64(ctx, fp0, fd);
11425 tcg_temp_free_i64(fp0);
11427 break;
11428 case OPC_MUL_PS:
11429 check_ps(ctx);
11431 TCGv_i64 fp0 = tcg_temp_new_i64();
11432 TCGv_i64 fp1 = tcg_temp_new_i64();
11434 gen_load_fpr64(ctx, fp0, fs);
11435 gen_load_fpr64(ctx, fp1, ft);
11436 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11437 tcg_temp_free_i64(fp1);
11438 gen_store_fpr64(ctx, fp0, fd);
11439 tcg_temp_free_i64(fp0);
11441 break;
11442 case OPC_ABS_PS:
11443 check_ps(ctx);
11445 TCGv_i64 fp0 = tcg_temp_new_i64();
11447 gen_load_fpr64(ctx, fp0, fs);
11448 gen_helper_float_abs_ps(fp0, fp0);
11449 gen_store_fpr64(ctx, fp0, fd);
11450 tcg_temp_free_i64(fp0);
11452 break;
11453 case OPC_MOV_PS:
11454 check_ps(ctx);
11456 TCGv_i64 fp0 = tcg_temp_new_i64();
11458 gen_load_fpr64(ctx, fp0, fs);
11459 gen_store_fpr64(ctx, fp0, fd);
11460 tcg_temp_free_i64(fp0);
11462 break;
11463 case OPC_NEG_PS:
11464 check_ps(ctx);
11466 TCGv_i64 fp0 = tcg_temp_new_i64();
11468 gen_load_fpr64(ctx, fp0, fs);
11469 gen_helper_float_chs_ps(fp0, fp0);
11470 gen_store_fpr64(ctx, fp0, fd);
11471 tcg_temp_free_i64(fp0);
11473 break;
11474 case OPC_MOVCF_PS:
11475 check_ps(ctx);
11476 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11477 break;
11478 case OPC_MOVZ_PS:
11479 check_ps(ctx);
11481 TCGLabel *l1 = gen_new_label();
11482 TCGv_i64 fp0;
11484 if (ft != 0)
11485 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11486 fp0 = tcg_temp_new_i64();
11487 gen_load_fpr64(ctx, fp0, fs);
11488 gen_store_fpr64(ctx, fp0, fd);
11489 tcg_temp_free_i64(fp0);
11490 gen_set_label(l1);
11492 break;
11493 case OPC_MOVN_PS:
11494 check_ps(ctx);
11496 TCGLabel *l1 = gen_new_label();
11497 TCGv_i64 fp0;
11499 if (ft != 0) {
11500 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11501 fp0 = tcg_temp_new_i64();
11502 gen_load_fpr64(ctx, fp0, fs);
11503 gen_store_fpr64(ctx, fp0, fd);
11504 tcg_temp_free_i64(fp0);
11505 gen_set_label(l1);
11508 break;
11509 case OPC_ADDR_PS:
11510 check_ps(ctx);
11512 TCGv_i64 fp0 = tcg_temp_new_i64();
11513 TCGv_i64 fp1 = tcg_temp_new_i64();
11515 gen_load_fpr64(ctx, fp0, ft);
11516 gen_load_fpr64(ctx, fp1, fs);
11517 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11518 tcg_temp_free_i64(fp1);
11519 gen_store_fpr64(ctx, fp0, fd);
11520 tcg_temp_free_i64(fp0);
11522 break;
11523 case OPC_MULR_PS:
11524 check_ps(ctx);
11526 TCGv_i64 fp0 = tcg_temp_new_i64();
11527 TCGv_i64 fp1 = tcg_temp_new_i64();
11529 gen_load_fpr64(ctx, fp0, ft);
11530 gen_load_fpr64(ctx, fp1, fs);
11531 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11532 tcg_temp_free_i64(fp1);
11533 gen_store_fpr64(ctx, fp0, fd);
11534 tcg_temp_free_i64(fp0);
11536 break;
11537 case OPC_RECIP2_PS:
11538 check_ps(ctx);
11540 TCGv_i64 fp0 = tcg_temp_new_i64();
11541 TCGv_i64 fp1 = tcg_temp_new_i64();
11543 gen_load_fpr64(ctx, fp0, fs);
11544 gen_load_fpr64(ctx, fp1, ft);
11545 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11546 tcg_temp_free_i64(fp1);
11547 gen_store_fpr64(ctx, fp0, fd);
11548 tcg_temp_free_i64(fp0);
11550 break;
11551 case OPC_RECIP1_PS:
11552 check_ps(ctx);
11554 TCGv_i64 fp0 = tcg_temp_new_i64();
11556 gen_load_fpr64(ctx, fp0, fs);
11557 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11558 gen_store_fpr64(ctx, fp0, fd);
11559 tcg_temp_free_i64(fp0);
11561 break;
11562 case OPC_RSQRT1_PS:
11563 check_ps(ctx);
11565 TCGv_i64 fp0 = tcg_temp_new_i64();
11567 gen_load_fpr64(ctx, fp0, fs);
11568 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11569 gen_store_fpr64(ctx, fp0, fd);
11570 tcg_temp_free_i64(fp0);
11572 break;
11573 case OPC_RSQRT2_PS:
11574 check_ps(ctx);
11576 TCGv_i64 fp0 = tcg_temp_new_i64();
11577 TCGv_i64 fp1 = tcg_temp_new_i64();
11579 gen_load_fpr64(ctx, fp0, fs);
11580 gen_load_fpr64(ctx, fp1, ft);
11581 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11582 tcg_temp_free_i64(fp1);
11583 gen_store_fpr64(ctx, fp0, fd);
11584 tcg_temp_free_i64(fp0);
11586 break;
11587 case OPC_CVT_S_PU:
11588 check_cp1_64bitmode(ctx);
11590 TCGv_i32 fp0 = tcg_temp_new_i32();
11592 gen_load_fpr32h(ctx, fp0, fs);
11593 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11594 gen_store_fpr32(ctx, fp0, fd);
11595 tcg_temp_free_i32(fp0);
11597 break;
11598 case OPC_CVT_PW_PS:
11599 check_ps(ctx);
11601 TCGv_i64 fp0 = tcg_temp_new_i64();
11603 gen_load_fpr64(ctx, fp0, fs);
11604 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11605 gen_store_fpr64(ctx, fp0, fd);
11606 tcg_temp_free_i64(fp0);
11608 break;
11609 case OPC_CVT_S_PL:
11610 check_cp1_64bitmode(ctx);
11612 TCGv_i32 fp0 = tcg_temp_new_i32();
11614 gen_load_fpr32(ctx, fp0, fs);
11615 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11616 gen_store_fpr32(ctx, fp0, fd);
11617 tcg_temp_free_i32(fp0);
11619 break;
11620 case OPC_PLL_PS:
11621 check_ps(ctx);
11623 TCGv_i32 fp0 = tcg_temp_new_i32();
11624 TCGv_i32 fp1 = tcg_temp_new_i32();
11626 gen_load_fpr32(ctx, fp0, fs);
11627 gen_load_fpr32(ctx, fp1, ft);
11628 gen_store_fpr32h(ctx, fp0, fd);
11629 gen_store_fpr32(ctx, fp1, fd);
11630 tcg_temp_free_i32(fp0);
11631 tcg_temp_free_i32(fp1);
11633 break;
11634 case OPC_PLU_PS:
11635 check_ps(ctx);
11637 TCGv_i32 fp0 = tcg_temp_new_i32();
11638 TCGv_i32 fp1 = tcg_temp_new_i32();
11640 gen_load_fpr32(ctx, fp0, fs);
11641 gen_load_fpr32h(ctx, fp1, ft);
11642 gen_store_fpr32(ctx, fp1, fd);
11643 gen_store_fpr32h(ctx, fp0, fd);
11644 tcg_temp_free_i32(fp0);
11645 tcg_temp_free_i32(fp1);
11647 break;
11648 case OPC_PUL_PS:
11649 check_ps(ctx);
11651 TCGv_i32 fp0 = tcg_temp_new_i32();
11652 TCGv_i32 fp1 = tcg_temp_new_i32();
11654 gen_load_fpr32h(ctx, fp0, fs);
11655 gen_load_fpr32(ctx, fp1, ft);
11656 gen_store_fpr32(ctx, fp1, fd);
11657 gen_store_fpr32h(ctx, fp0, fd);
11658 tcg_temp_free_i32(fp0);
11659 tcg_temp_free_i32(fp1);
11661 break;
11662 case OPC_PUU_PS:
11663 check_ps(ctx);
11665 TCGv_i32 fp0 = tcg_temp_new_i32();
11666 TCGv_i32 fp1 = tcg_temp_new_i32();
11668 gen_load_fpr32h(ctx, fp0, fs);
11669 gen_load_fpr32h(ctx, fp1, ft);
11670 gen_store_fpr32(ctx, fp1, fd);
11671 gen_store_fpr32h(ctx, fp0, fd);
11672 tcg_temp_free_i32(fp0);
11673 tcg_temp_free_i32(fp1);
11675 break;
11676 case OPC_CMP_F_PS:
11677 case OPC_CMP_UN_PS:
11678 case OPC_CMP_EQ_PS:
11679 case OPC_CMP_UEQ_PS:
11680 case OPC_CMP_OLT_PS:
11681 case OPC_CMP_ULT_PS:
11682 case OPC_CMP_OLE_PS:
11683 case OPC_CMP_ULE_PS:
11684 case OPC_CMP_SF_PS:
11685 case OPC_CMP_NGLE_PS:
11686 case OPC_CMP_SEQ_PS:
11687 case OPC_CMP_NGL_PS:
11688 case OPC_CMP_LT_PS:
11689 case OPC_CMP_NGE_PS:
11690 case OPC_CMP_LE_PS:
11691 case OPC_CMP_NGT_PS:
11692 if (ctx->opcode & (1 << 6)) {
11693 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
11694 } else {
11695 gen_cmp_ps(ctx, func-48, ft, fs, cc);
11697 break;
11698 default:
11699 MIPS_INVAL("farith");
11700 generate_exception_end(ctx, EXCP_RI);
11701 return;
11705 /* Coprocessor 3 (FPU) */
11706 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
11707 int fd, int fs, int base, int index)
11709 TCGv t0 = tcg_temp_new();
11711 if (base == 0) {
11712 gen_load_gpr(t0, index);
11713 } else if (index == 0) {
11714 gen_load_gpr(t0, base);
11715 } else {
11716 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11718 /* Don't do NOP if destination is zero: we must perform the actual
11719 memory access. */
11720 switch (opc) {
11721 case OPC_LWXC1:
11722 check_cop1x(ctx);
11724 TCGv_i32 fp0 = tcg_temp_new_i32();
11726 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11727 tcg_gen_trunc_tl_i32(fp0, t0);
11728 gen_store_fpr32(ctx, fp0, fd);
11729 tcg_temp_free_i32(fp0);
11731 break;
11732 case OPC_LDXC1:
11733 check_cop1x(ctx);
11734 check_cp1_registers(ctx, fd);
11736 TCGv_i64 fp0 = tcg_temp_new_i64();
11737 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11738 gen_store_fpr64(ctx, fp0, fd);
11739 tcg_temp_free_i64(fp0);
11741 break;
11742 case OPC_LUXC1:
11743 check_cp1_64bitmode(ctx);
11744 tcg_gen_andi_tl(t0, t0, ~0x7);
11746 TCGv_i64 fp0 = tcg_temp_new_i64();
11748 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11749 gen_store_fpr64(ctx, fp0, fd);
11750 tcg_temp_free_i64(fp0);
11752 break;
11753 case OPC_SWXC1:
11754 check_cop1x(ctx);
11756 TCGv_i32 fp0 = tcg_temp_new_i32();
11757 gen_load_fpr32(ctx, fp0, fs);
11758 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11759 tcg_temp_free_i32(fp0);
11761 break;
11762 case OPC_SDXC1:
11763 check_cop1x(ctx);
11764 check_cp1_registers(ctx, fs);
11766 TCGv_i64 fp0 = tcg_temp_new_i64();
11767 gen_load_fpr64(ctx, fp0, fs);
11768 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11769 tcg_temp_free_i64(fp0);
11771 break;
11772 case OPC_SUXC1:
11773 check_cp1_64bitmode(ctx);
11774 tcg_gen_andi_tl(t0, t0, ~0x7);
11776 TCGv_i64 fp0 = tcg_temp_new_i64();
11777 gen_load_fpr64(ctx, fp0, fs);
11778 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11779 tcg_temp_free_i64(fp0);
11781 break;
11783 tcg_temp_free(t0);
11786 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
11787 int fd, int fr, int fs, int ft)
11789 switch (opc) {
11790 case OPC_ALNV_PS:
11791 check_ps(ctx);
11793 TCGv t0 = tcg_temp_local_new();
11794 TCGv_i32 fp = tcg_temp_new_i32();
11795 TCGv_i32 fph = tcg_temp_new_i32();
11796 TCGLabel *l1 = gen_new_label();
11797 TCGLabel *l2 = gen_new_label();
11799 gen_load_gpr(t0, fr);
11800 tcg_gen_andi_tl(t0, t0, 0x7);
11802 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11803 gen_load_fpr32(ctx, fp, fs);
11804 gen_load_fpr32h(ctx, fph, fs);
11805 gen_store_fpr32(ctx, fp, fd);
11806 gen_store_fpr32h(ctx, fph, fd);
11807 tcg_gen_br(l2);
11808 gen_set_label(l1);
11809 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11810 tcg_temp_free(t0);
11811 #ifdef TARGET_WORDS_BIGENDIAN
11812 gen_load_fpr32(ctx, fp, fs);
11813 gen_load_fpr32h(ctx, fph, ft);
11814 gen_store_fpr32h(ctx, fp, fd);
11815 gen_store_fpr32(ctx, fph, fd);
11816 #else
11817 gen_load_fpr32h(ctx, fph, fs);
11818 gen_load_fpr32(ctx, fp, ft);
11819 gen_store_fpr32(ctx, fph, fd);
11820 gen_store_fpr32h(ctx, fp, fd);
11821 #endif
11822 gen_set_label(l2);
11823 tcg_temp_free_i32(fp);
11824 tcg_temp_free_i32(fph);
11826 break;
11827 case OPC_MADD_S:
11828 check_cop1x(ctx);
11830 TCGv_i32 fp0 = tcg_temp_new_i32();
11831 TCGv_i32 fp1 = tcg_temp_new_i32();
11832 TCGv_i32 fp2 = tcg_temp_new_i32();
11834 gen_load_fpr32(ctx, fp0, fs);
11835 gen_load_fpr32(ctx, fp1, ft);
11836 gen_load_fpr32(ctx, fp2, fr);
11837 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11838 tcg_temp_free_i32(fp0);
11839 tcg_temp_free_i32(fp1);
11840 gen_store_fpr32(ctx, fp2, fd);
11841 tcg_temp_free_i32(fp2);
11843 break;
11844 case OPC_MADD_D:
11845 check_cop1x(ctx);
11846 check_cp1_registers(ctx, fd | fs | ft | fr);
11848 TCGv_i64 fp0 = tcg_temp_new_i64();
11849 TCGv_i64 fp1 = tcg_temp_new_i64();
11850 TCGv_i64 fp2 = tcg_temp_new_i64();
11852 gen_load_fpr64(ctx, fp0, fs);
11853 gen_load_fpr64(ctx, fp1, ft);
11854 gen_load_fpr64(ctx, fp2, fr);
11855 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11856 tcg_temp_free_i64(fp0);
11857 tcg_temp_free_i64(fp1);
11858 gen_store_fpr64(ctx, fp2, fd);
11859 tcg_temp_free_i64(fp2);
11861 break;
11862 case OPC_MADD_PS:
11863 check_ps(ctx);
11865 TCGv_i64 fp0 = tcg_temp_new_i64();
11866 TCGv_i64 fp1 = tcg_temp_new_i64();
11867 TCGv_i64 fp2 = tcg_temp_new_i64();
11869 gen_load_fpr64(ctx, fp0, fs);
11870 gen_load_fpr64(ctx, fp1, ft);
11871 gen_load_fpr64(ctx, fp2, fr);
11872 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11873 tcg_temp_free_i64(fp0);
11874 tcg_temp_free_i64(fp1);
11875 gen_store_fpr64(ctx, fp2, fd);
11876 tcg_temp_free_i64(fp2);
11878 break;
11879 case OPC_MSUB_S:
11880 check_cop1x(ctx);
11882 TCGv_i32 fp0 = tcg_temp_new_i32();
11883 TCGv_i32 fp1 = tcg_temp_new_i32();
11884 TCGv_i32 fp2 = tcg_temp_new_i32();
11886 gen_load_fpr32(ctx, fp0, fs);
11887 gen_load_fpr32(ctx, fp1, ft);
11888 gen_load_fpr32(ctx, fp2, fr);
11889 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11890 tcg_temp_free_i32(fp0);
11891 tcg_temp_free_i32(fp1);
11892 gen_store_fpr32(ctx, fp2, fd);
11893 tcg_temp_free_i32(fp2);
11895 break;
11896 case OPC_MSUB_D:
11897 check_cop1x(ctx);
11898 check_cp1_registers(ctx, fd | fs | ft | fr);
11900 TCGv_i64 fp0 = tcg_temp_new_i64();
11901 TCGv_i64 fp1 = tcg_temp_new_i64();
11902 TCGv_i64 fp2 = tcg_temp_new_i64();
11904 gen_load_fpr64(ctx, fp0, fs);
11905 gen_load_fpr64(ctx, fp1, ft);
11906 gen_load_fpr64(ctx, fp2, fr);
11907 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11908 tcg_temp_free_i64(fp0);
11909 tcg_temp_free_i64(fp1);
11910 gen_store_fpr64(ctx, fp2, fd);
11911 tcg_temp_free_i64(fp2);
11913 break;
11914 case OPC_MSUB_PS:
11915 check_ps(ctx);
11917 TCGv_i64 fp0 = tcg_temp_new_i64();
11918 TCGv_i64 fp1 = tcg_temp_new_i64();
11919 TCGv_i64 fp2 = tcg_temp_new_i64();
11921 gen_load_fpr64(ctx, fp0, fs);
11922 gen_load_fpr64(ctx, fp1, ft);
11923 gen_load_fpr64(ctx, fp2, fr);
11924 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11925 tcg_temp_free_i64(fp0);
11926 tcg_temp_free_i64(fp1);
11927 gen_store_fpr64(ctx, fp2, fd);
11928 tcg_temp_free_i64(fp2);
11930 break;
11931 case OPC_NMADD_S:
11932 check_cop1x(ctx);
11934 TCGv_i32 fp0 = tcg_temp_new_i32();
11935 TCGv_i32 fp1 = tcg_temp_new_i32();
11936 TCGv_i32 fp2 = tcg_temp_new_i32();
11938 gen_load_fpr32(ctx, fp0, fs);
11939 gen_load_fpr32(ctx, fp1, ft);
11940 gen_load_fpr32(ctx, fp2, fr);
11941 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11942 tcg_temp_free_i32(fp0);
11943 tcg_temp_free_i32(fp1);
11944 gen_store_fpr32(ctx, fp2, fd);
11945 tcg_temp_free_i32(fp2);
11947 break;
11948 case OPC_NMADD_D:
11949 check_cop1x(ctx);
11950 check_cp1_registers(ctx, fd | fs | ft | fr);
11952 TCGv_i64 fp0 = tcg_temp_new_i64();
11953 TCGv_i64 fp1 = tcg_temp_new_i64();
11954 TCGv_i64 fp2 = tcg_temp_new_i64();
11956 gen_load_fpr64(ctx, fp0, fs);
11957 gen_load_fpr64(ctx, fp1, ft);
11958 gen_load_fpr64(ctx, fp2, fr);
11959 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11960 tcg_temp_free_i64(fp0);
11961 tcg_temp_free_i64(fp1);
11962 gen_store_fpr64(ctx, fp2, fd);
11963 tcg_temp_free_i64(fp2);
11965 break;
11966 case OPC_NMADD_PS:
11967 check_ps(ctx);
11969 TCGv_i64 fp0 = tcg_temp_new_i64();
11970 TCGv_i64 fp1 = tcg_temp_new_i64();
11971 TCGv_i64 fp2 = tcg_temp_new_i64();
11973 gen_load_fpr64(ctx, fp0, fs);
11974 gen_load_fpr64(ctx, fp1, ft);
11975 gen_load_fpr64(ctx, fp2, fr);
11976 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11977 tcg_temp_free_i64(fp0);
11978 tcg_temp_free_i64(fp1);
11979 gen_store_fpr64(ctx, fp2, fd);
11980 tcg_temp_free_i64(fp2);
11982 break;
11983 case OPC_NMSUB_S:
11984 check_cop1x(ctx);
11986 TCGv_i32 fp0 = tcg_temp_new_i32();
11987 TCGv_i32 fp1 = tcg_temp_new_i32();
11988 TCGv_i32 fp2 = tcg_temp_new_i32();
11990 gen_load_fpr32(ctx, fp0, fs);
11991 gen_load_fpr32(ctx, fp1, ft);
11992 gen_load_fpr32(ctx, fp2, fr);
11993 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11994 tcg_temp_free_i32(fp0);
11995 tcg_temp_free_i32(fp1);
11996 gen_store_fpr32(ctx, fp2, fd);
11997 tcg_temp_free_i32(fp2);
11999 break;
12000 case OPC_NMSUB_D:
12001 check_cop1x(ctx);
12002 check_cp1_registers(ctx, fd | fs | ft | fr);
12004 TCGv_i64 fp0 = tcg_temp_new_i64();
12005 TCGv_i64 fp1 = tcg_temp_new_i64();
12006 TCGv_i64 fp2 = tcg_temp_new_i64();
12008 gen_load_fpr64(ctx, fp0, fs);
12009 gen_load_fpr64(ctx, fp1, ft);
12010 gen_load_fpr64(ctx, fp2, fr);
12011 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
12012 tcg_temp_free_i64(fp0);
12013 tcg_temp_free_i64(fp1);
12014 gen_store_fpr64(ctx, fp2, fd);
12015 tcg_temp_free_i64(fp2);
12017 break;
12018 case OPC_NMSUB_PS:
12019 check_ps(ctx);
12021 TCGv_i64 fp0 = tcg_temp_new_i64();
12022 TCGv_i64 fp1 = tcg_temp_new_i64();
12023 TCGv_i64 fp2 = tcg_temp_new_i64();
12025 gen_load_fpr64(ctx, fp0, fs);
12026 gen_load_fpr64(ctx, fp1, ft);
12027 gen_load_fpr64(ctx, fp2, fr);
12028 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
12029 tcg_temp_free_i64(fp0);
12030 tcg_temp_free_i64(fp1);
12031 gen_store_fpr64(ctx, fp2, fd);
12032 tcg_temp_free_i64(fp2);
12034 break;
12035 default:
12036 MIPS_INVAL("flt3_arith");
12037 generate_exception_end(ctx, EXCP_RI);
12038 return;
12042 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12044 TCGv t0;
12046 #if !defined(CONFIG_USER_ONLY)
12047 /* The Linux kernel will emulate rdhwr if it's not supported natively.
12048 Therefore only check the ISA in system mode. */
12049 check_insn(ctx, ISA_MIPS32R2);
12050 #endif
12051 t0 = tcg_temp_new();
12053 switch (rd) {
12054 case 0:
12055 gen_helper_rdhwr_cpunum(t0, cpu_env);
12056 gen_store_gpr(t0, rt);
12057 break;
12058 case 1:
12059 gen_helper_rdhwr_synci_step(t0, cpu_env);
12060 gen_store_gpr(t0, rt);
12061 break;
12062 case 2:
12063 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12064 gen_io_start();
12066 gen_helper_rdhwr_cc(t0, cpu_env);
12067 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12068 gen_io_end();
12070 gen_store_gpr(t0, rt);
12071 /* Break the TB to be able to take timer interrupts immediately
12072 after reading count. DISAS_STOP isn't sufficient, we need to ensure
12073 we break completely out of translated code. */
12074 gen_save_pc(ctx->base.pc_next + 4);
12075 ctx->base.is_jmp = DISAS_EXIT;
12076 break;
12077 case 3:
12078 gen_helper_rdhwr_ccres(t0, cpu_env);
12079 gen_store_gpr(t0, rt);
12080 break;
12081 case 4:
12082 check_insn(ctx, ISA_MIPS32R6);
12083 if (sel != 0) {
12084 /* Performance counter registers are not implemented other than
12085 * control register 0.
12087 generate_exception(ctx, EXCP_RI);
12089 gen_helper_rdhwr_performance(t0, cpu_env);
12090 gen_store_gpr(t0, rt);
12091 break;
12092 case 5:
12093 check_insn(ctx, ISA_MIPS32R6);
12094 gen_helper_rdhwr_xnp(t0, cpu_env);
12095 gen_store_gpr(t0, rt);
12096 break;
12097 case 29:
12098 #if defined(CONFIG_USER_ONLY)
12099 tcg_gen_ld_tl(t0, cpu_env,
12100 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12101 gen_store_gpr(t0, rt);
12102 break;
12103 #else
12104 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12105 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12106 tcg_gen_ld_tl(t0, cpu_env,
12107 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12108 gen_store_gpr(t0, rt);
12109 } else {
12110 generate_exception_end(ctx, EXCP_RI);
12112 break;
12113 #endif
12114 default: /* Invalid */
12115 MIPS_INVAL("rdhwr");
12116 generate_exception_end(ctx, EXCP_RI);
12117 break;
12119 tcg_temp_free(t0);
12122 static inline void clear_branch_hflags(DisasContext *ctx)
12124 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12125 if (ctx->base.is_jmp == DISAS_NEXT) {
12126 save_cpu_state(ctx, 0);
12127 } else {
12128 /* it is not safe to save ctx->hflags as hflags may be changed
12129 in execution time by the instruction in delay / forbidden slot. */
12130 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12134 static void gen_branch(DisasContext *ctx, int insn_bytes)
12136 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12137 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12138 /* Branches completion */
12139 clear_branch_hflags(ctx);
12140 ctx->base.is_jmp = DISAS_NORETURN;
12141 /* FIXME: Need to clear can_do_io. */
12142 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12143 case MIPS_HFLAG_FBNSLOT:
12144 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12145 break;
12146 case MIPS_HFLAG_B:
12147 /* unconditional branch */
12148 if (proc_hflags & MIPS_HFLAG_BX) {
12149 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12151 gen_goto_tb(ctx, 0, ctx->btarget);
12152 break;
12153 case MIPS_HFLAG_BL:
12154 /* blikely taken case */
12155 gen_goto_tb(ctx, 0, ctx->btarget);
12156 break;
12157 case MIPS_HFLAG_BC:
12158 /* Conditional branch */
12160 TCGLabel *l1 = gen_new_label();
12162 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12163 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12164 gen_set_label(l1);
12165 gen_goto_tb(ctx, 0, ctx->btarget);
12167 break;
12168 case MIPS_HFLAG_BR:
12169 /* unconditional branch to register */
12170 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12171 TCGv t0 = tcg_temp_new();
12172 TCGv_i32 t1 = tcg_temp_new_i32();
12174 tcg_gen_andi_tl(t0, btarget, 0x1);
12175 tcg_gen_trunc_tl_i32(t1, t0);
12176 tcg_temp_free(t0);
12177 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12178 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12179 tcg_gen_or_i32(hflags, hflags, t1);
12180 tcg_temp_free_i32(t1);
12182 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12183 } else {
12184 tcg_gen_mov_tl(cpu_PC, btarget);
12186 if (ctx->base.singlestep_enabled) {
12187 save_cpu_state(ctx, 0);
12188 gen_helper_raise_exception_debug(cpu_env);
12190 tcg_gen_lookup_and_goto_ptr();
12191 break;
12192 default:
12193 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
12194 abort();
12199 /* Compact Branches */
12200 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12201 int rs, int rt, int32_t offset)
12203 int bcond_compute = 0;
12204 TCGv t0 = tcg_temp_new();
12205 TCGv t1 = tcg_temp_new();
12206 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12208 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12209 #ifdef MIPS_DEBUG_DISAS
12210 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12211 "\n", ctx->base.pc_next);
12212 #endif
12213 generate_exception_end(ctx, EXCP_RI);
12214 goto out;
12217 /* Load needed operands and calculate btarget */
12218 switch (opc) {
12219 /* compact branch */
12220 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12221 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12222 gen_load_gpr(t0, rs);
12223 gen_load_gpr(t1, rt);
12224 bcond_compute = 1;
12225 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12226 if (rs <= rt && rs == 0) {
12227 /* OPC_BEQZALC, OPC_BNEZALC */
12228 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12230 break;
12231 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12232 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12233 gen_load_gpr(t0, rs);
12234 gen_load_gpr(t1, rt);
12235 bcond_compute = 1;
12236 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12237 break;
12238 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12239 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12240 if (rs == 0 || rs == rt) {
12241 /* OPC_BLEZALC, OPC_BGEZALC */
12242 /* OPC_BGTZALC, OPC_BLTZALC */
12243 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12245 gen_load_gpr(t0, rs);
12246 gen_load_gpr(t1, rt);
12247 bcond_compute = 1;
12248 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12249 break;
12250 case OPC_BC:
12251 case OPC_BALC:
12252 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12253 break;
12254 case OPC_BEQZC:
12255 case OPC_BNEZC:
12256 if (rs != 0) {
12257 /* OPC_BEQZC, OPC_BNEZC */
12258 gen_load_gpr(t0, rs);
12259 bcond_compute = 1;
12260 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12261 } else {
12262 /* OPC_JIC, OPC_JIALC */
12263 TCGv tbase = tcg_temp_new();
12264 TCGv toffset = tcg_temp_new();
12266 gen_load_gpr(tbase, rt);
12267 tcg_gen_movi_tl(toffset, offset);
12268 gen_op_addr_add(ctx, btarget, tbase, toffset);
12269 tcg_temp_free(tbase);
12270 tcg_temp_free(toffset);
12272 break;
12273 default:
12274 MIPS_INVAL("Compact branch/jump");
12275 generate_exception_end(ctx, EXCP_RI);
12276 goto out;
12279 if (bcond_compute == 0) {
12280 /* Uncoditional compact branch */
12281 switch (opc) {
12282 case OPC_JIALC:
12283 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12284 /* Fallthrough */
12285 case OPC_JIC:
12286 ctx->hflags |= MIPS_HFLAG_BR;
12287 break;
12288 case OPC_BALC:
12289 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12290 /* Fallthrough */
12291 case OPC_BC:
12292 ctx->hflags |= MIPS_HFLAG_B;
12293 break;
12294 default:
12295 MIPS_INVAL("Compact branch/jump");
12296 generate_exception_end(ctx, EXCP_RI);
12297 goto out;
12300 /* Generating branch here as compact branches don't have delay slot */
12301 gen_branch(ctx, 4);
12302 } else {
12303 /* Conditional compact branch */
12304 TCGLabel *fs = gen_new_label();
12305 save_cpu_state(ctx, 0);
12307 switch (opc) {
12308 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12309 if (rs == 0 && rt != 0) {
12310 /* OPC_BLEZALC */
12311 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12312 } else if (rs != 0 && rt != 0 && rs == rt) {
12313 /* OPC_BGEZALC */
12314 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12315 } else {
12316 /* OPC_BGEUC */
12317 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12319 break;
12320 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12321 if (rs == 0 && rt != 0) {
12322 /* OPC_BGTZALC */
12323 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12324 } else if (rs != 0 && rt != 0 && rs == rt) {
12325 /* OPC_BLTZALC */
12326 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12327 } else {
12328 /* OPC_BLTUC */
12329 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12331 break;
12332 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12333 if (rs == 0 && rt != 0) {
12334 /* OPC_BLEZC */
12335 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12336 } else if (rs != 0 && rt != 0 && rs == rt) {
12337 /* OPC_BGEZC */
12338 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12339 } else {
12340 /* OPC_BGEC */
12341 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12343 break;
12344 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12345 if (rs == 0 && rt != 0) {
12346 /* OPC_BGTZC */
12347 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12348 } else if (rs != 0 && rt != 0 && rs == rt) {
12349 /* OPC_BLTZC */
12350 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12351 } else {
12352 /* OPC_BLTC */
12353 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12355 break;
12356 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12357 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12358 if (rs >= rt) {
12359 /* OPC_BOVC, OPC_BNVC */
12360 TCGv t2 = tcg_temp_new();
12361 TCGv t3 = tcg_temp_new();
12362 TCGv t4 = tcg_temp_new();
12363 TCGv input_overflow = tcg_temp_new();
12365 gen_load_gpr(t0, rs);
12366 gen_load_gpr(t1, rt);
12367 tcg_gen_ext32s_tl(t2, t0);
12368 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12369 tcg_gen_ext32s_tl(t3, t1);
12370 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12371 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12373 tcg_gen_add_tl(t4, t2, t3);
12374 tcg_gen_ext32s_tl(t4, t4);
12375 tcg_gen_xor_tl(t2, t2, t3);
12376 tcg_gen_xor_tl(t3, t4, t3);
12377 tcg_gen_andc_tl(t2, t3, t2);
12378 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12379 tcg_gen_or_tl(t4, t4, input_overflow);
12380 if (opc == OPC_BOVC) {
12381 /* OPC_BOVC */
12382 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12383 } else {
12384 /* OPC_BNVC */
12385 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12387 tcg_temp_free(input_overflow);
12388 tcg_temp_free(t4);
12389 tcg_temp_free(t3);
12390 tcg_temp_free(t2);
12391 } else if (rs < rt && rs == 0) {
12392 /* OPC_BEQZALC, OPC_BNEZALC */
12393 if (opc == OPC_BEQZALC) {
12394 /* OPC_BEQZALC */
12395 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12396 } else {
12397 /* OPC_BNEZALC */
12398 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12400 } else {
12401 /* OPC_BEQC, OPC_BNEC */
12402 if (opc == OPC_BEQC) {
12403 /* OPC_BEQC */
12404 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12405 } else {
12406 /* OPC_BNEC */
12407 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12410 break;
12411 case OPC_BEQZC:
12412 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12413 break;
12414 case OPC_BNEZC:
12415 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12416 break;
12417 default:
12418 MIPS_INVAL("Compact conditional branch/jump");
12419 generate_exception_end(ctx, EXCP_RI);
12420 goto out;
12423 /* Generating branch here as compact branches don't have delay slot */
12424 gen_goto_tb(ctx, 1, ctx->btarget);
12425 gen_set_label(fs);
12427 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12430 out:
12431 tcg_temp_free(t0);
12432 tcg_temp_free(t1);
12435 /* ISA extensions (ASEs) */
12436 /* MIPS16 extension to MIPS32 */
12438 /* MIPS16 major opcodes */
12439 enum {
12440 M16_OPC_ADDIUSP = 0x00,
12441 M16_OPC_ADDIUPC = 0x01,
12442 M16_OPC_B = 0x02,
12443 M16_OPC_JAL = 0x03,
12444 M16_OPC_BEQZ = 0x04,
12445 M16_OPC_BNEQZ = 0x05,
12446 M16_OPC_SHIFT = 0x06,
12447 M16_OPC_LD = 0x07,
12448 M16_OPC_RRIA = 0x08,
12449 M16_OPC_ADDIU8 = 0x09,
12450 M16_OPC_SLTI = 0x0a,
12451 M16_OPC_SLTIU = 0x0b,
12452 M16_OPC_I8 = 0x0c,
12453 M16_OPC_LI = 0x0d,
12454 M16_OPC_CMPI = 0x0e,
12455 M16_OPC_SD = 0x0f,
12456 M16_OPC_LB = 0x10,
12457 M16_OPC_LH = 0x11,
12458 M16_OPC_LWSP = 0x12,
12459 M16_OPC_LW = 0x13,
12460 M16_OPC_LBU = 0x14,
12461 M16_OPC_LHU = 0x15,
12462 M16_OPC_LWPC = 0x16,
12463 M16_OPC_LWU = 0x17,
12464 M16_OPC_SB = 0x18,
12465 M16_OPC_SH = 0x19,
12466 M16_OPC_SWSP = 0x1a,
12467 M16_OPC_SW = 0x1b,
12468 M16_OPC_RRR = 0x1c,
12469 M16_OPC_RR = 0x1d,
12470 M16_OPC_EXTEND = 0x1e,
12471 M16_OPC_I64 = 0x1f
12474 /* I8 funct field */
12475 enum {
12476 I8_BTEQZ = 0x0,
12477 I8_BTNEZ = 0x1,
12478 I8_SWRASP = 0x2,
12479 I8_ADJSP = 0x3,
12480 I8_SVRS = 0x4,
12481 I8_MOV32R = 0x5,
12482 I8_MOVR32 = 0x7
12485 /* RRR f field */
12486 enum {
12487 RRR_DADDU = 0x0,
12488 RRR_ADDU = 0x1,
12489 RRR_DSUBU = 0x2,
12490 RRR_SUBU = 0x3
12493 /* RR funct field */
12494 enum {
12495 RR_JR = 0x00,
12496 RR_SDBBP = 0x01,
12497 RR_SLT = 0x02,
12498 RR_SLTU = 0x03,
12499 RR_SLLV = 0x04,
12500 RR_BREAK = 0x05,
12501 RR_SRLV = 0x06,
12502 RR_SRAV = 0x07,
12503 RR_DSRL = 0x08,
12504 RR_CMP = 0x0a,
12505 RR_NEG = 0x0b,
12506 RR_AND = 0x0c,
12507 RR_OR = 0x0d,
12508 RR_XOR = 0x0e,
12509 RR_NOT = 0x0f,
12510 RR_MFHI = 0x10,
12511 RR_CNVT = 0x11,
12512 RR_MFLO = 0x12,
12513 RR_DSRA = 0x13,
12514 RR_DSLLV = 0x14,
12515 RR_DSRLV = 0x16,
12516 RR_DSRAV = 0x17,
12517 RR_MULT = 0x18,
12518 RR_MULTU = 0x19,
12519 RR_DIV = 0x1a,
12520 RR_DIVU = 0x1b,
12521 RR_DMULT = 0x1c,
12522 RR_DMULTU = 0x1d,
12523 RR_DDIV = 0x1e,
12524 RR_DDIVU = 0x1f
12527 /* I64 funct field */
12528 enum {
12529 I64_LDSP = 0x0,
12530 I64_SDSP = 0x1,
12531 I64_SDRASP = 0x2,
12532 I64_DADJSP = 0x3,
12533 I64_LDPC = 0x4,
12534 I64_DADDIU5 = 0x5,
12535 I64_DADDIUPC = 0x6,
12536 I64_DADDIUSP = 0x7
12539 /* RR ry field for CNVT */
12540 enum {
12541 RR_RY_CNVT_ZEB = 0x0,
12542 RR_RY_CNVT_ZEH = 0x1,
12543 RR_RY_CNVT_ZEW = 0x2,
12544 RR_RY_CNVT_SEB = 0x4,
12545 RR_RY_CNVT_SEH = 0x5,
12546 RR_RY_CNVT_SEW = 0x6,
12549 static int xlat (int r)
12551 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12553 return map[r];
12556 static void gen_mips16_save (DisasContext *ctx,
12557 int xsregs, int aregs,
12558 int do_ra, int do_s0, int do_s1,
12559 int framesize)
12561 TCGv t0 = tcg_temp_new();
12562 TCGv t1 = tcg_temp_new();
12563 TCGv t2 = tcg_temp_new();
12564 int args, astatic;
12566 switch (aregs) {
12567 case 0:
12568 case 1:
12569 case 2:
12570 case 3:
12571 case 11:
12572 args = 0;
12573 break;
12574 case 4:
12575 case 5:
12576 case 6:
12577 case 7:
12578 args = 1;
12579 break;
12580 case 8:
12581 case 9:
12582 case 10:
12583 args = 2;
12584 break;
12585 case 12:
12586 case 13:
12587 args = 3;
12588 break;
12589 case 14:
12590 args = 4;
12591 break;
12592 default:
12593 generate_exception_end(ctx, EXCP_RI);
12594 return;
12597 switch (args) {
12598 case 4:
12599 gen_base_offset_addr(ctx, t0, 29, 12);
12600 gen_load_gpr(t1, 7);
12601 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12602 /* Fall through */
12603 case 3:
12604 gen_base_offset_addr(ctx, t0, 29, 8);
12605 gen_load_gpr(t1, 6);
12606 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12607 /* Fall through */
12608 case 2:
12609 gen_base_offset_addr(ctx, t0, 29, 4);
12610 gen_load_gpr(t1, 5);
12611 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12612 /* Fall through */
12613 case 1:
12614 gen_base_offset_addr(ctx, t0, 29, 0);
12615 gen_load_gpr(t1, 4);
12616 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12619 gen_load_gpr(t0, 29);
12621 #define DECR_AND_STORE(reg) do { \
12622 tcg_gen_movi_tl(t2, -4); \
12623 gen_op_addr_add(ctx, t0, t0, t2); \
12624 gen_load_gpr(t1, reg); \
12625 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12626 } while (0)
12628 if (do_ra) {
12629 DECR_AND_STORE(31);
12632 switch (xsregs) {
12633 case 7:
12634 DECR_AND_STORE(30);
12635 /* Fall through */
12636 case 6:
12637 DECR_AND_STORE(23);
12638 /* Fall through */
12639 case 5:
12640 DECR_AND_STORE(22);
12641 /* Fall through */
12642 case 4:
12643 DECR_AND_STORE(21);
12644 /* Fall through */
12645 case 3:
12646 DECR_AND_STORE(20);
12647 /* Fall through */
12648 case 2:
12649 DECR_AND_STORE(19);
12650 /* Fall through */
12651 case 1:
12652 DECR_AND_STORE(18);
12655 if (do_s1) {
12656 DECR_AND_STORE(17);
12658 if (do_s0) {
12659 DECR_AND_STORE(16);
12662 switch (aregs) {
12663 case 0:
12664 case 4:
12665 case 8:
12666 case 12:
12667 case 14:
12668 astatic = 0;
12669 break;
12670 case 1:
12671 case 5:
12672 case 9:
12673 case 13:
12674 astatic = 1;
12675 break;
12676 case 2:
12677 case 6:
12678 case 10:
12679 astatic = 2;
12680 break;
12681 case 3:
12682 case 7:
12683 astatic = 3;
12684 break;
12685 case 11:
12686 astatic = 4;
12687 break;
12688 default:
12689 generate_exception_end(ctx, EXCP_RI);
12690 return;
12693 if (astatic > 0) {
12694 DECR_AND_STORE(7);
12695 if (astatic > 1) {
12696 DECR_AND_STORE(6);
12697 if (astatic > 2) {
12698 DECR_AND_STORE(5);
12699 if (astatic > 3) {
12700 DECR_AND_STORE(4);
12705 #undef DECR_AND_STORE
12707 tcg_gen_movi_tl(t2, -framesize);
12708 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12709 tcg_temp_free(t0);
12710 tcg_temp_free(t1);
12711 tcg_temp_free(t2);
12714 static void gen_mips16_restore (DisasContext *ctx,
12715 int xsregs, int aregs,
12716 int do_ra, int do_s0, int do_s1,
12717 int framesize)
12719 int astatic;
12720 TCGv t0 = tcg_temp_new();
12721 TCGv t1 = tcg_temp_new();
12722 TCGv t2 = tcg_temp_new();
12724 tcg_gen_movi_tl(t2, framesize);
12725 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12727 #define DECR_AND_LOAD(reg) do { \
12728 tcg_gen_movi_tl(t2, -4); \
12729 gen_op_addr_add(ctx, t0, t0, t2); \
12730 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12731 gen_store_gpr(t1, reg); \
12732 } while (0)
12734 if (do_ra) {
12735 DECR_AND_LOAD(31);
12738 switch (xsregs) {
12739 case 7:
12740 DECR_AND_LOAD(30);
12741 /* Fall through */
12742 case 6:
12743 DECR_AND_LOAD(23);
12744 /* Fall through */
12745 case 5:
12746 DECR_AND_LOAD(22);
12747 /* Fall through */
12748 case 4:
12749 DECR_AND_LOAD(21);
12750 /* Fall through */
12751 case 3:
12752 DECR_AND_LOAD(20);
12753 /* Fall through */
12754 case 2:
12755 DECR_AND_LOAD(19);
12756 /* Fall through */
12757 case 1:
12758 DECR_AND_LOAD(18);
12761 if (do_s1) {
12762 DECR_AND_LOAD(17);
12764 if (do_s0) {
12765 DECR_AND_LOAD(16);
12768 switch (aregs) {
12769 case 0:
12770 case 4:
12771 case 8:
12772 case 12:
12773 case 14:
12774 astatic = 0;
12775 break;
12776 case 1:
12777 case 5:
12778 case 9:
12779 case 13:
12780 astatic = 1;
12781 break;
12782 case 2:
12783 case 6:
12784 case 10:
12785 astatic = 2;
12786 break;
12787 case 3:
12788 case 7:
12789 astatic = 3;
12790 break;
12791 case 11:
12792 astatic = 4;
12793 break;
12794 default:
12795 generate_exception_end(ctx, EXCP_RI);
12796 return;
12799 if (astatic > 0) {
12800 DECR_AND_LOAD(7);
12801 if (astatic > 1) {
12802 DECR_AND_LOAD(6);
12803 if (astatic > 2) {
12804 DECR_AND_LOAD(5);
12805 if (astatic > 3) {
12806 DECR_AND_LOAD(4);
12811 #undef DECR_AND_LOAD
12813 tcg_gen_movi_tl(t2, framesize);
12814 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12815 tcg_temp_free(t0);
12816 tcg_temp_free(t1);
12817 tcg_temp_free(t2);
12820 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
12821 int is_64_bit, int extended)
12823 TCGv t0;
12825 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12826 generate_exception_end(ctx, EXCP_RI);
12827 return;
12830 t0 = tcg_temp_new();
12832 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12833 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12834 if (!is_64_bit) {
12835 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12838 tcg_temp_free(t0);
12841 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12842 int16_t offset)
12844 TCGv_i32 t0 = tcg_const_i32(op);
12845 TCGv t1 = tcg_temp_new();
12846 gen_base_offset_addr(ctx, t1, base, offset);
12847 gen_helper_cache(cpu_env, t1, t0);
12850 #if defined(TARGET_MIPS64)
12851 static void decode_i64_mips16 (DisasContext *ctx,
12852 int ry, int funct, int16_t offset,
12853 int extended)
12855 switch (funct) {
12856 case I64_LDSP:
12857 check_insn(ctx, ISA_MIPS3);
12858 check_mips_64(ctx);
12859 offset = extended ? offset : offset << 3;
12860 gen_ld(ctx, OPC_LD, ry, 29, offset);
12861 break;
12862 case I64_SDSP:
12863 check_insn(ctx, ISA_MIPS3);
12864 check_mips_64(ctx);
12865 offset = extended ? offset : offset << 3;
12866 gen_st(ctx, OPC_SD, ry, 29, offset);
12867 break;
12868 case I64_SDRASP:
12869 check_insn(ctx, ISA_MIPS3);
12870 check_mips_64(ctx);
12871 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12872 gen_st(ctx, OPC_SD, 31, 29, offset);
12873 break;
12874 case I64_DADJSP:
12875 check_insn(ctx, ISA_MIPS3);
12876 check_mips_64(ctx);
12877 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12878 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12879 break;
12880 case I64_LDPC:
12881 check_insn(ctx, ISA_MIPS3);
12882 check_mips_64(ctx);
12883 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12884 generate_exception_end(ctx, EXCP_RI);
12885 } else {
12886 offset = extended ? offset : offset << 3;
12887 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
12889 break;
12890 case I64_DADDIU5:
12891 check_insn(ctx, ISA_MIPS3);
12892 check_mips_64(ctx);
12893 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
12894 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
12895 break;
12896 case I64_DADDIUPC:
12897 check_insn(ctx, ISA_MIPS3);
12898 check_mips_64(ctx);
12899 offset = extended ? offset : offset << 2;
12900 gen_addiupc(ctx, ry, offset, 1, extended);
12901 break;
12902 case I64_DADDIUSP:
12903 check_insn(ctx, ISA_MIPS3);
12904 check_mips_64(ctx);
12905 offset = extended ? offset : offset << 2;
12906 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12907 break;
12910 #endif
12912 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
12914 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
12915 int op, rx, ry, funct, sa;
12916 int16_t imm, offset;
12918 ctx->opcode = (ctx->opcode << 16) | extend;
12919 op = (ctx->opcode >> 11) & 0x1f;
12920 sa = (ctx->opcode >> 22) & 0x1f;
12921 funct = (ctx->opcode >> 8) & 0x7;
12922 rx = xlat((ctx->opcode >> 8) & 0x7);
12923 ry = xlat((ctx->opcode >> 5) & 0x7);
12924 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12925 | ((ctx->opcode >> 21) & 0x3f) << 5
12926 | (ctx->opcode & 0x1f));
12928 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
12929 counterparts. */
12930 switch (op) {
12931 case M16_OPC_ADDIUSP:
12932 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12933 break;
12934 case M16_OPC_ADDIUPC:
12935 gen_addiupc(ctx, rx, imm, 0, 1);
12936 break;
12937 case M16_OPC_B:
12938 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12939 /* No delay slot, so just process as a normal instruction */
12940 break;
12941 case M16_OPC_BEQZ:
12942 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12943 /* No delay slot, so just process as a normal instruction */
12944 break;
12945 case M16_OPC_BNEQZ:
12946 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12947 /* No delay slot, so just process as a normal instruction */
12948 break;
12949 case M16_OPC_SHIFT:
12950 switch (ctx->opcode & 0x3) {
12951 case 0x0:
12952 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12953 break;
12954 case 0x1:
12955 #if defined(TARGET_MIPS64)
12956 check_mips_64(ctx);
12957 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12958 #else
12959 generate_exception_end(ctx, EXCP_RI);
12960 #endif
12961 break;
12962 case 0x2:
12963 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12964 break;
12965 case 0x3:
12966 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12967 break;
12969 break;
12970 #if defined(TARGET_MIPS64)
12971 case M16_OPC_LD:
12972 check_insn(ctx, ISA_MIPS3);
12973 check_mips_64(ctx);
12974 gen_ld(ctx, OPC_LD, ry, rx, offset);
12975 break;
12976 #endif
12977 case M16_OPC_RRIA:
12978 imm = ctx->opcode & 0xf;
12979 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12980 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12981 imm = (int16_t) (imm << 1) >> 1;
12982 if ((ctx->opcode >> 4) & 0x1) {
12983 #if defined(TARGET_MIPS64)
12984 check_mips_64(ctx);
12985 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12986 #else
12987 generate_exception_end(ctx, EXCP_RI);
12988 #endif
12989 } else {
12990 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12992 break;
12993 case M16_OPC_ADDIU8:
12994 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12995 break;
12996 case M16_OPC_SLTI:
12997 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12998 break;
12999 case M16_OPC_SLTIU:
13000 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13001 break;
13002 case M16_OPC_I8:
13003 switch (funct) {
13004 case I8_BTEQZ:
13005 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
13006 break;
13007 case I8_BTNEZ:
13008 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
13009 break;
13010 case I8_SWRASP:
13011 gen_st(ctx, OPC_SW, 31, 29, imm);
13012 break;
13013 case I8_ADJSP:
13014 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
13015 break;
13016 case I8_SVRS:
13017 check_insn(ctx, ISA_MIPS32);
13019 int xsregs = (ctx->opcode >> 24) & 0x7;
13020 int aregs = (ctx->opcode >> 16) & 0xf;
13021 int do_ra = (ctx->opcode >> 6) & 0x1;
13022 int do_s0 = (ctx->opcode >> 5) & 0x1;
13023 int do_s1 = (ctx->opcode >> 4) & 0x1;
13024 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
13025 | (ctx->opcode & 0xf)) << 3;
13027 if (ctx->opcode & (1 << 7)) {
13028 gen_mips16_save(ctx, xsregs, aregs,
13029 do_ra, do_s0, do_s1,
13030 framesize);
13031 } else {
13032 gen_mips16_restore(ctx, xsregs, aregs,
13033 do_ra, do_s0, do_s1,
13034 framesize);
13037 break;
13038 default:
13039 generate_exception_end(ctx, EXCP_RI);
13040 break;
13042 break;
13043 case M16_OPC_LI:
13044 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13045 break;
13046 case M16_OPC_CMPI:
13047 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13048 break;
13049 #if defined(TARGET_MIPS64)
13050 case M16_OPC_SD:
13051 check_insn(ctx, ISA_MIPS3);
13052 check_mips_64(ctx);
13053 gen_st(ctx, OPC_SD, ry, rx, offset);
13054 break;
13055 #endif
13056 case M16_OPC_LB:
13057 gen_ld(ctx, OPC_LB, ry, rx, offset);
13058 break;
13059 case M16_OPC_LH:
13060 gen_ld(ctx, OPC_LH, ry, rx, offset);
13061 break;
13062 case M16_OPC_LWSP:
13063 gen_ld(ctx, OPC_LW, rx, 29, offset);
13064 break;
13065 case M16_OPC_LW:
13066 gen_ld(ctx, OPC_LW, ry, rx, offset);
13067 break;
13068 case M16_OPC_LBU:
13069 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13070 break;
13071 case M16_OPC_LHU:
13072 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13073 break;
13074 case M16_OPC_LWPC:
13075 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13076 break;
13077 #if defined(TARGET_MIPS64)
13078 case M16_OPC_LWU:
13079 check_insn(ctx, ISA_MIPS3);
13080 check_mips_64(ctx);
13081 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13082 break;
13083 #endif
13084 case M16_OPC_SB:
13085 gen_st(ctx, OPC_SB, ry, rx, offset);
13086 break;
13087 case M16_OPC_SH:
13088 gen_st(ctx, OPC_SH, ry, rx, offset);
13089 break;
13090 case M16_OPC_SWSP:
13091 gen_st(ctx, OPC_SW, rx, 29, offset);
13092 break;
13093 case M16_OPC_SW:
13094 gen_st(ctx, OPC_SW, ry, rx, offset);
13095 break;
13096 #if defined(TARGET_MIPS64)
13097 case M16_OPC_I64:
13098 decode_i64_mips16(ctx, ry, funct, offset, 1);
13099 break;
13100 #endif
13101 default:
13102 generate_exception_end(ctx, EXCP_RI);
13103 break;
13106 return 4;
13109 static inline bool is_uhi(int sdbbp_code)
13111 #ifdef CONFIG_USER_ONLY
13112 return false;
13113 #else
13114 return semihosting_enabled() && sdbbp_code == 1;
13115 #endif
13118 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
13120 int rx, ry;
13121 int sa;
13122 int op, cnvt_op, op1, offset;
13123 int funct;
13124 int n_bytes;
13126 op = (ctx->opcode >> 11) & 0x1f;
13127 sa = (ctx->opcode >> 2) & 0x7;
13128 sa = sa == 0 ? 8 : sa;
13129 rx = xlat((ctx->opcode >> 8) & 0x7);
13130 cnvt_op = (ctx->opcode >> 5) & 0x7;
13131 ry = xlat((ctx->opcode >> 5) & 0x7);
13132 op1 = offset = ctx->opcode & 0x1f;
13134 n_bytes = 2;
13136 switch (op) {
13137 case M16_OPC_ADDIUSP:
13139 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13141 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13143 break;
13144 case M16_OPC_ADDIUPC:
13145 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13146 break;
13147 case M16_OPC_B:
13148 offset = (ctx->opcode & 0x7ff) << 1;
13149 offset = (int16_t)(offset << 4) >> 4;
13150 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13151 /* No delay slot, so just process as a normal instruction */
13152 break;
13153 case M16_OPC_JAL:
13154 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
13155 offset = (((ctx->opcode & 0x1f) << 21)
13156 | ((ctx->opcode >> 5) & 0x1f) << 16
13157 | offset) << 2;
13158 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13159 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13160 n_bytes = 4;
13161 break;
13162 case M16_OPC_BEQZ:
13163 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13164 ((int8_t)ctx->opcode) << 1, 0);
13165 /* No delay slot, so just process as a normal instruction */
13166 break;
13167 case M16_OPC_BNEQZ:
13168 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13169 ((int8_t)ctx->opcode) << 1, 0);
13170 /* No delay slot, so just process as a normal instruction */
13171 break;
13172 case M16_OPC_SHIFT:
13173 switch (ctx->opcode & 0x3) {
13174 case 0x0:
13175 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13176 break;
13177 case 0x1:
13178 #if defined(TARGET_MIPS64)
13179 check_insn(ctx, ISA_MIPS3);
13180 check_mips_64(ctx);
13181 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13182 #else
13183 generate_exception_end(ctx, EXCP_RI);
13184 #endif
13185 break;
13186 case 0x2:
13187 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13188 break;
13189 case 0x3:
13190 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13191 break;
13193 break;
13194 #if defined(TARGET_MIPS64)
13195 case M16_OPC_LD:
13196 check_insn(ctx, ISA_MIPS3);
13197 check_mips_64(ctx);
13198 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13199 break;
13200 #endif
13201 case M16_OPC_RRIA:
13203 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13205 if ((ctx->opcode >> 4) & 1) {
13206 #if defined(TARGET_MIPS64)
13207 check_insn(ctx, ISA_MIPS3);
13208 check_mips_64(ctx);
13209 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13210 #else
13211 generate_exception_end(ctx, EXCP_RI);
13212 #endif
13213 } else {
13214 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13217 break;
13218 case M16_OPC_ADDIU8:
13220 int16_t imm = (int8_t) ctx->opcode;
13222 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13224 break;
13225 case M16_OPC_SLTI:
13227 int16_t imm = (uint8_t) ctx->opcode;
13228 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13230 break;
13231 case M16_OPC_SLTIU:
13233 int16_t imm = (uint8_t) ctx->opcode;
13234 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13236 break;
13237 case M16_OPC_I8:
13239 int reg32;
13241 funct = (ctx->opcode >> 8) & 0x7;
13242 switch (funct) {
13243 case I8_BTEQZ:
13244 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13245 ((int8_t)ctx->opcode) << 1, 0);
13246 break;
13247 case I8_BTNEZ:
13248 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13249 ((int8_t)ctx->opcode) << 1, 0);
13250 break;
13251 case I8_SWRASP:
13252 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13253 break;
13254 case I8_ADJSP:
13255 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13256 ((int8_t)ctx->opcode) << 3);
13257 break;
13258 case I8_SVRS:
13259 check_insn(ctx, ISA_MIPS32);
13261 int do_ra = ctx->opcode & (1 << 6);
13262 int do_s0 = ctx->opcode & (1 << 5);
13263 int do_s1 = ctx->opcode & (1 << 4);
13264 int framesize = ctx->opcode & 0xf;
13266 if (framesize == 0) {
13267 framesize = 128;
13268 } else {
13269 framesize = framesize << 3;
13272 if (ctx->opcode & (1 << 7)) {
13273 gen_mips16_save(ctx, 0, 0,
13274 do_ra, do_s0, do_s1, framesize);
13275 } else {
13276 gen_mips16_restore(ctx, 0, 0,
13277 do_ra, do_s0, do_s1, framesize);
13280 break;
13281 case I8_MOV32R:
13283 int rz = xlat(ctx->opcode & 0x7);
13285 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13286 ((ctx->opcode >> 5) & 0x7);
13287 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13289 break;
13290 case I8_MOVR32:
13291 reg32 = ctx->opcode & 0x1f;
13292 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13293 break;
13294 default:
13295 generate_exception_end(ctx, EXCP_RI);
13296 break;
13299 break;
13300 case M16_OPC_LI:
13302 int16_t imm = (uint8_t) ctx->opcode;
13304 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13306 break;
13307 case M16_OPC_CMPI:
13309 int16_t imm = (uint8_t) ctx->opcode;
13310 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13312 break;
13313 #if defined(TARGET_MIPS64)
13314 case M16_OPC_SD:
13315 check_insn(ctx, ISA_MIPS3);
13316 check_mips_64(ctx);
13317 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13318 break;
13319 #endif
13320 case M16_OPC_LB:
13321 gen_ld(ctx, OPC_LB, ry, rx, offset);
13322 break;
13323 case M16_OPC_LH:
13324 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13325 break;
13326 case M16_OPC_LWSP:
13327 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13328 break;
13329 case M16_OPC_LW:
13330 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13331 break;
13332 case M16_OPC_LBU:
13333 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13334 break;
13335 case M16_OPC_LHU:
13336 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13337 break;
13338 case M16_OPC_LWPC:
13339 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13340 break;
13341 #if defined (TARGET_MIPS64)
13342 case M16_OPC_LWU:
13343 check_insn(ctx, ISA_MIPS3);
13344 check_mips_64(ctx);
13345 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13346 break;
13347 #endif
13348 case M16_OPC_SB:
13349 gen_st(ctx, OPC_SB, ry, rx, offset);
13350 break;
13351 case M16_OPC_SH:
13352 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13353 break;
13354 case M16_OPC_SWSP:
13355 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13356 break;
13357 case M16_OPC_SW:
13358 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13359 break;
13360 case M16_OPC_RRR:
13362 int rz = xlat((ctx->opcode >> 2) & 0x7);
13363 int mips32_op;
13365 switch (ctx->opcode & 0x3) {
13366 case RRR_ADDU:
13367 mips32_op = OPC_ADDU;
13368 break;
13369 case RRR_SUBU:
13370 mips32_op = OPC_SUBU;
13371 break;
13372 #if defined(TARGET_MIPS64)
13373 case RRR_DADDU:
13374 mips32_op = OPC_DADDU;
13375 check_insn(ctx, ISA_MIPS3);
13376 check_mips_64(ctx);
13377 break;
13378 case RRR_DSUBU:
13379 mips32_op = OPC_DSUBU;
13380 check_insn(ctx, ISA_MIPS3);
13381 check_mips_64(ctx);
13382 break;
13383 #endif
13384 default:
13385 generate_exception_end(ctx, EXCP_RI);
13386 goto done;
13389 gen_arith(ctx, mips32_op, rz, rx, ry);
13390 done:
13393 break;
13394 case M16_OPC_RR:
13395 switch (op1) {
13396 case RR_JR:
13398 int nd = (ctx->opcode >> 7) & 0x1;
13399 int link = (ctx->opcode >> 6) & 0x1;
13400 int ra = (ctx->opcode >> 5) & 0x1;
13402 if (nd) {
13403 check_insn(ctx, ISA_MIPS32);
13406 if (link) {
13407 op = OPC_JALR;
13408 } else {
13409 op = OPC_JR;
13412 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13413 (nd ? 0 : 2));
13415 break;
13416 case RR_SDBBP:
13417 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13418 gen_helper_do_semihosting(cpu_env);
13419 } else {
13420 /* XXX: not clear which exception should be raised
13421 * when in debug mode...
13423 check_insn(ctx, ISA_MIPS32);
13424 generate_exception_end(ctx, EXCP_DBp);
13426 break;
13427 case RR_SLT:
13428 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13429 break;
13430 case RR_SLTU:
13431 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13432 break;
13433 case RR_BREAK:
13434 generate_exception_end(ctx, EXCP_BREAK);
13435 break;
13436 case RR_SLLV:
13437 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13438 break;
13439 case RR_SRLV:
13440 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13441 break;
13442 case RR_SRAV:
13443 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13444 break;
13445 #if defined (TARGET_MIPS64)
13446 case RR_DSRL:
13447 check_insn(ctx, ISA_MIPS3);
13448 check_mips_64(ctx);
13449 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13450 break;
13451 #endif
13452 case RR_CMP:
13453 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13454 break;
13455 case RR_NEG:
13456 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13457 break;
13458 case RR_AND:
13459 gen_logic(ctx, OPC_AND, rx, rx, ry);
13460 break;
13461 case RR_OR:
13462 gen_logic(ctx, OPC_OR, rx, rx, ry);
13463 break;
13464 case RR_XOR:
13465 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13466 break;
13467 case RR_NOT:
13468 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13469 break;
13470 case RR_MFHI:
13471 gen_HILO(ctx, OPC_MFHI, 0, rx);
13472 break;
13473 case RR_CNVT:
13474 check_insn(ctx, ISA_MIPS32);
13475 switch (cnvt_op) {
13476 case RR_RY_CNVT_ZEB:
13477 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13478 break;
13479 case RR_RY_CNVT_ZEH:
13480 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13481 break;
13482 case RR_RY_CNVT_SEB:
13483 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13484 break;
13485 case RR_RY_CNVT_SEH:
13486 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13487 break;
13488 #if defined (TARGET_MIPS64)
13489 case RR_RY_CNVT_ZEW:
13490 check_insn(ctx, ISA_MIPS64);
13491 check_mips_64(ctx);
13492 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13493 break;
13494 case RR_RY_CNVT_SEW:
13495 check_insn(ctx, ISA_MIPS64);
13496 check_mips_64(ctx);
13497 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13498 break;
13499 #endif
13500 default:
13501 generate_exception_end(ctx, EXCP_RI);
13502 break;
13504 break;
13505 case RR_MFLO:
13506 gen_HILO(ctx, OPC_MFLO, 0, rx);
13507 break;
13508 #if defined (TARGET_MIPS64)
13509 case RR_DSRA:
13510 check_insn(ctx, ISA_MIPS3);
13511 check_mips_64(ctx);
13512 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13513 break;
13514 case RR_DSLLV:
13515 check_insn(ctx, ISA_MIPS3);
13516 check_mips_64(ctx);
13517 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13518 break;
13519 case RR_DSRLV:
13520 check_insn(ctx, ISA_MIPS3);
13521 check_mips_64(ctx);
13522 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13523 break;
13524 case RR_DSRAV:
13525 check_insn(ctx, ISA_MIPS3);
13526 check_mips_64(ctx);
13527 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13528 break;
13529 #endif
13530 case RR_MULT:
13531 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13532 break;
13533 case RR_MULTU:
13534 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13535 break;
13536 case RR_DIV:
13537 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13538 break;
13539 case RR_DIVU:
13540 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13541 break;
13542 #if defined (TARGET_MIPS64)
13543 case RR_DMULT:
13544 check_insn(ctx, ISA_MIPS3);
13545 check_mips_64(ctx);
13546 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13547 break;
13548 case RR_DMULTU:
13549 check_insn(ctx, ISA_MIPS3);
13550 check_mips_64(ctx);
13551 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13552 break;
13553 case RR_DDIV:
13554 check_insn(ctx, ISA_MIPS3);
13555 check_mips_64(ctx);
13556 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13557 break;
13558 case RR_DDIVU:
13559 check_insn(ctx, ISA_MIPS3);
13560 check_mips_64(ctx);
13561 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13562 break;
13563 #endif
13564 default:
13565 generate_exception_end(ctx, EXCP_RI);
13566 break;
13568 break;
13569 case M16_OPC_EXTEND:
13570 decode_extended_mips16_opc(env, ctx);
13571 n_bytes = 4;
13572 break;
13573 #if defined(TARGET_MIPS64)
13574 case M16_OPC_I64:
13575 funct = (ctx->opcode >> 8) & 0x7;
13576 decode_i64_mips16(ctx, ry, funct, offset, 0);
13577 break;
13578 #endif
13579 default:
13580 generate_exception_end(ctx, EXCP_RI);
13581 break;
13584 return n_bytes;
13587 /* microMIPS extension to MIPS32/MIPS64 */
13590 * microMIPS32/microMIPS64 major opcodes
13592 * 1. MIPS Architecture for Programmers Volume II-B:
13593 * The microMIPS32 Instruction Set (Revision 3.05)
13595 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13597 * 2. MIPS Architecture For Programmers Volume II-A:
13598 * The MIPS64 Instruction Set (Revision 3.51)
13601 enum {
13602 POOL32A = 0x00,
13603 POOL16A = 0x01,
13604 LBU16 = 0x02,
13605 MOVE16 = 0x03,
13606 ADDI32 = 0x04,
13607 R6_LUI = 0x04,
13608 AUI = 0x04,
13609 LBU32 = 0x05,
13610 SB32 = 0x06,
13611 LB32 = 0x07,
13613 POOL32B = 0x08,
13614 POOL16B = 0x09,
13615 LHU16 = 0x0a,
13616 ANDI16 = 0x0b,
13617 ADDIU32 = 0x0c,
13618 LHU32 = 0x0d,
13619 SH32 = 0x0e,
13620 LH32 = 0x0f,
13622 POOL32I = 0x10,
13623 POOL16C = 0x11,
13624 LWSP16 = 0x12,
13625 POOL16D = 0x13,
13626 ORI32 = 0x14,
13627 POOL32F = 0x15,
13628 POOL32S = 0x16, /* MIPS64 */
13629 DADDIU32 = 0x17, /* MIPS64 */
13631 POOL32C = 0x18,
13632 LWGP16 = 0x19,
13633 LW16 = 0x1a,
13634 POOL16E = 0x1b,
13635 XORI32 = 0x1c,
13636 JALS32 = 0x1d,
13637 BOVC = 0x1d,
13638 BEQC = 0x1d,
13639 BEQZALC = 0x1d,
13640 ADDIUPC = 0x1e,
13641 PCREL = 0x1e,
13642 BNVC = 0x1f,
13643 BNEC = 0x1f,
13644 BNEZALC = 0x1f,
13646 R6_BEQZC = 0x20,
13647 JIC = 0x20,
13648 POOL16F = 0x21,
13649 SB16 = 0x22,
13650 BEQZ16 = 0x23,
13651 BEQZC16 = 0x23,
13652 SLTI32 = 0x24,
13653 BEQ32 = 0x25,
13654 BC = 0x25,
13655 SWC132 = 0x26,
13656 LWC132 = 0x27,
13658 /* 0x29 is reserved */
13659 RES_29 = 0x29,
13660 R6_BNEZC = 0x28,
13661 JIALC = 0x28,
13662 SH16 = 0x2a,
13663 BNEZ16 = 0x2b,
13664 BNEZC16 = 0x2b,
13665 SLTIU32 = 0x2c,
13666 BNE32 = 0x2d,
13667 BALC = 0x2d,
13668 SDC132 = 0x2e,
13669 LDC132 = 0x2f,
13671 /* 0x31 is reserved */
13672 RES_31 = 0x31,
13673 BLEZALC = 0x30,
13674 BGEZALC = 0x30,
13675 BGEUC = 0x30,
13676 SWSP16 = 0x32,
13677 B16 = 0x33,
13678 BC16 = 0x33,
13679 ANDI32 = 0x34,
13680 J32 = 0x35,
13681 BGTZC = 0x35,
13682 BLTZC = 0x35,
13683 BLTC = 0x35,
13684 SD32 = 0x36, /* MIPS64 */
13685 LD32 = 0x37, /* MIPS64 */
13687 /* 0x39 is reserved */
13688 RES_39 = 0x39,
13689 BGTZALC = 0x38,
13690 BLTZALC = 0x38,
13691 BLTUC = 0x38,
13692 SW16 = 0x3a,
13693 LI16 = 0x3b,
13694 JALX32 = 0x3c,
13695 JAL32 = 0x3d,
13696 BLEZC = 0x3d,
13697 BGEZC = 0x3d,
13698 BGEC = 0x3d,
13699 SW32 = 0x3e,
13700 LW32 = 0x3f
13703 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13704 enum {
13705 ADDIUPC_00 = 0x00,
13706 ADDIUPC_01 = 0x01,
13707 ADDIUPC_02 = 0x02,
13708 ADDIUPC_03 = 0x03,
13709 ADDIUPC_04 = 0x04,
13710 ADDIUPC_05 = 0x05,
13711 ADDIUPC_06 = 0x06,
13712 ADDIUPC_07 = 0x07,
13713 AUIPC = 0x1e,
13714 ALUIPC = 0x1f,
13715 LWPC_08 = 0x08,
13716 LWPC_09 = 0x09,
13717 LWPC_0A = 0x0A,
13718 LWPC_0B = 0x0B,
13719 LWPC_0C = 0x0C,
13720 LWPC_0D = 0x0D,
13721 LWPC_0E = 0x0E,
13722 LWPC_0F = 0x0F,
13725 /* POOL32A encoding of minor opcode field */
13727 enum {
13728 /* These opcodes are distinguished only by bits 9..6; those bits are
13729 * what are recorded below. */
13730 SLL32 = 0x0,
13731 SRL32 = 0x1,
13732 SRA = 0x2,
13733 ROTR = 0x3,
13734 SELEQZ = 0x5,
13735 SELNEZ = 0x6,
13736 R6_RDHWR = 0x7,
13738 SLLV = 0x0,
13739 SRLV = 0x1,
13740 SRAV = 0x2,
13741 ROTRV = 0x3,
13742 ADD = 0x4,
13743 ADDU32 = 0x5,
13744 SUB = 0x6,
13745 SUBU32 = 0x7,
13746 MUL = 0x8,
13747 AND = 0x9,
13748 OR32 = 0xa,
13749 NOR = 0xb,
13750 XOR32 = 0xc,
13751 SLT = 0xd,
13752 SLTU = 0xe,
13754 MOVN = 0x0,
13755 R6_MUL = 0x0,
13756 MOVZ = 0x1,
13757 MUH = 0x1,
13758 MULU = 0x2,
13759 MUHU = 0x3,
13760 LWXS = 0x4,
13761 R6_DIV = 0x4,
13762 MOD = 0x5,
13763 R6_DIVU = 0x6,
13764 MODU = 0x7,
13766 /* The following can be distinguished by their lower 6 bits. */
13767 BREAK32 = 0x07,
13768 INS = 0x0c,
13769 LSA = 0x0f,
13770 ALIGN = 0x1f,
13771 EXT = 0x2c,
13772 POOL32AXF = 0x3c,
13773 SIGRIE = 0x3f
13776 /* POOL32AXF encoding of minor opcode field extension */
13779 * 1. MIPS Architecture for Programmers Volume II-B:
13780 * The microMIPS32 Instruction Set (Revision 3.05)
13782 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13784 * 2. MIPS Architecture for Programmers VolumeIV-e:
13785 * The MIPS DSP Application-Specific Extension
13786 * to the microMIPS32 Architecture (Revision 2.34)
13788 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13791 enum {
13792 /* bits 11..6 */
13793 TEQ = 0x00,
13794 TGE = 0x08,
13795 TGEU = 0x10,
13796 TLT = 0x20,
13797 TLTU = 0x28,
13798 TNE = 0x30,
13800 MFC0 = 0x03,
13801 MTC0 = 0x0b,
13803 /* begin of microMIPS32 DSP */
13805 /* bits 13..12 for 0x01 */
13806 MFHI_ACC = 0x0,
13807 MFLO_ACC = 0x1,
13808 MTHI_ACC = 0x2,
13809 MTLO_ACC = 0x3,
13811 /* bits 13..12 for 0x2a */
13812 MADD_ACC = 0x0,
13813 MADDU_ACC = 0x1,
13814 MSUB_ACC = 0x2,
13815 MSUBU_ACC = 0x3,
13817 /* bits 13..12 for 0x32 */
13818 MULT_ACC = 0x0,
13819 MULTU_ACC = 0x1,
13821 /* end of microMIPS32 DSP */
13823 /* bits 15..12 for 0x2c */
13824 BITSWAP = 0x0,
13825 SEB = 0x2,
13826 SEH = 0x3,
13827 CLO = 0x4,
13828 CLZ = 0x5,
13829 RDHWR = 0x6,
13830 WSBH = 0x7,
13831 MULT = 0x8,
13832 MULTU = 0x9,
13833 DIV = 0xa,
13834 DIVU = 0xb,
13835 MADD = 0xc,
13836 MADDU = 0xd,
13837 MSUB = 0xe,
13838 MSUBU = 0xf,
13840 /* bits 15..12 for 0x34 */
13841 MFC2 = 0x4,
13842 MTC2 = 0x5,
13843 MFHC2 = 0x8,
13844 MTHC2 = 0x9,
13845 CFC2 = 0xc,
13846 CTC2 = 0xd,
13848 /* bits 15..12 for 0x3c */
13849 JALR = 0x0,
13850 JR = 0x0, /* alias */
13851 JALRC = 0x0,
13852 JRC = 0x0,
13853 JALR_HB = 0x1,
13854 JALRC_HB = 0x1,
13855 JALRS = 0x4,
13856 JALRS_HB = 0x5,
13858 /* bits 15..12 for 0x05 */
13859 RDPGPR = 0xe,
13860 WRPGPR = 0xf,
13862 /* bits 15..12 for 0x0d */
13863 TLBP = 0x0,
13864 TLBR = 0x1,
13865 TLBWI = 0x2,
13866 TLBWR = 0x3,
13867 TLBINV = 0x4,
13868 TLBINVF = 0x5,
13869 WAIT = 0x9,
13870 IRET = 0xd,
13871 DERET = 0xe,
13872 ERET = 0xf,
13874 /* bits 15..12 for 0x15 */
13875 DMT = 0x0,
13876 DVPE = 0x1,
13877 EMT = 0x2,
13878 EVPE = 0x3,
13880 /* bits 15..12 for 0x1d */
13881 DI = 0x4,
13882 EI = 0x5,
13884 /* bits 15..12 for 0x2d */
13885 SYNC = 0x6,
13886 SYSCALL = 0x8,
13887 SDBBP = 0xd,
13889 /* bits 15..12 for 0x35 */
13890 MFHI32 = 0x0,
13891 MFLO32 = 0x1,
13892 MTHI32 = 0x2,
13893 MTLO32 = 0x3,
13896 /* POOL32B encoding of minor opcode field (bits 15..12) */
13898 enum {
13899 LWC2 = 0x0,
13900 LWP = 0x1,
13901 LDP = 0x4,
13902 LWM32 = 0x5,
13903 CACHE = 0x6,
13904 LDM = 0x7,
13905 SWC2 = 0x8,
13906 SWP = 0x9,
13907 SDP = 0xc,
13908 SWM32 = 0xd,
13909 SDM = 0xf
13912 /* POOL32C encoding of minor opcode field (bits 15..12) */
13914 enum {
13915 LWL = 0x0,
13916 SWL = 0x8,
13917 LWR = 0x1,
13918 SWR = 0x9,
13919 PREF = 0x2,
13920 ST_EVA = 0xa,
13921 LL = 0x3,
13922 SC = 0xb,
13923 LDL = 0x4,
13924 SDL = 0xc,
13925 LDR = 0x5,
13926 SDR = 0xd,
13927 LD_EVA = 0x6,
13928 LWU = 0xe,
13929 LLD = 0x7,
13930 SCD = 0xf
13933 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13935 enum {
13936 LBUE = 0x0,
13937 LHUE = 0x1,
13938 LWLE = 0x2,
13939 LWRE = 0x3,
13940 LBE = 0x4,
13941 LHE = 0x5,
13942 LLE = 0x6,
13943 LWE = 0x7,
13946 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13948 enum {
13949 SWLE = 0x0,
13950 SWRE = 0x1,
13951 PREFE = 0x2,
13952 CACHEE = 0x3,
13953 SBE = 0x4,
13954 SHE = 0x5,
13955 SCE = 0x6,
13956 SWE = 0x7,
13959 /* POOL32F encoding of minor opcode field (bits 5..0) */
13961 enum {
13962 /* These are the bit 7..6 values */
13963 ADD_FMT = 0x0,
13965 SUB_FMT = 0x1,
13967 MUL_FMT = 0x2,
13969 DIV_FMT = 0x3,
13971 /* These are the bit 8..6 values */
13972 MOVN_FMT = 0x0,
13973 RSQRT2_FMT = 0x0,
13974 MOVF_FMT = 0x0,
13975 RINT_FMT = 0x0,
13976 SELNEZ_FMT = 0x0,
13978 MOVZ_FMT = 0x1,
13979 LWXC1 = 0x1,
13980 MOVT_FMT = 0x1,
13981 CLASS_FMT = 0x1,
13982 SELEQZ_FMT = 0x1,
13984 PLL_PS = 0x2,
13985 SWXC1 = 0x2,
13986 SEL_FMT = 0x2,
13988 PLU_PS = 0x3,
13989 LDXC1 = 0x3,
13991 MOVN_FMT_04 = 0x4,
13992 PUL_PS = 0x4,
13993 SDXC1 = 0x4,
13994 RECIP2_FMT = 0x4,
13996 MOVZ_FMT_05 = 0x05,
13997 PUU_PS = 0x5,
13998 LUXC1 = 0x5,
14000 CVT_PS_S = 0x6,
14001 SUXC1 = 0x6,
14002 ADDR_PS = 0x6,
14003 PREFX = 0x6,
14004 MADDF_FMT = 0x6,
14006 MULR_PS = 0x7,
14007 MSUBF_FMT = 0x7,
14009 MADD_S = 0x01,
14010 MADD_D = 0x09,
14011 MADD_PS = 0x11,
14012 ALNV_PS = 0x19,
14013 MSUB_S = 0x21,
14014 MSUB_D = 0x29,
14015 MSUB_PS = 0x31,
14017 NMADD_S = 0x02,
14018 NMADD_D = 0x0a,
14019 NMADD_PS = 0x12,
14020 NMSUB_S = 0x22,
14021 NMSUB_D = 0x2a,
14022 NMSUB_PS = 0x32,
14024 MIN_FMT = 0x3,
14025 MAX_FMT = 0xb,
14026 MINA_FMT = 0x23,
14027 MAXA_FMT = 0x2b,
14028 POOL32FXF = 0x3b,
14030 CABS_COND_FMT = 0x1c, /* MIPS3D */
14031 C_COND_FMT = 0x3c,
14033 CMP_CONDN_S = 0x5,
14034 CMP_CONDN_D = 0x15
14037 /* POOL32Fxf encoding of minor opcode extension field */
14039 enum {
14040 CVT_L = 0x04,
14041 RSQRT_FMT = 0x08,
14042 FLOOR_L = 0x0c,
14043 CVT_PW_PS = 0x1c,
14044 CVT_W = 0x24,
14045 SQRT_FMT = 0x28,
14046 FLOOR_W = 0x2c,
14047 CVT_PS_PW = 0x3c,
14048 CFC1 = 0x40,
14049 RECIP_FMT = 0x48,
14050 CEIL_L = 0x4c,
14051 CTC1 = 0x60,
14052 CEIL_W = 0x6c,
14053 MFC1 = 0x80,
14054 CVT_S_PL = 0x84,
14055 TRUNC_L = 0x8c,
14056 MTC1 = 0xa0,
14057 CVT_S_PU = 0xa4,
14058 TRUNC_W = 0xac,
14059 MFHC1 = 0xc0,
14060 ROUND_L = 0xcc,
14061 MTHC1 = 0xe0,
14062 ROUND_W = 0xec,
14064 MOV_FMT = 0x01,
14065 MOVF = 0x05,
14066 ABS_FMT = 0x0d,
14067 RSQRT1_FMT = 0x1d,
14068 MOVT = 0x25,
14069 NEG_FMT = 0x2d,
14070 CVT_D = 0x4d,
14071 RECIP1_FMT = 0x5d,
14072 CVT_S = 0x6d
14075 /* POOL32I encoding of minor opcode field (bits 25..21) */
14077 enum {
14078 BLTZ = 0x00,
14079 BLTZAL = 0x01,
14080 BGEZ = 0x02,
14081 BGEZAL = 0x03,
14082 BLEZ = 0x04,
14083 BNEZC = 0x05,
14084 BGTZ = 0x06,
14085 BEQZC = 0x07,
14086 TLTI = 0x08,
14087 BC1EQZC = 0x08,
14088 TGEI = 0x09,
14089 BC1NEZC = 0x09,
14090 TLTIU = 0x0a,
14091 BC2EQZC = 0x0a,
14092 TGEIU = 0x0b,
14093 BC2NEZC = 0x0a,
14094 TNEI = 0x0c,
14095 R6_SYNCI = 0x0c,
14096 LUI = 0x0d,
14097 TEQI = 0x0e,
14098 SYNCI = 0x10,
14099 BLTZALS = 0x11,
14100 BGEZALS = 0x13,
14101 BC2F = 0x14,
14102 BC2T = 0x15,
14103 BPOSGE64 = 0x1a,
14104 BPOSGE32 = 0x1b,
14105 /* These overlap and are distinguished by bit16 of the instruction */
14106 BC1F = 0x1c,
14107 BC1T = 0x1d,
14108 BC1ANY2F = 0x1c,
14109 BC1ANY2T = 0x1d,
14110 BC1ANY4F = 0x1e,
14111 BC1ANY4T = 0x1f
14114 /* POOL16A encoding of minor opcode field */
14116 enum {
14117 ADDU16 = 0x0,
14118 SUBU16 = 0x1
14121 /* POOL16B encoding of minor opcode field */
14123 enum {
14124 SLL16 = 0x0,
14125 SRL16 = 0x1
14128 /* POOL16C encoding of minor opcode field */
14130 enum {
14131 NOT16 = 0x00,
14132 XOR16 = 0x04,
14133 AND16 = 0x08,
14134 OR16 = 0x0c,
14135 LWM16 = 0x10,
14136 SWM16 = 0x14,
14137 JR16 = 0x18,
14138 JRC16 = 0x1a,
14139 JALR16 = 0x1c,
14140 JALR16S = 0x1e,
14141 MFHI16 = 0x20,
14142 MFLO16 = 0x24,
14143 BREAK16 = 0x28,
14144 SDBBP16 = 0x2c,
14145 JRADDIUSP = 0x30
14148 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14150 enum {
14151 R6_NOT16 = 0x00,
14152 R6_AND16 = 0x01,
14153 R6_LWM16 = 0x02,
14154 R6_JRC16 = 0x03,
14155 MOVEP = 0x04,
14156 MOVEP_05 = 0x05,
14157 MOVEP_06 = 0x06,
14158 MOVEP_07 = 0x07,
14159 R6_XOR16 = 0x08,
14160 R6_OR16 = 0x09,
14161 R6_SWM16 = 0x0a,
14162 JALRC16 = 0x0b,
14163 MOVEP_0C = 0x0c,
14164 MOVEP_0D = 0x0d,
14165 MOVEP_0E = 0x0e,
14166 MOVEP_0F = 0x0f,
14167 JRCADDIUSP = 0x13,
14168 R6_BREAK16 = 0x1b,
14169 R6_SDBBP16 = 0x3b
14172 /* POOL16D encoding of minor opcode field */
14174 enum {
14175 ADDIUS5 = 0x0,
14176 ADDIUSP = 0x1
14179 /* POOL16E encoding of minor opcode field */
14181 enum {
14182 ADDIUR2 = 0x0,
14183 ADDIUR1SP = 0x1
14186 static int mmreg (int r)
14188 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14190 return map[r];
14193 /* Used for 16-bit store instructions. */
14194 static int mmreg2 (int r)
14196 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14198 return map[r];
14201 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14202 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14203 #define uMIPS_RS2(op) uMIPS_RS(op)
14204 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14205 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14206 #define uMIPS_RS5(op) (op & 0x1f)
14208 /* Signed immediate */
14209 #define SIMM(op, start, width) \
14210 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
14211 << (32-width)) \
14212 >> (32-width))
14213 /* Zero-extended immediate */
14214 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
14216 static void gen_addiur1sp(DisasContext *ctx)
14218 int rd = mmreg(uMIPS_RD(ctx->opcode));
14220 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14223 static void gen_addiur2(DisasContext *ctx)
14225 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14226 int rd = mmreg(uMIPS_RD(ctx->opcode));
14227 int rs = mmreg(uMIPS_RS(ctx->opcode));
14229 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14232 static void gen_addiusp(DisasContext *ctx)
14234 int encoded = ZIMM(ctx->opcode, 1, 9);
14235 int decoded;
14237 if (encoded <= 1) {
14238 decoded = 256 + encoded;
14239 } else if (encoded <= 255) {
14240 decoded = encoded;
14241 } else if (encoded <= 509) {
14242 decoded = encoded - 512;
14243 } else {
14244 decoded = encoded - 768;
14247 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14250 static void gen_addius5(DisasContext *ctx)
14252 int imm = SIMM(ctx->opcode, 1, 4);
14253 int rd = (ctx->opcode >> 5) & 0x1f;
14255 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14258 static void gen_andi16(DisasContext *ctx)
14260 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14261 31, 32, 63, 64, 255, 32768, 65535 };
14262 int rd = mmreg(uMIPS_RD(ctx->opcode));
14263 int rs = mmreg(uMIPS_RS(ctx->opcode));
14264 int encoded = ZIMM(ctx->opcode, 0, 4);
14266 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14269 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
14270 int base, int16_t offset)
14272 TCGv t0, t1;
14273 TCGv_i32 t2;
14275 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14276 generate_exception_end(ctx, EXCP_RI);
14277 return;
14280 t0 = tcg_temp_new();
14282 gen_base_offset_addr(ctx, t0, base, offset);
14284 t1 = tcg_const_tl(reglist);
14285 t2 = tcg_const_i32(ctx->mem_idx);
14287 save_cpu_state(ctx, 1);
14288 switch (opc) {
14289 case LWM32:
14290 gen_helper_lwm(cpu_env, t0, t1, t2);
14291 break;
14292 case SWM32:
14293 gen_helper_swm(cpu_env, t0, t1, t2);
14294 break;
14295 #ifdef TARGET_MIPS64
14296 case LDM:
14297 gen_helper_ldm(cpu_env, t0, t1, t2);
14298 break;
14299 case SDM:
14300 gen_helper_sdm(cpu_env, t0, t1, t2);
14301 break;
14302 #endif
14304 tcg_temp_free(t0);
14305 tcg_temp_free(t1);
14306 tcg_temp_free_i32(t2);
14310 static void gen_pool16c_insn(DisasContext *ctx)
14312 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14313 int rs = mmreg(ctx->opcode & 0x7);
14315 switch (((ctx->opcode) >> 4) & 0x3f) {
14316 case NOT16 + 0:
14317 case NOT16 + 1:
14318 case NOT16 + 2:
14319 case NOT16 + 3:
14320 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14321 break;
14322 case XOR16 + 0:
14323 case XOR16 + 1:
14324 case XOR16 + 2:
14325 case XOR16 + 3:
14326 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14327 break;
14328 case AND16 + 0:
14329 case AND16 + 1:
14330 case AND16 + 2:
14331 case AND16 + 3:
14332 gen_logic(ctx, OPC_AND, rd, rd, rs);
14333 break;
14334 case OR16 + 0:
14335 case OR16 + 1:
14336 case OR16 + 2:
14337 case OR16 + 3:
14338 gen_logic(ctx, OPC_OR, rd, rd, rs);
14339 break;
14340 case LWM16 + 0:
14341 case LWM16 + 1:
14342 case LWM16 + 2:
14343 case LWM16 + 3:
14345 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14346 int offset = ZIMM(ctx->opcode, 0, 4);
14348 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14349 29, offset << 2);
14351 break;
14352 case SWM16 + 0:
14353 case SWM16 + 1:
14354 case SWM16 + 2:
14355 case SWM16 + 3:
14357 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14358 int offset = ZIMM(ctx->opcode, 0, 4);
14360 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14361 29, offset << 2);
14363 break;
14364 case JR16 + 0:
14365 case JR16 + 1:
14367 int reg = ctx->opcode & 0x1f;
14369 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14371 break;
14372 case JRC16 + 0:
14373 case JRC16 + 1:
14375 int reg = ctx->opcode & 0x1f;
14376 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14377 /* Let normal delay slot handling in our caller take us
14378 to the branch target. */
14380 break;
14381 case JALR16 + 0:
14382 case JALR16 + 1:
14383 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14384 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14385 break;
14386 case JALR16S + 0:
14387 case JALR16S + 1:
14388 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14389 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14390 break;
14391 case MFHI16 + 0:
14392 case MFHI16 + 1:
14393 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14394 break;
14395 case MFLO16 + 0:
14396 case MFLO16 + 1:
14397 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14398 break;
14399 case BREAK16:
14400 generate_exception_end(ctx, EXCP_BREAK);
14401 break;
14402 case SDBBP16:
14403 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14404 gen_helper_do_semihosting(cpu_env);
14405 } else {
14406 /* XXX: not clear which exception should be raised
14407 * when in debug mode...
14409 check_insn(ctx, ISA_MIPS32);
14410 generate_exception_end(ctx, EXCP_DBp);
14412 break;
14413 case JRADDIUSP + 0:
14414 case JRADDIUSP + 1:
14416 int imm = ZIMM(ctx->opcode, 0, 5);
14417 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14418 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14419 /* Let normal delay slot handling in our caller take us
14420 to the branch target. */
14422 break;
14423 default:
14424 generate_exception_end(ctx, EXCP_RI);
14425 break;
14429 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14430 int enc_rs)
14432 int rd, rs, re, rt;
14433 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14434 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14435 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14436 rd = rd_enc[enc_dest];
14437 re = re_enc[enc_dest];
14438 rs = rs_rt_enc[enc_rs];
14439 rt = rs_rt_enc[enc_rt];
14440 if (rs) {
14441 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
14442 } else {
14443 tcg_gen_movi_tl(cpu_gpr[rd], 0);
14445 if (rt) {
14446 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
14447 } else {
14448 tcg_gen_movi_tl(cpu_gpr[re], 0);
14452 static void gen_pool16c_r6_insn(DisasContext *ctx)
14454 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14455 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14457 switch (ctx->opcode & 0xf) {
14458 case R6_NOT16:
14459 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14460 break;
14461 case R6_AND16:
14462 gen_logic(ctx, OPC_AND, rt, rt, rs);
14463 break;
14464 case R6_LWM16:
14466 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14467 int offset = extract32(ctx->opcode, 4, 4);
14468 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14470 break;
14471 case R6_JRC16: /* JRCADDIUSP */
14472 if ((ctx->opcode >> 4) & 1) {
14473 /* JRCADDIUSP */
14474 int imm = extract32(ctx->opcode, 5, 5);
14475 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14476 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14477 } else {
14478 /* JRC16 */
14479 rs = extract32(ctx->opcode, 5, 5);
14480 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14482 break;
14483 case MOVEP:
14484 case MOVEP_05:
14485 case MOVEP_06:
14486 case MOVEP_07:
14487 case MOVEP_0C:
14488 case MOVEP_0D:
14489 case MOVEP_0E:
14490 case MOVEP_0F:
14492 int enc_dest = uMIPS_RD(ctx->opcode);
14493 int enc_rt = uMIPS_RS2(ctx->opcode);
14494 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14495 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14497 break;
14498 case R6_XOR16:
14499 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14500 break;
14501 case R6_OR16:
14502 gen_logic(ctx, OPC_OR, rt, rt, rs);
14503 break;
14504 case R6_SWM16:
14506 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14507 int offset = extract32(ctx->opcode, 4, 4);
14508 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14510 break;
14511 case JALRC16: /* BREAK16, SDBBP16 */
14512 switch (ctx->opcode & 0x3f) {
14513 case JALRC16:
14514 case JALRC16 + 0x20:
14515 /* JALRC16 */
14516 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14517 31, 0, 0);
14518 break;
14519 case R6_BREAK16:
14520 /* BREAK16 */
14521 generate_exception(ctx, EXCP_BREAK);
14522 break;
14523 case R6_SDBBP16:
14524 /* SDBBP16 */
14525 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14526 gen_helper_do_semihosting(cpu_env);
14527 } else {
14528 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14529 generate_exception(ctx, EXCP_RI);
14530 } else {
14531 generate_exception(ctx, EXCP_DBp);
14534 break;
14536 break;
14537 default:
14538 generate_exception(ctx, EXCP_RI);
14539 break;
14543 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
14545 TCGv t0 = tcg_temp_new();
14546 TCGv t1 = tcg_temp_new();
14548 gen_load_gpr(t0, base);
14550 if (index != 0) {
14551 gen_load_gpr(t1, index);
14552 tcg_gen_shli_tl(t1, t1, 2);
14553 gen_op_addr_add(ctx, t0, t1, t0);
14556 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14557 gen_store_gpr(t1, rd);
14559 tcg_temp_free(t0);
14560 tcg_temp_free(t1);
14563 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
14564 int base, int16_t offset)
14566 TCGv t0, t1;
14568 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14569 generate_exception_end(ctx, EXCP_RI);
14570 return;
14573 t0 = tcg_temp_new();
14574 t1 = tcg_temp_new();
14576 gen_base_offset_addr(ctx, t0, base, offset);
14578 switch (opc) {
14579 case LWP:
14580 if (rd == base) {
14581 generate_exception_end(ctx, EXCP_RI);
14582 return;
14584 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14585 gen_store_gpr(t1, rd);
14586 tcg_gen_movi_tl(t1, 4);
14587 gen_op_addr_add(ctx, t0, t0, t1);
14588 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14589 gen_store_gpr(t1, rd+1);
14590 break;
14591 case SWP:
14592 gen_load_gpr(t1, rd);
14593 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14594 tcg_gen_movi_tl(t1, 4);
14595 gen_op_addr_add(ctx, t0, t0, t1);
14596 gen_load_gpr(t1, rd+1);
14597 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14598 break;
14599 #ifdef TARGET_MIPS64
14600 case LDP:
14601 if (rd == base) {
14602 generate_exception_end(ctx, EXCP_RI);
14603 return;
14605 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14606 gen_store_gpr(t1, rd);
14607 tcg_gen_movi_tl(t1, 8);
14608 gen_op_addr_add(ctx, t0, t0, t1);
14609 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14610 gen_store_gpr(t1, rd+1);
14611 break;
14612 case SDP:
14613 gen_load_gpr(t1, rd);
14614 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14615 tcg_gen_movi_tl(t1, 8);
14616 gen_op_addr_add(ctx, t0, t0, t1);
14617 gen_load_gpr(t1, rd+1);
14618 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14619 break;
14620 #endif
14622 tcg_temp_free(t0);
14623 tcg_temp_free(t1);
14626 static void gen_sync(int stype)
14628 TCGBar tcg_mo = TCG_BAR_SC;
14630 switch (stype) {
14631 case 0x4: /* SYNC_WMB */
14632 tcg_mo |= TCG_MO_ST_ST;
14633 break;
14634 case 0x10: /* SYNC_MB */
14635 tcg_mo |= TCG_MO_ALL;
14636 break;
14637 case 0x11: /* SYNC_ACQUIRE */
14638 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14639 break;
14640 case 0x12: /* SYNC_RELEASE */
14641 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14642 break;
14643 case 0x13: /* SYNC_RMB */
14644 tcg_mo |= TCG_MO_LD_LD;
14645 break;
14646 default:
14647 tcg_mo |= TCG_MO_ALL;
14648 break;
14651 tcg_gen_mb(tcg_mo);
14654 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14656 int extension = (ctx->opcode >> 6) & 0x3f;
14657 int minor = (ctx->opcode >> 12) & 0xf;
14658 uint32_t mips32_op;
14660 switch (extension) {
14661 case TEQ:
14662 mips32_op = OPC_TEQ;
14663 goto do_trap;
14664 case TGE:
14665 mips32_op = OPC_TGE;
14666 goto do_trap;
14667 case TGEU:
14668 mips32_op = OPC_TGEU;
14669 goto do_trap;
14670 case TLT:
14671 mips32_op = OPC_TLT;
14672 goto do_trap;
14673 case TLTU:
14674 mips32_op = OPC_TLTU;
14675 goto do_trap;
14676 case TNE:
14677 mips32_op = OPC_TNE;
14678 do_trap:
14679 gen_trap(ctx, mips32_op, rs, rt, -1);
14680 break;
14681 #ifndef CONFIG_USER_ONLY
14682 case MFC0:
14683 case MFC0 + 32:
14684 check_cp0_enabled(ctx);
14685 if (rt == 0) {
14686 /* Treat as NOP. */
14687 break;
14689 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14690 break;
14691 case MTC0:
14692 case MTC0 + 32:
14693 check_cp0_enabled(ctx);
14695 TCGv t0 = tcg_temp_new();
14697 gen_load_gpr(t0, rt);
14698 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14699 tcg_temp_free(t0);
14701 break;
14702 #endif
14703 case 0x2a:
14704 switch (minor & 3) {
14705 case MADD_ACC:
14706 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14707 break;
14708 case MADDU_ACC:
14709 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14710 break;
14711 case MSUB_ACC:
14712 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14713 break;
14714 case MSUBU_ACC:
14715 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14716 break;
14717 default:
14718 goto pool32axf_invalid;
14720 break;
14721 case 0x32:
14722 switch (minor & 3) {
14723 case MULT_ACC:
14724 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14725 break;
14726 case MULTU_ACC:
14727 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14728 break;
14729 default:
14730 goto pool32axf_invalid;
14732 break;
14733 case 0x2c:
14734 switch (minor) {
14735 case BITSWAP:
14736 check_insn(ctx, ISA_MIPS32R6);
14737 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14738 break;
14739 case SEB:
14740 gen_bshfl(ctx, OPC_SEB, rs, rt);
14741 break;
14742 case SEH:
14743 gen_bshfl(ctx, OPC_SEH, rs, rt);
14744 break;
14745 case CLO:
14746 mips32_op = OPC_CLO;
14747 goto do_cl;
14748 case CLZ:
14749 mips32_op = OPC_CLZ;
14750 do_cl:
14751 check_insn(ctx, ISA_MIPS32);
14752 gen_cl(ctx, mips32_op, rt, rs);
14753 break;
14754 case RDHWR:
14755 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14756 gen_rdhwr(ctx, rt, rs, 0);
14757 break;
14758 case WSBH:
14759 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14760 break;
14761 case MULT:
14762 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14763 mips32_op = OPC_MULT;
14764 goto do_mul;
14765 case MULTU:
14766 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14767 mips32_op = OPC_MULTU;
14768 goto do_mul;
14769 case DIV:
14770 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14771 mips32_op = OPC_DIV;
14772 goto do_div;
14773 case DIVU:
14774 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14775 mips32_op = OPC_DIVU;
14776 goto do_div;
14777 do_div:
14778 check_insn(ctx, ISA_MIPS32);
14779 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14780 break;
14781 case MADD:
14782 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14783 mips32_op = OPC_MADD;
14784 goto do_mul;
14785 case MADDU:
14786 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14787 mips32_op = OPC_MADDU;
14788 goto do_mul;
14789 case MSUB:
14790 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14791 mips32_op = OPC_MSUB;
14792 goto do_mul;
14793 case MSUBU:
14794 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14795 mips32_op = OPC_MSUBU;
14796 do_mul:
14797 check_insn(ctx, ISA_MIPS32);
14798 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14799 break;
14800 default:
14801 goto pool32axf_invalid;
14803 break;
14804 case 0x34:
14805 switch (minor) {
14806 case MFC2:
14807 case MTC2:
14808 case MFHC2:
14809 case MTHC2:
14810 case CFC2:
14811 case CTC2:
14812 generate_exception_err(ctx, EXCP_CpU, 2);
14813 break;
14814 default:
14815 goto pool32axf_invalid;
14817 break;
14818 case 0x3c:
14819 switch (minor) {
14820 case JALR: /* JALRC */
14821 case JALR_HB: /* JALRC_HB */
14822 if (ctx->insn_flags & ISA_MIPS32R6) {
14823 /* JALRC, JALRC_HB */
14824 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14825 } else {
14826 /* JALR, JALR_HB */
14827 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14828 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14830 break;
14831 case JALRS:
14832 case JALRS_HB:
14833 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14834 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14835 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14836 break;
14837 default:
14838 goto pool32axf_invalid;
14840 break;
14841 case 0x05:
14842 switch (minor) {
14843 case RDPGPR:
14844 check_cp0_enabled(ctx);
14845 check_insn(ctx, ISA_MIPS32R2);
14846 gen_load_srsgpr(rs, rt);
14847 break;
14848 case WRPGPR:
14849 check_cp0_enabled(ctx);
14850 check_insn(ctx, ISA_MIPS32R2);
14851 gen_store_srsgpr(rs, rt);
14852 break;
14853 default:
14854 goto pool32axf_invalid;
14856 break;
14857 #ifndef CONFIG_USER_ONLY
14858 case 0x0d:
14859 switch (minor) {
14860 case TLBP:
14861 mips32_op = OPC_TLBP;
14862 goto do_cp0;
14863 case TLBR:
14864 mips32_op = OPC_TLBR;
14865 goto do_cp0;
14866 case TLBWI:
14867 mips32_op = OPC_TLBWI;
14868 goto do_cp0;
14869 case TLBWR:
14870 mips32_op = OPC_TLBWR;
14871 goto do_cp0;
14872 case TLBINV:
14873 mips32_op = OPC_TLBINV;
14874 goto do_cp0;
14875 case TLBINVF:
14876 mips32_op = OPC_TLBINVF;
14877 goto do_cp0;
14878 case WAIT:
14879 mips32_op = OPC_WAIT;
14880 goto do_cp0;
14881 case DERET:
14882 mips32_op = OPC_DERET;
14883 goto do_cp0;
14884 case ERET:
14885 mips32_op = OPC_ERET;
14886 do_cp0:
14887 gen_cp0(env, ctx, mips32_op, rt, rs);
14888 break;
14889 default:
14890 goto pool32axf_invalid;
14892 break;
14893 case 0x1d:
14894 switch (minor) {
14895 case DI:
14896 check_cp0_enabled(ctx);
14898 TCGv t0 = tcg_temp_new();
14900 save_cpu_state(ctx, 1);
14901 gen_helper_di(t0, cpu_env);
14902 gen_store_gpr(t0, rs);
14903 /* Stop translation as we may have switched the execution mode */
14904 ctx->base.is_jmp = DISAS_STOP;
14905 tcg_temp_free(t0);
14907 break;
14908 case EI:
14909 check_cp0_enabled(ctx);
14911 TCGv t0 = tcg_temp_new();
14913 save_cpu_state(ctx, 1);
14914 gen_helper_ei(t0, cpu_env);
14915 gen_store_gpr(t0, rs);
14916 /* DISAS_STOP isn't sufficient, we need to ensure we break out
14917 of translated code to check for pending interrupts. */
14918 gen_save_pc(ctx->base.pc_next + 4);
14919 ctx->base.is_jmp = DISAS_EXIT;
14920 tcg_temp_free(t0);
14922 break;
14923 default:
14924 goto pool32axf_invalid;
14926 break;
14927 #endif
14928 case 0x2d:
14929 switch (minor) {
14930 case SYNC:
14931 gen_sync(extract32(ctx->opcode, 16, 5));
14932 break;
14933 case SYSCALL:
14934 generate_exception_end(ctx, EXCP_SYSCALL);
14935 break;
14936 case SDBBP:
14937 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14938 gen_helper_do_semihosting(cpu_env);
14939 } else {
14940 check_insn(ctx, ISA_MIPS32);
14941 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14942 generate_exception_end(ctx, EXCP_RI);
14943 } else {
14944 generate_exception_end(ctx, EXCP_DBp);
14947 break;
14948 default:
14949 goto pool32axf_invalid;
14951 break;
14952 case 0x01:
14953 switch (minor & 3) {
14954 case MFHI_ACC:
14955 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14956 break;
14957 case MFLO_ACC:
14958 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14959 break;
14960 case MTHI_ACC:
14961 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14962 break;
14963 case MTLO_ACC:
14964 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14965 break;
14966 default:
14967 goto pool32axf_invalid;
14969 break;
14970 case 0x35:
14971 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14972 switch (minor) {
14973 case MFHI32:
14974 gen_HILO(ctx, OPC_MFHI, 0, rs);
14975 break;
14976 case MFLO32:
14977 gen_HILO(ctx, OPC_MFLO, 0, rs);
14978 break;
14979 case MTHI32:
14980 gen_HILO(ctx, OPC_MTHI, 0, rs);
14981 break;
14982 case MTLO32:
14983 gen_HILO(ctx, OPC_MTLO, 0, rs);
14984 break;
14985 default:
14986 goto pool32axf_invalid;
14988 break;
14989 default:
14990 pool32axf_invalid:
14991 MIPS_INVAL("pool32axf");
14992 generate_exception_end(ctx, EXCP_RI);
14993 break;
14997 /* Values for microMIPS fmt field. Variable-width, depending on which
14998 formats the instruction supports. */
15000 enum {
15001 FMT_SD_S = 0,
15002 FMT_SD_D = 1,
15004 FMT_SDPS_S = 0,
15005 FMT_SDPS_D = 1,
15006 FMT_SDPS_PS = 2,
15008 FMT_SWL_S = 0,
15009 FMT_SWL_W = 1,
15010 FMT_SWL_L = 2,
15012 FMT_DWL_D = 0,
15013 FMT_DWL_W = 1,
15014 FMT_DWL_L = 2
15017 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
15019 int extension = (ctx->opcode >> 6) & 0x3ff;
15020 uint32_t mips32_op;
15022 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
15023 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
15024 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
15026 switch (extension) {
15027 case FLOAT_1BIT_FMT(CFC1, 0):
15028 mips32_op = OPC_CFC1;
15029 goto do_cp1;
15030 case FLOAT_1BIT_FMT(CTC1, 0):
15031 mips32_op = OPC_CTC1;
15032 goto do_cp1;
15033 case FLOAT_1BIT_FMT(MFC1, 0):
15034 mips32_op = OPC_MFC1;
15035 goto do_cp1;
15036 case FLOAT_1BIT_FMT(MTC1, 0):
15037 mips32_op = OPC_MTC1;
15038 goto do_cp1;
15039 case FLOAT_1BIT_FMT(MFHC1, 0):
15040 mips32_op = OPC_MFHC1;
15041 goto do_cp1;
15042 case FLOAT_1BIT_FMT(MTHC1, 0):
15043 mips32_op = OPC_MTHC1;
15044 do_cp1:
15045 gen_cp1(ctx, mips32_op, rt, rs);
15046 break;
15048 /* Reciprocal square root */
15049 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15050 mips32_op = OPC_RSQRT_S;
15051 goto do_unaryfp;
15052 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15053 mips32_op = OPC_RSQRT_D;
15054 goto do_unaryfp;
15056 /* Square root */
15057 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15058 mips32_op = OPC_SQRT_S;
15059 goto do_unaryfp;
15060 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15061 mips32_op = OPC_SQRT_D;
15062 goto do_unaryfp;
15064 /* Reciprocal */
15065 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15066 mips32_op = OPC_RECIP_S;
15067 goto do_unaryfp;
15068 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15069 mips32_op = OPC_RECIP_D;
15070 goto do_unaryfp;
15072 /* Floor */
15073 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15074 mips32_op = OPC_FLOOR_L_S;
15075 goto do_unaryfp;
15076 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15077 mips32_op = OPC_FLOOR_L_D;
15078 goto do_unaryfp;
15079 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15080 mips32_op = OPC_FLOOR_W_S;
15081 goto do_unaryfp;
15082 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15083 mips32_op = OPC_FLOOR_W_D;
15084 goto do_unaryfp;
15086 /* Ceiling */
15087 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15088 mips32_op = OPC_CEIL_L_S;
15089 goto do_unaryfp;
15090 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15091 mips32_op = OPC_CEIL_L_D;
15092 goto do_unaryfp;
15093 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15094 mips32_op = OPC_CEIL_W_S;
15095 goto do_unaryfp;
15096 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15097 mips32_op = OPC_CEIL_W_D;
15098 goto do_unaryfp;
15100 /* Truncation */
15101 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15102 mips32_op = OPC_TRUNC_L_S;
15103 goto do_unaryfp;
15104 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15105 mips32_op = OPC_TRUNC_L_D;
15106 goto do_unaryfp;
15107 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15108 mips32_op = OPC_TRUNC_W_S;
15109 goto do_unaryfp;
15110 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15111 mips32_op = OPC_TRUNC_W_D;
15112 goto do_unaryfp;
15114 /* Round */
15115 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15116 mips32_op = OPC_ROUND_L_S;
15117 goto do_unaryfp;
15118 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15119 mips32_op = OPC_ROUND_L_D;
15120 goto do_unaryfp;
15121 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15122 mips32_op = OPC_ROUND_W_S;
15123 goto do_unaryfp;
15124 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15125 mips32_op = OPC_ROUND_W_D;
15126 goto do_unaryfp;
15128 /* Integer to floating-point conversion */
15129 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15130 mips32_op = OPC_CVT_L_S;
15131 goto do_unaryfp;
15132 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15133 mips32_op = OPC_CVT_L_D;
15134 goto do_unaryfp;
15135 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15136 mips32_op = OPC_CVT_W_S;
15137 goto do_unaryfp;
15138 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15139 mips32_op = OPC_CVT_W_D;
15140 goto do_unaryfp;
15142 /* Paired-foo conversions */
15143 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15144 mips32_op = OPC_CVT_S_PL;
15145 goto do_unaryfp;
15146 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15147 mips32_op = OPC_CVT_S_PU;
15148 goto do_unaryfp;
15149 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15150 mips32_op = OPC_CVT_PW_PS;
15151 goto do_unaryfp;
15152 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15153 mips32_op = OPC_CVT_PS_PW;
15154 goto do_unaryfp;
15156 /* Floating-point moves */
15157 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15158 mips32_op = OPC_MOV_S;
15159 goto do_unaryfp;
15160 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15161 mips32_op = OPC_MOV_D;
15162 goto do_unaryfp;
15163 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15164 mips32_op = OPC_MOV_PS;
15165 goto do_unaryfp;
15167 /* Absolute value */
15168 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15169 mips32_op = OPC_ABS_S;
15170 goto do_unaryfp;
15171 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15172 mips32_op = OPC_ABS_D;
15173 goto do_unaryfp;
15174 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15175 mips32_op = OPC_ABS_PS;
15176 goto do_unaryfp;
15178 /* Negation */
15179 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15180 mips32_op = OPC_NEG_S;
15181 goto do_unaryfp;
15182 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15183 mips32_op = OPC_NEG_D;
15184 goto do_unaryfp;
15185 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15186 mips32_op = OPC_NEG_PS;
15187 goto do_unaryfp;
15189 /* Reciprocal square root step */
15190 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15191 mips32_op = OPC_RSQRT1_S;
15192 goto do_unaryfp;
15193 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15194 mips32_op = OPC_RSQRT1_D;
15195 goto do_unaryfp;
15196 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15197 mips32_op = OPC_RSQRT1_PS;
15198 goto do_unaryfp;
15200 /* Reciprocal step */
15201 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15202 mips32_op = OPC_RECIP1_S;
15203 goto do_unaryfp;
15204 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15205 mips32_op = OPC_RECIP1_S;
15206 goto do_unaryfp;
15207 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15208 mips32_op = OPC_RECIP1_PS;
15209 goto do_unaryfp;
15211 /* Conversions from double */
15212 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15213 mips32_op = OPC_CVT_D_S;
15214 goto do_unaryfp;
15215 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15216 mips32_op = OPC_CVT_D_W;
15217 goto do_unaryfp;
15218 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15219 mips32_op = OPC_CVT_D_L;
15220 goto do_unaryfp;
15222 /* Conversions from single */
15223 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15224 mips32_op = OPC_CVT_S_D;
15225 goto do_unaryfp;
15226 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15227 mips32_op = OPC_CVT_S_W;
15228 goto do_unaryfp;
15229 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15230 mips32_op = OPC_CVT_S_L;
15231 do_unaryfp:
15232 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15233 break;
15235 /* Conditional moves on floating-point codes */
15236 case COND_FLOAT_MOV(MOVT, 0):
15237 case COND_FLOAT_MOV(MOVT, 1):
15238 case COND_FLOAT_MOV(MOVT, 2):
15239 case COND_FLOAT_MOV(MOVT, 3):
15240 case COND_FLOAT_MOV(MOVT, 4):
15241 case COND_FLOAT_MOV(MOVT, 5):
15242 case COND_FLOAT_MOV(MOVT, 6):
15243 case COND_FLOAT_MOV(MOVT, 7):
15244 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15245 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15246 break;
15247 case COND_FLOAT_MOV(MOVF, 0):
15248 case COND_FLOAT_MOV(MOVF, 1):
15249 case COND_FLOAT_MOV(MOVF, 2):
15250 case COND_FLOAT_MOV(MOVF, 3):
15251 case COND_FLOAT_MOV(MOVF, 4):
15252 case COND_FLOAT_MOV(MOVF, 5):
15253 case COND_FLOAT_MOV(MOVF, 6):
15254 case COND_FLOAT_MOV(MOVF, 7):
15255 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15256 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15257 break;
15258 default:
15259 MIPS_INVAL("pool32fxf");
15260 generate_exception_end(ctx, EXCP_RI);
15261 break;
15265 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15267 int32_t offset;
15268 uint16_t insn;
15269 int rt, rs, rd, rr;
15270 int16_t imm;
15271 uint32_t op, minor, minor2, mips32_op;
15272 uint32_t cond, fmt, cc;
15274 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
15275 ctx->opcode = (ctx->opcode << 16) | insn;
15277 rt = (ctx->opcode >> 21) & 0x1f;
15278 rs = (ctx->opcode >> 16) & 0x1f;
15279 rd = (ctx->opcode >> 11) & 0x1f;
15280 rr = (ctx->opcode >> 6) & 0x1f;
15281 imm = (int16_t) ctx->opcode;
15283 op = (ctx->opcode >> 26) & 0x3f;
15284 switch (op) {
15285 case POOL32A:
15286 minor = ctx->opcode & 0x3f;
15287 switch (minor) {
15288 case 0x00:
15289 minor = (ctx->opcode >> 6) & 0xf;
15290 switch (minor) {
15291 case SLL32:
15292 mips32_op = OPC_SLL;
15293 goto do_shifti;
15294 case SRA:
15295 mips32_op = OPC_SRA;
15296 goto do_shifti;
15297 case SRL32:
15298 mips32_op = OPC_SRL;
15299 goto do_shifti;
15300 case ROTR:
15301 mips32_op = OPC_ROTR;
15302 do_shifti:
15303 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15304 break;
15305 case SELEQZ:
15306 check_insn(ctx, ISA_MIPS32R6);
15307 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15308 break;
15309 case SELNEZ:
15310 check_insn(ctx, ISA_MIPS32R6);
15311 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15312 break;
15313 case R6_RDHWR:
15314 check_insn(ctx, ISA_MIPS32R6);
15315 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15316 break;
15317 default:
15318 goto pool32a_invalid;
15320 break;
15321 case 0x10:
15322 minor = (ctx->opcode >> 6) & 0xf;
15323 switch (minor) {
15324 /* Arithmetic */
15325 case ADD:
15326 mips32_op = OPC_ADD;
15327 goto do_arith;
15328 case ADDU32:
15329 mips32_op = OPC_ADDU;
15330 goto do_arith;
15331 case SUB:
15332 mips32_op = OPC_SUB;
15333 goto do_arith;
15334 case SUBU32:
15335 mips32_op = OPC_SUBU;
15336 goto do_arith;
15337 case MUL:
15338 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15339 mips32_op = OPC_MUL;
15340 do_arith:
15341 gen_arith(ctx, mips32_op, rd, rs, rt);
15342 break;
15343 /* Shifts */
15344 case SLLV:
15345 mips32_op = OPC_SLLV;
15346 goto do_shift;
15347 case SRLV:
15348 mips32_op = OPC_SRLV;
15349 goto do_shift;
15350 case SRAV:
15351 mips32_op = OPC_SRAV;
15352 goto do_shift;
15353 case ROTRV:
15354 mips32_op = OPC_ROTRV;
15355 do_shift:
15356 gen_shift(ctx, mips32_op, rd, rs, rt);
15357 break;
15358 /* Logical operations */
15359 case AND:
15360 mips32_op = OPC_AND;
15361 goto do_logic;
15362 case OR32:
15363 mips32_op = OPC_OR;
15364 goto do_logic;
15365 case NOR:
15366 mips32_op = OPC_NOR;
15367 goto do_logic;
15368 case XOR32:
15369 mips32_op = OPC_XOR;
15370 do_logic:
15371 gen_logic(ctx, mips32_op, rd, rs, rt);
15372 break;
15373 /* Set less than */
15374 case SLT:
15375 mips32_op = OPC_SLT;
15376 goto do_slt;
15377 case SLTU:
15378 mips32_op = OPC_SLTU;
15379 do_slt:
15380 gen_slt(ctx, mips32_op, rd, rs, rt);
15381 break;
15382 default:
15383 goto pool32a_invalid;
15385 break;
15386 case 0x18:
15387 minor = (ctx->opcode >> 6) & 0xf;
15388 switch (minor) {
15389 /* Conditional moves */
15390 case MOVN: /* MUL */
15391 if (ctx->insn_flags & ISA_MIPS32R6) {
15392 /* MUL */
15393 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15394 } else {
15395 /* MOVN */
15396 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15398 break;
15399 case MOVZ: /* MUH */
15400 if (ctx->insn_flags & ISA_MIPS32R6) {
15401 /* MUH */
15402 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15403 } else {
15404 /* MOVZ */
15405 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15407 break;
15408 case MULU:
15409 check_insn(ctx, ISA_MIPS32R6);
15410 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15411 break;
15412 case MUHU:
15413 check_insn(ctx, ISA_MIPS32R6);
15414 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15415 break;
15416 case LWXS: /* DIV */
15417 if (ctx->insn_flags & ISA_MIPS32R6) {
15418 /* DIV */
15419 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15420 } else {
15421 /* LWXS */
15422 gen_ldxs(ctx, rs, rt, rd);
15424 break;
15425 case MOD:
15426 check_insn(ctx, ISA_MIPS32R6);
15427 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15428 break;
15429 case R6_DIVU:
15430 check_insn(ctx, ISA_MIPS32R6);
15431 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15432 break;
15433 case MODU:
15434 check_insn(ctx, ISA_MIPS32R6);
15435 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15436 break;
15437 default:
15438 goto pool32a_invalid;
15440 break;
15441 case INS:
15442 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15443 return;
15444 case LSA:
15445 check_insn(ctx, ISA_MIPS32R6);
15446 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
15447 extract32(ctx->opcode, 9, 2));
15448 break;
15449 case ALIGN:
15450 check_insn(ctx, ISA_MIPS32R6);
15451 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15452 break;
15453 case EXT:
15454 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15455 return;
15456 case POOL32AXF:
15457 gen_pool32axf(env, ctx, rt, rs);
15458 break;
15459 case BREAK32:
15460 generate_exception_end(ctx, EXCP_BREAK);
15461 break;
15462 case SIGRIE:
15463 check_insn(ctx, ISA_MIPS32R6);
15464 generate_exception_end(ctx, EXCP_RI);
15465 break;
15466 default:
15467 pool32a_invalid:
15468 MIPS_INVAL("pool32a");
15469 generate_exception_end(ctx, EXCP_RI);
15470 break;
15472 break;
15473 case POOL32B:
15474 minor = (ctx->opcode >> 12) & 0xf;
15475 switch (minor) {
15476 case CACHE:
15477 check_cp0_enabled(ctx);
15478 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15479 gen_cache_operation(ctx, rt, rs, imm);
15481 break;
15482 case LWC2:
15483 case SWC2:
15484 /* COP2: Not implemented. */
15485 generate_exception_err(ctx, EXCP_CpU, 2);
15486 break;
15487 #ifdef TARGET_MIPS64
15488 case LDP:
15489 case SDP:
15490 check_insn(ctx, ISA_MIPS3);
15491 check_mips_64(ctx);
15492 #endif
15493 /* fall through */
15494 case LWP:
15495 case SWP:
15496 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15497 break;
15498 #ifdef TARGET_MIPS64
15499 case LDM:
15500 case SDM:
15501 check_insn(ctx, ISA_MIPS3);
15502 check_mips_64(ctx);
15503 #endif
15504 /* fall through */
15505 case LWM32:
15506 case SWM32:
15507 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15508 break;
15509 default:
15510 MIPS_INVAL("pool32b");
15511 generate_exception_end(ctx, EXCP_RI);
15512 break;
15514 break;
15515 case POOL32F:
15516 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15517 minor = ctx->opcode & 0x3f;
15518 check_cp1_enabled(ctx);
15519 switch (minor) {
15520 case ALNV_PS:
15521 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15522 mips32_op = OPC_ALNV_PS;
15523 goto do_madd;
15524 case MADD_S:
15525 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15526 mips32_op = OPC_MADD_S;
15527 goto do_madd;
15528 case MADD_D:
15529 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15530 mips32_op = OPC_MADD_D;
15531 goto do_madd;
15532 case MADD_PS:
15533 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15534 mips32_op = OPC_MADD_PS;
15535 goto do_madd;
15536 case MSUB_S:
15537 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15538 mips32_op = OPC_MSUB_S;
15539 goto do_madd;
15540 case MSUB_D:
15541 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15542 mips32_op = OPC_MSUB_D;
15543 goto do_madd;
15544 case MSUB_PS:
15545 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15546 mips32_op = OPC_MSUB_PS;
15547 goto do_madd;
15548 case NMADD_S:
15549 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15550 mips32_op = OPC_NMADD_S;
15551 goto do_madd;
15552 case NMADD_D:
15553 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15554 mips32_op = OPC_NMADD_D;
15555 goto do_madd;
15556 case NMADD_PS:
15557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15558 mips32_op = OPC_NMADD_PS;
15559 goto do_madd;
15560 case NMSUB_S:
15561 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15562 mips32_op = OPC_NMSUB_S;
15563 goto do_madd;
15564 case NMSUB_D:
15565 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15566 mips32_op = OPC_NMSUB_D;
15567 goto do_madd;
15568 case NMSUB_PS:
15569 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15570 mips32_op = OPC_NMSUB_PS;
15571 do_madd:
15572 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15573 break;
15574 case CABS_COND_FMT:
15575 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15576 cond = (ctx->opcode >> 6) & 0xf;
15577 cc = (ctx->opcode >> 13) & 0x7;
15578 fmt = (ctx->opcode >> 10) & 0x3;
15579 switch (fmt) {
15580 case 0x0:
15581 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15582 break;
15583 case 0x1:
15584 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15585 break;
15586 case 0x2:
15587 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15588 break;
15589 default:
15590 goto pool32f_invalid;
15592 break;
15593 case C_COND_FMT:
15594 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15595 cond = (ctx->opcode >> 6) & 0xf;
15596 cc = (ctx->opcode >> 13) & 0x7;
15597 fmt = (ctx->opcode >> 10) & 0x3;
15598 switch (fmt) {
15599 case 0x0:
15600 gen_cmp_s(ctx, cond, rt, rs, cc);
15601 break;
15602 case 0x1:
15603 gen_cmp_d(ctx, cond, rt, rs, cc);
15604 break;
15605 case 0x2:
15606 gen_cmp_ps(ctx, cond, rt, rs, cc);
15607 break;
15608 default:
15609 goto pool32f_invalid;
15611 break;
15612 case CMP_CONDN_S:
15613 check_insn(ctx, ISA_MIPS32R6);
15614 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15615 break;
15616 case CMP_CONDN_D:
15617 check_insn(ctx, ISA_MIPS32R6);
15618 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15619 break;
15620 case POOL32FXF:
15621 gen_pool32fxf(ctx, rt, rs);
15622 break;
15623 case 0x00:
15624 /* PLL foo */
15625 switch ((ctx->opcode >> 6) & 0x7) {
15626 case PLL_PS:
15627 mips32_op = OPC_PLL_PS;
15628 goto do_ps;
15629 case PLU_PS:
15630 mips32_op = OPC_PLU_PS;
15631 goto do_ps;
15632 case PUL_PS:
15633 mips32_op = OPC_PUL_PS;
15634 goto do_ps;
15635 case PUU_PS:
15636 mips32_op = OPC_PUU_PS;
15637 goto do_ps;
15638 case CVT_PS_S:
15639 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15640 mips32_op = OPC_CVT_PS_S;
15641 do_ps:
15642 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15643 break;
15644 default:
15645 goto pool32f_invalid;
15647 break;
15648 case MIN_FMT:
15649 check_insn(ctx, ISA_MIPS32R6);
15650 switch ((ctx->opcode >> 9) & 0x3) {
15651 case FMT_SDPS_S:
15652 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15653 break;
15654 case FMT_SDPS_D:
15655 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15656 break;
15657 default:
15658 goto pool32f_invalid;
15660 break;
15661 case 0x08:
15662 /* [LS][WDU]XC1 */
15663 switch ((ctx->opcode >> 6) & 0x7) {
15664 case LWXC1:
15665 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15666 mips32_op = OPC_LWXC1;
15667 goto do_ldst_cp1;
15668 case SWXC1:
15669 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15670 mips32_op = OPC_SWXC1;
15671 goto do_ldst_cp1;
15672 case LDXC1:
15673 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15674 mips32_op = OPC_LDXC1;
15675 goto do_ldst_cp1;
15676 case SDXC1:
15677 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15678 mips32_op = OPC_SDXC1;
15679 goto do_ldst_cp1;
15680 case LUXC1:
15681 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15682 mips32_op = OPC_LUXC1;
15683 goto do_ldst_cp1;
15684 case SUXC1:
15685 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15686 mips32_op = OPC_SUXC1;
15687 do_ldst_cp1:
15688 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15689 break;
15690 default:
15691 goto pool32f_invalid;
15693 break;
15694 case MAX_FMT:
15695 check_insn(ctx, ISA_MIPS32R6);
15696 switch ((ctx->opcode >> 9) & 0x3) {
15697 case FMT_SDPS_S:
15698 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15699 break;
15700 case FMT_SDPS_D:
15701 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15702 break;
15703 default:
15704 goto pool32f_invalid;
15706 break;
15707 case 0x18:
15708 /* 3D insns */
15709 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15710 fmt = (ctx->opcode >> 9) & 0x3;
15711 switch ((ctx->opcode >> 6) & 0x7) {
15712 case RSQRT2_FMT:
15713 switch (fmt) {
15714 case FMT_SDPS_S:
15715 mips32_op = OPC_RSQRT2_S;
15716 goto do_3d;
15717 case FMT_SDPS_D:
15718 mips32_op = OPC_RSQRT2_D;
15719 goto do_3d;
15720 case FMT_SDPS_PS:
15721 mips32_op = OPC_RSQRT2_PS;
15722 goto do_3d;
15723 default:
15724 goto pool32f_invalid;
15726 break;
15727 case RECIP2_FMT:
15728 switch (fmt) {
15729 case FMT_SDPS_S:
15730 mips32_op = OPC_RECIP2_S;
15731 goto do_3d;
15732 case FMT_SDPS_D:
15733 mips32_op = OPC_RECIP2_D;
15734 goto do_3d;
15735 case FMT_SDPS_PS:
15736 mips32_op = OPC_RECIP2_PS;
15737 goto do_3d;
15738 default:
15739 goto pool32f_invalid;
15741 break;
15742 case ADDR_PS:
15743 mips32_op = OPC_ADDR_PS;
15744 goto do_3d;
15745 case MULR_PS:
15746 mips32_op = OPC_MULR_PS;
15747 do_3d:
15748 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15749 break;
15750 default:
15751 goto pool32f_invalid;
15753 break;
15754 case 0x20:
15755 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15756 cc = (ctx->opcode >> 13) & 0x7;
15757 fmt = (ctx->opcode >> 9) & 0x3;
15758 switch ((ctx->opcode >> 6) & 0x7) {
15759 case MOVF_FMT: /* RINT_FMT */
15760 if (ctx->insn_flags & ISA_MIPS32R6) {
15761 /* RINT_FMT */
15762 switch (fmt) {
15763 case FMT_SDPS_S:
15764 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15765 break;
15766 case FMT_SDPS_D:
15767 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15768 break;
15769 default:
15770 goto pool32f_invalid;
15772 } else {
15773 /* MOVF_FMT */
15774 switch (fmt) {
15775 case FMT_SDPS_S:
15776 gen_movcf_s(ctx, rs, rt, cc, 0);
15777 break;
15778 case FMT_SDPS_D:
15779 gen_movcf_d(ctx, rs, rt, cc, 0);
15780 break;
15781 case FMT_SDPS_PS:
15782 check_ps(ctx);
15783 gen_movcf_ps(ctx, rs, rt, cc, 0);
15784 break;
15785 default:
15786 goto pool32f_invalid;
15789 break;
15790 case MOVT_FMT: /* CLASS_FMT */
15791 if (ctx->insn_flags & ISA_MIPS32R6) {
15792 /* CLASS_FMT */
15793 switch (fmt) {
15794 case FMT_SDPS_S:
15795 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15796 break;
15797 case FMT_SDPS_D:
15798 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15799 break;
15800 default:
15801 goto pool32f_invalid;
15803 } else {
15804 /* MOVT_FMT */
15805 switch (fmt) {
15806 case FMT_SDPS_S:
15807 gen_movcf_s(ctx, rs, rt, cc, 1);
15808 break;
15809 case FMT_SDPS_D:
15810 gen_movcf_d(ctx, rs, rt, cc, 1);
15811 break;
15812 case FMT_SDPS_PS:
15813 check_ps(ctx);
15814 gen_movcf_ps(ctx, rs, rt, cc, 1);
15815 break;
15816 default:
15817 goto pool32f_invalid;
15820 break;
15821 case PREFX:
15822 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15823 break;
15824 default:
15825 goto pool32f_invalid;
15827 break;
15828 #define FINSN_3ARG_SDPS(prfx) \
15829 switch ((ctx->opcode >> 8) & 0x3) { \
15830 case FMT_SDPS_S: \
15831 mips32_op = OPC_##prfx##_S; \
15832 goto do_fpop; \
15833 case FMT_SDPS_D: \
15834 mips32_op = OPC_##prfx##_D; \
15835 goto do_fpop; \
15836 case FMT_SDPS_PS: \
15837 check_ps(ctx); \
15838 mips32_op = OPC_##prfx##_PS; \
15839 goto do_fpop; \
15840 default: \
15841 goto pool32f_invalid; \
15843 case MINA_FMT:
15844 check_insn(ctx, ISA_MIPS32R6);
15845 switch ((ctx->opcode >> 9) & 0x3) {
15846 case FMT_SDPS_S:
15847 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15848 break;
15849 case FMT_SDPS_D:
15850 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15851 break;
15852 default:
15853 goto pool32f_invalid;
15855 break;
15856 case MAXA_FMT:
15857 check_insn(ctx, ISA_MIPS32R6);
15858 switch ((ctx->opcode >> 9) & 0x3) {
15859 case FMT_SDPS_S:
15860 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15861 break;
15862 case FMT_SDPS_D:
15863 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15864 break;
15865 default:
15866 goto pool32f_invalid;
15868 break;
15869 case 0x30:
15870 /* regular FP ops */
15871 switch ((ctx->opcode >> 6) & 0x3) {
15872 case ADD_FMT:
15873 FINSN_3ARG_SDPS(ADD);
15874 break;
15875 case SUB_FMT:
15876 FINSN_3ARG_SDPS(SUB);
15877 break;
15878 case MUL_FMT:
15879 FINSN_3ARG_SDPS(MUL);
15880 break;
15881 case DIV_FMT:
15882 fmt = (ctx->opcode >> 8) & 0x3;
15883 if (fmt == 1) {
15884 mips32_op = OPC_DIV_D;
15885 } else if (fmt == 0) {
15886 mips32_op = OPC_DIV_S;
15887 } else {
15888 goto pool32f_invalid;
15890 goto do_fpop;
15891 default:
15892 goto pool32f_invalid;
15894 break;
15895 case 0x38:
15896 /* cmovs */
15897 switch ((ctx->opcode >> 6) & 0x7) {
15898 case MOVN_FMT: /* SELEQZ_FMT */
15899 if (ctx->insn_flags & ISA_MIPS32R6) {
15900 /* SELEQZ_FMT */
15901 switch ((ctx->opcode >> 9) & 0x3) {
15902 case FMT_SDPS_S:
15903 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15904 break;
15905 case FMT_SDPS_D:
15906 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15907 break;
15908 default:
15909 goto pool32f_invalid;
15911 } else {
15912 /* MOVN_FMT */
15913 FINSN_3ARG_SDPS(MOVN);
15915 break;
15916 case MOVN_FMT_04:
15917 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15918 FINSN_3ARG_SDPS(MOVN);
15919 break;
15920 case MOVZ_FMT: /* SELNEZ_FMT */
15921 if (ctx->insn_flags & ISA_MIPS32R6) {
15922 /* SELNEZ_FMT */
15923 switch ((ctx->opcode >> 9) & 0x3) {
15924 case FMT_SDPS_S:
15925 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15926 break;
15927 case FMT_SDPS_D:
15928 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15929 break;
15930 default:
15931 goto pool32f_invalid;
15933 } else {
15934 /* MOVZ_FMT */
15935 FINSN_3ARG_SDPS(MOVZ);
15937 break;
15938 case MOVZ_FMT_05:
15939 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15940 FINSN_3ARG_SDPS(MOVZ);
15941 break;
15942 case SEL_FMT:
15943 check_insn(ctx, ISA_MIPS32R6);
15944 switch ((ctx->opcode >> 9) & 0x3) {
15945 case FMT_SDPS_S:
15946 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15947 break;
15948 case FMT_SDPS_D:
15949 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15950 break;
15951 default:
15952 goto pool32f_invalid;
15954 break;
15955 case MADDF_FMT:
15956 check_insn(ctx, ISA_MIPS32R6);
15957 switch ((ctx->opcode >> 9) & 0x3) {
15958 case FMT_SDPS_S:
15959 mips32_op = OPC_MADDF_S;
15960 goto do_fpop;
15961 case FMT_SDPS_D:
15962 mips32_op = OPC_MADDF_D;
15963 goto do_fpop;
15964 default:
15965 goto pool32f_invalid;
15967 break;
15968 case MSUBF_FMT:
15969 check_insn(ctx, ISA_MIPS32R6);
15970 switch ((ctx->opcode >> 9) & 0x3) {
15971 case FMT_SDPS_S:
15972 mips32_op = OPC_MSUBF_S;
15973 goto do_fpop;
15974 case FMT_SDPS_D:
15975 mips32_op = OPC_MSUBF_D;
15976 goto do_fpop;
15977 default:
15978 goto pool32f_invalid;
15980 break;
15981 default:
15982 goto pool32f_invalid;
15984 break;
15985 do_fpop:
15986 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15987 break;
15988 default:
15989 pool32f_invalid:
15990 MIPS_INVAL("pool32f");
15991 generate_exception_end(ctx, EXCP_RI);
15992 break;
15994 } else {
15995 generate_exception_err(ctx, EXCP_CpU, 1);
15997 break;
15998 case POOL32I:
15999 minor = (ctx->opcode >> 21) & 0x1f;
16000 switch (minor) {
16001 case BLTZ:
16002 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16003 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
16004 break;
16005 case BLTZAL:
16006 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16007 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
16008 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16009 break;
16010 case BLTZALS:
16011 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16012 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
16013 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16014 break;
16015 case BGEZ:
16016 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16017 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
16018 break;
16019 case BGEZAL:
16020 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16021 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
16022 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16023 break;
16024 case BGEZALS:
16025 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16026 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16027 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16028 break;
16029 case BLEZ:
16030 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16031 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16032 break;
16033 case BGTZ:
16034 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16035 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16036 break;
16038 /* Traps */
16039 case TLTI: /* BC1EQZC */
16040 if (ctx->insn_flags & ISA_MIPS32R6) {
16041 /* BC1EQZC */
16042 check_cp1_enabled(ctx);
16043 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16044 } else {
16045 /* TLTI */
16046 mips32_op = OPC_TLTI;
16047 goto do_trapi;
16049 break;
16050 case TGEI: /* BC1NEZC */
16051 if (ctx->insn_flags & ISA_MIPS32R6) {
16052 /* BC1NEZC */
16053 check_cp1_enabled(ctx);
16054 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16055 } else {
16056 /* TGEI */
16057 mips32_op = OPC_TGEI;
16058 goto do_trapi;
16060 break;
16061 case TLTIU:
16062 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16063 mips32_op = OPC_TLTIU;
16064 goto do_trapi;
16065 case TGEIU:
16066 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16067 mips32_op = OPC_TGEIU;
16068 goto do_trapi;
16069 case TNEI: /* SYNCI */
16070 if (ctx->insn_flags & ISA_MIPS32R6) {
16071 /* SYNCI */
16072 /* Break the TB to be able to sync copied instructions
16073 immediately */
16074 ctx->base.is_jmp = DISAS_STOP;
16075 } else {
16076 /* TNEI */
16077 mips32_op = OPC_TNEI;
16078 goto do_trapi;
16080 break;
16081 case TEQI:
16082 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16083 mips32_op = OPC_TEQI;
16084 do_trapi:
16085 gen_trap(ctx, mips32_op, rs, -1, imm);
16086 break;
16088 case BNEZC:
16089 case BEQZC:
16090 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16091 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16092 4, rs, 0, imm << 1, 0);
16093 /* Compact branches don't have a delay slot, so just let
16094 the normal delay slot handling take us to the branch
16095 target. */
16096 break;
16097 case LUI:
16098 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16099 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16100 break;
16101 case SYNCI:
16102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16103 /* Break the TB to be able to sync copied instructions
16104 immediately */
16105 ctx->base.is_jmp = DISAS_STOP;
16106 break;
16107 case BC2F:
16108 case BC2T:
16109 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16110 /* COP2: Not implemented. */
16111 generate_exception_err(ctx, EXCP_CpU, 2);
16112 break;
16113 case BC1F:
16114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16115 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16116 goto do_cp1branch;
16117 case BC1T:
16118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16119 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16120 goto do_cp1branch;
16121 case BC1ANY4F:
16122 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16123 mips32_op = OPC_BC1FANY4;
16124 goto do_cp1mips3d;
16125 case BC1ANY4T:
16126 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16127 mips32_op = OPC_BC1TANY4;
16128 do_cp1mips3d:
16129 check_cop1x(ctx);
16130 check_insn(ctx, ASE_MIPS3D);
16131 /* Fall through */
16132 do_cp1branch:
16133 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16134 check_cp1_enabled(ctx);
16135 gen_compute_branch1(ctx, mips32_op,
16136 (ctx->opcode >> 18) & 0x7, imm << 1);
16137 } else {
16138 generate_exception_err(ctx, EXCP_CpU, 1);
16140 break;
16141 case BPOSGE64:
16142 case BPOSGE32:
16143 /* MIPS DSP: not implemented */
16144 /* Fall through */
16145 default:
16146 MIPS_INVAL("pool32i");
16147 generate_exception_end(ctx, EXCP_RI);
16148 break;
16150 break;
16151 case POOL32C:
16152 minor = (ctx->opcode >> 12) & 0xf;
16153 offset = sextract32(ctx->opcode, 0,
16154 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
16155 switch (minor) {
16156 case LWL:
16157 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16158 mips32_op = OPC_LWL;
16159 goto do_ld_lr;
16160 case SWL:
16161 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16162 mips32_op = OPC_SWL;
16163 goto do_st_lr;
16164 case LWR:
16165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16166 mips32_op = OPC_LWR;
16167 goto do_ld_lr;
16168 case SWR:
16169 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16170 mips32_op = OPC_SWR;
16171 goto do_st_lr;
16172 #if defined(TARGET_MIPS64)
16173 case LDL:
16174 check_insn(ctx, ISA_MIPS3);
16175 check_mips_64(ctx);
16176 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16177 mips32_op = OPC_LDL;
16178 goto do_ld_lr;
16179 case SDL:
16180 check_insn(ctx, ISA_MIPS3);
16181 check_mips_64(ctx);
16182 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16183 mips32_op = OPC_SDL;
16184 goto do_st_lr;
16185 case LDR:
16186 check_insn(ctx, ISA_MIPS3);
16187 check_mips_64(ctx);
16188 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16189 mips32_op = OPC_LDR;
16190 goto do_ld_lr;
16191 case SDR:
16192 check_insn(ctx, ISA_MIPS3);
16193 check_mips_64(ctx);
16194 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16195 mips32_op = OPC_SDR;
16196 goto do_st_lr;
16197 case LWU:
16198 check_insn(ctx, ISA_MIPS3);
16199 check_mips_64(ctx);
16200 mips32_op = OPC_LWU;
16201 goto do_ld_lr;
16202 case LLD:
16203 check_insn(ctx, ISA_MIPS3);
16204 check_mips_64(ctx);
16205 mips32_op = OPC_LLD;
16206 goto do_ld_lr;
16207 #endif
16208 case LL:
16209 mips32_op = OPC_LL;
16210 goto do_ld_lr;
16211 do_ld_lr:
16212 gen_ld(ctx, mips32_op, rt, rs, offset);
16213 break;
16214 do_st_lr:
16215 gen_st(ctx, mips32_op, rt, rs, offset);
16216 break;
16217 case SC:
16218 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
16219 break;
16220 #if defined(TARGET_MIPS64)
16221 case SCD:
16222 check_insn(ctx, ISA_MIPS3);
16223 check_mips_64(ctx);
16224 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
16225 break;
16226 #endif
16227 case LD_EVA:
16228 if (!ctx->eva) {
16229 MIPS_INVAL("pool32c ld-eva");
16230 generate_exception_end(ctx, EXCP_RI);
16231 break;
16233 check_cp0_enabled(ctx);
16235 minor2 = (ctx->opcode >> 9) & 0x7;
16236 offset = sextract32(ctx->opcode, 0, 9);
16237 switch (minor2) {
16238 case LBUE:
16239 mips32_op = OPC_LBUE;
16240 goto do_ld_lr;
16241 case LHUE:
16242 mips32_op = OPC_LHUE;
16243 goto do_ld_lr;
16244 case LWLE:
16245 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16246 mips32_op = OPC_LWLE;
16247 goto do_ld_lr;
16248 case LWRE:
16249 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16250 mips32_op = OPC_LWRE;
16251 goto do_ld_lr;
16252 case LBE:
16253 mips32_op = OPC_LBE;
16254 goto do_ld_lr;
16255 case LHE:
16256 mips32_op = OPC_LHE;
16257 goto do_ld_lr;
16258 case LLE:
16259 mips32_op = OPC_LLE;
16260 goto do_ld_lr;
16261 case LWE:
16262 mips32_op = OPC_LWE;
16263 goto do_ld_lr;
16265 break;
16266 case ST_EVA:
16267 if (!ctx->eva) {
16268 MIPS_INVAL("pool32c st-eva");
16269 generate_exception_end(ctx, EXCP_RI);
16270 break;
16272 check_cp0_enabled(ctx);
16274 minor2 = (ctx->opcode >> 9) & 0x7;
16275 offset = sextract32(ctx->opcode, 0, 9);
16276 switch (minor2) {
16277 case SWLE:
16278 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16279 mips32_op = OPC_SWLE;
16280 goto do_st_lr;
16281 case SWRE:
16282 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16283 mips32_op = OPC_SWRE;
16284 goto do_st_lr;
16285 case PREFE:
16286 /* Treat as no-op */
16287 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16288 /* hint codes 24-31 are reserved and signal RI */
16289 generate_exception(ctx, EXCP_RI);
16291 break;
16292 case CACHEE:
16293 /* Treat as no-op */
16294 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16295 gen_cache_operation(ctx, rt, rs, offset);
16297 break;
16298 case SBE:
16299 mips32_op = OPC_SBE;
16300 goto do_st_lr;
16301 case SHE:
16302 mips32_op = OPC_SHE;
16303 goto do_st_lr;
16304 case SCE:
16305 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
16306 break;
16307 case SWE:
16308 mips32_op = OPC_SWE;
16309 goto do_st_lr;
16311 break;
16312 case PREF:
16313 /* Treat as no-op */
16314 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
16315 /* hint codes 24-31 are reserved and signal RI */
16316 generate_exception(ctx, EXCP_RI);
16318 break;
16319 default:
16320 MIPS_INVAL("pool32c");
16321 generate_exception_end(ctx, EXCP_RI);
16322 break;
16324 break;
16325 case ADDI32: /* AUI, LUI */
16326 if (ctx->insn_flags & ISA_MIPS32R6) {
16327 /* AUI, LUI */
16328 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16329 } else {
16330 /* ADDI32 */
16331 mips32_op = OPC_ADDI;
16332 goto do_addi;
16334 break;
16335 case ADDIU32:
16336 mips32_op = OPC_ADDIU;
16337 do_addi:
16338 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16339 break;
16341 /* Logical operations */
16342 case ORI32:
16343 mips32_op = OPC_ORI;
16344 goto do_logici;
16345 case XORI32:
16346 mips32_op = OPC_XORI;
16347 goto do_logici;
16348 case ANDI32:
16349 mips32_op = OPC_ANDI;
16350 do_logici:
16351 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16352 break;
16354 /* Set less than immediate */
16355 case SLTI32:
16356 mips32_op = OPC_SLTI;
16357 goto do_slti;
16358 case SLTIU32:
16359 mips32_op = OPC_SLTIU;
16360 do_slti:
16361 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16362 break;
16363 case JALX32:
16364 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16365 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16366 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16367 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16368 break;
16369 case JALS32: /* BOVC, BEQC, BEQZALC */
16370 if (ctx->insn_flags & ISA_MIPS32R6) {
16371 if (rs >= rt) {
16372 /* BOVC */
16373 mips32_op = OPC_BOVC;
16374 } else if (rs < rt && rs == 0) {
16375 /* BEQZALC */
16376 mips32_op = OPC_BEQZALC;
16377 } else {
16378 /* BEQC */
16379 mips32_op = OPC_BEQC;
16381 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16382 } else {
16383 /* JALS32 */
16384 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16385 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16386 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16388 break;
16389 case BEQ32: /* BC */
16390 if (ctx->insn_flags & ISA_MIPS32R6) {
16391 /* BC */
16392 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16393 sextract32(ctx->opcode << 1, 0, 27));
16394 } else {
16395 /* BEQ32 */
16396 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16398 break;
16399 case BNE32: /* BALC */
16400 if (ctx->insn_flags & ISA_MIPS32R6) {
16401 /* BALC */
16402 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16403 sextract32(ctx->opcode << 1, 0, 27));
16404 } else {
16405 /* BNE32 */
16406 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16408 break;
16409 case J32: /* BGTZC, BLTZC, BLTC */
16410 if (ctx->insn_flags & ISA_MIPS32R6) {
16411 if (rs == 0 && rt != 0) {
16412 /* BGTZC */
16413 mips32_op = OPC_BGTZC;
16414 } else if (rs != 0 && rt != 0 && rs == rt) {
16415 /* BLTZC */
16416 mips32_op = OPC_BLTZC;
16417 } else {
16418 /* BLTC */
16419 mips32_op = OPC_BLTC;
16421 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16422 } else {
16423 /* J32 */
16424 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16425 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16427 break;
16428 case JAL32: /* BLEZC, BGEZC, BGEC */
16429 if (ctx->insn_flags & ISA_MIPS32R6) {
16430 if (rs == 0 && rt != 0) {
16431 /* BLEZC */
16432 mips32_op = OPC_BLEZC;
16433 } else if (rs != 0 && rt != 0 && rs == rt) {
16434 /* BGEZC */
16435 mips32_op = OPC_BGEZC;
16436 } else {
16437 /* BGEC */
16438 mips32_op = OPC_BGEC;
16440 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16441 } else {
16442 /* JAL32 */
16443 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16444 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16445 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16447 break;
16448 /* Floating point (COP1) */
16449 case LWC132:
16450 mips32_op = OPC_LWC1;
16451 goto do_cop1;
16452 case LDC132:
16453 mips32_op = OPC_LDC1;
16454 goto do_cop1;
16455 case SWC132:
16456 mips32_op = OPC_SWC1;
16457 goto do_cop1;
16458 case SDC132:
16459 mips32_op = OPC_SDC1;
16460 do_cop1:
16461 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16462 break;
16463 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16464 if (ctx->insn_flags & ISA_MIPS32R6) {
16465 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16466 switch ((ctx->opcode >> 16) & 0x1f) {
16467 case ADDIUPC_00:
16468 case ADDIUPC_01:
16469 case ADDIUPC_02:
16470 case ADDIUPC_03:
16471 case ADDIUPC_04:
16472 case ADDIUPC_05:
16473 case ADDIUPC_06:
16474 case ADDIUPC_07:
16475 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16476 break;
16477 case AUIPC:
16478 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16479 break;
16480 case ALUIPC:
16481 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16482 break;
16483 case LWPC_08:
16484 case LWPC_09:
16485 case LWPC_0A:
16486 case LWPC_0B:
16487 case LWPC_0C:
16488 case LWPC_0D:
16489 case LWPC_0E:
16490 case LWPC_0F:
16491 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16492 break;
16493 default:
16494 generate_exception(ctx, EXCP_RI);
16495 break;
16497 } else {
16498 /* ADDIUPC */
16499 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16500 offset = SIMM(ctx->opcode, 0, 23) << 2;
16502 gen_addiupc(ctx, reg, offset, 0, 0);
16504 break;
16505 case BNVC: /* BNEC, BNEZALC */
16506 check_insn(ctx, ISA_MIPS32R6);
16507 if (rs >= rt) {
16508 /* BNVC */
16509 mips32_op = OPC_BNVC;
16510 } else if (rs < rt && rs == 0) {
16511 /* BNEZALC */
16512 mips32_op = OPC_BNEZALC;
16513 } else {
16514 /* BNEC */
16515 mips32_op = OPC_BNEC;
16517 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16518 break;
16519 case R6_BNEZC: /* JIALC */
16520 check_insn(ctx, ISA_MIPS32R6);
16521 if (rt != 0) {
16522 /* BNEZC */
16523 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16524 sextract32(ctx->opcode << 1, 0, 22));
16525 } else {
16526 /* JIALC */
16527 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16529 break;
16530 case R6_BEQZC: /* JIC */
16531 check_insn(ctx, ISA_MIPS32R6);
16532 if (rt != 0) {
16533 /* BEQZC */
16534 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16535 sextract32(ctx->opcode << 1, 0, 22));
16536 } else {
16537 /* JIC */
16538 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16540 break;
16541 case BLEZALC: /* BGEZALC, BGEUC */
16542 check_insn(ctx, ISA_MIPS32R6);
16543 if (rs == 0 && rt != 0) {
16544 /* BLEZALC */
16545 mips32_op = OPC_BLEZALC;
16546 } else if (rs != 0 && rt != 0 && rs == rt) {
16547 /* BGEZALC */
16548 mips32_op = OPC_BGEZALC;
16549 } else {
16550 /* BGEUC */
16551 mips32_op = OPC_BGEUC;
16553 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16554 break;
16555 case BGTZALC: /* BLTZALC, BLTUC */
16556 check_insn(ctx, ISA_MIPS32R6);
16557 if (rs == 0 && rt != 0) {
16558 /* BGTZALC */
16559 mips32_op = OPC_BGTZALC;
16560 } else if (rs != 0 && rt != 0 && rs == rt) {
16561 /* BLTZALC */
16562 mips32_op = OPC_BLTZALC;
16563 } else {
16564 /* BLTUC */
16565 mips32_op = OPC_BLTUC;
16567 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16568 break;
16569 /* Loads and stores */
16570 case LB32:
16571 mips32_op = OPC_LB;
16572 goto do_ld;
16573 case LBU32:
16574 mips32_op = OPC_LBU;
16575 goto do_ld;
16576 case LH32:
16577 mips32_op = OPC_LH;
16578 goto do_ld;
16579 case LHU32:
16580 mips32_op = OPC_LHU;
16581 goto do_ld;
16582 case LW32:
16583 mips32_op = OPC_LW;
16584 goto do_ld;
16585 #ifdef TARGET_MIPS64
16586 case LD32:
16587 check_insn(ctx, ISA_MIPS3);
16588 check_mips_64(ctx);
16589 mips32_op = OPC_LD;
16590 goto do_ld;
16591 case SD32:
16592 check_insn(ctx, ISA_MIPS3);
16593 check_mips_64(ctx);
16594 mips32_op = OPC_SD;
16595 goto do_st;
16596 #endif
16597 case SB32:
16598 mips32_op = OPC_SB;
16599 goto do_st;
16600 case SH32:
16601 mips32_op = OPC_SH;
16602 goto do_st;
16603 case SW32:
16604 mips32_op = OPC_SW;
16605 goto do_st;
16606 do_ld:
16607 gen_ld(ctx, mips32_op, rt, rs, imm);
16608 break;
16609 do_st:
16610 gen_st(ctx, mips32_op, rt, rs, imm);
16611 break;
16612 default:
16613 generate_exception_end(ctx, EXCP_RI);
16614 break;
16618 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
16620 uint32_t op;
16622 /* make sure instructions are on a halfword boundary */
16623 if (ctx->base.pc_next & 0x1) {
16624 env->CP0_BadVAddr = ctx->base.pc_next;
16625 generate_exception_end(ctx, EXCP_AdEL);
16626 return 2;
16629 op = (ctx->opcode >> 10) & 0x3f;
16630 /* Enforce properly-sized instructions in a delay slot */
16631 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16632 switch (op & 0x7) { /* MSB-3..MSB-5 */
16633 case 0:
16634 /* POOL32A, POOL32B, POOL32I, POOL32C */
16635 case 4:
16636 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16637 case 5:
16638 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16639 case 6:
16640 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16641 case 7:
16642 /* LB32, LH32, LWC132, LDC132, LW32 */
16643 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16644 generate_exception_end(ctx, EXCP_RI);
16645 return 2;
16647 break;
16648 case 1:
16649 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16650 case 2:
16651 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16652 case 3:
16653 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16654 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16655 generate_exception_end(ctx, EXCP_RI);
16656 return 2;
16658 break;
16662 switch (op) {
16663 case POOL16A:
16665 int rd = mmreg(uMIPS_RD(ctx->opcode));
16666 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16667 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16668 uint32_t opc = 0;
16670 switch (ctx->opcode & 0x1) {
16671 case ADDU16:
16672 opc = OPC_ADDU;
16673 break;
16674 case SUBU16:
16675 opc = OPC_SUBU;
16676 break;
16678 if (ctx->insn_flags & ISA_MIPS32R6) {
16679 /* In the Release 6 the register number location in
16680 * the instruction encoding has changed.
16682 gen_arith(ctx, opc, rs1, rd, rs2);
16683 } else {
16684 gen_arith(ctx, opc, rd, rs1, rs2);
16687 break;
16688 case POOL16B:
16690 int rd = mmreg(uMIPS_RD(ctx->opcode));
16691 int rs = mmreg(uMIPS_RS(ctx->opcode));
16692 int amount = (ctx->opcode >> 1) & 0x7;
16693 uint32_t opc = 0;
16694 amount = amount == 0 ? 8 : amount;
16696 switch (ctx->opcode & 0x1) {
16697 case SLL16:
16698 opc = OPC_SLL;
16699 break;
16700 case SRL16:
16701 opc = OPC_SRL;
16702 break;
16705 gen_shift_imm(ctx, opc, rd, rs, amount);
16707 break;
16708 case POOL16C:
16709 if (ctx->insn_flags & ISA_MIPS32R6) {
16710 gen_pool16c_r6_insn(ctx);
16711 } else {
16712 gen_pool16c_insn(ctx);
16714 break;
16715 case LWGP16:
16717 int rd = mmreg(uMIPS_RD(ctx->opcode));
16718 int rb = 28; /* GP */
16719 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16721 gen_ld(ctx, OPC_LW, rd, rb, offset);
16723 break;
16724 case POOL16F:
16725 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16726 if (ctx->opcode & 1) {
16727 generate_exception_end(ctx, EXCP_RI);
16728 } else {
16729 /* MOVEP */
16730 int enc_dest = uMIPS_RD(ctx->opcode);
16731 int enc_rt = uMIPS_RS2(ctx->opcode);
16732 int enc_rs = uMIPS_RS1(ctx->opcode);
16733 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16735 break;
16736 case LBU16:
16738 int rd = mmreg(uMIPS_RD(ctx->opcode));
16739 int rb = mmreg(uMIPS_RS(ctx->opcode));
16740 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16741 offset = (offset == 0xf ? -1 : offset);
16743 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16745 break;
16746 case LHU16:
16748 int rd = mmreg(uMIPS_RD(ctx->opcode));
16749 int rb = mmreg(uMIPS_RS(ctx->opcode));
16750 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16752 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16754 break;
16755 case LWSP16:
16757 int rd = (ctx->opcode >> 5) & 0x1f;
16758 int rb = 29; /* SP */
16759 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16761 gen_ld(ctx, OPC_LW, rd, rb, offset);
16763 break;
16764 case LW16:
16766 int rd = mmreg(uMIPS_RD(ctx->opcode));
16767 int rb = mmreg(uMIPS_RS(ctx->opcode));
16768 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16770 gen_ld(ctx, OPC_LW, rd, rb, offset);
16772 break;
16773 case SB16:
16775 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16776 int rb = mmreg(uMIPS_RS(ctx->opcode));
16777 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16779 gen_st(ctx, OPC_SB, rd, rb, offset);
16781 break;
16782 case SH16:
16784 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16785 int rb = mmreg(uMIPS_RS(ctx->opcode));
16786 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16788 gen_st(ctx, OPC_SH, rd, rb, offset);
16790 break;
16791 case SWSP16:
16793 int rd = (ctx->opcode >> 5) & 0x1f;
16794 int rb = 29; /* SP */
16795 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16797 gen_st(ctx, OPC_SW, rd, rb, offset);
16799 break;
16800 case SW16:
16802 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16803 int rb = mmreg(uMIPS_RS(ctx->opcode));
16804 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16806 gen_st(ctx, OPC_SW, rd, rb, offset);
16808 break;
16809 case MOVE16:
16811 int rd = uMIPS_RD5(ctx->opcode);
16812 int rs = uMIPS_RS5(ctx->opcode);
16814 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16816 break;
16817 case ANDI16:
16818 gen_andi16(ctx);
16819 break;
16820 case POOL16D:
16821 switch (ctx->opcode & 0x1) {
16822 case ADDIUS5:
16823 gen_addius5(ctx);
16824 break;
16825 case ADDIUSP:
16826 gen_addiusp(ctx);
16827 break;
16829 break;
16830 case POOL16E:
16831 switch (ctx->opcode & 0x1) {
16832 case ADDIUR2:
16833 gen_addiur2(ctx);
16834 break;
16835 case ADDIUR1SP:
16836 gen_addiur1sp(ctx);
16837 break;
16839 break;
16840 case B16: /* BC16 */
16841 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16842 sextract32(ctx->opcode, 0, 10) << 1,
16843 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16844 break;
16845 case BNEZ16: /* BNEZC16 */
16846 case BEQZ16: /* BEQZC16 */
16847 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16848 mmreg(uMIPS_RD(ctx->opcode)),
16849 0, sextract32(ctx->opcode, 0, 7) << 1,
16850 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
16852 break;
16853 case LI16:
16855 int reg = mmreg(uMIPS_RD(ctx->opcode));
16856 int imm = ZIMM(ctx->opcode, 0, 7);
16858 imm = (imm == 0x7f ? -1 : imm);
16859 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16861 break;
16862 case RES_29:
16863 case RES_31:
16864 case RES_39:
16865 generate_exception_end(ctx, EXCP_RI);
16866 break;
16867 default:
16868 decode_micromips32_opc(env, ctx);
16869 return 4;
16872 return 2;
16877 * nanoMIPS opcodes
16881 /* MAJOR, P16, and P32 pools opcodes */
16882 enum {
16883 NM_P_ADDIU = 0x00,
16884 NM_ADDIUPC = 0x01,
16885 NM_MOVE_BALC = 0x02,
16886 NM_P16_MV = 0x04,
16887 NM_LW16 = 0x05,
16888 NM_BC16 = 0x06,
16889 NM_P16_SR = 0x07,
16891 NM_POOL32A = 0x08,
16892 NM_P_BAL = 0x0a,
16893 NM_P16_SHIFT = 0x0c,
16894 NM_LWSP16 = 0x0d,
16895 NM_BALC16 = 0x0e,
16896 NM_P16_4X4 = 0x0f,
16898 NM_P_GP_W = 0x10,
16899 NM_P_GP_BH = 0x11,
16900 NM_P_J = 0x12,
16901 NM_P16C = 0x14,
16902 NM_LWGP16 = 0x15,
16903 NM_P16_LB = 0x17,
16905 NM_P48I = 0x18,
16906 NM_P16_A1 = 0x1c,
16907 NM_LW4X4 = 0x1d,
16908 NM_P16_LH = 0x1f,
16910 NM_P_U12 = 0x20,
16911 NM_P_LS_U12 = 0x21,
16912 NM_P_BR1 = 0x22,
16913 NM_P16_A2 = 0x24,
16914 NM_SW16 = 0x25,
16915 NM_BEQZC16 = 0x26,
16917 NM_POOL32F = 0x28,
16918 NM_P_LS_S9 = 0x29,
16919 NM_P_BR2 = 0x2a,
16921 NM_P16_ADDU = 0x2c,
16922 NM_SWSP16 = 0x2d,
16923 NM_BNEZC16 = 0x2e,
16924 NM_MOVEP = 0x2f,
16926 NM_POOL32S = 0x30,
16927 NM_P_BRI = 0x32,
16928 NM_LI16 = 0x34,
16929 NM_SWGP16 = 0x35,
16930 NM_P16_BR = 0x36,
16932 NM_P_LUI = 0x38,
16933 NM_ANDI16 = 0x3c,
16934 NM_SW4X4 = 0x3d,
16935 NM_MOVEPREV = 0x3f,
16938 /* POOL32A instruction pool */
16939 enum {
16940 NM_POOL32A0 = 0x00,
16941 NM_SPECIAL2 = 0x01,
16942 NM_COP2_1 = 0x02,
16943 NM_UDI = 0x03,
16944 NM_POOL32A5 = 0x05,
16945 NM_POOL32A7 = 0x07,
16948 /* P.GP.W instruction pool */
16949 enum {
16950 NM_ADDIUGP_W = 0x00,
16951 NM_LWGP = 0x02,
16952 NM_SWGP = 0x03,
16955 /* P48I instruction pool */
16956 enum {
16957 NM_LI48 = 0x00,
16958 NM_ADDIU48 = 0x01,
16959 NM_ADDIUGP48 = 0x02,
16960 NM_ADDIUPC48 = 0x03,
16961 NM_LWPC48 = 0x0b,
16962 NM_SWPC48 = 0x0f,
16965 /* P.U12 instruction pool */
16966 enum {
16967 NM_ORI = 0x00,
16968 NM_XORI = 0x01,
16969 NM_ANDI = 0x02,
16970 NM_P_SR = 0x03,
16971 NM_SLTI = 0x04,
16972 NM_SLTIU = 0x05,
16973 NM_SEQI = 0x06,
16974 NM_ADDIUNEG = 0x08,
16975 NM_P_SHIFT = 0x0c,
16976 NM_P_ROTX = 0x0d,
16977 NM_P_INS = 0x0e,
16978 NM_P_EXT = 0x0f,
16981 /* POOL32F instruction pool */
16982 enum {
16983 NM_POOL32F_0 = 0x00,
16984 NM_POOL32F_3 = 0x03,
16985 NM_POOL32F_5 = 0x05,
16988 /* POOL32S instruction pool */
16989 enum {
16990 NM_POOL32S_0 = 0x00,
16991 NM_POOL32S_4 = 0x04,
16994 /* P.LUI instruction pool */
16995 enum {
16996 NM_LUI = 0x00,
16997 NM_ALUIPC = 0x01,
17000 /* P.GP.BH instruction pool */
17001 enum {
17002 NM_LBGP = 0x00,
17003 NM_SBGP = 0x01,
17004 NM_LBUGP = 0x02,
17005 NM_ADDIUGP_B = 0x03,
17006 NM_P_GP_LH = 0x04,
17007 NM_P_GP_SH = 0x05,
17008 NM_P_GP_CP1 = 0x06,
17011 /* P.LS.U12 instruction pool */
17012 enum {
17013 NM_LB = 0x00,
17014 NM_SB = 0x01,
17015 NM_LBU = 0x02,
17016 NM_P_PREFU12 = 0x03,
17017 NM_LH = 0x04,
17018 NM_SH = 0x05,
17019 NM_LHU = 0x06,
17020 NM_LWU = 0x07,
17021 NM_LW = 0x08,
17022 NM_SW = 0x09,
17023 NM_LWC1 = 0x0a,
17024 NM_SWC1 = 0x0b,
17025 NM_LDC1 = 0x0e,
17026 NM_SDC1 = 0x0f,
17029 /* P.LS.S9 instruction pool */
17030 enum {
17031 NM_P_LS_S0 = 0x00,
17032 NM_P_LS_S1 = 0x01,
17033 NM_P_LS_E0 = 0x02,
17034 NM_P_LS_WM = 0x04,
17035 NM_P_LS_UAWM = 0x05,
17038 /* P.BAL instruction pool */
17039 enum {
17040 NM_BC = 0x00,
17041 NM_BALC = 0x01,
17044 /* P.J instruction pool */
17045 enum {
17046 NM_JALRC = 0x00,
17047 NM_JALRC_HB = 0x01,
17048 NM_P_BALRSC = 0x08,
17051 /* P.BR1 instruction pool */
17052 enum {
17053 NM_BEQC = 0x00,
17054 NM_P_BR3A = 0x01,
17055 NM_BGEC = 0x02,
17056 NM_BGEUC = 0x03,
17059 /* P.BR2 instruction pool */
17060 enum {
17061 NM_BNEC = 0x00,
17062 NM_BLTC = 0x02,
17063 NM_BLTUC = 0x03,
17066 /* P.BRI instruction pool */
17067 enum {
17068 NM_BEQIC = 0x00,
17069 NM_BBEQZC = 0x01,
17070 NM_BGEIC = 0x02,
17071 NM_BGEIUC = 0x03,
17072 NM_BNEIC = 0x04,
17073 NM_BBNEZC = 0x05,
17074 NM_BLTIC = 0x06,
17075 NM_BLTIUC = 0x07,
17078 /* P16.SHIFT instruction pool */
17079 enum {
17080 NM_SLL16 = 0x00,
17081 NM_SRL16 = 0x01,
17084 /* POOL16C instruction pool */
17085 enum {
17086 NM_POOL16C_0 = 0x00,
17087 NM_LWXS16 = 0x01,
17090 /* P16.A1 instruction pool */
17091 enum {
17092 NM_ADDIUR1SP = 0x01,
17095 /* P16.A2 instruction pool */
17096 enum {
17097 NM_ADDIUR2 = 0x00,
17098 NM_P_ADDIURS5 = 0x01,
17101 /* P16.ADDU instruction pool */
17102 enum {
17103 NM_ADDU16 = 0x00,
17104 NM_SUBU16 = 0x01,
17107 /* P16.SR instruction pool */
17108 enum {
17109 NM_SAVE16 = 0x00,
17110 NM_RESTORE_JRC16 = 0x01,
17113 /* P16.4X4 instruction pool */
17114 enum {
17115 NM_ADDU4X4 = 0x00,
17116 NM_MUL4X4 = 0x01,
17119 /* P16.LB instruction pool */
17120 enum {
17121 NM_LB16 = 0x00,
17122 NM_SB16 = 0x01,
17123 NM_LBU16 = 0x02,
17126 /* P16.LH instruction pool */
17127 enum {
17128 NM_LH16 = 0x00,
17129 NM_SH16 = 0x01,
17130 NM_LHU16 = 0x02,
17133 /* P.RI instruction pool */
17134 enum {
17135 NM_SIGRIE = 0x00,
17136 NM_P_SYSCALL = 0x01,
17137 NM_BREAK = 0x02,
17138 NM_SDBBP = 0x03,
17141 /* POOL32A0 instruction pool */
17142 enum {
17143 NM_P_TRAP = 0x00,
17144 NM_SEB = 0x01,
17145 NM_SLLV = 0x02,
17146 NM_MUL = 0x03,
17147 NM_MFC0 = 0x06,
17148 NM_MFHC0 = 0x07,
17149 NM_SEH = 0x09,
17150 NM_SRLV = 0x0a,
17151 NM_MUH = 0x0b,
17152 NM_MTC0 = 0x0e,
17153 NM_MTHC0 = 0x0f,
17154 NM_SRAV = 0x12,
17155 NM_MULU = 0x13,
17156 NM_ROTRV = 0x1a,
17157 NM_MUHU = 0x1b,
17158 NM_ADD = 0x22,
17159 NM_DIV = 0x23,
17160 NM_ADDU = 0x2a,
17161 NM_MOD = 0x2b,
17162 NM_SUB = 0x32,
17163 NM_DIVU = 0x33,
17164 NM_RDHWR = 0x38,
17165 NM_SUBU = 0x3a,
17166 NM_MODU = 0x3b,
17167 NM_P_CMOVE = 0x42,
17168 NM_FORK = 0x45,
17169 NM_MFTR = 0x46,
17170 NM_MFHTR = 0x47,
17171 NM_AND = 0x4a,
17172 NM_YIELD = 0x4d,
17173 NM_MTTR = 0x4e,
17174 NM_MTHTR = 0x4f,
17175 NM_OR = 0x52,
17176 NM_D_E_MT_VPE = 0x56,
17177 NM_NOR = 0x5a,
17178 NM_XOR = 0x62,
17179 NM_SLT = 0x6a,
17180 NM_P_SLTU = 0x72,
17181 NM_SOV = 0x7a,
17184 /* POOL32A5 instruction pool */
17185 enum {
17186 NM_CMP_EQ_PH = 0x00,
17187 NM_CMP_LT_PH = 0x08,
17188 NM_CMP_LE_PH = 0x10,
17189 NM_CMPGU_EQ_QB = 0x18,
17190 NM_CMPGU_LT_QB = 0x20,
17191 NM_CMPGU_LE_QB = 0x28,
17192 NM_CMPGDU_EQ_QB = 0x30,
17193 NM_CMPGDU_LT_QB = 0x38,
17194 NM_CMPGDU_LE_QB = 0x40,
17195 NM_CMPU_EQ_QB = 0x48,
17196 NM_CMPU_LT_QB = 0x50,
17197 NM_CMPU_LE_QB = 0x58,
17198 NM_ADDQ_S_W = 0x60,
17199 NM_SUBQ_S_W = 0x68,
17200 NM_ADDSC = 0x70,
17201 NM_ADDWC = 0x78,
17203 NM_ADDQ_S_PH = 0x01,
17204 NM_ADDQH_R_PH = 0x09,
17205 NM_ADDQH_R_W = 0x11,
17206 NM_ADDU_S_QB = 0x19,
17207 NM_ADDU_S_PH = 0x21,
17208 NM_ADDUH_R_QB = 0x29,
17209 NM_SHRAV_R_PH = 0x31,
17210 NM_SHRAV_R_QB = 0x39,
17211 NM_SUBQ_S_PH = 0x41,
17212 NM_SUBQH_R_PH = 0x49,
17213 NM_SUBQH_R_W = 0x51,
17214 NM_SUBU_S_QB = 0x59,
17215 NM_SUBU_S_PH = 0x61,
17216 NM_SUBUH_R_QB = 0x69,
17217 NM_SHLLV_S_PH = 0x71,
17218 NM_PRECR_SRA_R_PH_W = 0x79,
17220 NM_MULEU_S_PH_QBL = 0x12,
17221 NM_MULEU_S_PH_QBR = 0x1a,
17222 NM_MULQ_RS_PH = 0x22,
17223 NM_MULQ_S_PH = 0x2a,
17224 NM_MULQ_RS_W = 0x32,
17225 NM_MULQ_S_W = 0x3a,
17226 NM_APPEND = 0x42,
17227 NM_MODSUB = 0x52,
17228 NM_SHRAV_R_W = 0x5a,
17229 NM_SHRLV_PH = 0x62,
17230 NM_SHRLV_QB = 0x6a,
17231 NM_SHLLV_QB = 0x72,
17232 NM_SHLLV_S_W = 0x7a,
17234 NM_SHILO = 0x03,
17236 NM_MULEQ_S_W_PHL = 0x04,
17237 NM_MULEQ_S_W_PHR = 0x0c,
17239 NM_MUL_S_PH = 0x05,
17240 NM_PRECR_QB_PH = 0x0d,
17241 NM_PRECRQ_QB_PH = 0x15,
17242 NM_PRECRQ_PH_W = 0x1d,
17243 NM_PRECRQ_RS_PH_W = 0x25,
17244 NM_PRECRQU_S_QB_PH = 0x2d,
17245 NM_PACKRL_PH = 0x35,
17246 NM_PICK_QB = 0x3d,
17247 NM_PICK_PH = 0x45,
17249 NM_SHRA_R_W = 0x5e,
17250 NM_SHRA_R_PH = 0x66,
17251 NM_SHLL_S_PH = 0x76,
17252 NM_SHLL_S_W = 0x7e,
17254 NM_REPL_PH = 0x07
17257 /* POOL32A7 instruction pool */
17258 enum {
17259 NM_P_LSX = 0x00,
17260 NM_LSA = 0x01,
17261 NM_EXTW = 0x03,
17262 NM_POOL32AXF = 0x07,
17265 /* P.SR instruction pool */
17266 enum {
17267 NM_PP_SR = 0x00,
17268 NM_P_SR_F = 0x01,
17271 /* P.SHIFT instruction pool */
17272 enum {
17273 NM_P_SLL = 0x00,
17274 NM_SRL = 0x02,
17275 NM_SRA = 0x04,
17276 NM_ROTR = 0x06,
17279 /* P.ROTX instruction pool */
17280 enum {
17281 NM_ROTX = 0x00,
17284 /* P.INS instruction pool */
17285 enum {
17286 NM_INS = 0x00,
17289 /* P.EXT instruction pool */
17290 enum {
17291 NM_EXT = 0x00,
17294 /* POOL32F_0 (fmt) instruction pool */
17295 enum {
17296 NM_RINT_S = 0x04,
17297 NM_RINT_D = 0x44,
17298 NM_ADD_S = 0x06,
17299 NM_SELEQZ_S = 0x07,
17300 NM_SELEQZ_D = 0x47,
17301 NM_CLASS_S = 0x0c,
17302 NM_CLASS_D = 0x4c,
17303 NM_SUB_S = 0x0e,
17304 NM_SELNEZ_S = 0x0f,
17305 NM_SELNEZ_D = 0x4f,
17306 NM_MUL_S = 0x16,
17307 NM_SEL_S = 0x17,
17308 NM_SEL_D = 0x57,
17309 NM_DIV_S = 0x1e,
17310 NM_ADD_D = 0x26,
17311 NM_SUB_D = 0x2e,
17312 NM_MUL_D = 0x36,
17313 NM_MADDF_S = 0x37,
17314 NM_MADDF_D = 0x77,
17315 NM_DIV_D = 0x3e,
17316 NM_MSUBF_S = 0x3f,
17317 NM_MSUBF_D = 0x7f,
17320 /* POOL32F_3 instruction pool */
17321 enum {
17322 NM_MIN_FMT = 0x00,
17323 NM_MAX_FMT = 0x01,
17324 NM_MINA_FMT = 0x04,
17325 NM_MAXA_FMT = 0x05,
17326 NM_POOL32FXF = 0x07,
17329 /* POOL32F_5 instruction pool */
17330 enum {
17331 NM_CMP_CONDN_S = 0x00,
17332 NM_CMP_CONDN_D = 0x02,
17335 /* P.GP.LH instruction pool */
17336 enum {
17337 NM_LHGP = 0x00,
17338 NM_LHUGP = 0x01,
17341 /* P.GP.SH instruction pool */
17342 enum {
17343 NM_SHGP = 0x00,
17346 /* P.GP.CP1 instruction pool */
17347 enum {
17348 NM_LWC1GP = 0x00,
17349 NM_SWC1GP = 0x01,
17350 NM_LDC1GP = 0x02,
17351 NM_SDC1GP = 0x03,
17354 /* P.LS.S0 instruction pool */
17355 enum {
17356 NM_LBS9 = 0x00,
17357 NM_LHS9 = 0x04,
17358 NM_LWS9 = 0x08,
17359 NM_LDS9 = 0x0c,
17361 NM_SBS9 = 0x01,
17362 NM_SHS9 = 0x05,
17363 NM_SWS9 = 0x09,
17364 NM_SDS9 = 0x0d,
17366 NM_LBUS9 = 0x02,
17367 NM_LHUS9 = 0x06,
17368 NM_LWC1S9 = 0x0a,
17369 NM_LDC1S9 = 0x0e,
17371 NM_P_PREFS9 = 0x03,
17372 NM_LWUS9 = 0x07,
17373 NM_SWC1S9 = 0x0b,
17374 NM_SDC1S9 = 0x0f,
17377 /* P.LS.S1 instruction pool */
17378 enum {
17379 NM_ASET_ACLR = 0x02,
17380 NM_UALH = 0x04,
17381 NM_UASH = 0x05,
17382 NM_CACHE = 0x07,
17383 NM_P_LL = 0x0a,
17384 NM_P_SC = 0x0b,
17387 /* P.LS.E0 instruction pool */
17388 enum {
17389 NM_LBE = 0x00,
17390 NM_SBE = 0x01,
17391 NM_LBUE = 0x02,
17392 NM_P_PREFE = 0x03,
17393 NM_LHE = 0x04,
17394 NM_SHE = 0x05,
17395 NM_LHUE = 0x06,
17396 NM_CACHEE = 0x07,
17397 NM_LWE = 0x08,
17398 NM_SWE = 0x09,
17399 NM_P_LLE = 0x0a,
17400 NM_P_SCE = 0x0b,
17403 /* P.PREFE instruction pool */
17404 enum {
17405 NM_SYNCIE = 0x00,
17406 NM_PREFE = 0x01,
17409 /* P.LLE instruction pool */
17410 enum {
17411 NM_LLE = 0x00,
17412 NM_LLWPE = 0x01,
17415 /* P.SCE instruction pool */
17416 enum {
17417 NM_SCE = 0x00,
17418 NM_SCWPE = 0x01,
17421 /* P.LS.WM instruction pool */
17422 enum {
17423 NM_LWM = 0x00,
17424 NM_SWM = 0x01,
17427 /* P.LS.UAWM instruction pool */
17428 enum {
17429 NM_UALWM = 0x00,
17430 NM_UASWM = 0x01,
17433 /* P.BR3A instruction pool */
17434 enum {
17435 NM_BC1EQZC = 0x00,
17436 NM_BC1NEZC = 0x01,
17437 NM_BC2EQZC = 0x02,
17438 NM_BC2NEZC = 0x03,
17439 NM_BPOSGE32C = 0x04,
17442 /* P16.RI instruction pool */
17443 enum {
17444 NM_P16_SYSCALL = 0x01,
17445 NM_BREAK16 = 0x02,
17446 NM_SDBBP16 = 0x03,
17449 /* POOL16C_0 instruction pool */
17450 enum {
17451 NM_POOL16C_00 = 0x00,
17454 /* P16.JRC instruction pool */
17455 enum {
17456 NM_JRC = 0x00,
17457 NM_JALRC16 = 0x01,
17460 /* P.SYSCALL instruction pool */
17461 enum {
17462 NM_SYSCALL = 0x00,
17463 NM_HYPCALL = 0x01,
17466 /* P.TRAP instruction pool */
17467 enum {
17468 NM_TEQ = 0x00,
17469 NM_TNE = 0x01,
17472 /* P.CMOVE instruction pool */
17473 enum {
17474 NM_MOVZ = 0x00,
17475 NM_MOVN = 0x01,
17478 /* POOL32Axf instruction pool */
17479 enum {
17480 NM_POOL32AXF_1 = 0x01,
17481 NM_POOL32AXF_2 = 0x02,
17482 NM_POOL32AXF_4 = 0x04,
17483 NM_POOL32AXF_5 = 0x05,
17484 NM_POOL32AXF_7 = 0x07,
17487 /* POOL32Axf_1 instruction pool */
17488 enum {
17489 NM_POOL32AXF_1_0 = 0x00,
17490 NM_POOL32AXF_1_1 = 0x01,
17491 NM_POOL32AXF_1_3 = 0x03,
17492 NM_POOL32AXF_1_4 = 0x04,
17493 NM_POOL32AXF_1_5 = 0x05,
17494 NM_POOL32AXF_1_7 = 0x07,
17497 /* POOL32Axf_2 instruction pool */
17498 enum {
17499 NM_POOL32AXF_2_0_7 = 0x00,
17500 NM_POOL32AXF_2_8_15 = 0x01,
17501 NM_POOL32AXF_2_16_23 = 0x02,
17502 NM_POOL32AXF_2_24_31 = 0x03,
17505 /* POOL32Axf_7 instruction pool */
17506 enum {
17507 NM_SHRA_R_QB = 0x0,
17508 NM_SHRL_PH = 0x1,
17509 NM_REPL_QB = 0x2,
17512 /* POOL32Axf_1_0 instruction pool */
17513 enum {
17514 NM_MFHI = 0x0,
17515 NM_MFLO = 0x1,
17516 NM_MTHI = 0x2,
17517 NM_MTLO = 0x3,
17520 /* POOL32Axf_1_1 instruction pool */
17521 enum {
17522 NM_MTHLIP = 0x0,
17523 NM_SHILOV = 0x1,
17526 /* POOL32Axf_1_3 instruction pool */
17527 enum {
17528 NM_RDDSP = 0x0,
17529 NM_WRDSP = 0x1,
17530 NM_EXTP = 0x2,
17531 NM_EXTPDP = 0x3,
17534 /* POOL32Axf_1_4 instruction pool */
17535 enum {
17536 NM_SHLL_QB = 0x0,
17537 NM_SHRL_QB = 0x1,
17540 /* POOL32Axf_1_5 instruction pool */
17541 enum {
17542 NM_MAQ_S_W_PHR = 0x0,
17543 NM_MAQ_S_W_PHL = 0x1,
17544 NM_MAQ_SA_W_PHR = 0x2,
17545 NM_MAQ_SA_W_PHL = 0x3,
17548 /* POOL32Axf_1_7 instruction pool */
17549 enum {
17550 NM_EXTR_W = 0x0,
17551 NM_EXTR_R_W = 0x1,
17552 NM_EXTR_RS_W = 0x2,
17553 NM_EXTR_S_H = 0x3,
17556 /* POOL32Axf_2_0_7 instruction pool */
17557 enum {
17558 NM_DPA_W_PH = 0x0,
17559 NM_DPAQ_S_W_PH = 0x1,
17560 NM_DPS_W_PH = 0x2,
17561 NM_DPSQ_S_W_PH = 0x3,
17562 NM_BALIGN = 0x4,
17563 NM_MADD = 0x5,
17564 NM_MULT = 0x6,
17565 NM_EXTRV_W = 0x7,
17568 /* POOL32Axf_2_8_15 instruction pool */
17569 enum {
17570 NM_DPAX_W_PH = 0x0,
17571 NM_DPAQ_SA_L_W = 0x1,
17572 NM_DPSX_W_PH = 0x2,
17573 NM_DPSQ_SA_L_W = 0x3,
17574 NM_MADDU = 0x5,
17575 NM_MULTU = 0x6,
17576 NM_EXTRV_R_W = 0x7,
17579 /* POOL32Axf_2_16_23 instruction pool */
17580 enum {
17581 NM_DPAU_H_QBL = 0x0,
17582 NM_DPAQX_S_W_PH = 0x1,
17583 NM_DPSU_H_QBL = 0x2,
17584 NM_DPSQX_S_W_PH = 0x3,
17585 NM_EXTPV = 0x4,
17586 NM_MSUB = 0x5,
17587 NM_MULSA_W_PH = 0x6,
17588 NM_EXTRV_RS_W = 0x7,
17591 /* POOL32Axf_2_24_31 instruction pool */
17592 enum {
17593 NM_DPAU_H_QBR = 0x0,
17594 NM_DPAQX_SA_W_PH = 0x1,
17595 NM_DPSU_H_QBR = 0x2,
17596 NM_DPSQX_SA_W_PH = 0x3,
17597 NM_EXTPDPV = 0x4,
17598 NM_MSUBU = 0x5,
17599 NM_MULSAQ_S_W_PH = 0x6,
17600 NM_EXTRV_S_H = 0x7,
17603 /* POOL32Axf_{4, 5} instruction pool */
17604 enum {
17605 NM_CLO = 0x25,
17606 NM_CLZ = 0x2d,
17608 NM_TLBP = 0x01,
17609 NM_TLBR = 0x09,
17610 NM_TLBWI = 0x11,
17611 NM_TLBWR = 0x19,
17612 NM_TLBINV = 0x03,
17613 NM_TLBINVF = 0x0b,
17614 NM_DI = 0x23,
17615 NM_EI = 0x2b,
17616 NM_RDPGPR = 0x70,
17617 NM_WRPGPR = 0x78,
17618 NM_WAIT = 0x61,
17619 NM_DERET = 0x71,
17620 NM_ERETX = 0x79,
17622 /* nanoMIPS DSP instructions */
17623 NM_ABSQ_S_QB = 0x00,
17624 NM_ABSQ_S_PH = 0x08,
17625 NM_ABSQ_S_W = 0x10,
17626 NM_PRECEQ_W_PHL = 0x28,
17627 NM_PRECEQ_W_PHR = 0x30,
17628 NM_PRECEQU_PH_QBL = 0x38,
17629 NM_PRECEQU_PH_QBR = 0x48,
17630 NM_PRECEU_PH_QBL = 0x58,
17631 NM_PRECEU_PH_QBR = 0x68,
17632 NM_PRECEQU_PH_QBLA = 0x39,
17633 NM_PRECEQU_PH_QBRA = 0x49,
17634 NM_PRECEU_PH_QBLA = 0x59,
17635 NM_PRECEU_PH_QBRA = 0x69,
17636 NM_REPLV_PH = 0x01,
17637 NM_REPLV_QB = 0x09,
17638 NM_BITREV = 0x18,
17639 NM_INSV = 0x20,
17640 NM_RADDU_W_QB = 0x78,
17642 NM_BITSWAP = 0x05,
17643 NM_WSBH = 0x3d,
17646 /* PP.SR instruction pool */
17647 enum {
17648 NM_SAVE = 0x00,
17649 NM_RESTORE = 0x02,
17650 NM_RESTORE_JRC = 0x03,
17653 /* P.SR.F instruction pool */
17654 enum {
17655 NM_SAVEF = 0x00,
17656 NM_RESTOREF = 0x01,
17659 /* P16.SYSCALL instruction pool */
17660 enum {
17661 NM_SYSCALL16 = 0x00,
17662 NM_HYPCALL16 = 0x01,
17665 /* POOL16C_00 instruction pool */
17666 enum {
17667 NM_NOT16 = 0x00,
17668 NM_XOR16 = 0x01,
17669 NM_AND16 = 0x02,
17670 NM_OR16 = 0x03,
17673 /* PP.LSX and PP.LSXS instruction pool */
17674 enum {
17675 NM_LBX = 0x00,
17676 NM_LHX = 0x04,
17677 NM_LWX = 0x08,
17678 NM_LDX = 0x0c,
17680 NM_SBX = 0x01,
17681 NM_SHX = 0x05,
17682 NM_SWX = 0x09,
17683 NM_SDX = 0x0d,
17685 NM_LBUX = 0x02,
17686 NM_LHUX = 0x06,
17687 NM_LWC1X = 0x0a,
17688 NM_LDC1X = 0x0e,
17690 NM_LWUX = 0x07,
17691 NM_SWC1X = 0x0b,
17692 NM_SDC1X = 0x0f,
17694 NM_LHXS = 0x04,
17695 NM_LWXS = 0x08,
17696 NM_LDXS = 0x0c,
17698 NM_SHXS = 0x05,
17699 NM_SWXS = 0x09,
17700 NM_SDXS = 0x0d,
17702 NM_LHUXS = 0x06,
17703 NM_LWC1XS = 0x0a,
17704 NM_LDC1XS = 0x0e,
17706 NM_LWUXS = 0x07,
17707 NM_SWC1XS = 0x0b,
17708 NM_SDC1XS = 0x0f,
17711 /* ERETx instruction pool */
17712 enum {
17713 NM_ERET = 0x00,
17714 NM_ERETNC = 0x01,
17717 /* POOL32FxF_{0, 1} insturction pool */
17718 enum {
17719 NM_CFC1 = 0x40,
17720 NM_CTC1 = 0x60,
17721 NM_MFC1 = 0x80,
17722 NM_MTC1 = 0xa0,
17723 NM_MFHC1 = 0xc0,
17724 NM_MTHC1 = 0xe0,
17726 NM_CVT_S_PL = 0x84,
17727 NM_CVT_S_PU = 0xa4,
17729 NM_CVT_L_S = 0x004,
17730 NM_CVT_L_D = 0x104,
17731 NM_CVT_W_S = 0x024,
17732 NM_CVT_W_D = 0x124,
17734 NM_RSQRT_S = 0x008,
17735 NM_RSQRT_D = 0x108,
17737 NM_SQRT_S = 0x028,
17738 NM_SQRT_D = 0x128,
17740 NM_RECIP_S = 0x048,
17741 NM_RECIP_D = 0x148,
17743 NM_FLOOR_L_S = 0x00c,
17744 NM_FLOOR_L_D = 0x10c,
17746 NM_FLOOR_W_S = 0x02c,
17747 NM_FLOOR_W_D = 0x12c,
17749 NM_CEIL_L_S = 0x04c,
17750 NM_CEIL_L_D = 0x14c,
17751 NM_CEIL_W_S = 0x06c,
17752 NM_CEIL_W_D = 0x16c,
17753 NM_TRUNC_L_S = 0x08c,
17754 NM_TRUNC_L_D = 0x18c,
17755 NM_TRUNC_W_S = 0x0ac,
17756 NM_TRUNC_W_D = 0x1ac,
17757 NM_ROUND_L_S = 0x0cc,
17758 NM_ROUND_L_D = 0x1cc,
17759 NM_ROUND_W_S = 0x0ec,
17760 NM_ROUND_W_D = 0x1ec,
17762 NM_MOV_S = 0x01,
17763 NM_MOV_D = 0x81,
17764 NM_ABS_S = 0x0d,
17765 NM_ABS_D = 0x8d,
17766 NM_NEG_S = 0x2d,
17767 NM_NEG_D = 0xad,
17768 NM_CVT_D_S = 0x04d,
17769 NM_CVT_D_W = 0x0cd,
17770 NM_CVT_D_L = 0x14d,
17771 NM_CVT_S_D = 0x06d,
17772 NM_CVT_S_W = 0x0ed,
17773 NM_CVT_S_L = 0x16d,
17776 /* P.LL instruction pool */
17777 enum {
17778 NM_LL = 0x00,
17779 NM_LLWP = 0x01,
17782 /* P.SC instruction pool */
17783 enum {
17784 NM_SC = 0x00,
17785 NM_SCWP = 0x01,
17788 /* P.DVP instruction pool */
17789 enum {
17790 NM_DVP = 0x00,
17791 NM_EVP = 0x01,
17797 * nanoMIPS decoding engine
17802 /* extraction utilities */
17804 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17805 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17806 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17807 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17808 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17809 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17811 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17812 static inline int decode_gpr_gpr3(int r)
17814 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17816 return map[r & 0x7];
17819 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17820 static inline int decode_gpr_gpr3_src_store(int r)
17822 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17824 return map[r & 0x7];
17827 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17828 static inline int decode_gpr_gpr4(int r)
17830 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17831 16, 17, 18, 19, 20, 21, 22, 23 };
17833 return map[r & 0xf];
17836 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17837 static inline int decode_gpr_gpr4_zero(int r)
17839 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17840 16, 17, 18, 19, 20, 21, 22, 23 };
17842 return map[r & 0xf];
17846 /* extraction utilities */
17848 #define NANOMIPS_EXTRACT_RD(op) ((op >> 7) & 0x7)
17849 #define NANOMIPS_EXTRACT_RS(op) ((op >> 4) & 0x7)
17850 #define NANOMIPS_EXTRACT_RS2(op) uMIPS_RS(op)
17851 #define NANOMIPS_EXTRACT_RS1(op) ((op >> 1) & 0x7)
17852 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17853 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17856 static void gen_adjust_sp(DisasContext *ctx, int u)
17858 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17861 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17862 uint8_t gp, uint16_t u)
17864 int counter = 0;
17865 TCGv va = tcg_temp_new();
17866 TCGv t0 = tcg_temp_new();
17868 while (counter != count) {
17869 bool use_gp = gp && (counter == count - 1);
17870 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17871 int this_offset = -((counter + 1) << 2);
17872 gen_base_offset_addr(ctx, va, 29, this_offset);
17873 gen_load_gpr(t0, this_rt);
17874 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17875 (MO_TEUL | ctx->default_tcg_memop_mask));
17876 counter++;
17879 /* adjust stack pointer */
17880 gen_adjust_sp(ctx, -u);
17882 tcg_temp_free(t0);
17883 tcg_temp_free(va);
17886 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17887 uint8_t gp, uint16_t u)
17889 int counter = 0;
17890 TCGv va = tcg_temp_new();
17891 TCGv t0 = tcg_temp_new();
17893 while (counter != count) {
17894 bool use_gp = gp && (counter == count - 1);
17895 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17896 int this_offset = u - ((counter + 1) << 2);
17897 gen_base_offset_addr(ctx, va, 29, this_offset);
17898 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17899 ctx->default_tcg_memop_mask);
17900 tcg_gen_ext32s_tl(t0, t0);
17901 gen_store_gpr(t0, this_rt);
17902 counter++;
17905 /* adjust stack pointer */
17906 gen_adjust_sp(ctx, u);
17908 tcg_temp_free(t0);
17909 tcg_temp_free(va);
17912 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17914 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
17915 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
17917 switch (extract32(ctx->opcode, 2, 2)) {
17918 case NM_NOT16:
17919 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17920 break;
17921 case NM_AND16:
17922 gen_logic(ctx, OPC_AND, rt, rt, rs);
17923 break;
17924 case NM_XOR16:
17925 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17926 break;
17927 case NM_OR16:
17928 gen_logic(ctx, OPC_OR, rt, rt, rs);
17929 break;
17933 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17935 int rt = extract32(ctx->opcode, 21, 5);
17936 int rs = extract32(ctx->opcode, 16, 5);
17937 int rd = extract32(ctx->opcode, 11, 5);
17939 switch (extract32(ctx->opcode, 3, 7)) {
17940 case NM_P_TRAP:
17941 switch (extract32(ctx->opcode, 10, 1)) {
17942 case NM_TEQ:
17943 check_nms(ctx);
17944 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17945 break;
17946 case NM_TNE:
17947 check_nms(ctx);
17948 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17949 break;
17951 break;
17952 case NM_RDHWR:
17953 check_nms(ctx);
17954 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17955 break;
17956 case NM_SEB:
17957 check_nms(ctx);
17958 gen_bshfl(ctx, OPC_SEB, rs, rt);
17959 break;
17960 case NM_SEH:
17961 gen_bshfl(ctx, OPC_SEH, rs, rt);
17962 break;
17963 case NM_SLLV:
17964 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17965 break;
17966 case NM_SRLV:
17967 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17968 break;
17969 case NM_SRAV:
17970 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17971 break;
17972 case NM_ROTRV:
17973 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17974 break;
17975 case NM_ADD:
17976 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17977 break;
17978 case NM_ADDU:
17979 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17980 break;
17981 case NM_SUB:
17982 check_nms(ctx);
17983 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17984 break;
17985 case NM_SUBU:
17986 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17987 break;
17988 case NM_P_CMOVE:
17989 switch (extract32(ctx->opcode, 10, 1)) {
17990 case NM_MOVZ:
17991 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17992 break;
17993 case NM_MOVN:
17994 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17995 break;
17997 break;
17998 case NM_AND:
17999 gen_logic(ctx, OPC_AND, rd, rs, rt);
18000 break;
18001 case NM_OR:
18002 gen_logic(ctx, OPC_OR, rd, rs, rt);
18003 break;
18004 case NM_NOR:
18005 gen_logic(ctx, OPC_NOR, rd, rs, rt);
18006 break;
18007 case NM_XOR:
18008 gen_logic(ctx, OPC_XOR, rd, rs, rt);
18009 break;
18010 case NM_SLT:
18011 gen_slt(ctx, OPC_SLT, rd, rs, rt);
18012 break;
18013 case NM_P_SLTU:
18014 if (rd == 0) {
18015 /* P_DVP */
18016 #ifndef CONFIG_USER_ONLY
18017 TCGv t0 = tcg_temp_new();
18018 switch (extract32(ctx->opcode, 10, 1)) {
18019 case NM_DVP:
18020 if (ctx->vp) {
18021 check_cp0_enabled(ctx);
18022 gen_helper_dvp(t0, cpu_env);
18023 gen_store_gpr(t0, rt);
18025 break;
18026 case NM_EVP:
18027 if (ctx->vp) {
18028 check_cp0_enabled(ctx);
18029 gen_helper_evp(t0, cpu_env);
18030 gen_store_gpr(t0, rt);
18032 break;
18034 tcg_temp_free(t0);
18035 #endif
18036 } else {
18037 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18039 break;
18040 case NM_SOV:
18042 TCGv t0 = tcg_temp_new();
18043 TCGv t1 = tcg_temp_new();
18044 TCGv t2 = tcg_temp_new();
18046 gen_load_gpr(t1, rs);
18047 gen_load_gpr(t2, rt);
18048 tcg_gen_add_tl(t0, t1, t2);
18049 tcg_gen_ext32s_tl(t0, t0);
18050 tcg_gen_xor_tl(t1, t1, t2);
18051 tcg_gen_xor_tl(t2, t0, t2);
18052 tcg_gen_andc_tl(t1, t2, t1);
18054 /* operands of same sign, result different sign */
18055 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18056 gen_store_gpr(t0, rd);
18058 tcg_temp_free(t0);
18059 tcg_temp_free(t1);
18060 tcg_temp_free(t2);
18062 break;
18063 case NM_MUL:
18064 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18065 break;
18066 case NM_MUH:
18067 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18068 break;
18069 case NM_MULU:
18070 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18071 break;
18072 case NM_MUHU:
18073 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18074 break;
18075 case NM_DIV:
18076 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18077 break;
18078 case NM_MOD:
18079 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18080 break;
18081 case NM_DIVU:
18082 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18083 break;
18084 case NM_MODU:
18085 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18086 break;
18087 #ifndef CONFIG_USER_ONLY
18088 case NM_MFC0:
18089 check_cp0_enabled(ctx);
18090 if (rt == 0) {
18091 /* Treat as NOP. */
18092 break;
18094 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18095 break;
18096 case NM_MTC0:
18097 check_cp0_enabled(ctx);
18099 TCGv t0 = tcg_temp_new();
18101 gen_load_gpr(t0, rt);
18102 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18103 tcg_temp_free(t0);
18105 break;
18106 case NM_D_E_MT_VPE:
18108 uint8_t sc = extract32(ctx->opcode, 10, 1);
18109 TCGv t0 = tcg_temp_new();
18111 switch (sc) {
18112 case 0:
18113 if (rs == 1) {
18114 /* DMT */
18115 check_cp0_mt(ctx);
18116 gen_helper_dmt(t0);
18117 gen_store_gpr(t0, rt);
18118 } else if (rs == 0) {
18119 /* DVPE */
18120 check_cp0_mt(ctx);
18121 gen_helper_dvpe(t0, cpu_env);
18122 gen_store_gpr(t0, rt);
18123 } else {
18124 generate_exception_end(ctx, EXCP_RI);
18126 break;
18127 case 1:
18128 if (rs == 1) {
18129 /* EMT */
18130 check_cp0_mt(ctx);
18131 gen_helper_emt(t0);
18132 gen_store_gpr(t0, rt);
18133 } else if (rs == 0) {
18134 /* EVPE */
18135 check_cp0_mt(ctx);
18136 gen_helper_evpe(t0, cpu_env);
18137 gen_store_gpr(t0, rt);
18138 } else {
18139 generate_exception_end(ctx, EXCP_RI);
18141 break;
18144 tcg_temp_free(t0);
18146 break;
18147 case NM_FORK:
18148 check_mt(ctx);
18150 TCGv t0 = tcg_temp_new();
18151 TCGv t1 = tcg_temp_new();
18153 gen_load_gpr(t0, rt);
18154 gen_load_gpr(t1, rs);
18155 gen_helper_fork(t0, t1);
18156 tcg_temp_free(t0);
18157 tcg_temp_free(t1);
18159 break;
18160 case NM_MFTR:
18161 case NM_MFHTR:
18162 check_cp0_enabled(ctx);
18163 if (rd == 0) {
18164 /* Treat as NOP. */
18165 return;
18167 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18168 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18169 break;
18170 case NM_MTTR:
18171 case NM_MTHTR:
18172 check_cp0_enabled(ctx);
18173 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18174 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18175 break;
18176 case NM_YIELD:
18177 check_mt(ctx);
18179 TCGv t0 = tcg_temp_new();
18181 gen_load_gpr(t0, rs);
18182 gen_helper_yield(t0, cpu_env, t0);
18183 gen_store_gpr(t0, rt);
18184 tcg_temp_free(t0);
18186 break;
18187 #endif
18188 default:
18189 generate_exception_end(ctx, EXCP_RI);
18190 break;
18194 /* dsp */
18195 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18196 int ret, int v1, int v2)
18198 TCGv_i32 t0;
18199 TCGv v0_t;
18200 TCGv v1_t;
18202 t0 = tcg_temp_new_i32();
18204 v0_t = tcg_temp_new();
18205 v1_t = tcg_temp_new();
18207 tcg_gen_movi_i32(t0, v2 >> 3);
18209 gen_load_gpr(v0_t, ret);
18210 gen_load_gpr(v1_t, v1);
18212 switch (opc) {
18213 case NM_MAQ_S_W_PHR:
18214 check_dsp(ctx);
18215 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18216 break;
18217 case NM_MAQ_S_W_PHL:
18218 check_dsp(ctx);
18219 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18220 break;
18221 case NM_MAQ_SA_W_PHR:
18222 check_dsp(ctx);
18223 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18224 break;
18225 case NM_MAQ_SA_W_PHL:
18226 check_dsp(ctx);
18227 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18228 break;
18229 default:
18230 generate_exception_end(ctx, EXCP_RI);
18231 break;
18234 tcg_temp_free_i32(t0);
18236 tcg_temp_free(v0_t);
18237 tcg_temp_free(v1_t);
18241 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18242 int ret, int v1, int v2)
18244 int16_t imm;
18245 TCGv t0 = tcg_temp_new();
18246 TCGv t1 = tcg_temp_new();
18247 TCGv v0_t = tcg_temp_new();
18249 gen_load_gpr(v0_t, v1);
18251 switch (opc) {
18252 case NM_POOL32AXF_1_0:
18253 check_dsp(ctx);
18254 switch (extract32(ctx->opcode, 12, 2)) {
18255 case NM_MFHI:
18256 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18257 break;
18258 case NM_MFLO:
18259 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18260 break;
18261 case NM_MTHI:
18262 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18263 break;
18264 case NM_MTLO:
18265 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18266 break;
18268 break;
18269 case NM_POOL32AXF_1_1:
18270 check_dsp(ctx);
18271 switch (extract32(ctx->opcode, 12, 2)) {
18272 case NM_MTHLIP:
18273 tcg_gen_movi_tl(t0, v2);
18274 gen_helper_mthlip(t0, v0_t, cpu_env);
18275 break;
18276 case NM_SHILOV:
18277 tcg_gen_movi_tl(t0, v2 >> 3);
18278 gen_helper_shilo(t0, v0_t, cpu_env);
18279 break;
18280 default:
18281 generate_exception_end(ctx, EXCP_RI);
18282 break;
18284 break;
18285 case NM_POOL32AXF_1_3:
18286 check_dsp(ctx);
18287 imm = extract32(ctx->opcode, 14, 7);
18288 switch (extract32(ctx->opcode, 12, 2)) {
18289 case NM_RDDSP:
18290 tcg_gen_movi_tl(t0, imm);
18291 gen_helper_rddsp(t0, t0, cpu_env);
18292 gen_store_gpr(t0, ret);
18293 break;
18294 case NM_WRDSP:
18295 gen_load_gpr(t0, ret);
18296 tcg_gen_movi_tl(t1, imm);
18297 gen_helper_wrdsp(t0, t1, cpu_env);
18298 break;
18299 case NM_EXTP:
18300 tcg_gen_movi_tl(t0, v2 >> 3);
18301 tcg_gen_movi_tl(t1, v1);
18302 gen_helper_extp(t0, t0, t1, cpu_env);
18303 gen_store_gpr(t0, ret);
18304 break;
18305 case NM_EXTPDP:
18306 tcg_gen_movi_tl(t0, v2 >> 3);
18307 tcg_gen_movi_tl(t1, v1);
18308 gen_helper_extpdp(t0, t0, t1, cpu_env);
18309 gen_store_gpr(t0, ret);
18310 break;
18312 break;
18313 case NM_POOL32AXF_1_4:
18314 check_dsp(ctx);
18315 tcg_gen_movi_tl(t0, v2 >> 2);
18316 switch (extract32(ctx->opcode, 12, 1)) {
18317 case NM_SHLL_QB:
18318 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18319 gen_store_gpr(t0, ret);
18320 break;
18321 case NM_SHRL_QB:
18322 gen_helper_shrl_qb(t0, t0, v0_t);
18323 gen_store_gpr(t0, ret);
18324 break;
18326 break;
18327 case NM_POOL32AXF_1_5:
18328 opc = extract32(ctx->opcode, 12, 2);
18329 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18330 break;
18331 case NM_POOL32AXF_1_7:
18332 check_dsp(ctx);
18333 tcg_gen_movi_tl(t0, v2 >> 3);
18334 tcg_gen_movi_tl(t1, v1);
18335 switch (extract32(ctx->opcode, 12, 2)) {
18336 case NM_EXTR_W:
18337 gen_helper_extr_w(t0, t0, t1, cpu_env);
18338 gen_store_gpr(t0, ret);
18339 break;
18340 case NM_EXTR_R_W:
18341 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18342 gen_store_gpr(t0, ret);
18343 break;
18344 case NM_EXTR_RS_W:
18345 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18346 gen_store_gpr(t0, ret);
18347 break;
18348 case NM_EXTR_S_H:
18349 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18350 gen_store_gpr(t0, ret);
18351 break;
18353 break;
18354 default:
18355 generate_exception_end(ctx, EXCP_RI);
18356 break;
18359 tcg_temp_free(t0);
18360 tcg_temp_free(t1);
18361 tcg_temp_free(v0_t);
18364 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18365 TCGv v0, TCGv v1, int rd)
18367 TCGv_i32 t0;
18369 t0 = tcg_temp_new_i32();
18371 tcg_gen_movi_i32(t0, rd >> 3);
18373 switch (opc) {
18374 case NM_POOL32AXF_2_0_7:
18375 switch (extract32(ctx->opcode, 9, 3)) {
18376 case NM_DPA_W_PH:
18377 check_dsp_r2(ctx);
18378 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18379 break;
18380 case NM_DPAQ_S_W_PH:
18381 check_dsp(ctx);
18382 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18383 break;
18384 case NM_DPS_W_PH:
18385 check_dsp_r2(ctx);
18386 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18387 break;
18388 case NM_DPSQ_S_W_PH:
18389 check_dsp(ctx);
18390 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18391 break;
18392 default:
18393 generate_exception_end(ctx, EXCP_RI);
18394 break;
18396 break;
18397 case NM_POOL32AXF_2_8_15:
18398 switch (extract32(ctx->opcode, 9, 3)) {
18399 case NM_DPAX_W_PH:
18400 check_dsp_r2(ctx);
18401 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18402 break;
18403 case NM_DPAQ_SA_L_W:
18404 check_dsp(ctx);
18405 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18406 break;
18407 case NM_DPSX_W_PH:
18408 check_dsp_r2(ctx);
18409 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18410 break;
18411 case NM_DPSQ_SA_L_W:
18412 check_dsp(ctx);
18413 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18414 break;
18415 default:
18416 generate_exception_end(ctx, EXCP_RI);
18417 break;
18419 break;
18420 case NM_POOL32AXF_2_16_23:
18421 switch (extract32(ctx->opcode, 9, 3)) {
18422 case NM_DPAU_H_QBL:
18423 check_dsp(ctx);
18424 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18425 break;
18426 case NM_DPAQX_S_W_PH:
18427 check_dsp_r2(ctx);
18428 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18429 break;
18430 case NM_DPSU_H_QBL:
18431 check_dsp(ctx);
18432 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18433 break;
18434 case NM_DPSQX_S_W_PH:
18435 check_dsp_r2(ctx);
18436 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18437 break;
18438 case NM_MULSA_W_PH:
18439 check_dsp_r2(ctx);
18440 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18441 break;
18442 default:
18443 generate_exception_end(ctx, EXCP_RI);
18444 break;
18446 break;
18447 case NM_POOL32AXF_2_24_31:
18448 switch (extract32(ctx->opcode, 9, 3)) {
18449 case NM_DPAU_H_QBR:
18450 check_dsp(ctx);
18451 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18452 break;
18453 case NM_DPAQX_SA_W_PH:
18454 check_dsp_r2(ctx);
18455 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18456 break;
18457 case NM_DPSU_H_QBR:
18458 check_dsp(ctx);
18459 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18460 break;
18461 case NM_DPSQX_SA_W_PH:
18462 check_dsp_r2(ctx);
18463 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18464 break;
18465 case NM_MULSAQ_S_W_PH:
18466 check_dsp(ctx);
18467 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18468 break;
18469 default:
18470 generate_exception_end(ctx, EXCP_RI);
18471 break;
18473 break;
18474 default:
18475 generate_exception_end(ctx, EXCP_RI);
18476 break;
18479 tcg_temp_free_i32(t0);
18482 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18483 int rt, int rs, int rd)
18485 int ret = rt;
18486 TCGv t0 = tcg_temp_new();
18487 TCGv t1 = tcg_temp_new();
18488 TCGv v0_t = tcg_temp_new();
18489 TCGv v1_t = tcg_temp_new();
18491 gen_load_gpr(v0_t, rt);
18492 gen_load_gpr(v1_t, rs);
18494 switch (opc) {
18495 case NM_POOL32AXF_2_0_7:
18496 switch (extract32(ctx->opcode, 9, 3)) {
18497 case NM_DPA_W_PH:
18498 case NM_DPAQ_S_W_PH:
18499 case NM_DPS_W_PH:
18500 case NM_DPSQ_S_W_PH:
18501 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18502 break;
18503 case NM_BALIGN:
18504 check_dsp_r2(ctx);
18505 if (rt != 0) {
18506 gen_load_gpr(t0, rs);
18507 rd &= 3;
18508 if (rd != 0 && rd != 2) {
18509 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18510 tcg_gen_ext32u_tl(t0, t0);
18511 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18512 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18514 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18516 break;
18517 case NM_MADD:
18518 check_dsp(ctx);
18520 int acc = extract32(ctx->opcode, 14, 2);
18521 TCGv_i64 t2 = tcg_temp_new_i64();
18522 TCGv_i64 t3 = tcg_temp_new_i64();
18524 gen_load_gpr(t0, rt);
18525 gen_load_gpr(t1, rs);
18526 tcg_gen_ext_tl_i64(t2, t0);
18527 tcg_gen_ext_tl_i64(t3, t1);
18528 tcg_gen_mul_i64(t2, t2, t3);
18529 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18530 tcg_gen_add_i64(t2, t2, t3);
18531 tcg_temp_free_i64(t3);
18532 gen_move_low32(cpu_LO[acc], t2);
18533 gen_move_high32(cpu_HI[acc], t2);
18534 tcg_temp_free_i64(t2);
18536 break;
18537 case NM_MULT:
18538 check_dsp(ctx);
18540 int acc = extract32(ctx->opcode, 14, 2);
18541 TCGv_i32 t2 = tcg_temp_new_i32();
18542 TCGv_i32 t3 = tcg_temp_new_i32();
18544 gen_load_gpr(t0, rs);
18545 gen_load_gpr(t1, rt);
18546 tcg_gen_trunc_tl_i32(t2, t0);
18547 tcg_gen_trunc_tl_i32(t3, t1);
18548 tcg_gen_muls2_i32(t2, t3, t2, t3);
18549 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18550 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18551 tcg_temp_free_i32(t2);
18552 tcg_temp_free_i32(t3);
18554 break;
18555 case NM_EXTRV_W:
18556 check_dsp(ctx);
18557 gen_load_gpr(v1_t, rs);
18558 tcg_gen_movi_tl(t0, rd >> 3);
18559 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18560 gen_store_gpr(t0, ret);
18561 break;
18563 break;
18564 case NM_POOL32AXF_2_8_15:
18565 switch (extract32(ctx->opcode, 9, 3)) {
18566 case NM_DPAX_W_PH:
18567 case NM_DPAQ_SA_L_W:
18568 case NM_DPSX_W_PH:
18569 case NM_DPSQ_SA_L_W:
18570 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18571 break;
18572 case NM_MADDU:
18573 check_dsp(ctx);
18575 int acc = extract32(ctx->opcode, 14, 2);
18576 TCGv_i64 t2 = tcg_temp_new_i64();
18577 TCGv_i64 t3 = tcg_temp_new_i64();
18579 gen_load_gpr(t0, rs);
18580 gen_load_gpr(t1, rt);
18581 tcg_gen_ext32u_tl(t0, t0);
18582 tcg_gen_ext32u_tl(t1, t1);
18583 tcg_gen_extu_tl_i64(t2, t0);
18584 tcg_gen_extu_tl_i64(t3, t1);
18585 tcg_gen_mul_i64(t2, t2, t3);
18586 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18587 tcg_gen_add_i64(t2, t2, t3);
18588 tcg_temp_free_i64(t3);
18589 gen_move_low32(cpu_LO[acc], t2);
18590 gen_move_high32(cpu_HI[acc], t2);
18591 tcg_temp_free_i64(t2);
18593 break;
18594 case NM_MULTU:
18595 check_dsp(ctx);
18597 int acc = extract32(ctx->opcode, 14, 2);
18598 TCGv_i32 t2 = tcg_temp_new_i32();
18599 TCGv_i32 t3 = tcg_temp_new_i32();
18601 gen_load_gpr(t0, rs);
18602 gen_load_gpr(t1, rt);
18603 tcg_gen_trunc_tl_i32(t2, t0);
18604 tcg_gen_trunc_tl_i32(t3, t1);
18605 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18606 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18607 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18608 tcg_temp_free_i32(t2);
18609 tcg_temp_free_i32(t3);
18611 break;
18612 case NM_EXTRV_R_W:
18613 check_dsp(ctx);
18614 tcg_gen_movi_tl(t0, rd >> 3);
18615 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18616 gen_store_gpr(t0, ret);
18617 break;
18618 default:
18619 generate_exception_end(ctx, EXCP_RI);
18620 break;
18622 break;
18623 case NM_POOL32AXF_2_16_23:
18624 switch (extract32(ctx->opcode, 9, 3)) {
18625 case NM_DPAU_H_QBL:
18626 case NM_DPAQX_S_W_PH:
18627 case NM_DPSU_H_QBL:
18628 case NM_DPSQX_S_W_PH:
18629 case NM_MULSA_W_PH:
18630 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18631 break;
18632 case NM_EXTPV:
18633 check_dsp(ctx);
18634 tcg_gen_movi_tl(t0, rd >> 3);
18635 gen_helper_extp(t0, t0, v1_t, cpu_env);
18636 gen_store_gpr(t0, ret);
18637 break;
18638 case NM_MSUB:
18639 check_dsp(ctx);
18641 int acc = extract32(ctx->opcode, 14, 2);
18642 TCGv_i64 t2 = tcg_temp_new_i64();
18643 TCGv_i64 t3 = tcg_temp_new_i64();
18645 gen_load_gpr(t0, rs);
18646 gen_load_gpr(t1, rt);
18647 tcg_gen_ext_tl_i64(t2, t0);
18648 tcg_gen_ext_tl_i64(t3, t1);
18649 tcg_gen_mul_i64(t2, t2, t3);
18650 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18651 tcg_gen_sub_i64(t2, t3, t2);
18652 tcg_temp_free_i64(t3);
18653 gen_move_low32(cpu_LO[acc], t2);
18654 gen_move_high32(cpu_HI[acc], t2);
18655 tcg_temp_free_i64(t2);
18657 break;
18658 case NM_EXTRV_RS_W:
18659 check_dsp(ctx);
18660 tcg_gen_movi_tl(t0, rd >> 3);
18661 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18662 gen_store_gpr(t0, ret);
18663 break;
18665 break;
18666 case NM_POOL32AXF_2_24_31:
18667 switch (extract32(ctx->opcode, 9, 3)) {
18668 case NM_DPAU_H_QBR:
18669 case NM_DPAQX_SA_W_PH:
18670 case NM_DPSU_H_QBR:
18671 case NM_DPSQX_SA_W_PH:
18672 case NM_MULSAQ_S_W_PH:
18673 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18674 break;
18675 case NM_EXTPDPV:
18676 check_dsp(ctx);
18677 tcg_gen_movi_tl(t0, rd >> 3);
18678 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18679 gen_store_gpr(t0, ret);
18680 break;
18681 case NM_MSUBU:
18682 check_dsp(ctx);
18684 int acc = extract32(ctx->opcode, 14, 2);
18685 TCGv_i64 t2 = tcg_temp_new_i64();
18686 TCGv_i64 t3 = tcg_temp_new_i64();
18688 gen_load_gpr(t0, rs);
18689 gen_load_gpr(t1, rt);
18690 tcg_gen_ext32u_tl(t0, t0);
18691 tcg_gen_ext32u_tl(t1, t1);
18692 tcg_gen_extu_tl_i64(t2, t0);
18693 tcg_gen_extu_tl_i64(t3, t1);
18694 tcg_gen_mul_i64(t2, t2, t3);
18695 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18696 tcg_gen_sub_i64(t2, t3, t2);
18697 tcg_temp_free_i64(t3);
18698 gen_move_low32(cpu_LO[acc], t2);
18699 gen_move_high32(cpu_HI[acc], t2);
18700 tcg_temp_free_i64(t2);
18702 break;
18703 case NM_EXTRV_S_H:
18704 check_dsp(ctx);
18705 tcg_gen_movi_tl(t0, rd >> 3);
18706 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18707 gen_store_gpr(t0, ret);
18708 break;
18710 break;
18711 default:
18712 generate_exception_end(ctx, EXCP_RI);
18713 break;
18716 tcg_temp_free(t0);
18717 tcg_temp_free(t1);
18719 tcg_temp_free(v0_t);
18720 tcg_temp_free(v1_t);
18723 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18724 int rt, int rs)
18726 int ret = rt;
18727 TCGv t0 = tcg_temp_new();
18728 TCGv v0_t = tcg_temp_new();
18730 gen_load_gpr(v0_t, rs);
18732 switch (opc) {
18733 case NM_ABSQ_S_QB:
18734 check_dsp_r2(ctx);
18735 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18736 gen_store_gpr(v0_t, ret);
18737 break;
18738 case NM_ABSQ_S_PH:
18739 check_dsp(ctx);
18740 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18741 gen_store_gpr(v0_t, ret);
18742 break;
18743 case NM_ABSQ_S_W:
18744 check_dsp(ctx);
18745 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18746 gen_store_gpr(v0_t, ret);
18747 break;
18748 case NM_PRECEQ_W_PHL:
18749 check_dsp(ctx);
18750 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18751 tcg_gen_ext32s_tl(v0_t, v0_t);
18752 gen_store_gpr(v0_t, ret);
18753 break;
18754 case NM_PRECEQ_W_PHR:
18755 check_dsp(ctx);
18756 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18757 tcg_gen_shli_tl(v0_t, v0_t, 16);
18758 tcg_gen_ext32s_tl(v0_t, v0_t);
18759 gen_store_gpr(v0_t, ret);
18760 break;
18761 case NM_PRECEQU_PH_QBL:
18762 check_dsp(ctx);
18763 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18764 gen_store_gpr(v0_t, ret);
18765 break;
18766 case NM_PRECEQU_PH_QBR:
18767 check_dsp(ctx);
18768 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18769 gen_store_gpr(v0_t, ret);
18770 break;
18771 case NM_PRECEQU_PH_QBLA:
18772 check_dsp(ctx);
18773 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18774 gen_store_gpr(v0_t, ret);
18775 break;
18776 case NM_PRECEQU_PH_QBRA:
18777 check_dsp(ctx);
18778 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18779 gen_store_gpr(v0_t, ret);
18780 break;
18781 case NM_PRECEU_PH_QBL:
18782 check_dsp(ctx);
18783 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18784 gen_store_gpr(v0_t, ret);
18785 break;
18786 case NM_PRECEU_PH_QBR:
18787 check_dsp(ctx);
18788 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18789 gen_store_gpr(v0_t, ret);
18790 break;
18791 case NM_PRECEU_PH_QBLA:
18792 check_dsp(ctx);
18793 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18794 gen_store_gpr(v0_t, ret);
18795 break;
18796 case NM_PRECEU_PH_QBRA:
18797 check_dsp(ctx);
18798 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18799 gen_store_gpr(v0_t, ret);
18800 break;
18801 case NM_REPLV_PH:
18802 check_dsp(ctx);
18803 tcg_gen_ext16u_tl(v0_t, v0_t);
18804 tcg_gen_shli_tl(t0, v0_t, 16);
18805 tcg_gen_or_tl(v0_t, v0_t, t0);
18806 tcg_gen_ext32s_tl(v0_t, v0_t);
18807 gen_store_gpr(v0_t, ret);
18808 break;
18809 case NM_REPLV_QB:
18810 check_dsp(ctx);
18811 tcg_gen_ext8u_tl(v0_t, v0_t);
18812 tcg_gen_shli_tl(t0, v0_t, 8);
18813 tcg_gen_or_tl(v0_t, v0_t, t0);
18814 tcg_gen_shli_tl(t0, v0_t, 16);
18815 tcg_gen_or_tl(v0_t, v0_t, t0);
18816 tcg_gen_ext32s_tl(v0_t, v0_t);
18817 gen_store_gpr(v0_t, ret);
18818 break;
18819 case NM_BITREV:
18820 check_dsp(ctx);
18821 gen_helper_bitrev(v0_t, v0_t);
18822 gen_store_gpr(v0_t, ret);
18823 break;
18824 case NM_INSV:
18825 check_dsp(ctx);
18827 TCGv tv0 = tcg_temp_new();
18829 gen_load_gpr(tv0, rt);
18830 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18831 gen_store_gpr(v0_t, ret);
18832 tcg_temp_free(tv0);
18834 break;
18835 case NM_RADDU_W_QB:
18836 check_dsp(ctx);
18837 gen_helper_raddu_w_qb(v0_t, v0_t);
18838 gen_store_gpr(v0_t, ret);
18839 break;
18840 case NM_BITSWAP:
18841 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18842 break;
18843 case NM_CLO:
18844 check_nms(ctx);
18845 gen_cl(ctx, OPC_CLO, ret, rs);
18846 break;
18847 case NM_CLZ:
18848 check_nms(ctx);
18849 gen_cl(ctx, OPC_CLZ, ret, rs);
18850 break;
18851 case NM_WSBH:
18852 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18853 break;
18854 default:
18855 generate_exception_end(ctx, EXCP_RI);
18856 break;
18859 tcg_temp_free(v0_t);
18860 tcg_temp_free(t0);
18863 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18864 int rt, int rs, int rd)
18866 TCGv t0 = tcg_temp_new();
18867 TCGv rs_t = tcg_temp_new();
18869 gen_load_gpr(rs_t, rs);
18871 switch (opc) {
18872 case NM_SHRA_R_QB:
18873 check_dsp_r2(ctx);
18874 tcg_gen_movi_tl(t0, rd >> 2);
18875 switch (extract32(ctx->opcode, 12, 1)) {
18876 case 0:
18877 /* NM_SHRA_QB */
18878 gen_helper_shra_qb(t0, t0, rs_t);
18879 gen_store_gpr(t0, rt);
18880 break;
18881 case 1:
18882 /* NM_SHRA_R_QB */
18883 gen_helper_shra_r_qb(t0, t0, rs_t);
18884 gen_store_gpr(t0, rt);
18885 break;
18887 break;
18888 case NM_SHRL_PH:
18889 check_dsp_r2(ctx);
18890 tcg_gen_movi_tl(t0, rd >> 1);
18891 gen_helper_shrl_ph(t0, t0, rs_t);
18892 gen_store_gpr(t0, rt);
18893 break;
18894 case NM_REPL_QB:
18895 check_dsp(ctx);
18897 int16_t imm;
18898 target_long result;
18899 imm = extract32(ctx->opcode, 13, 8);
18900 result = (uint32_t)imm << 24 |
18901 (uint32_t)imm << 16 |
18902 (uint32_t)imm << 8 |
18903 (uint32_t)imm;
18904 result = (int32_t)result;
18905 tcg_gen_movi_tl(t0, result);
18906 gen_store_gpr(t0, rt);
18908 break;
18909 default:
18910 generate_exception_end(ctx, EXCP_RI);
18911 break;
18913 tcg_temp_free(t0);
18914 tcg_temp_free(rs_t);
18918 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18920 int rt = extract32(ctx->opcode, 21, 5);
18921 int rs = extract32(ctx->opcode, 16, 5);
18922 int rd = extract32(ctx->opcode, 11, 5);
18924 switch (extract32(ctx->opcode, 6, 3)) {
18925 case NM_POOL32AXF_1:
18927 int32_t op1 = extract32(ctx->opcode, 9, 3);
18928 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18930 break;
18931 case NM_POOL32AXF_2:
18933 int32_t op1 = extract32(ctx->opcode, 12, 2);
18934 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18936 break;
18937 case NM_POOL32AXF_4:
18939 int32_t op1 = extract32(ctx->opcode, 9, 7);
18940 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18942 break;
18943 case NM_POOL32AXF_5:
18944 switch (extract32(ctx->opcode, 9, 7)) {
18945 #ifndef CONFIG_USER_ONLY
18946 case NM_TLBP:
18947 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18948 break;
18949 case NM_TLBR:
18950 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18951 break;
18952 case NM_TLBWI:
18953 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18954 break;
18955 case NM_TLBWR:
18956 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18957 break;
18958 case NM_TLBINV:
18959 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18960 break;
18961 case NM_TLBINVF:
18962 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18963 break;
18964 case NM_DI:
18965 check_cp0_enabled(ctx);
18967 TCGv t0 = tcg_temp_new();
18969 save_cpu_state(ctx, 1);
18970 gen_helper_di(t0, cpu_env);
18971 gen_store_gpr(t0, rt);
18972 /* Stop translation as we may have switched the execution mode */
18973 ctx->base.is_jmp = DISAS_STOP;
18974 tcg_temp_free(t0);
18976 break;
18977 case NM_EI:
18978 check_cp0_enabled(ctx);
18980 TCGv t0 = tcg_temp_new();
18982 save_cpu_state(ctx, 1);
18983 gen_helper_ei(t0, cpu_env);
18984 gen_store_gpr(t0, rt);
18985 /* Stop translation as we may have switched the execution mode */
18986 ctx->base.is_jmp = DISAS_STOP;
18987 tcg_temp_free(t0);
18989 break;
18990 case NM_RDPGPR:
18991 gen_load_srsgpr(rs, rt);
18992 break;
18993 case NM_WRPGPR:
18994 gen_store_srsgpr(rs, rt);
18995 break;
18996 case NM_WAIT:
18997 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18998 break;
18999 case NM_DERET:
19000 gen_cp0(env, ctx, OPC_DERET, 0, 0);
19001 break;
19002 case NM_ERETX:
19003 gen_cp0(env, ctx, OPC_ERET, 0, 0);
19004 break;
19005 #endif
19006 default:
19007 generate_exception_end(ctx, EXCP_RI);
19008 break;
19010 break;
19011 case NM_POOL32AXF_7:
19013 int32_t op1 = extract32(ctx->opcode, 9, 3);
19014 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
19016 break;
19017 default:
19018 generate_exception_end(ctx, EXCP_RI);
19019 break;
19023 /* Immediate Value Compact Branches */
19024 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19025 int rt, int32_t imm, int32_t offset)
19027 TCGCond cond;
19028 int bcond_compute = 0;
19029 TCGv t0 = tcg_temp_new();
19030 TCGv t1 = tcg_temp_new();
19032 gen_load_gpr(t0, rt);
19033 tcg_gen_movi_tl(t1, imm);
19034 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19036 /* Load needed operands and calculate btarget */
19037 switch (opc) {
19038 case NM_BEQIC:
19039 if (rt == 0 && imm == 0) {
19040 /* Unconditional branch */
19041 } else if (rt == 0 && imm != 0) {
19042 /* Treat as NOP */
19043 goto out;
19044 } else {
19045 bcond_compute = 1;
19046 cond = TCG_COND_EQ;
19048 break;
19049 case NM_BBEQZC:
19050 case NM_BBNEZC:
19051 check_nms(ctx);
19052 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19053 generate_exception_end(ctx, EXCP_RI);
19054 goto out;
19055 } else if (rt == 0 && opc == NM_BBEQZC) {
19056 /* Unconditional branch */
19057 } else if (rt == 0 && opc == NM_BBNEZC) {
19058 /* Treat as NOP */
19059 goto out;
19060 } else {
19061 tcg_gen_shri_tl(t0, t0, imm);
19062 tcg_gen_andi_tl(t0, t0, 1);
19063 tcg_gen_movi_tl(t1, 0);
19064 bcond_compute = 1;
19065 if (opc == NM_BBEQZC) {
19066 cond = TCG_COND_EQ;
19067 } else {
19068 cond = TCG_COND_NE;
19071 break;
19072 case NM_BNEIC:
19073 if (rt == 0 && imm == 0) {
19074 /* Treat as NOP */
19075 goto out;
19076 } else if (rt == 0 && imm != 0) {
19077 /* Unconditional branch */
19078 } else {
19079 bcond_compute = 1;
19080 cond = TCG_COND_NE;
19082 break;
19083 case NM_BGEIC:
19084 if (rt == 0 && imm == 0) {
19085 /* Unconditional branch */
19086 } else {
19087 bcond_compute = 1;
19088 cond = TCG_COND_GE;
19090 break;
19091 case NM_BLTIC:
19092 bcond_compute = 1;
19093 cond = TCG_COND_LT;
19094 break;
19095 case NM_BGEIUC:
19096 if (rt == 0 && imm == 0) {
19097 /* Unconditional branch */
19098 } else {
19099 bcond_compute = 1;
19100 cond = TCG_COND_GEU;
19102 break;
19103 case NM_BLTIUC:
19104 bcond_compute = 1;
19105 cond = TCG_COND_LTU;
19106 break;
19107 default:
19108 MIPS_INVAL("Immediate Value Compact branch");
19109 generate_exception_end(ctx, EXCP_RI);
19110 goto out;
19113 if (bcond_compute == 0) {
19114 /* Uncoditional compact branch */
19115 gen_goto_tb(ctx, 0, ctx->btarget);
19116 } else {
19117 /* Conditional compact branch */
19118 TCGLabel *fs = gen_new_label();
19120 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19122 gen_goto_tb(ctx, 1, ctx->btarget);
19123 gen_set_label(fs);
19125 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19128 out:
19129 tcg_temp_free(t0);
19130 tcg_temp_free(t1);
19133 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19134 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19135 int rt)
19137 TCGv t0 = tcg_temp_new();
19138 TCGv t1 = tcg_temp_new();
19140 /* load rs */
19141 gen_load_gpr(t0, rs);
19143 /* link */
19144 if (rt != 0) {
19145 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19148 /* calculate btarget */
19149 tcg_gen_shli_tl(t0, t0, 1);
19150 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19151 gen_op_addr_add(ctx, btarget, t1, t0);
19153 /* unconditional branch to register */
19154 tcg_gen_mov_tl(cpu_PC, btarget);
19155 tcg_gen_lookup_and_goto_ptr();
19157 tcg_temp_free(t0);
19158 tcg_temp_free(t1);
19161 /* nanoMIPS Branches */
19162 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19163 int rs, int rt, int32_t offset)
19165 int bcond_compute = 0;
19166 TCGv t0 = tcg_temp_new();
19167 TCGv t1 = tcg_temp_new();
19169 /* Load needed operands and calculate btarget */
19170 switch (opc) {
19171 /* compact branch */
19172 case OPC_BGEC:
19173 case OPC_BLTC:
19174 gen_load_gpr(t0, rs);
19175 gen_load_gpr(t1, rt);
19176 bcond_compute = 1;
19177 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19178 break;
19179 case OPC_BGEUC:
19180 case OPC_BLTUC:
19181 if (rs == 0 || rs == rt) {
19182 /* OPC_BLEZALC, OPC_BGEZALC */
19183 /* OPC_BGTZALC, OPC_BLTZALC */
19184 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19186 gen_load_gpr(t0, rs);
19187 gen_load_gpr(t1, rt);
19188 bcond_compute = 1;
19189 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19190 break;
19191 case OPC_BC:
19192 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19193 break;
19194 case OPC_BEQZC:
19195 if (rs != 0) {
19196 /* OPC_BEQZC, OPC_BNEZC */
19197 gen_load_gpr(t0, rs);
19198 bcond_compute = 1;
19199 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19200 } else {
19201 /* OPC_JIC, OPC_JIALC */
19202 TCGv tbase = tcg_temp_new();
19203 TCGv toffset = tcg_temp_new();
19205 gen_load_gpr(tbase, rt);
19206 tcg_gen_movi_tl(toffset, offset);
19207 gen_op_addr_add(ctx, btarget, tbase, toffset);
19208 tcg_temp_free(tbase);
19209 tcg_temp_free(toffset);
19211 break;
19212 default:
19213 MIPS_INVAL("Compact branch/jump");
19214 generate_exception_end(ctx, EXCP_RI);
19215 goto out;
19218 if (bcond_compute == 0) {
19219 /* Uncoditional compact branch */
19220 switch (opc) {
19221 case OPC_BC:
19222 gen_goto_tb(ctx, 0, ctx->btarget);
19223 break;
19224 default:
19225 MIPS_INVAL("Compact branch/jump");
19226 generate_exception_end(ctx, EXCP_RI);
19227 goto out;
19229 } else {
19230 /* Conditional compact branch */
19231 TCGLabel *fs = gen_new_label();
19233 switch (opc) {
19234 case OPC_BGEUC:
19235 if (rs == 0 && rt != 0) {
19236 /* OPC_BLEZALC */
19237 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19238 } else if (rs != 0 && rt != 0 && rs == rt) {
19239 /* OPC_BGEZALC */
19240 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19241 } else {
19242 /* OPC_BGEUC */
19243 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19245 break;
19246 case OPC_BLTUC:
19247 if (rs == 0 && rt != 0) {
19248 /* OPC_BGTZALC */
19249 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19250 } else if (rs != 0 && rt != 0 && rs == rt) {
19251 /* OPC_BLTZALC */
19252 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19253 } else {
19254 /* OPC_BLTUC */
19255 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19257 break;
19258 case OPC_BGEC:
19259 if (rs == 0 && rt != 0) {
19260 /* OPC_BLEZC */
19261 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19262 } else if (rs != 0 && rt != 0 && rs == rt) {
19263 /* OPC_BGEZC */
19264 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19265 } else {
19266 /* OPC_BGEC */
19267 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19269 break;
19270 case OPC_BLTC:
19271 if (rs == 0 && rt != 0) {
19272 /* OPC_BGTZC */
19273 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19274 } else if (rs != 0 && rt != 0 && rs == rt) {
19275 /* OPC_BLTZC */
19276 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19277 } else {
19278 /* OPC_BLTC */
19279 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19281 break;
19282 case OPC_BEQZC:
19283 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19284 break;
19285 default:
19286 MIPS_INVAL("Compact conditional branch/jump");
19287 generate_exception_end(ctx, EXCP_RI);
19288 goto out;
19291 /* Generating branch here as compact branches don't have delay slot */
19292 gen_goto_tb(ctx, 1, ctx->btarget);
19293 gen_set_label(fs);
19295 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19298 out:
19299 tcg_temp_free(t0);
19300 tcg_temp_free(t1);
19304 /* nanoMIPS CP1 Branches */
19305 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19306 int32_t ft, int32_t offset)
19308 target_ulong btarget;
19309 TCGv_i64 t0 = tcg_temp_new_i64();
19311 gen_load_fpr64(ctx, t0, ft);
19312 tcg_gen_andi_i64(t0, t0, 1);
19314 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19316 switch (op) {
19317 case NM_BC1EQZC:
19318 tcg_gen_xori_i64(t0, t0, 1);
19319 ctx->hflags |= MIPS_HFLAG_BC;
19320 break;
19321 case NM_BC1NEZC:
19322 /* t0 already set */
19323 ctx->hflags |= MIPS_HFLAG_BC;
19324 break;
19325 default:
19326 MIPS_INVAL("cp1 cond branch");
19327 generate_exception_end(ctx, EXCP_RI);
19328 goto out;
19331 tcg_gen_trunc_i64_tl(bcond, t0);
19333 ctx->btarget = btarget;
19335 out:
19336 tcg_temp_free_i64(t0);
19340 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19342 TCGv t0, t1;
19343 t0 = tcg_temp_new();
19344 t1 = tcg_temp_new();
19346 gen_load_gpr(t0, rs);
19347 gen_load_gpr(t1, rt);
19349 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19350 /* PP.LSXS instructions require shifting */
19351 switch (extract32(ctx->opcode, 7, 4)) {
19352 case NM_SHXS:
19353 check_nms(ctx);
19354 case NM_LHXS:
19355 case NM_LHUXS:
19356 tcg_gen_shli_tl(t0, t0, 1);
19357 break;
19358 case NM_SWXS:
19359 check_nms(ctx);
19360 case NM_LWXS:
19361 case NM_LWC1XS:
19362 case NM_SWC1XS:
19363 tcg_gen_shli_tl(t0, t0, 2);
19364 break;
19365 case NM_LDC1XS:
19366 case NM_SDC1XS:
19367 tcg_gen_shli_tl(t0, t0, 3);
19368 break;
19371 gen_op_addr_add(ctx, t0, t0, t1);
19373 switch (extract32(ctx->opcode, 7, 4)) {
19374 case NM_LBX:
19375 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19376 MO_SB);
19377 gen_store_gpr(t0, rd);
19378 break;
19379 case NM_LHX:
19380 /*case NM_LHXS:*/
19381 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19382 MO_TESW);
19383 gen_store_gpr(t0, rd);
19384 break;
19385 case NM_LWX:
19386 /*case NM_LWXS:*/
19387 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19388 MO_TESL);
19389 gen_store_gpr(t0, rd);
19390 break;
19391 case NM_LBUX:
19392 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19393 MO_UB);
19394 gen_store_gpr(t0, rd);
19395 break;
19396 case NM_LHUX:
19397 /*case NM_LHUXS:*/
19398 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19399 MO_TEUW);
19400 gen_store_gpr(t0, rd);
19401 break;
19402 case NM_SBX:
19403 check_nms(ctx);
19404 gen_load_gpr(t1, rd);
19405 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19406 MO_8);
19407 break;
19408 case NM_SHX:
19409 /*case NM_SHXS:*/
19410 check_nms(ctx);
19411 gen_load_gpr(t1, rd);
19412 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19413 MO_TEUW);
19414 break;
19415 case NM_SWX:
19416 /*case NM_SWXS:*/
19417 check_nms(ctx);
19418 gen_load_gpr(t1, rd);
19419 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19420 MO_TEUL);
19421 break;
19422 case NM_LWC1X:
19423 /*case NM_LWC1XS:*/
19424 case NM_LDC1X:
19425 /*case NM_LDC1XS:*/
19426 case NM_SWC1X:
19427 /*case NM_SWC1XS:*/
19428 case NM_SDC1X:
19429 /*case NM_SDC1XS:*/
19430 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19431 check_cp1_enabled(ctx);
19432 switch (extract32(ctx->opcode, 7, 4)) {
19433 case NM_LWC1X:
19434 /*case NM_LWC1XS:*/
19435 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19436 break;
19437 case NM_LDC1X:
19438 /*case NM_LDC1XS:*/
19439 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19440 break;
19441 case NM_SWC1X:
19442 /*case NM_SWC1XS:*/
19443 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19444 break;
19445 case NM_SDC1X:
19446 /*case NM_SDC1XS:*/
19447 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19448 break;
19450 } else {
19451 generate_exception_err(ctx, EXCP_CpU, 1);
19453 break;
19454 default:
19455 generate_exception_end(ctx, EXCP_RI);
19456 break;
19459 tcg_temp_free(t0);
19460 tcg_temp_free(t1);
19463 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19465 int rt, rs, rd;
19467 rt = extract32(ctx->opcode, 21, 5);
19468 rs = extract32(ctx->opcode, 16, 5);
19469 rd = extract32(ctx->opcode, 11, 5);
19471 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19472 generate_exception_end(ctx, EXCP_RI);
19473 return;
19475 check_cp1_enabled(ctx);
19476 switch (extract32(ctx->opcode, 0, 3)) {
19477 case NM_POOL32F_0:
19478 switch (extract32(ctx->opcode, 3, 7)) {
19479 case NM_RINT_S:
19480 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19481 break;
19482 case NM_RINT_D:
19483 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19484 break;
19485 case NM_CLASS_S:
19486 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19487 break;
19488 case NM_CLASS_D:
19489 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19490 break;
19491 case NM_ADD_S:
19492 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19493 break;
19494 case NM_ADD_D:
19495 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19496 break;
19497 case NM_SUB_S:
19498 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19499 break;
19500 case NM_SUB_D:
19501 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19502 break;
19503 case NM_MUL_S:
19504 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19505 break;
19506 case NM_MUL_D:
19507 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19508 break;
19509 case NM_DIV_S:
19510 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19511 break;
19512 case NM_DIV_D:
19513 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19514 break;
19515 case NM_SELEQZ_S:
19516 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19517 break;
19518 case NM_SELEQZ_D:
19519 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19520 break;
19521 case NM_SELNEZ_S:
19522 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19523 break;
19524 case NM_SELNEZ_D:
19525 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19526 break;
19527 case NM_SEL_S:
19528 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19529 break;
19530 case NM_SEL_D:
19531 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19532 break;
19533 case NM_MADDF_S:
19534 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19535 break;
19536 case NM_MADDF_D:
19537 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19538 break;
19539 case NM_MSUBF_S:
19540 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19541 break;
19542 case NM_MSUBF_D:
19543 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19544 break;
19545 default:
19546 generate_exception_end(ctx, EXCP_RI);
19547 break;
19549 break;
19550 case NM_POOL32F_3:
19551 switch (extract32(ctx->opcode, 3, 3)) {
19552 case NM_MIN_FMT:
19553 switch (extract32(ctx->opcode, 9, 1)) {
19554 case FMT_SDPS_S:
19555 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19556 break;
19557 case FMT_SDPS_D:
19558 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19559 break;
19561 break;
19562 case NM_MAX_FMT:
19563 switch (extract32(ctx->opcode, 9, 1)) {
19564 case FMT_SDPS_S:
19565 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19566 break;
19567 case FMT_SDPS_D:
19568 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19569 break;
19571 break;
19572 case NM_MINA_FMT:
19573 switch (extract32(ctx->opcode, 9, 1)) {
19574 case FMT_SDPS_S:
19575 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19576 break;
19577 case FMT_SDPS_D:
19578 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19579 break;
19581 break;
19582 case NM_MAXA_FMT:
19583 switch (extract32(ctx->opcode, 9, 1)) {
19584 case FMT_SDPS_S:
19585 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19586 break;
19587 case FMT_SDPS_D:
19588 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19589 break;
19591 break;
19592 case NM_POOL32FXF:
19593 switch (extract32(ctx->opcode, 6, 8)) {
19594 case NM_CFC1:
19595 gen_cp1(ctx, OPC_CFC1, rt, rs);
19596 break;
19597 case NM_CTC1:
19598 gen_cp1(ctx, OPC_CTC1, rt, rs);
19599 break;
19600 case NM_MFC1:
19601 gen_cp1(ctx, OPC_MFC1, rt, rs);
19602 break;
19603 case NM_MTC1:
19604 gen_cp1(ctx, OPC_MTC1, rt, rs);
19605 break;
19606 case NM_MFHC1:
19607 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19608 break;
19609 case NM_MTHC1:
19610 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19611 break;
19612 case NM_CVT_S_PL:
19613 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19614 break;
19615 case NM_CVT_S_PU:
19616 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19617 break;
19618 default:
19619 switch (extract32(ctx->opcode, 6, 9)) {
19620 case NM_CVT_L_S:
19621 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19622 break;
19623 case NM_CVT_L_D:
19624 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19625 break;
19626 case NM_CVT_W_S:
19627 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19628 break;
19629 case NM_CVT_W_D:
19630 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19631 break;
19632 case NM_RSQRT_S:
19633 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19634 break;
19635 case NM_RSQRT_D:
19636 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19637 break;
19638 case NM_SQRT_S:
19639 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19640 break;
19641 case NM_SQRT_D:
19642 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19643 break;
19644 case NM_RECIP_S:
19645 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19646 break;
19647 case NM_RECIP_D:
19648 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19649 break;
19650 case NM_FLOOR_L_S:
19651 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19652 break;
19653 case NM_FLOOR_L_D:
19654 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19655 break;
19656 case NM_FLOOR_W_S:
19657 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19658 break;
19659 case NM_FLOOR_W_D:
19660 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19661 break;
19662 case NM_CEIL_L_S:
19663 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19664 break;
19665 case NM_CEIL_L_D:
19666 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19667 break;
19668 case NM_CEIL_W_S:
19669 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19670 break;
19671 case NM_CEIL_W_D:
19672 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19673 break;
19674 case NM_TRUNC_L_S:
19675 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19676 break;
19677 case NM_TRUNC_L_D:
19678 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19679 break;
19680 case NM_TRUNC_W_S:
19681 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19682 break;
19683 case NM_TRUNC_W_D:
19684 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19685 break;
19686 case NM_ROUND_L_S:
19687 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19688 break;
19689 case NM_ROUND_L_D:
19690 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19691 break;
19692 case NM_ROUND_W_S:
19693 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19694 break;
19695 case NM_ROUND_W_D:
19696 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19697 break;
19698 case NM_MOV_S:
19699 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19700 break;
19701 case NM_MOV_D:
19702 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19703 break;
19704 case NM_ABS_S:
19705 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19706 break;
19707 case NM_ABS_D:
19708 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19709 break;
19710 case NM_NEG_S:
19711 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19712 break;
19713 case NM_NEG_D:
19714 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19715 break;
19716 case NM_CVT_D_S:
19717 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19718 break;
19719 case NM_CVT_D_W:
19720 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19721 break;
19722 case NM_CVT_D_L:
19723 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19724 break;
19725 case NM_CVT_S_D:
19726 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19727 break;
19728 case NM_CVT_S_W:
19729 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19730 break;
19731 case NM_CVT_S_L:
19732 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19733 break;
19734 default:
19735 generate_exception_end(ctx, EXCP_RI);
19736 break;
19738 break;
19740 break;
19742 break;
19743 case NM_POOL32F_5:
19744 switch (extract32(ctx->opcode, 3, 3)) {
19745 case NM_CMP_CONDN_S:
19746 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19747 break;
19748 case NM_CMP_CONDN_D:
19749 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19750 break;
19751 default:
19752 generate_exception_end(ctx, EXCP_RI);
19753 break;
19755 break;
19756 default:
19757 generate_exception_end(ctx, EXCP_RI);
19758 break;
19762 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19763 int rd, int rs, int rt)
19765 int ret = rd;
19766 TCGv t0 = tcg_temp_new();
19767 TCGv v1_t = tcg_temp_new();
19768 TCGv v2_t = tcg_temp_new();
19770 gen_load_gpr(v1_t, rs);
19771 gen_load_gpr(v2_t, rt);
19773 switch (opc) {
19774 case NM_CMP_EQ_PH:
19775 check_dsp(ctx);
19776 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19777 break;
19778 case NM_CMP_LT_PH:
19779 check_dsp(ctx);
19780 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19781 break;
19782 case NM_CMP_LE_PH:
19783 check_dsp(ctx);
19784 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19785 break;
19786 case NM_CMPU_EQ_QB:
19787 check_dsp(ctx);
19788 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19789 break;
19790 case NM_CMPU_LT_QB:
19791 check_dsp(ctx);
19792 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19793 break;
19794 case NM_CMPU_LE_QB:
19795 check_dsp(ctx);
19796 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19797 break;
19798 case NM_CMPGU_EQ_QB:
19799 check_dsp(ctx);
19800 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19801 gen_store_gpr(v1_t, ret);
19802 break;
19803 case NM_CMPGU_LT_QB:
19804 check_dsp(ctx);
19805 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19806 gen_store_gpr(v1_t, ret);
19807 break;
19808 case NM_CMPGU_LE_QB:
19809 check_dsp(ctx);
19810 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19811 gen_store_gpr(v1_t, ret);
19812 break;
19813 case NM_CMPGDU_EQ_QB:
19814 check_dsp_r2(ctx);
19815 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19816 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19817 gen_store_gpr(v1_t, ret);
19818 break;
19819 case NM_CMPGDU_LT_QB:
19820 check_dsp_r2(ctx);
19821 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19822 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19823 gen_store_gpr(v1_t, ret);
19824 break;
19825 case NM_CMPGDU_LE_QB:
19826 check_dsp_r2(ctx);
19827 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19828 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19829 gen_store_gpr(v1_t, ret);
19830 break;
19831 case NM_PACKRL_PH:
19832 check_dsp(ctx);
19833 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19834 gen_store_gpr(v1_t, ret);
19835 break;
19836 case NM_PICK_QB:
19837 check_dsp(ctx);
19838 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19839 gen_store_gpr(v1_t, ret);
19840 break;
19841 case NM_PICK_PH:
19842 check_dsp(ctx);
19843 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19844 gen_store_gpr(v1_t, ret);
19845 break;
19846 case NM_ADDQ_S_W:
19847 check_dsp(ctx);
19848 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19849 gen_store_gpr(v1_t, ret);
19850 break;
19851 case NM_SUBQ_S_W:
19852 check_dsp(ctx);
19853 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19854 gen_store_gpr(v1_t, ret);
19855 break;
19856 case NM_ADDSC:
19857 check_dsp(ctx);
19858 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19859 gen_store_gpr(v1_t, ret);
19860 break;
19861 case NM_ADDWC:
19862 check_dsp(ctx);
19863 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19864 gen_store_gpr(v1_t, ret);
19865 break;
19866 case NM_ADDQ_S_PH:
19867 check_dsp(ctx);
19868 switch (extract32(ctx->opcode, 10, 1)) {
19869 case 0:
19870 /* ADDQ_PH */
19871 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19872 gen_store_gpr(v1_t, ret);
19873 break;
19874 case 1:
19875 /* ADDQ_S_PH */
19876 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19877 gen_store_gpr(v1_t, ret);
19878 break;
19880 break;
19881 case NM_ADDQH_R_PH:
19882 check_dsp_r2(ctx);
19883 switch (extract32(ctx->opcode, 10, 1)) {
19884 case 0:
19885 /* ADDQH_PH */
19886 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19887 gen_store_gpr(v1_t, ret);
19888 break;
19889 case 1:
19890 /* ADDQH_R_PH */
19891 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19892 gen_store_gpr(v1_t, ret);
19893 break;
19895 break;
19896 case NM_ADDQH_R_W:
19897 check_dsp_r2(ctx);
19898 switch (extract32(ctx->opcode, 10, 1)) {
19899 case 0:
19900 /* ADDQH_W */
19901 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19902 gen_store_gpr(v1_t, ret);
19903 break;
19904 case 1:
19905 /* ADDQH_R_W */
19906 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19907 gen_store_gpr(v1_t, ret);
19908 break;
19910 break;
19911 case NM_ADDU_S_QB:
19912 check_dsp(ctx);
19913 switch (extract32(ctx->opcode, 10, 1)) {
19914 case 0:
19915 /* ADDU_QB */
19916 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19917 gen_store_gpr(v1_t, ret);
19918 break;
19919 case 1:
19920 /* ADDU_S_QB */
19921 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19922 gen_store_gpr(v1_t, ret);
19923 break;
19925 break;
19926 case NM_ADDU_S_PH:
19927 check_dsp_r2(ctx);
19928 switch (extract32(ctx->opcode, 10, 1)) {
19929 case 0:
19930 /* ADDU_PH */
19931 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19932 gen_store_gpr(v1_t, ret);
19933 break;
19934 case 1:
19935 /* ADDU_S_PH */
19936 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19937 gen_store_gpr(v1_t, ret);
19938 break;
19940 break;
19941 case NM_ADDUH_R_QB:
19942 check_dsp_r2(ctx);
19943 switch (extract32(ctx->opcode, 10, 1)) {
19944 case 0:
19945 /* ADDUH_QB */
19946 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19947 gen_store_gpr(v1_t, ret);
19948 break;
19949 case 1:
19950 /* ADDUH_R_QB */
19951 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19952 gen_store_gpr(v1_t, ret);
19953 break;
19955 break;
19956 case NM_SHRAV_R_PH:
19957 check_dsp(ctx);
19958 switch (extract32(ctx->opcode, 10, 1)) {
19959 case 0:
19960 /* SHRAV_PH */
19961 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19962 gen_store_gpr(v1_t, ret);
19963 break;
19964 case 1:
19965 /* SHRAV_R_PH */
19966 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19967 gen_store_gpr(v1_t, ret);
19968 break;
19970 break;
19971 case NM_SHRAV_R_QB:
19972 check_dsp_r2(ctx);
19973 switch (extract32(ctx->opcode, 10, 1)) {
19974 case 0:
19975 /* SHRAV_QB */
19976 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19977 gen_store_gpr(v1_t, ret);
19978 break;
19979 case 1:
19980 /* SHRAV_R_QB */
19981 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19982 gen_store_gpr(v1_t, ret);
19983 break;
19985 break;
19986 case NM_SUBQ_S_PH:
19987 check_dsp(ctx);
19988 switch (extract32(ctx->opcode, 10, 1)) {
19989 case 0:
19990 /* SUBQ_PH */
19991 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19992 gen_store_gpr(v1_t, ret);
19993 break;
19994 case 1:
19995 /* SUBQ_S_PH */
19996 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19997 gen_store_gpr(v1_t, ret);
19998 break;
20000 break;
20001 case NM_SUBQH_R_PH:
20002 check_dsp_r2(ctx);
20003 switch (extract32(ctx->opcode, 10, 1)) {
20004 case 0:
20005 /* SUBQH_PH */
20006 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
20007 gen_store_gpr(v1_t, ret);
20008 break;
20009 case 1:
20010 /* SUBQH_R_PH */
20011 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
20012 gen_store_gpr(v1_t, ret);
20013 break;
20015 break;
20016 case NM_SUBQH_R_W:
20017 check_dsp_r2(ctx);
20018 switch (extract32(ctx->opcode, 10, 1)) {
20019 case 0:
20020 /* SUBQH_W */
20021 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20022 gen_store_gpr(v1_t, ret);
20023 break;
20024 case 1:
20025 /* SUBQH_R_W */
20026 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20027 gen_store_gpr(v1_t, ret);
20028 break;
20030 break;
20031 case NM_SUBU_S_QB:
20032 check_dsp(ctx);
20033 switch (extract32(ctx->opcode, 10, 1)) {
20034 case 0:
20035 /* SUBU_QB */
20036 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20037 gen_store_gpr(v1_t, ret);
20038 break;
20039 case 1:
20040 /* SUBU_S_QB */
20041 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20042 gen_store_gpr(v1_t, ret);
20043 break;
20045 break;
20046 case NM_SUBU_S_PH:
20047 check_dsp_r2(ctx);
20048 switch (extract32(ctx->opcode, 10, 1)) {
20049 case 0:
20050 /* SUBU_PH */
20051 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20052 gen_store_gpr(v1_t, ret);
20053 break;
20054 case 1:
20055 /* SUBU_S_PH */
20056 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20057 gen_store_gpr(v1_t, ret);
20058 break;
20060 break;
20061 case NM_SUBUH_R_QB:
20062 check_dsp_r2(ctx);
20063 switch (extract32(ctx->opcode, 10, 1)) {
20064 case 0:
20065 /* SUBUH_QB */
20066 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20067 gen_store_gpr(v1_t, ret);
20068 break;
20069 case 1:
20070 /* SUBUH_R_QB */
20071 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20072 gen_store_gpr(v1_t, ret);
20073 break;
20075 break;
20076 case NM_SHLLV_S_PH:
20077 check_dsp(ctx);
20078 switch (extract32(ctx->opcode, 10, 1)) {
20079 case 0:
20080 /* SHLLV_PH */
20081 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20082 gen_store_gpr(v1_t, ret);
20083 break;
20084 case 1:
20085 /* SHLLV_S_PH */
20086 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20087 gen_store_gpr(v1_t, ret);
20088 break;
20090 break;
20091 case NM_PRECR_SRA_R_PH_W:
20092 check_dsp_r2(ctx);
20093 switch (extract32(ctx->opcode, 10, 1)) {
20094 case 0:
20095 /* PRECR_SRA_PH_W */
20097 TCGv_i32 sa_t = tcg_const_i32(rd);
20098 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20099 cpu_gpr[rt]);
20100 gen_store_gpr(v1_t, rt);
20101 tcg_temp_free_i32(sa_t);
20103 break;
20104 case 1:
20105 /* PRECR_SRA_R_PH_W */
20107 TCGv_i32 sa_t = tcg_const_i32(rd);
20108 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20109 cpu_gpr[rt]);
20110 gen_store_gpr(v1_t, rt);
20111 tcg_temp_free_i32(sa_t);
20113 break;
20115 break;
20116 case NM_MULEU_S_PH_QBL:
20117 check_dsp(ctx);
20118 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20119 gen_store_gpr(v1_t, ret);
20120 break;
20121 case NM_MULEU_S_PH_QBR:
20122 check_dsp(ctx);
20123 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20124 gen_store_gpr(v1_t, ret);
20125 break;
20126 case NM_MULQ_RS_PH:
20127 check_dsp(ctx);
20128 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20129 gen_store_gpr(v1_t, ret);
20130 break;
20131 case NM_MULQ_S_PH:
20132 check_dsp_r2(ctx);
20133 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20134 gen_store_gpr(v1_t, ret);
20135 break;
20136 case NM_MULQ_RS_W:
20137 check_dsp_r2(ctx);
20138 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20139 gen_store_gpr(v1_t, ret);
20140 break;
20141 case NM_MULQ_S_W:
20142 check_dsp_r2(ctx);
20143 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20144 gen_store_gpr(v1_t, ret);
20145 break;
20146 case NM_APPEND:
20147 check_dsp_r2(ctx);
20148 gen_load_gpr(t0, rs);
20149 if (rd != 0) {
20150 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20152 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20153 break;
20154 case NM_MODSUB:
20155 check_dsp(ctx);
20156 gen_helper_modsub(v1_t, v1_t, v2_t);
20157 gen_store_gpr(v1_t, ret);
20158 break;
20159 case NM_SHRAV_R_W:
20160 check_dsp(ctx);
20161 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20162 gen_store_gpr(v1_t, ret);
20163 break;
20164 case NM_SHRLV_PH:
20165 check_dsp_r2(ctx);
20166 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20167 gen_store_gpr(v1_t, ret);
20168 break;
20169 case NM_SHRLV_QB:
20170 check_dsp(ctx);
20171 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20172 gen_store_gpr(v1_t, ret);
20173 break;
20174 case NM_SHLLV_QB:
20175 check_dsp(ctx);
20176 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20177 gen_store_gpr(v1_t, ret);
20178 break;
20179 case NM_SHLLV_S_W:
20180 check_dsp(ctx);
20181 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20182 gen_store_gpr(v1_t, ret);
20183 break;
20184 case NM_SHILO:
20185 check_dsp(ctx);
20187 TCGv tv0 = tcg_temp_new();
20188 TCGv tv1 = tcg_temp_new();
20189 int16_t imm = extract32(ctx->opcode, 16, 7);
20191 tcg_gen_movi_tl(tv0, rd >> 3);
20192 tcg_gen_movi_tl(tv1, imm);
20193 gen_helper_shilo(tv0, tv1, cpu_env);
20195 break;
20196 case NM_MULEQ_S_W_PHL:
20197 check_dsp(ctx);
20198 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20199 gen_store_gpr(v1_t, ret);
20200 break;
20201 case NM_MULEQ_S_W_PHR:
20202 check_dsp(ctx);
20203 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20204 gen_store_gpr(v1_t, ret);
20205 break;
20206 case NM_MUL_S_PH:
20207 check_dsp_r2(ctx);
20208 switch (extract32(ctx->opcode, 10, 1)) {
20209 case 0:
20210 /* MUL_PH */
20211 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20212 gen_store_gpr(v1_t, ret);
20213 break;
20214 case 1:
20215 /* MUL_S_PH */
20216 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20217 gen_store_gpr(v1_t, ret);
20218 break;
20220 break;
20221 case NM_PRECR_QB_PH:
20222 check_dsp_r2(ctx);
20223 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20224 gen_store_gpr(v1_t, ret);
20225 break;
20226 case NM_PRECRQ_QB_PH:
20227 check_dsp(ctx);
20228 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20229 gen_store_gpr(v1_t, ret);
20230 break;
20231 case NM_PRECRQ_PH_W:
20232 check_dsp(ctx);
20233 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20234 gen_store_gpr(v1_t, ret);
20235 break;
20236 case NM_PRECRQ_RS_PH_W:
20237 check_dsp(ctx);
20238 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20239 gen_store_gpr(v1_t, ret);
20240 break;
20241 case NM_PRECRQU_S_QB_PH:
20242 check_dsp(ctx);
20243 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20244 gen_store_gpr(v1_t, ret);
20245 break;
20246 case NM_SHRA_R_W:
20247 check_dsp(ctx);
20248 tcg_gen_movi_tl(t0, rd);
20249 gen_helper_shra_r_w(v1_t, t0, v1_t);
20250 gen_store_gpr(v1_t, rt);
20251 break;
20252 case NM_SHRA_R_PH:
20253 check_dsp(ctx);
20254 tcg_gen_movi_tl(t0, rd >> 1);
20255 switch (extract32(ctx->opcode, 10, 1)) {
20256 case 0:
20257 /* SHRA_PH */
20258 gen_helper_shra_ph(v1_t, t0, v1_t);
20259 gen_store_gpr(v1_t, rt);
20260 break;
20261 case 1:
20262 /* SHRA_R_PH */
20263 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20264 gen_store_gpr(v1_t, rt);
20265 break;
20267 break;
20268 case NM_SHLL_S_PH:
20269 check_dsp(ctx);
20270 tcg_gen_movi_tl(t0, rd >> 1);
20271 switch (extract32(ctx->opcode, 10, 2)) {
20272 case 0:
20273 /* SHLL_PH */
20274 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20275 gen_store_gpr(v1_t, rt);
20276 break;
20277 case 2:
20278 /* SHLL_S_PH */
20279 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20280 gen_store_gpr(v1_t, rt);
20281 break;
20282 default:
20283 generate_exception_end(ctx, EXCP_RI);
20284 break;
20286 break;
20287 case NM_SHLL_S_W:
20288 check_dsp(ctx);
20289 tcg_gen_movi_tl(t0, rd);
20290 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20291 gen_store_gpr(v1_t, rt);
20292 break;
20293 case NM_REPL_PH:
20294 check_dsp(ctx);
20296 int16_t imm;
20297 imm = sextract32(ctx->opcode, 11, 11);
20298 imm = (int16_t)(imm << 6) >> 6;
20299 if (rt != 0) {
20300 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20303 break;
20304 default:
20305 generate_exception_end(ctx, EXCP_RI);
20306 break;
20310 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20312 uint16_t insn;
20313 uint32_t op;
20314 int rt, rs, rd;
20315 int offset;
20316 int imm;
20318 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
20319 ctx->opcode = (ctx->opcode << 16) | insn;
20321 rt = extract32(ctx->opcode, 21, 5);
20322 rs = extract32(ctx->opcode, 16, 5);
20323 rd = extract32(ctx->opcode, 11, 5);
20325 op = extract32(ctx->opcode, 26, 6);
20326 switch (op) {
20327 case NM_P_ADDIU:
20328 if (rt == 0) {
20329 /* P.RI */
20330 switch (extract32(ctx->opcode, 19, 2)) {
20331 case NM_SIGRIE:
20332 default:
20333 generate_exception_end(ctx, EXCP_RI);
20334 break;
20335 case NM_P_SYSCALL:
20336 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20337 generate_exception_end(ctx, EXCP_SYSCALL);
20338 } else {
20339 generate_exception_end(ctx, EXCP_RI);
20341 break;
20342 case NM_BREAK:
20343 generate_exception_end(ctx, EXCP_BREAK);
20344 break;
20345 case NM_SDBBP:
20346 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20347 gen_helper_do_semihosting(cpu_env);
20348 } else {
20349 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20350 generate_exception_end(ctx, EXCP_RI);
20351 } else {
20352 generate_exception_end(ctx, EXCP_DBp);
20355 break;
20357 } else {
20358 /* NM_ADDIU */
20359 imm = extract32(ctx->opcode, 0, 16);
20360 if (rs != 0) {
20361 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20362 } else {
20363 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20365 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20367 break;
20368 case NM_ADDIUPC:
20369 if (rt != 0) {
20370 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20371 extract32(ctx->opcode, 1, 20) << 1;
20372 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20373 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20375 break;
20376 case NM_POOL32A:
20377 switch (ctx->opcode & 0x07) {
20378 case NM_POOL32A0:
20379 gen_pool32a0_nanomips_insn(env, ctx);
20380 break;
20381 case NM_POOL32A5:
20383 int32_t op1 = extract32(ctx->opcode, 3, 7);
20384 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20386 break;
20387 case NM_POOL32A7:
20388 switch (extract32(ctx->opcode, 3, 3)) {
20389 case NM_P_LSX:
20390 gen_p_lsx(ctx, rd, rs, rt);
20391 break;
20392 case NM_LSA:
20393 /* In nanoMIPS, the shift field directly encodes the shift
20394 * amount, meaning that the supported shift values are in
20395 * the range 0 to 3 (instead of 1 to 4 in MIPSR6). */
20396 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
20397 extract32(ctx->opcode, 9, 2) - 1);
20398 break;
20399 case NM_EXTW:
20400 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20401 break;
20402 case NM_POOL32AXF:
20403 gen_pool32axf_nanomips_insn(env, ctx);
20404 break;
20405 default:
20406 generate_exception_end(ctx, EXCP_RI);
20407 break;
20409 break;
20410 default:
20411 generate_exception_end(ctx, EXCP_RI);
20412 break;
20414 break;
20415 case NM_P_GP_W:
20416 switch (ctx->opcode & 0x03) {
20417 case NM_ADDIUGP_W:
20418 if (rt != 0) {
20419 offset = extract32(ctx->opcode, 0, 21);
20420 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20422 break;
20423 case NM_LWGP:
20424 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20425 break;
20426 case NM_SWGP:
20427 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20428 break;
20429 default:
20430 generate_exception_end(ctx, EXCP_RI);
20431 break;
20433 break;
20434 case NM_P48I:
20436 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
20437 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20438 switch (extract32(ctx->opcode, 16, 5)) {
20439 case NM_LI48:
20440 check_nms(ctx);
20441 if (rt != 0) {
20442 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20444 break;
20445 case NM_ADDIU48:
20446 check_nms(ctx);
20447 if (rt != 0) {
20448 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20449 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20451 break;
20452 case NM_ADDIUGP48:
20453 check_nms(ctx);
20454 if (rt != 0) {
20455 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20457 break;
20458 case NM_ADDIUPC48:
20459 check_nms(ctx);
20460 if (rt != 0) {
20461 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20462 addr_off);
20464 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20466 break;
20467 case NM_LWPC48:
20468 check_nms(ctx);
20469 if (rt != 0) {
20470 TCGv t0;
20471 t0 = tcg_temp_new();
20473 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20474 addr_off);
20476 tcg_gen_movi_tl(t0, addr);
20477 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20478 tcg_temp_free(t0);
20480 break;
20481 case NM_SWPC48:
20482 check_nms(ctx);
20484 TCGv t0, t1;
20485 t0 = tcg_temp_new();
20486 t1 = tcg_temp_new();
20488 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20489 addr_off);
20491 tcg_gen_movi_tl(t0, addr);
20492 gen_load_gpr(t1, rt);
20494 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20496 tcg_temp_free(t0);
20497 tcg_temp_free(t1);
20499 break;
20500 default:
20501 generate_exception_end(ctx, EXCP_RI);
20502 break;
20504 return 6;
20506 case NM_P_U12:
20507 switch (extract32(ctx->opcode, 12, 4)) {
20508 case NM_ORI:
20509 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20510 break;
20511 case NM_XORI:
20512 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20513 break;
20514 case NM_ANDI:
20515 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20516 break;
20517 case NM_P_SR:
20518 switch (extract32(ctx->opcode, 20, 1)) {
20519 case NM_PP_SR:
20520 switch (ctx->opcode & 3) {
20521 case NM_SAVE:
20522 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20523 extract32(ctx->opcode, 2, 1),
20524 extract32(ctx->opcode, 3, 9) << 3);
20525 break;
20526 case NM_RESTORE:
20527 case NM_RESTORE_JRC:
20528 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20529 extract32(ctx->opcode, 2, 1),
20530 extract32(ctx->opcode, 3, 9) << 3);
20531 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20532 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20534 break;
20535 default:
20536 generate_exception_end(ctx, EXCP_RI);
20537 break;
20539 break;
20540 case NM_P_SR_F:
20541 generate_exception_end(ctx, EXCP_RI);
20542 break;
20544 break;
20545 case NM_SLTI:
20546 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20547 break;
20548 case NM_SLTIU:
20549 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20550 break;
20551 case NM_SEQI:
20553 TCGv t0 = tcg_temp_new();
20555 imm = extract32(ctx->opcode, 0, 12);
20556 gen_load_gpr(t0, rs);
20557 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20558 gen_store_gpr(t0, rt);
20560 tcg_temp_free(t0);
20562 break;
20563 case NM_ADDIUNEG:
20564 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20565 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20566 break;
20567 case NM_P_SHIFT:
20569 int shift = extract32(ctx->opcode, 0, 5);
20570 switch (extract32(ctx->opcode, 5, 4)) {
20571 case NM_P_SLL:
20572 if (rt == 0 && shift == 0) {
20573 /* NOP */
20574 } else if (rt == 0 && shift == 3) {
20575 /* EHB - treat as NOP */
20576 } else if (rt == 0 && shift == 5) {
20577 /* PAUSE - treat as NOP */
20578 } else if (rt == 0 && shift == 6) {
20579 /* SYNC */
20580 gen_sync(extract32(ctx->opcode, 16, 5));
20581 } else {
20582 /* SLL */
20583 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20584 extract32(ctx->opcode, 0, 5));
20586 break;
20587 case NM_SRL:
20588 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20589 extract32(ctx->opcode, 0, 5));
20590 break;
20591 case NM_SRA:
20592 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20593 extract32(ctx->opcode, 0, 5));
20594 break;
20595 case NM_ROTR:
20596 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20597 extract32(ctx->opcode, 0, 5));
20598 break;
20601 break;
20602 case NM_P_ROTX:
20603 check_nms(ctx);
20604 if (rt != 0) {
20605 TCGv t0 = tcg_temp_new();
20606 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20607 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20608 << 1);
20609 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20611 gen_load_gpr(t0, rs);
20612 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20613 tcg_temp_free(t0);
20615 tcg_temp_free_i32(shift);
20616 tcg_temp_free_i32(shiftx);
20617 tcg_temp_free_i32(stripe);
20619 break;
20620 case NM_P_INS:
20621 switch (((ctx->opcode >> 10) & 2) |
20622 (extract32(ctx->opcode, 5, 1))) {
20623 case NM_INS:
20624 check_nms(ctx);
20625 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20626 extract32(ctx->opcode, 6, 5));
20627 break;
20628 default:
20629 generate_exception_end(ctx, EXCP_RI);
20630 break;
20632 break;
20633 case NM_P_EXT:
20634 switch (((ctx->opcode >> 10) & 2) |
20635 (extract32(ctx->opcode, 5, 1))) {
20636 case NM_EXT:
20637 check_nms(ctx);
20638 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20639 extract32(ctx->opcode, 6, 5));
20640 break;
20641 default:
20642 generate_exception_end(ctx, EXCP_RI);
20643 break;
20645 break;
20646 default:
20647 generate_exception_end(ctx, EXCP_RI);
20648 break;
20650 break;
20651 case NM_POOL32F:
20652 gen_pool32f_nanomips_insn(ctx);
20653 break;
20654 case NM_POOL32S:
20655 break;
20656 case NM_P_LUI:
20657 switch (extract32(ctx->opcode, 1, 1)) {
20658 case NM_LUI:
20659 if (rt != 0) {
20660 tcg_gen_movi_tl(cpu_gpr[rt],
20661 sextract32(ctx->opcode, 0, 1) << 31 |
20662 extract32(ctx->opcode, 2, 10) << 21 |
20663 extract32(ctx->opcode, 12, 9) << 12);
20665 break;
20666 case NM_ALUIPC:
20667 if (rt != 0) {
20668 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20669 extract32(ctx->opcode, 2, 10) << 21 |
20670 extract32(ctx->opcode, 12, 9) << 12;
20671 target_long addr;
20672 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20673 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20675 break;
20677 break;
20678 case NM_P_GP_BH:
20680 uint32_t u = extract32(ctx->opcode, 0, 18);
20682 switch (extract32(ctx->opcode, 18, 3)) {
20683 case NM_LBGP:
20684 gen_ld(ctx, OPC_LB, rt, 28, u);
20685 break;
20686 case NM_SBGP:
20687 gen_st(ctx, OPC_SB, rt, 28, u);
20688 break;
20689 case NM_LBUGP:
20690 gen_ld(ctx, OPC_LBU, rt, 28, u);
20691 break;
20692 case NM_ADDIUGP_B:
20693 if (rt != 0) {
20694 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20696 break;
20697 case NM_P_GP_LH:
20698 u &= ~1;
20699 switch (ctx->opcode & 1) {
20700 case NM_LHGP:
20701 gen_ld(ctx, OPC_LH, rt, 28, u);
20702 break;
20703 case NM_LHUGP:
20704 gen_ld(ctx, OPC_LHU, rt, 28, u);
20705 break;
20707 break;
20708 case NM_P_GP_SH:
20709 u &= ~1;
20710 switch (ctx->opcode & 1) {
20711 case NM_SHGP:
20712 gen_st(ctx, OPC_SH, rt, 28, u);
20713 break;
20714 default:
20715 generate_exception_end(ctx, EXCP_RI);
20716 break;
20718 break;
20719 case NM_P_GP_CP1:
20720 u &= ~0x3;
20721 switch (ctx->opcode & 0x3) {
20722 case NM_LWC1GP:
20723 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20724 break;
20725 case NM_LDC1GP:
20726 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20727 break;
20728 case NM_SWC1GP:
20729 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20730 break;
20731 case NM_SDC1GP:
20732 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20733 break;
20735 break;
20736 default:
20737 generate_exception_end(ctx, EXCP_RI);
20738 break;
20741 break;
20742 case NM_P_LS_U12:
20744 uint32_t u = extract32(ctx->opcode, 0, 12);
20746 switch (extract32(ctx->opcode, 12, 4)) {
20747 case NM_P_PREFU12:
20748 if (rt == 31) {
20749 /* SYNCI */
20750 /* Break the TB to be able to sync copied instructions
20751 immediately */
20752 ctx->base.is_jmp = DISAS_STOP;
20753 } else {
20754 /* PREF */
20755 /* Treat as NOP. */
20757 break;
20758 case NM_LB:
20759 gen_ld(ctx, OPC_LB, rt, rs, u);
20760 break;
20761 case NM_LH:
20762 gen_ld(ctx, OPC_LH, rt, rs, u);
20763 break;
20764 case NM_LW:
20765 gen_ld(ctx, OPC_LW, rt, rs, u);
20766 break;
20767 case NM_LBU:
20768 gen_ld(ctx, OPC_LBU, rt, rs, u);
20769 break;
20770 case NM_LHU:
20771 gen_ld(ctx, OPC_LHU, rt, rs, u);
20772 break;
20773 case NM_SB:
20774 gen_st(ctx, OPC_SB, rt, rs, u);
20775 break;
20776 case NM_SH:
20777 gen_st(ctx, OPC_SH, rt, rs, u);
20778 break;
20779 case NM_SW:
20780 gen_st(ctx, OPC_SW, rt, rs, u);
20781 break;
20782 case NM_LWC1:
20783 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20784 break;
20785 case NM_LDC1:
20786 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20787 break;
20788 case NM_SWC1:
20789 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20790 break;
20791 case NM_SDC1:
20792 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20793 break;
20794 default:
20795 generate_exception_end(ctx, EXCP_RI);
20796 break;
20799 break;
20800 case NM_P_LS_S9:
20802 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20803 extract32(ctx->opcode, 0, 8);
20805 switch (extract32(ctx->opcode, 8, 3)) {
20806 case NM_P_LS_S0:
20807 switch (extract32(ctx->opcode, 11, 4)) {
20808 case NM_LBS9:
20809 gen_ld(ctx, OPC_LB, rt, rs, s);
20810 break;
20811 case NM_LHS9:
20812 gen_ld(ctx, OPC_LH, rt, rs, s);
20813 break;
20814 case NM_LWS9:
20815 gen_ld(ctx, OPC_LW, rt, rs, s);
20816 break;
20817 case NM_LBUS9:
20818 gen_ld(ctx, OPC_LBU, rt, rs, s);
20819 break;
20820 case NM_LHUS9:
20821 gen_ld(ctx, OPC_LHU, rt, rs, s);
20822 break;
20823 case NM_SBS9:
20824 gen_st(ctx, OPC_SB, rt, rs, s);
20825 break;
20826 case NM_SHS9:
20827 gen_st(ctx, OPC_SH, rt, rs, s);
20828 break;
20829 case NM_SWS9:
20830 gen_st(ctx, OPC_SW, rt, rs, s);
20831 break;
20832 case NM_LWC1S9:
20833 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20834 break;
20835 case NM_LDC1S9:
20836 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20837 break;
20838 case NM_SWC1S9:
20839 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20840 break;
20841 case NM_SDC1S9:
20842 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20843 break;
20844 case NM_P_PREFS9:
20845 if (rt == 31) {
20846 /* SYNCI */
20847 /* Break the TB to be able to sync copied instructions
20848 immediately */
20849 ctx->base.is_jmp = DISAS_STOP;
20850 } else {
20851 /* PREF */
20852 /* Treat as NOP. */
20854 break;
20855 default:
20856 generate_exception_end(ctx, EXCP_RI);
20857 break;
20859 break;
20860 case NM_P_LS_S1:
20861 switch (extract32(ctx->opcode, 11, 4)) {
20862 case NM_UALH:
20863 case NM_UASH:
20864 check_nms(ctx);
20866 TCGv t0 = tcg_temp_new();
20867 TCGv t1 = tcg_temp_new();
20869 gen_base_offset_addr(ctx, t0, rs, s);
20871 switch (extract32(ctx->opcode, 11, 4)) {
20872 case NM_UALH:
20873 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20874 MO_UNALN);
20875 gen_store_gpr(t0, rt);
20876 break;
20877 case NM_UASH:
20878 gen_load_gpr(t1, rt);
20879 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20880 MO_UNALN);
20881 break;
20883 tcg_temp_free(t0);
20884 tcg_temp_free(t1);
20886 break;
20887 case NM_P_LL:
20888 switch (ctx->opcode & 0x03) {
20889 case NM_LL:
20890 gen_ld(ctx, OPC_LL, rt, rs, s);
20891 break;
20892 case NM_LLWP:
20893 check_xnp(ctx);
20894 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20895 break;
20897 break;
20898 case NM_P_SC:
20899 switch (ctx->opcode & 0x03) {
20900 case NM_SC:
20901 gen_st_cond(ctx, OPC_SC, rt, rs, s);
20902 break;
20903 case NM_SCWP:
20904 check_xnp(ctx);
20905 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20906 break;
20908 break;
20909 case NM_CACHE:
20910 check_cp0_enabled(ctx);
20911 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20912 gen_cache_operation(ctx, rt, rs, s);
20914 break;
20916 break;
20917 case NM_P_LS_WM:
20918 case NM_P_LS_UAWM:
20919 check_nms(ctx);
20921 int count = extract32(ctx->opcode, 12, 3);
20922 int counter = 0;
20924 offset = sextract32(ctx->opcode, 15, 1) << 8 |
20925 extract32(ctx->opcode, 0, 8);
20926 TCGv va = tcg_temp_new();
20927 TCGv t1 = tcg_temp_new();
20928 TCGMemOp memop = (extract32(ctx->opcode, 8, 3)) ==
20929 NM_P_LS_UAWM ? MO_UNALN : 0;
20931 count = (count == 0) ? 8 : count;
20932 while (counter != count) {
20933 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
20934 int this_offset = offset + (counter << 2);
20936 gen_base_offset_addr(ctx, va, rs, this_offset);
20938 switch (extract32(ctx->opcode, 11, 1)) {
20939 case NM_LWM:
20940 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
20941 memop | MO_TESL);
20942 gen_store_gpr(t1, this_rt);
20943 if ((this_rt == rs) &&
20944 (counter != (count - 1))) {
20945 /* UNPREDICTABLE */
20947 break;
20948 case NM_SWM:
20949 this_rt = (rt == 0) ? 0 : this_rt;
20950 gen_load_gpr(t1, this_rt);
20951 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
20952 memop | MO_TEUL);
20953 break;
20955 counter++;
20957 tcg_temp_free(va);
20958 tcg_temp_free(t1);
20960 break;
20961 default:
20962 generate_exception_end(ctx, EXCP_RI);
20963 break;
20966 break;
20967 case NM_MOVE_BALC:
20968 check_nms(ctx);
20970 TCGv t0 = tcg_temp_new();
20971 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
20972 extract32(ctx->opcode, 1, 20) << 1;
20973 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
20974 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
20975 extract32(ctx->opcode, 21, 3));
20976 gen_load_gpr(t0, rt);
20977 tcg_gen_mov_tl(cpu_gpr[rd], t0);
20978 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20979 tcg_temp_free(t0);
20981 break;
20982 case NM_P_BAL:
20984 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
20985 extract32(ctx->opcode, 1, 24) << 1;
20987 if ((extract32(ctx->opcode, 25, 1)) == 0) {
20988 /* BC */
20989 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
20990 } else {
20991 /* BALC */
20992 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
20995 break;
20996 case NM_P_J:
20997 switch (extract32(ctx->opcode, 12, 4)) {
20998 case NM_JALRC:
20999 case NM_JALRC_HB:
21000 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21001 break;
21002 case NM_P_BALRSC:
21003 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21004 break;
21005 default:
21006 generate_exception_end(ctx, EXCP_RI);
21007 break;
21009 break;
21010 case NM_P_BR1:
21012 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21013 extract32(ctx->opcode, 1, 13) << 1;
21014 switch (extract32(ctx->opcode, 14, 2)) {
21015 case NM_BEQC:
21016 check_nms(ctx);
21017 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21018 break;
21019 case NM_P_BR3A:
21020 s = sextract32(ctx->opcode, 0, 1) << 14 |
21021 extract32(ctx->opcode, 1, 13) << 1;
21022 check_cp1_enabled(ctx);
21023 switch (extract32(ctx->opcode, 16, 5)) {
21024 case NM_BC1EQZC:
21025 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21026 break;
21027 case NM_BC1NEZC:
21028 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21029 break;
21030 case NM_BPOSGE32C:
21031 check_dsp_r3(ctx);
21033 int32_t imm = extract32(ctx->opcode, 1, 13) |
21034 extract32(ctx->opcode, 0, 1) << 13;
21036 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21037 imm);
21039 break;
21040 default:
21041 generate_exception_end(ctx, EXCP_RI);
21042 break;
21044 break;
21045 case NM_BGEC:
21046 if (rs == rt) {
21047 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21048 } else {
21049 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21051 break;
21052 case NM_BGEUC:
21053 if (rs == rt || rt == 0) {
21054 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21055 } else if (rs == 0) {
21056 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21057 } else {
21058 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21060 break;
21063 break;
21064 case NM_P_BR2:
21066 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21067 extract32(ctx->opcode, 1, 13) << 1;
21068 switch (extract32(ctx->opcode, 14, 2)) {
21069 case NM_BNEC:
21070 check_nms(ctx);
21071 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21072 break;
21073 case NM_BLTC:
21074 if (rs != 0 && rt != 0 && rs == rt) {
21075 /* NOP */
21076 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21077 } else {
21078 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21080 break;
21081 case NM_BLTUC:
21082 if (rs == 0 || rs == rt) {
21083 /* NOP */
21084 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21085 } else {
21086 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21088 break;
21089 default:
21090 generate_exception_end(ctx, EXCP_RI);
21091 break;
21094 break;
21095 case NM_P_BRI:
21097 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21098 extract32(ctx->opcode, 1, 10) << 1;
21099 uint32_t u = extract32(ctx->opcode, 11, 7);
21101 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21102 rt, u, s);
21104 break;
21105 default:
21106 generate_exception_end(ctx, EXCP_RI);
21107 break;
21109 return 4;
21112 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21114 uint32_t op;
21115 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD(ctx->opcode));
21116 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21117 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS1(ctx->opcode));
21118 int offset;
21119 int imm;
21121 /* make sure instructions are on a halfword boundary */
21122 if (ctx->base.pc_next & 0x1) {
21123 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21124 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21125 tcg_temp_free(tmp);
21126 generate_exception_end(ctx, EXCP_AdEL);
21127 return 2;
21130 op = extract32(ctx->opcode, 10, 6);
21131 switch (op) {
21132 case NM_P16_MV:
21133 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21134 if (rt != 0) {
21135 /* MOVE */
21136 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21137 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21138 } else {
21139 /* P16.RI */
21140 switch (extract32(ctx->opcode, 3, 2)) {
21141 case NM_P16_SYSCALL:
21142 if (extract32(ctx->opcode, 2, 1) == 0) {
21143 generate_exception_end(ctx, EXCP_SYSCALL);
21144 } else {
21145 generate_exception_end(ctx, EXCP_RI);
21147 break;
21148 case NM_BREAK16:
21149 generate_exception_end(ctx, EXCP_BREAK);
21150 break;
21151 case NM_SDBBP16:
21152 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21153 gen_helper_do_semihosting(cpu_env);
21154 } else {
21155 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21156 generate_exception_end(ctx, EXCP_RI);
21157 } else {
21158 generate_exception_end(ctx, EXCP_DBp);
21161 break;
21162 default:
21163 generate_exception_end(ctx, EXCP_RI);
21164 break;
21167 break;
21168 case NM_P16_SHIFT:
21170 int shift = extract32(ctx->opcode, 0, 3);
21171 uint32_t opc = 0;
21172 shift = (shift == 0) ? 8 : shift;
21174 switch (extract32(ctx->opcode, 3, 1)) {
21175 case NM_SLL16:
21176 opc = OPC_SLL;
21177 break;
21178 case NM_SRL16:
21179 opc = OPC_SRL;
21180 break;
21182 gen_shift_imm(ctx, opc, rt, rs, shift);
21184 break;
21185 case NM_P16C:
21186 switch (ctx->opcode & 1) {
21187 case NM_POOL16C_0:
21188 gen_pool16c_nanomips_insn(ctx);
21189 break;
21190 case NM_LWXS16:
21191 gen_ldxs(ctx, rt, rs, rd);
21192 break;
21194 break;
21195 case NM_P16_A1:
21196 switch (extract32(ctx->opcode, 6, 1)) {
21197 case NM_ADDIUR1SP:
21198 imm = extract32(ctx->opcode, 0, 6) << 2;
21199 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21200 break;
21201 default:
21202 generate_exception_end(ctx, EXCP_RI);
21203 break;
21205 break;
21206 case NM_P16_A2:
21207 switch (extract32(ctx->opcode, 3, 1)) {
21208 case NM_ADDIUR2:
21209 imm = extract32(ctx->opcode, 0, 3) << 2;
21210 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21211 break;
21212 case NM_P_ADDIURS5:
21213 rt = extract32(ctx->opcode, 5, 5);
21214 if (rt != 0) {
21215 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21216 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21217 (extract32(ctx->opcode, 0, 3));
21218 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21220 break;
21222 break;
21223 case NM_P16_ADDU:
21224 switch (ctx->opcode & 0x1) {
21225 case NM_ADDU16:
21226 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21227 break;
21228 case NM_SUBU16:
21229 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21230 break;
21232 break;
21233 case NM_P16_4X4:
21234 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21235 extract32(ctx->opcode, 5, 3);
21236 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21237 extract32(ctx->opcode, 0, 3);
21238 rt = decode_gpr_gpr4(rt);
21239 rs = decode_gpr_gpr4(rs);
21240 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21241 (extract32(ctx->opcode, 3, 1))) {
21242 case NM_ADDU4X4:
21243 check_nms(ctx);
21244 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21245 break;
21246 case NM_MUL4X4:
21247 check_nms(ctx);
21248 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21249 break;
21250 default:
21251 generate_exception_end(ctx, EXCP_RI);
21252 break;
21254 break;
21255 case NM_LI16:
21257 int imm = extract32(ctx->opcode, 0, 7);
21258 imm = (imm == 0x7f ? -1 : imm);
21259 if (rt != 0) {
21260 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21263 break;
21264 case NM_ANDI16:
21266 uint32_t u = extract32(ctx->opcode, 0, 4);
21267 u = (u == 12) ? 0xff :
21268 (u == 13) ? 0xffff : u;
21269 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21271 break;
21272 case NM_P16_LB:
21273 offset = extract32(ctx->opcode, 0, 2);
21274 switch (extract32(ctx->opcode, 2, 2)) {
21275 case NM_LB16:
21276 gen_ld(ctx, OPC_LB, rt, rs, offset);
21277 break;
21278 case NM_SB16:
21279 rt = decode_gpr_gpr3_src_store(
21280 NANOMIPS_EXTRACT_RD(ctx->opcode));
21281 gen_st(ctx, OPC_SB, rt, rs, offset);
21282 break;
21283 case NM_LBU16:
21284 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21285 break;
21286 default:
21287 generate_exception_end(ctx, EXCP_RI);
21288 break;
21290 break;
21291 case NM_P16_LH:
21292 offset = extract32(ctx->opcode, 1, 2) << 1;
21293 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21294 case NM_LH16:
21295 gen_ld(ctx, OPC_LH, rt, rs, offset);
21296 break;
21297 case NM_SH16:
21298 rt = decode_gpr_gpr3_src_store(
21299 NANOMIPS_EXTRACT_RD(ctx->opcode));
21300 gen_st(ctx, OPC_SH, rt, rs, offset);
21301 break;
21302 case NM_LHU16:
21303 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21304 break;
21305 default:
21306 generate_exception_end(ctx, EXCP_RI);
21307 break;
21309 break;
21310 case NM_LW16:
21311 offset = extract32(ctx->opcode, 0, 4) << 2;
21312 gen_ld(ctx, OPC_LW, rt, rs, offset);
21313 break;
21314 case NM_LWSP16:
21315 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21316 offset = extract32(ctx->opcode, 0, 5) << 2;
21317 gen_ld(ctx, OPC_LW, rt, 29, offset);
21318 break;
21319 case NM_LW4X4:
21320 check_nms(ctx);
21321 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21322 extract32(ctx->opcode, 5, 3);
21323 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21324 extract32(ctx->opcode, 0, 3);
21325 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21326 (extract32(ctx->opcode, 8, 1) << 2);
21327 rt = decode_gpr_gpr4(rt);
21328 rs = decode_gpr_gpr4(rs);
21329 gen_ld(ctx, OPC_LW, rt, rs, offset);
21330 break;
21331 case NM_SW4X4:
21332 check_nms(ctx);
21333 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21334 extract32(ctx->opcode, 5, 3);
21335 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21336 extract32(ctx->opcode, 0, 3);
21337 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21338 (extract32(ctx->opcode, 8, 1) << 2);
21339 rt = decode_gpr_gpr4_zero(rt);
21340 rs = decode_gpr_gpr4(rs);
21341 gen_st(ctx, OPC_SW, rt, rs, offset);
21342 break;
21343 case NM_LWGP16:
21344 offset = extract32(ctx->opcode, 0, 7) << 2;
21345 gen_ld(ctx, OPC_LW, rt, 28, offset);
21346 break;
21347 case NM_SWSP16:
21348 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21349 offset = extract32(ctx->opcode, 0, 5) << 2;
21350 gen_st(ctx, OPC_SW, rt, 29, offset);
21351 break;
21352 case NM_SW16:
21353 rt = decode_gpr_gpr3_src_store(
21354 NANOMIPS_EXTRACT_RD(ctx->opcode));
21355 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS(ctx->opcode));
21356 offset = extract32(ctx->opcode, 0, 4) << 2;
21357 gen_st(ctx, OPC_SW, rt, rs, offset);
21358 break;
21359 case NM_SWGP16:
21360 rt = decode_gpr_gpr3_src_store(
21361 NANOMIPS_EXTRACT_RD(ctx->opcode));
21362 offset = extract32(ctx->opcode, 0, 7) << 2;
21363 gen_st(ctx, OPC_SW, rt, 28, offset);
21364 break;
21365 case NM_BC16:
21366 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21367 (sextract32(ctx->opcode, 0, 1) << 10) |
21368 (extract32(ctx->opcode, 1, 9) << 1));
21369 break;
21370 case NM_BALC16:
21371 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21372 (sextract32(ctx->opcode, 0, 1) << 10) |
21373 (extract32(ctx->opcode, 1, 9) << 1));
21374 break;
21375 case NM_BEQZC16:
21376 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21377 (sextract32(ctx->opcode, 0, 1) << 7) |
21378 (extract32(ctx->opcode, 1, 6) << 1));
21379 break;
21380 case NM_BNEZC16:
21381 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21382 (sextract32(ctx->opcode, 0, 1) << 7) |
21383 (extract32(ctx->opcode, 1, 6) << 1));
21384 break;
21385 case NM_P16_BR:
21386 switch (ctx->opcode & 0xf) {
21387 case 0:
21388 /* P16.JRC */
21389 switch (extract32(ctx->opcode, 4, 1)) {
21390 case NM_JRC:
21391 gen_compute_branch_nm(ctx, OPC_JR, 2,
21392 extract32(ctx->opcode, 5, 5), 0, 0);
21393 break;
21394 case NM_JALRC16:
21395 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21396 extract32(ctx->opcode, 5, 5), 31, 0);
21397 break;
21399 break;
21400 default:
21402 /* P16.BRI */
21403 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21404 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21405 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21406 extract32(ctx->opcode, 0, 4) << 1);
21408 break;
21410 break;
21411 case NM_P16_SR:
21413 int count = extract32(ctx->opcode, 0, 4);
21414 int u = extract32(ctx->opcode, 4, 4) << 4;
21416 rt = 30 + extract32(ctx->opcode, 9, 1);
21417 switch (extract32(ctx->opcode, 8, 1)) {
21418 case NM_SAVE16:
21419 gen_save(ctx, rt, count, 0, u);
21420 break;
21421 case NM_RESTORE_JRC16:
21422 gen_restore(ctx, rt, count, 0, u);
21423 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21424 break;
21427 break;
21428 case NM_MOVEP:
21429 case NM_MOVEPREV:
21430 check_nms(ctx);
21432 static const int gpr2reg1[] = {4, 5, 6, 7};
21433 static const int gpr2reg2[] = {5, 6, 7, 8};
21434 int re;
21435 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21436 extract32(ctx->opcode, 8, 1);
21437 int r1 = gpr2reg1[rd2];
21438 int r2 = gpr2reg2[rd2];
21439 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21440 extract32(ctx->opcode, 0, 3);
21441 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21442 extract32(ctx->opcode, 5, 3);
21443 TCGv t0 = tcg_temp_new();
21444 TCGv t1 = tcg_temp_new();
21445 if (op == NM_MOVEP) {
21446 rd = r1;
21447 re = r2;
21448 rs = decode_gpr_gpr4_zero(r3);
21449 rt = decode_gpr_gpr4_zero(r4);
21450 } else {
21451 rd = decode_gpr_gpr4(r3);
21452 re = decode_gpr_gpr4(r4);
21453 rs = r1;
21454 rt = r2;
21456 gen_load_gpr(t0, rs);
21457 gen_load_gpr(t1, rt);
21458 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21459 tcg_gen_mov_tl(cpu_gpr[re], t1);
21460 tcg_temp_free(t0);
21461 tcg_temp_free(t1);
21463 break;
21464 default:
21465 return decode_nanomips_32_48_opc(env, ctx);
21468 return 2;
21472 /* SmartMIPS extension to MIPS32 */
21474 #if defined(TARGET_MIPS64)
21476 /* MDMX extension to MIPS64 */
21478 #endif
21480 /* MIPSDSP functions. */
21481 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21482 int rd, int base, int offset)
21484 TCGv t0;
21486 check_dsp(ctx);
21487 t0 = tcg_temp_new();
21489 if (base == 0) {
21490 gen_load_gpr(t0, offset);
21491 } else if (offset == 0) {
21492 gen_load_gpr(t0, base);
21493 } else {
21494 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21497 switch (opc) {
21498 case OPC_LBUX:
21499 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21500 gen_store_gpr(t0, rd);
21501 break;
21502 case OPC_LHX:
21503 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21504 gen_store_gpr(t0, rd);
21505 break;
21506 case OPC_LWX:
21507 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21508 gen_store_gpr(t0, rd);
21509 break;
21510 #if defined(TARGET_MIPS64)
21511 case OPC_LDX:
21512 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21513 gen_store_gpr(t0, rd);
21514 break;
21515 #endif
21517 tcg_temp_free(t0);
21520 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21521 int ret, int v1, int v2)
21523 TCGv v1_t;
21524 TCGv v2_t;
21526 if (ret == 0) {
21527 /* Treat as NOP. */
21528 return;
21531 v1_t = tcg_temp_new();
21532 v2_t = tcg_temp_new();
21534 gen_load_gpr(v1_t, v1);
21535 gen_load_gpr(v2_t, v2);
21537 switch (op1) {
21538 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21539 case OPC_MULT_G_2E:
21540 check_dsp_r2(ctx);
21541 switch (op2) {
21542 case OPC_ADDUH_QB:
21543 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21544 break;
21545 case OPC_ADDUH_R_QB:
21546 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21547 break;
21548 case OPC_ADDQH_PH:
21549 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21550 break;
21551 case OPC_ADDQH_R_PH:
21552 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21553 break;
21554 case OPC_ADDQH_W:
21555 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21556 break;
21557 case OPC_ADDQH_R_W:
21558 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21559 break;
21560 case OPC_SUBUH_QB:
21561 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21562 break;
21563 case OPC_SUBUH_R_QB:
21564 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21565 break;
21566 case OPC_SUBQH_PH:
21567 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21568 break;
21569 case OPC_SUBQH_R_PH:
21570 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21571 break;
21572 case OPC_SUBQH_W:
21573 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21574 break;
21575 case OPC_SUBQH_R_W:
21576 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21577 break;
21579 break;
21580 case OPC_ABSQ_S_PH_DSP:
21581 switch (op2) {
21582 case OPC_ABSQ_S_QB:
21583 check_dsp_r2(ctx);
21584 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21585 break;
21586 case OPC_ABSQ_S_PH:
21587 check_dsp(ctx);
21588 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21589 break;
21590 case OPC_ABSQ_S_W:
21591 check_dsp(ctx);
21592 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21593 break;
21594 case OPC_PRECEQ_W_PHL:
21595 check_dsp(ctx);
21596 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21597 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21598 break;
21599 case OPC_PRECEQ_W_PHR:
21600 check_dsp(ctx);
21601 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21602 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21603 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21604 break;
21605 case OPC_PRECEQU_PH_QBL:
21606 check_dsp(ctx);
21607 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21608 break;
21609 case OPC_PRECEQU_PH_QBR:
21610 check_dsp(ctx);
21611 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21612 break;
21613 case OPC_PRECEQU_PH_QBLA:
21614 check_dsp(ctx);
21615 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21616 break;
21617 case OPC_PRECEQU_PH_QBRA:
21618 check_dsp(ctx);
21619 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21620 break;
21621 case OPC_PRECEU_PH_QBL:
21622 check_dsp(ctx);
21623 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21624 break;
21625 case OPC_PRECEU_PH_QBR:
21626 check_dsp(ctx);
21627 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21628 break;
21629 case OPC_PRECEU_PH_QBLA:
21630 check_dsp(ctx);
21631 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21632 break;
21633 case OPC_PRECEU_PH_QBRA:
21634 check_dsp(ctx);
21635 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21636 break;
21638 break;
21639 case OPC_ADDU_QB_DSP:
21640 switch (op2) {
21641 case OPC_ADDQ_PH:
21642 check_dsp(ctx);
21643 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21644 break;
21645 case OPC_ADDQ_S_PH:
21646 check_dsp(ctx);
21647 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21648 break;
21649 case OPC_ADDQ_S_W:
21650 check_dsp(ctx);
21651 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21652 break;
21653 case OPC_ADDU_QB:
21654 check_dsp(ctx);
21655 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21656 break;
21657 case OPC_ADDU_S_QB:
21658 check_dsp(ctx);
21659 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21660 break;
21661 case OPC_ADDU_PH:
21662 check_dsp_r2(ctx);
21663 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21664 break;
21665 case OPC_ADDU_S_PH:
21666 check_dsp_r2(ctx);
21667 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21668 break;
21669 case OPC_SUBQ_PH:
21670 check_dsp(ctx);
21671 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21672 break;
21673 case OPC_SUBQ_S_PH:
21674 check_dsp(ctx);
21675 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21676 break;
21677 case OPC_SUBQ_S_W:
21678 check_dsp(ctx);
21679 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21680 break;
21681 case OPC_SUBU_QB:
21682 check_dsp(ctx);
21683 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21684 break;
21685 case OPC_SUBU_S_QB:
21686 check_dsp(ctx);
21687 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21688 break;
21689 case OPC_SUBU_PH:
21690 check_dsp_r2(ctx);
21691 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21692 break;
21693 case OPC_SUBU_S_PH:
21694 check_dsp_r2(ctx);
21695 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21696 break;
21697 case OPC_ADDSC:
21698 check_dsp(ctx);
21699 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21700 break;
21701 case OPC_ADDWC:
21702 check_dsp(ctx);
21703 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21704 break;
21705 case OPC_MODSUB:
21706 check_dsp(ctx);
21707 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21708 break;
21709 case OPC_RADDU_W_QB:
21710 check_dsp(ctx);
21711 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21712 break;
21714 break;
21715 case OPC_CMPU_EQ_QB_DSP:
21716 switch (op2) {
21717 case OPC_PRECR_QB_PH:
21718 check_dsp_r2(ctx);
21719 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21720 break;
21721 case OPC_PRECRQ_QB_PH:
21722 check_dsp(ctx);
21723 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21724 break;
21725 case OPC_PRECR_SRA_PH_W:
21726 check_dsp_r2(ctx);
21728 TCGv_i32 sa_t = tcg_const_i32(v2);
21729 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21730 cpu_gpr[ret]);
21731 tcg_temp_free_i32(sa_t);
21732 break;
21734 case OPC_PRECR_SRA_R_PH_W:
21735 check_dsp_r2(ctx);
21737 TCGv_i32 sa_t = tcg_const_i32(v2);
21738 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21739 cpu_gpr[ret]);
21740 tcg_temp_free_i32(sa_t);
21741 break;
21743 case OPC_PRECRQ_PH_W:
21744 check_dsp(ctx);
21745 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21746 break;
21747 case OPC_PRECRQ_RS_PH_W:
21748 check_dsp(ctx);
21749 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21750 break;
21751 case OPC_PRECRQU_S_QB_PH:
21752 check_dsp(ctx);
21753 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21754 break;
21756 break;
21757 #ifdef TARGET_MIPS64
21758 case OPC_ABSQ_S_QH_DSP:
21759 switch (op2) {
21760 case OPC_PRECEQ_L_PWL:
21761 check_dsp(ctx);
21762 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21763 break;
21764 case OPC_PRECEQ_L_PWR:
21765 check_dsp(ctx);
21766 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21767 break;
21768 case OPC_PRECEQ_PW_QHL:
21769 check_dsp(ctx);
21770 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21771 break;
21772 case OPC_PRECEQ_PW_QHR:
21773 check_dsp(ctx);
21774 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21775 break;
21776 case OPC_PRECEQ_PW_QHLA:
21777 check_dsp(ctx);
21778 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21779 break;
21780 case OPC_PRECEQ_PW_QHRA:
21781 check_dsp(ctx);
21782 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21783 break;
21784 case OPC_PRECEQU_QH_OBL:
21785 check_dsp(ctx);
21786 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21787 break;
21788 case OPC_PRECEQU_QH_OBR:
21789 check_dsp(ctx);
21790 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21791 break;
21792 case OPC_PRECEQU_QH_OBLA:
21793 check_dsp(ctx);
21794 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21795 break;
21796 case OPC_PRECEQU_QH_OBRA:
21797 check_dsp(ctx);
21798 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21799 break;
21800 case OPC_PRECEU_QH_OBL:
21801 check_dsp(ctx);
21802 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21803 break;
21804 case OPC_PRECEU_QH_OBR:
21805 check_dsp(ctx);
21806 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21807 break;
21808 case OPC_PRECEU_QH_OBLA:
21809 check_dsp(ctx);
21810 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21811 break;
21812 case OPC_PRECEU_QH_OBRA:
21813 check_dsp(ctx);
21814 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21815 break;
21816 case OPC_ABSQ_S_OB:
21817 check_dsp_r2(ctx);
21818 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21819 break;
21820 case OPC_ABSQ_S_PW:
21821 check_dsp(ctx);
21822 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21823 break;
21824 case OPC_ABSQ_S_QH:
21825 check_dsp(ctx);
21826 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21827 break;
21829 break;
21830 case OPC_ADDU_OB_DSP:
21831 switch (op2) {
21832 case OPC_RADDU_L_OB:
21833 check_dsp(ctx);
21834 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21835 break;
21836 case OPC_SUBQ_PW:
21837 check_dsp(ctx);
21838 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21839 break;
21840 case OPC_SUBQ_S_PW:
21841 check_dsp(ctx);
21842 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21843 break;
21844 case OPC_SUBQ_QH:
21845 check_dsp(ctx);
21846 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21847 break;
21848 case OPC_SUBQ_S_QH:
21849 check_dsp(ctx);
21850 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21851 break;
21852 case OPC_SUBU_OB:
21853 check_dsp(ctx);
21854 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21855 break;
21856 case OPC_SUBU_S_OB:
21857 check_dsp(ctx);
21858 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21859 break;
21860 case OPC_SUBU_QH:
21861 check_dsp_r2(ctx);
21862 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21863 break;
21864 case OPC_SUBU_S_QH:
21865 check_dsp_r2(ctx);
21866 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21867 break;
21868 case OPC_SUBUH_OB:
21869 check_dsp_r2(ctx);
21870 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21871 break;
21872 case OPC_SUBUH_R_OB:
21873 check_dsp_r2(ctx);
21874 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21875 break;
21876 case OPC_ADDQ_PW:
21877 check_dsp(ctx);
21878 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21879 break;
21880 case OPC_ADDQ_S_PW:
21881 check_dsp(ctx);
21882 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21883 break;
21884 case OPC_ADDQ_QH:
21885 check_dsp(ctx);
21886 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21887 break;
21888 case OPC_ADDQ_S_QH:
21889 check_dsp(ctx);
21890 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21891 break;
21892 case OPC_ADDU_OB:
21893 check_dsp(ctx);
21894 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21895 break;
21896 case OPC_ADDU_S_OB:
21897 check_dsp(ctx);
21898 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21899 break;
21900 case OPC_ADDU_QH:
21901 check_dsp_r2(ctx);
21902 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21903 break;
21904 case OPC_ADDU_S_QH:
21905 check_dsp_r2(ctx);
21906 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21907 break;
21908 case OPC_ADDUH_OB:
21909 check_dsp_r2(ctx);
21910 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
21911 break;
21912 case OPC_ADDUH_R_OB:
21913 check_dsp_r2(ctx);
21914 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21915 break;
21917 break;
21918 case OPC_CMPU_EQ_OB_DSP:
21919 switch (op2) {
21920 case OPC_PRECR_OB_QH:
21921 check_dsp_r2(ctx);
21922 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21923 break;
21924 case OPC_PRECR_SRA_QH_PW:
21925 check_dsp_r2(ctx);
21927 TCGv_i32 ret_t = tcg_const_i32(ret);
21928 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
21929 tcg_temp_free_i32(ret_t);
21930 break;
21932 case OPC_PRECR_SRA_R_QH_PW:
21933 check_dsp_r2(ctx);
21935 TCGv_i32 sa_v = tcg_const_i32(ret);
21936 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
21937 tcg_temp_free_i32(sa_v);
21938 break;
21940 case OPC_PRECRQ_OB_QH:
21941 check_dsp(ctx);
21942 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
21943 break;
21944 case OPC_PRECRQ_PW_L:
21945 check_dsp(ctx);
21946 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
21947 break;
21948 case OPC_PRECRQ_QH_PW:
21949 check_dsp(ctx);
21950 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
21951 break;
21952 case OPC_PRECRQ_RS_QH_PW:
21953 check_dsp(ctx);
21954 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21955 break;
21956 case OPC_PRECRQU_S_OB_QH:
21957 check_dsp(ctx);
21958 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21959 break;
21961 break;
21962 #endif
21965 tcg_temp_free(v1_t);
21966 tcg_temp_free(v2_t);
21969 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
21970 int ret, int v1, int v2)
21972 uint32_t op2;
21973 TCGv t0;
21974 TCGv v1_t;
21975 TCGv v2_t;
21977 if (ret == 0) {
21978 /* Treat as NOP. */
21979 return;
21982 t0 = tcg_temp_new();
21983 v1_t = tcg_temp_new();
21984 v2_t = tcg_temp_new();
21986 tcg_gen_movi_tl(t0, v1);
21987 gen_load_gpr(v1_t, v1);
21988 gen_load_gpr(v2_t, v2);
21990 switch (opc) {
21991 case OPC_SHLL_QB_DSP:
21993 op2 = MASK_SHLL_QB(ctx->opcode);
21994 switch (op2) {
21995 case OPC_SHLL_QB:
21996 check_dsp(ctx);
21997 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
21998 break;
21999 case OPC_SHLLV_QB:
22000 check_dsp(ctx);
22001 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22002 break;
22003 case OPC_SHLL_PH:
22004 check_dsp(ctx);
22005 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22006 break;
22007 case OPC_SHLLV_PH:
22008 check_dsp(ctx);
22009 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22010 break;
22011 case OPC_SHLL_S_PH:
22012 check_dsp(ctx);
22013 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22014 break;
22015 case OPC_SHLLV_S_PH:
22016 check_dsp(ctx);
22017 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22018 break;
22019 case OPC_SHLL_S_W:
22020 check_dsp(ctx);
22021 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22022 break;
22023 case OPC_SHLLV_S_W:
22024 check_dsp(ctx);
22025 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22026 break;
22027 case OPC_SHRL_QB:
22028 check_dsp(ctx);
22029 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22030 break;
22031 case OPC_SHRLV_QB:
22032 check_dsp(ctx);
22033 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22034 break;
22035 case OPC_SHRL_PH:
22036 check_dsp_r2(ctx);
22037 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22038 break;
22039 case OPC_SHRLV_PH:
22040 check_dsp_r2(ctx);
22041 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22042 break;
22043 case OPC_SHRA_QB:
22044 check_dsp_r2(ctx);
22045 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22046 break;
22047 case OPC_SHRA_R_QB:
22048 check_dsp_r2(ctx);
22049 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22050 break;
22051 case OPC_SHRAV_QB:
22052 check_dsp_r2(ctx);
22053 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22054 break;
22055 case OPC_SHRAV_R_QB:
22056 check_dsp_r2(ctx);
22057 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22058 break;
22059 case OPC_SHRA_PH:
22060 check_dsp(ctx);
22061 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22062 break;
22063 case OPC_SHRA_R_PH:
22064 check_dsp(ctx);
22065 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22066 break;
22067 case OPC_SHRAV_PH:
22068 check_dsp(ctx);
22069 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22070 break;
22071 case OPC_SHRAV_R_PH:
22072 check_dsp(ctx);
22073 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22074 break;
22075 case OPC_SHRA_R_W:
22076 check_dsp(ctx);
22077 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22078 break;
22079 case OPC_SHRAV_R_W:
22080 check_dsp(ctx);
22081 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22082 break;
22083 default: /* Invalid */
22084 MIPS_INVAL("MASK SHLL.QB");
22085 generate_exception_end(ctx, EXCP_RI);
22086 break;
22088 break;
22090 #ifdef TARGET_MIPS64
22091 case OPC_SHLL_OB_DSP:
22092 op2 = MASK_SHLL_OB(ctx->opcode);
22093 switch (op2) {
22094 case OPC_SHLL_PW:
22095 check_dsp(ctx);
22096 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22097 break;
22098 case OPC_SHLLV_PW:
22099 check_dsp(ctx);
22100 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22101 break;
22102 case OPC_SHLL_S_PW:
22103 check_dsp(ctx);
22104 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22105 break;
22106 case OPC_SHLLV_S_PW:
22107 check_dsp(ctx);
22108 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22109 break;
22110 case OPC_SHLL_OB:
22111 check_dsp(ctx);
22112 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22113 break;
22114 case OPC_SHLLV_OB:
22115 check_dsp(ctx);
22116 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22117 break;
22118 case OPC_SHLL_QH:
22119 check_dsp(ctx);
22120 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22121 break;
22122 case OPC_SHLLV_QH:
22123 check_dsp(ctx);
22124 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22125 break;
22126 case OPC_SHLL_S_QH:
22127 check_dsp(ctx);
22128 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22129 break;
22130 case OPC_SHLLV_S_QH:
22131 check_dsp(ctx);
22132 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22133 break;
22134 case OPC_SHRA_OB:
22135 check_dsp_r2(ctx);
22136 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22137 break;
22138 case OPC_SHRAV_OB:
22139 check_dsp_r2(ctx);
22140 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22141 break;
22142 case OPC_SHRA_R_OB:
22143 check_dsp_r2(ctx);
22144 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22145 break;
22146 case OPC_SHRAV_R_OB:
22147 check_dsp_r2(ctx);
22148 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22149 break;
22150 case OPC_SHRA_PW:
22151 check_dsp(ctx);
22152 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22153 break;
22154 case OPC_SHRAV_PW:
22155 check_dsp(ctx);
22156 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22157 break;
22158 case OPC_SHRA_R_PW:
22159 check_dsp(ctx);
22160 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22161 break;
22162 case OPC_SHRAV_R_PW:
22163 check_dsp(ctx);
22164 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22165 break;
22166 case OPC_SHRA_QH:
22167 check_dsp(ctx);
22168 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22169 break;
22170 case OPC_SHRAV_QH:
22171 check_dsp(ctx);
22172 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22173 break;
22174 case OPC_SHRA_R_QH:
22175 check_dsp(ctx);
22176 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22177 break;
22178 case OPC_SHRAV_R_QH:
22179 check_dsp(ctx);
22180 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22181 break;
22182 case OPC_SHRL_OB:
22183 check_dsp(ctx);
22184 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22185 break;
22186 case OPC_SHRLV_OB:
22187 check_dsp(ctx);
22188 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22189 break;
22190 case OPC_SHRL_QH:
22191 check_dsp_r2(ctx);
22192 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22193 break;
22194 case OPC_SHRLV_QH:
22195 check_dsp_r2(ctx);
22196 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22197 break;
22198 default: /* Invalid */
22199 MIPS_INVAL("MASK SHLL.OB");
22200 generate_exception_end(ctx, EXCP_RI);
22201 break;
22203 break;
22204 #endif
22207 tcg_temp_free(t0);
22208 tcg_temp_free(v1_t);
22209 tcg_temp_free(v2_t);
22212 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22213 int ret, int v1, int v2, int check_ret)
22215 TCGv_i32 t0;
22216 TCGv v1_t;
22217 TCGv v2_t;
22219 if ((ret == 0) && (check_ret == 1)) {
22220 /* Treat as NOP. */
22221 return;
22224 t0 = tcg_temp_new_i32();
22225 v1_t = tcg_temp_new();
22226 v2_t = tcg_temp_new();
22228 tcg_gen_movi_i32(t0, ret);
22229 gen_load_gpr(v1_t, v1);
22230 gen_load_gpr(v2_t, v2);
22232 switch (op1) {
22233 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22234 * the same mask and op1. */
22235 case OPC_MULT_G_2E:
22236 check_dsp_r2(ctx);
22237 switch (op2) {
22238 case OPC_MUL_PH:
22239 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22240 break;
22241 case OPC_MUL_S_PH:
22242 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22243 break;
22244 case OPC_MULQ_S_W:
22245 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22246 break;
22247 case OPC_MULQ_RS_W:
22248 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22249 break;
22251 break;
22252 case OPC_DPA_W_PH_DSP:
22253 switch (op2) {
22254 case OPC_DPAU_H_QBL:
22255 check_dsp(ctx);
22256 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22257 break;
22258 case OPC_DPAU_H_QBR:
22259 check_dsp(ctx);
22260 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22261 break;
22262 case OPC_DPSU_H_QBL:
22263 check_dsp(ctx);
22264 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22265 break;
22266 case OPC_DPSU_H_QBR:
22267 check_dsp(ctx);
22268 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22269 break;
22270 case OPC_DPA_W_PH:
22271 check_dsp_r2(ctx);
22272 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22273 break;
22274 case OPC_DPAX_W_PH:
22275 check_dsp_r2(ctx);
22276 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22277 break;
22278 case OPC_DPAQ_S_W_PH:
22279 check_dsp(ctx);
22280 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22281 break;
22282 case OPC_DPAQX_S_W_PH:
22283 check_dsp_r2(ctx);
22284 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22285 break;
22286 case OPC_DPAQX_SA_W_PH:
22287 check_dsp_r2(ctx);
22288 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22289 break;
22290 case OPC_DPS_W_PH:
22291 check_dsp_r2(ctx);
22292 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22293 break;
22294 case OPC_DPSX_W_PH:
22295 check_dsp_r2(ctx);
22296 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22297 break;
22298 case OPC_DPSQ_S_W_PH:
22299 check_dsp(ctx);
22300 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22301 break;
22302 case OPC_DPSQX_S_W_PH:
22303 check_dsp_r2(ctx);
22304 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22305 break;
22306 case OPC_DPSQX_SA_W_PH:
22307 check_dsp_r2(ctx);
22308 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22309 break;
22310 case OPC_MULSAQ_S_W_PH:
22311 check_dsp(ctx);
22312 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22313 break;
22314 case OPC_DPAQ_SA_L_W:
22315 check_dsp(ctx);
22316 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22317 break;
22318 case OPC_DPSQ_SA_L_W:
22319 check_dsp(ctx);
22320 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22321 break;
22322 case OPC_MAQ_S_W_PHL:
22323 check_dsp(ctx);
22324 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22325 break;
22326 case OPC_MAQ_S_W_PHR:
22327 check_dsp(ctx);
22328 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22329 break;
22330 case OPC_MAQ_SA_W_PHL:
22331 check_dsp(ctx);
22332 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22333 break;
22334 case OPC_MAQ_SA_W_PHR:
22335 check_dsp(ctx);
22336 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22337 break;
22338 case OPC_MULSA_W_PH:
22339 check_dsp_r2(ctx);
22340 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22341 break;
22343 break;
22344 #ifdef TARGET_MIPS64
22345 case OPC_DPAQ_W_QH_DSP:
22347 int ac = ret & 0x03;
22348 tcg_gen_movi_i32(t0, ac);
22350 switch (op2) {
22351 case OPC_DMADD:
22352 check_dsp(ctx);
22353 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22354 break;
22355 case OPC_DMADDU:
22356 check_dsp(ctx);
22357 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22358 break;
22359 case OPC_DMSUB:
22360 check_dsp(ctx);
22361 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22362 break;
22363 case OPC_DMSUBU:
22364 check_dsp(ctx);
22365 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22366 break;
22367 case OPC_DPA_W_QH:
22368 check_dsp_r2(ctx);
22369 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22370 break;
22371 case OPC_DPAQ_S_W_QH:
22372 check_dsp(ctx);
22373 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22374 break;
22375 case OPC_DPAQ_SA_L_PW:
22376 check_dsp(ctx);
22377 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22378 break;
22379 case OPC_DPAU_H_OBL:
22380 check_dsp(ctx);
22381 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22382 break;
22383 case OPC_DPAU_H_OBR:
22384 check_dsp(ctx);
22385 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22386 break;
22387 case OPC_DPS_W_QH:
22388 check_dsp_r2(ctx);
22389 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22390 break;
22391 case OPC_DPSQ_S_W_QH:
22392 check_dsp(ctx);
22393 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22394 break;
22395 case OPC_DPSQ_SA_L_PW:
22396 check_dsp(ctx);
22397 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22398 break;
22399 case OPC_DPSU_H_OBL:
22400 check_dsp(ctx);
22401 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22402 break;
22403 case OPC_DPSU_H_OBR:
22404 check_dsp(ctx);
22405 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22406 break;
22407 case OPC_MAQ_S_L_PWL:
22408 check_dsp(ctx);
22409 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22410 break;
22411 case OPC_MAQ_S_L_PWR:
22412 check_dsp(ctx);
22413 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22414 break;
22415 case OPC_MAQ_S_W_QHLL:
22416 check_dsp(ctx);
22417 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22418 break;
22419 case OPC_MAQ_SA_W_QHLL:
22420 check_dsp(ctx);
22421 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22422 break;
22423 case OPC_MAQ_S_W_QHLR:
22424 check_dsp(ctx);
22425 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22426 break;
22427 case OPC_MAQ_SA_W_QHLR:
22428 check_dsp(ctx);
22429 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22430 break;
22431 case OPC_MAQ_S_W_QHRL:
22432 check_dsp(ctx);
22433 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22434 break;
22435 case OPC_MAQ_SA_W_QHRL:
22436 check_dsp(ctx);
22437 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22438 break;
22439 case OPC_MAQ_S_W_QHRR:
22440 check_dsp(ctx);
22441 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22442 break;
22443 case OPC_MAQ_SA_W_QHRR:
22444 check_dsp(ctx);
22445 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22446 break;
22447 case OPC_MULSAQ_S_L_PW:
22448 check_dsp(ctx);
22449 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22450 break;
22451 case OPC_MULSAQ_S_W_QH:
22452 check_dsp(ctx);
22453 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22454 break;
22457 break;
22458 #endif
22459 case OPC_ADDU_QB_DSP:
22460 switch (op2) {
22461 case OPC_MULEU_S_PH_QBL:
22462 check_dsp(ctx);
22463 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22464 break;
22465 case OPC_MULEU_S_PH_QBR:
22466 check_dsp(ctx);
22467 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22468 break;
22469 case OPC_MULQ_RS_PH:
22470 check_dsp(ctx);
22471 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22472 break;
22473 case OPC_MULEQ_S_W_PHL:
22474 check_dsp(ctx);
22475 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22476 break;
22477 case OPC_MULEQ_S_W_PHR:
22478 check_dsp(ctx);
22479 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22480 break;
22481 case OPC_MULQ_S_PH:
22482 check_dsp_r2(ctx);
22483 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22484 break;
22486 break;
22487 #ifdef TARGET_MIPS64
22488 case OPC_ADDU_OB_DSP:
22489 switch (op2) {
22490 case OPC_MULEQ_S_PW_QHL:
22491 check_dsp(ctx);
22492 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22493 break;
22494 case OPC_MULEQ_S_PW_QHR:
22495 check_dsp(ctx);
22496 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22497 break;
22498 case OPC_MULEU_S_QH_OBL:
22499 check_dsp(ctx);
22500 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22501 break;
22502 case OPC_MULEU_S_QH_OBR:
22503 check_dsp(ctx);
22504 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22505 break;
22506 case OPC_MULQ_RS_QH:
22507 check_dsp(ctx);
22508 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22509 break;
22511 break;
22512 #endif
22515 tcg_temp_free_i32(t0);
22516 tcg_temp_free(v1_t);
22517 tcg_temp_free(v2_t);
22520 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22521 int ret, int val)
22523 int16_t imm;
22524 TCGv t0;
22525 TCGv val_t;
22527 if (ret == 0) {
22528 /* Treat as NOP. */
22529 return;
22532 t0 = tcg_temp_new();
22533 val_t = tcg_temp_new();
22534 gen_load_gpr(val_t, val);
22536 switch (op1) {
22537 case OPC_ABSQ_S_PH_DSP:
22538 switch (op2) {
22539 case OPC_BITREV:
22540 check_dsp(ctx);
22541 gen_helper_bitrev(cpu_gpr[ret], val_t);
22542 break;
22543 case OPC_REPL_QB:
22544 check_dsp(ctx);
22546 target_long result;
22547 imm = (ctx->opcode >> 16) & 0xFF;
22548 result = (uint32_t)imm << 24 |
22549 (uint32_t)imm << 16 |
22550 (uint32_t)imm << 8 |
22551 (uint32_t)imm;
22552 result = (int32_t)result;
22553 tcg_gen_movi_tl(cpu_gpr[ret], result);
22555 break;
22556 case OPC_REPLV_QB:
22557 check_dsp(ctx);
22558 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22559 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22560 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22561 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22562 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22563 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22564 break;
22565 case OPC_REPL_PH:
22566 check_dsp(ctx);
22568 imm = (ctx->opcode >> 16) & 0x03FF;
22569 imm = (int16_t)(imm << 6) >> 6;
22570 tcg_gen_movi_tl(cpu_gpr[ret], \
22571 (target_long)((int32_t)imm << 16 | \
22572 (uint16_t)imm));
22574 break;
22575 case OPC_REPLV_PH:
22576 check_dsp(ctx);
22577 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22578 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22579 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22580 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22581 break;
22583 break;
22584 #ifdef TARGET_MIPS64
22585 case OPC_ABSQ_S_QH_DSP:
22586 switch (op2) {
22587 case OPC_REPL_OB:
22588 check_dsp(ctx);
22590 target_long temp;
22592 imm = (ctx->opcode >> 16) & 0xFF;
22593 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22594 temp = (temp << 16) | temp;
22595 temp = (temp << 32) | temp;
22596 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22597 break;
22599 case OPC_REPL_PW:
22600 check_dsp(ctx);
22602 target_long temp;
22604 imm = (ctx->opcode >> 16) & 0x03FF;
22605 imm = (int16_t)(imm << 6) >> 6;
22606 temp = ((target_long)imm << 32) \
22607 | ((target_long)imm & 0xFFFFFFFF);
22608 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22609 break;
22611 case OPC_REPL_QH:
22612 check_dsp(ctx);
22614 target_long temp;
22616 imm = (ctx->opcode >> 16) & 0x03FF;
22617 imm = (int16_t)(imm << 6) >> 6;
22619 temp = ((uint64_t)(uint16_t)imm << 48) |
22620 ((uint64_t)(uint16_t)imm << 32) |
22621 ((uint64_t)(uint16_t)imm << 16) |
22622 (uint64_t)(uint16_t)imm;
22623 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22624 break;
22626 case OPC_REPLV_OB:
22627 check_dsp(ctx);
22628 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22629 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22630 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22631 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22632 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22633 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22634 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22635 break;
22636 case OPC_REPLV_PW:
22637 check_dsp(ctx);
22638 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22639 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22640 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22641 break;
22642 case OPC_REPLV_QH:
22643 check_dsp(ctx);
22644 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22645 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22646 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22647 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22648 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22649 break;
22651 break;
22652 #endif
22654 tcg_temp_free(t0);
22655 tcg_temp_free(val_t);
22658 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22659 uint32_t op1, uint32_t op2,
22660 int ret, int v1, int v2, int check_ret)
22662 TCGv t1;
22663 TCGv v1_t;
22664 TCGv v2_t;
22666 if ((ret == 0) && (check_ret == 1)) {
22667 /* Treat as NOP. */
22668 return;
22671 t1 = tcg_temp_new();
22672 v1_t = tcg_temp_new();
22673 v2_t = tcg_temp_new();
22675 gen_load_gpr(v1_t, v1);
22676 gen_load_gpr(v2_t, v2);
22678 switch (op1) {
22679 case OPC_CMPU_EQ_QB_DSP:
22680 switch (op2) {
22681 case OPC_CMPU_EQ_QB:
22682 check_dsp(ctx);
22683 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22684 break;
22685 case OPC_CMPU_LT_QB:
22686 check_dsp(ctx);
22687 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22688 break;
22689 case OPC_CMPU_LE_QB:
22690 check_dsp(ctx);
22691 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22692 break;
22693 case OPC_CMPGU_EQ_QB:
22694 check_dsp(ctx);
22695 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22696 break;
22697 case OPC_CMPGU_LT_QB:
22698 check_dsp(ctx);
22699 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22700 break;
22701 case OPC_CMPGU_LE_QB:
22702 check_dsp(ctx);
22703 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22704 break;
22705 case OPC_CMPGDU_EQ_QB:
22706 check_dsp_r2(ctx);
22707 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22708 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22709 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22710 tcg_gen_shli_tl(t1, t1, 24);
22711 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22712 break;
22713 case OPC_CMPGDU_LT_QB:
22714 check_dsp_r2(ctx);
22715 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22716 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22717 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22718 tcg_gen_shli_tl(t1, t1, 24);
22719 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22720 break;
22721 case OPC_CMPGDU_LE_QB:
22722 check_dsp_r2(ctx);
22723 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22724 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22725 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22726 tcg_gen_shli_tl(t1, t1, 24);
22727 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22728 break;
22729 case OPC_CMP_EQ_PH:
22730 check_dsp(ctx);
22731 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22732 break;
22733 case OPC_CMP_LT_PH:
22734 check_dsp(ctx);
22735 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22736 break;
22737 case OPC_CMP_LE_PH:
22738 check_dsp(ctx);
22739 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22740 break;
22741 case OPC_PICK_QB:
22742 check_dsp(ctx);
22743 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22744 break;
22745 case OPC_PICK_PH:
22746 check_dsp(ctx);
22747 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22748 break;
22749 case OPC_PACKRL_PH:
22750 check_dsp(ctx);
22751 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22752 break;
22754 break;
22755 #ifdef TARGET_MIPS64
22756 case OPC_CMPU_EQ_OB_DSP:
22757 switch (op2) {
22758 case OPC_CMP_EQ_PW:
22759 check_dsp(ctx);
22760 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22761 break;
22762 case OPC_CMP_LT_PW:
22763 check_dsp(ctx);
22764 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22765 break;
22766 case OPC_CMP_LE_PW:
22767 check_dsp(ctx);
22768 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22769 break;
22770 case OPC_CMP_EQ_QH:
22771 check_dsp(ctx);
22772 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22773 break;
22774 case OPC_CMP_LT_QH:
22775 check_dsp(ctx);
22776 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22777 break;
22778 case OPC_CMP_LE_QH:
22779 check_dsp(ctx);
22780 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22781 break;
22782 case OPC_CMPGDU_EQ_OB:
22783 check_dsp_r2(ctx);
22784 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22785 break;
22786 case OPC_CMPGDU_LT_OB:
22787 check_dsp_r2(ctx);
22788 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22789 break;
22790 case OPC_CMPGDU_LE_OB:
22791 check_dsp_r2(ctx);
22792 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22793 break;
22794 case OPC_CMPGU_EQ_OB:
22795 check_dsp(ctx);
22796 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22797 break;
22798 case OPC_CMPGU_LT_OB:
22799 check_dsp(ctx);
22800 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22801 break;
22802 case OPC_CMPGU_LE_OB:
22803 check_dsp(ctx);
22804 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22805 break;
22806 case OPC_CMPU_EQ_OB:
22807 check_dsp(ctx);
22808 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22809 break;
22810 case OPC_CMPU_LT_OB:
22811 check_dsp(ctx);
22812 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22813 break;
22814 case OPC_CMPU_LE_OB:
22815 check_dsp(ctx);
22816 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22817 break;
22818 case OPC_PACKRL_PW:
22819 check_dsp(ctx);
22820 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22821 break;
22822 case OPC_PICK_OB:
22823 check_dsp(ctx);
22824 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22825 break;
22826 case OPC_PICK_PW:
22827 check_dsp(ctx);
22828 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22829 break;
22830 case OPC_PICK_QH:
22831 check_dsp(ctx);
22832 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22833 break;
22835 break;
22836 #endif
22839 tcg_temp_free(t1);
22840 tcg_temp_free(v1_t);
22841 tcg_temp_free(v2_t);
22844 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22845 uint32_t op1, int rt, int rs, int sa)
22847 TCGv t0;
22849 check_dsp_r2(ctx);
22851 if (rt == 0) {
22852 /* Treat as NOP. */
22853 return;
22856 t0 = tcg_temp_new();
22857 gen_load_gpr(t0, rs);
22859 switch (op1) {
22860 case OPC_APPEND_DSP:
22861 switch (MASK_APPEND(ctx->opcode)) {
22862 case OPC_APPEND:
22863 if (sa != 0) {
22864 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22866 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22867 break;
22868 case OPC_PREPEND:
22869 if (sa != 0) {
22870 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22871 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22872 tcg_gen_shli_tl(t0, t0, 32 - sa);
22873 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22875 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22876 break;
22877 case OPC_BALIGN:
22878 sa &= 3;
22879 if (sa != 0 && sa != 2) {
22880 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22881 tcg_gen_ext32u_tl(t0, t0);
22882 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22883 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22885 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22886 break;
22887 default: /* Invalid */
22888 MIPS_INVAL("MASK APPEND");
22889 generate_exception_end(ctx, EXCP_RI);
22890 break;
22892 break;
22893 #ifdef TARGET_MIPS64
22894 case OPC_DAPPEND_DSP:
22895 switch (MASK_DAPPEND(ctx->opcode)) {
22896 case OPC_DAPPEND:
22897 if (sa != 0) {
22898 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22900 break;
22901 case OPC_PREPENDD:
22902 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22903 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
22904 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
22905 break;
22906 case OPC_PREPENDW:
22907 if (sa != 0) {
22908 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22909 tcg_gen_shli_tl(t0, t0, 64 - sa);
22910 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22912 break;
22913 case OPC_DBALIGN:
22914 sa &= 7;
22915 if (sa != 0 && sa != 2 && sa != 4) {
22916 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22917 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
22918 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22920 break;
22921 default: /* Invalid */
22922 MIPS_INVAL("MASK DAPPEND");
22923 generate_exception_end(ctx, EXCP_RI);
22924 break;
22926 break;
22927 #endif
22929 tcg_temp_free(t0);
22932 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22933 int ret, int v1, int v2, int check_ret)
22936 TCGv t0;
22937 TCGv t1;
22938 TCGv v1_t;
22939 TCGv v2_t;
22940 int16_t imm;
22942 if ((ret == 0) && (check_ret == 1)) {
22943 /* Treat as NOP. */
22944 return;
22947 t0 = tcg_temp_new();
22948 t1 = tcg_temp_new();
22949 v1_t = tcg_temp_new();
22950 v2_t = tcg_temp_new();
22952 gen_load_gpr(v1_t, v1);
22953 gen_load_gpr(v2_t, v2);
22955 switch (op1) {
22956 case OPC_EXTR_W_DSP:
22957 check_dsp(ctx);
22958 switch (op2) {
22959 case OPC_EXTR_W:
22960 tcg_gen_movi_tl(t0, v2);
22961 tcg_gen_movi_tl(t1, v1);
22962 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
22963 break;
22964 case OPC_EXTR_R_W:
22965 tcg_gen_movi_tl(t0, v2);
22966 tcg_gen_movi_tl(t1, v1);
22967 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
22968 break;
22969 case OPC_EXTR_RS_W:
22970 tcg_gen_movi_tl(t0, v2);
22971 tcg_gen_movi_tl(t1, v1);
22972 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
22973 break;
22974 case OPC_EXTR_S_H:
22975 tcg_gen_movi_tl(t0, v2);
22976 tcg_gen_movi_tl(t1, v1);
22977 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
22978 break;
22979 case OPC_EXTRV_S_H:
22980 tcg_gen_movi_tl(t0, v2);
22981 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
22982 break;
22983 case OPC_EXTRV_W:
22984 tcg_gen_movi_tl(t0, v2);
22985 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22986 break;
22987 case OPC_EXTRV_R_W:
22988 tcg_gen_movi_tl(t0, v2);
22989 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22990 break;
22991 case OPC_EXTRV_RS_W:
22992 tcg_gen_movi_tl(t0, v2);
22993 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
22994 break;
22995 case OPC_EXTP:
22996 tcg_gen_movi_tl(t0, v2);
22997 tcg_gen_movi_tl(t1, v1);
22998 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
22999 break;
23000 case OPC_EXTPV:
23001 tcg_gen_movi_tl(t0, v2);
23002 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23003 break;
23004 case OPC_EXTPDP:
23005 tcg_gen_movi_tl(t0, v2);
23006 tcg_gen_movi_tl(t1, v1);
23007 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23008 break;
23009 case OPC_EXTPDPV:
23010 tcg_gen_movi_tl(t0, v2);
23011 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23012 break;
23013 case OPC_SHILO:
23014 imm = (ctx->opcode >> 20) & 0x3F;
23015 tcg_gen_movi_tl(t0, ret);
23016 tcg_gen_movi_tl(t1, imm);
23017 gen_helper_shilo(t0, t1, cpu_env);
23018 break;
23019 case OPC_SHILOV:
23020 tcg_gen_movi_tl(t0, ret);
23021 gen_helper_shilo(t0, v1_t, cpu_env);
23022 break;
23023 case OPC_MTHLIP:
23024 tcg_gen_movi_tl(t0, ret);
23025 gen_helper_mthlip(t0, v1_t, cpu_env);
23026 break;
23027 case OPC_WRDSP:
23028 imm = (ctx->opcode >> 11) & 0x3FF;
23029 tcg_gen_movi_tl(t0, imm);
23030 gen_helper_wrdsp(v1_t, t0, cpu_env);
23031 break;
23032 case OPC_RDDSP:
23033 imm = (ctx->opcode >> 16) & 0x03FF;
23034 tcg_gen_movi_tl(t0, imm);
23035 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23036 break;
23038 break;
23039 #ifdef TARGET_MIPS64
23040 case OPC_DEXTR_W_DSP:
23041 check_dsp(ctx);
23042 switch (op2) {
23043 case OPC_DMTHLIP:
23044 tcg_gen_movi_tl(t0, ret);
23045 gen_helper_dmthlip(v1_t, t0, cpu_env);
23046 break;
23047 case OPC_DSHILO:
23049 int shift = (ctx->opcode >> 19) & 0x7F;
23050 int ac = (ctx->opcode >> 11) & 0x03;
23051 tcg_gen_movi_tl(t0, shift);
23052 tcg_gen_movi_tl(t1, ac);
23053 gen_helper_dshilo(t0, t1, cpu_env);
23054 break;
23056 case OPC_DSHILOV:
23058 int ac = (ctx->opcode >> 11) & 0x03;
23059 tcg_gen_movi_tl(t0, ac);
23060 gen_helper_dshilo(v1_t, t0, cpu_env);
23061 break;
23063 case OPC_DEXTP:
23064 tcg_gen_movi_tl(t0, v2);
23065 tcg_gen_movi_tl(t1, v1);
23067 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23068 break;
23069 case OPC_DEXTPV:
23070 tcg_gen_movi_tl(t0, v2);
23071 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23072 break;
23073 case OPC_DEXTPDP:
23074 tcg_gen_movi_tl(t0, v2);
23075 tcg_gen_movi_tl(t1, v1);
23076 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23077 break;
23078 case OPC_DEXTPDPV:
23079 tcg_gen_movi_tl(t0, v2);
23080 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23081 break;
23082 case OPC_DEXTR_L:
23083 tcg_gen_movi_tl(t0, v2);
23084 tcg_gen_movi_tl(t1, v1);
23085 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23086 break;
23087 case OPC_DEXTR_R_L:
23088 tcg_gen_movi_tl(t0, v2);
23089 tcg_gen_movi_tl(t1, v1);
23090 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23091 break;
23092 case OPC_DEXTR_RS_L:
23093 tcg_gen_movi_tl(t0, v2);
23094 tcg_gen_movi_tl(t1, v1);
23095 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23096 break;
23097 case OPC_DEXTR_W:
23098 tcg_gen_movi_tl(t0, v2);
23099 tcg_gen_movi_tl(t1, v1);
23100 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23101 break;
23102 case OPC_DEXTR_R_W:
23103 tcg_gen_movi_tl(t0, v2);
23104 tcg_gen_movi_tl(t1, v1);
23105 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23106 break;
23107 case OPC_DEXTR_RS_W:
23108 tcg_gen_movi_tl(t0, v2);
23109 tcg_gen_movi_tl(t1, v1);
23110 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23111 break;
23112 case OPC_DEXTR_S_H:
23113 tcg_gen_movi_tl(t0, v2);
23114 tcg_gen_movi_tl(t1, v1);
23115 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23116 break;
23117 case OPC_DEXTRV_S_H:
23118 tcg_gen_movi_tl(t0, v2);
23119 tcg_gen_movi_tl(t1, v1);
23120 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23121 break;
23122 case OPC_DEXTRV_L:
23123 tcg_gen_movi_tl(t0, v2);
23124 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23125 break;
23126 case OPC_DEXTRV_R_L:
23127 tcg_gen_movi_tl(t0, v2);
23128 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23129 break;
23130 case OPC_DEXTRV_RS_L:
23131 tcg_gen_movi_tl(t0, v2);
23132 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23133 break;
23134 case OPC_DEXTRV_W:
23135 tcg_gen_movi_tl(t0, v2);
23136 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23137 break;
23138 case OPC_DEXTRV_R_W:
23139 tcg_gen_movi_tl(t0, v2);
23140 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23141 break;
23142 case OPC_DEXTRV_RS_W:
23143 tcg_gen_movi_tl(t0, v2);
23144 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23145 break;
23147 break;
23148 #endif
23151 tcg_temp_free(t0);
23152 tcg_temp_free(t1);
23153 tcg_temp_free(v1_t);
23154 tcg_temp_free(v2_t);
23157 /* End MIPSDSP functions. */
23159 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23161 int rs, rt, rd, sa;
23162 uint32_t op1, op2;
23164 rs = (ctx->opcode >> 21) & 0x1f;
23165 rt = (ctx->opcode >> 16) & 0x1f;
23166 rd = (ctx->opcode >> 11) & 0x1f;
23167 sa = (ctx->opcode >> 6) & 0x1f;
23169 op1 = MASK_SPECIAL(ctx->opcode);
23170 switch (op1) {
23171 case OPC_LSA:
23172 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23173 break;
23174 case OPC_MULT:
23175 case OPC_MULTU:
23176 case OPC_DIV:
23177 case OPC_DIVU:
23178 op2 = MASK_R6_MULDIV(ctx->opcode);
23179 switch (op2) {
23180 case R6_OPC_MUL:
23181 case R6_OPC_MUH:
23182 case R6_OPC_MULU:
23183 case R6_OPC_MUHU:
23184 case R6_OPC_DIV:
23185 case R6_OPC_MOD:
23186 case R6_OPC_DIVU:
23187 case R6_OPC_MODU:
23188 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23189 break;
23190 default:
23191 MIPS_INVAL("special_r6 muldiv");
23192 generate_exception_end(ctx, EXCP_RI);
23193 break;
23195 break;
23196 case OPC_SELEQZ:
23197 case OPC_SELNEZ:
23198 gen_cond_move(ctx, op1, rd, rs, rt);
23199 break;
23200 case R6_OPC_CLO:
23201 case R6_OPC_CLZ:
23202 if (rt == 0 && sa == 1) {
23203 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23204 We need additionally to check other fields */
23205 gen_cl(ctx, op1, rd, rs);
23206 } else {
23207 generate_exception_end(ctx, EXCP_RI);
23209 break;
23210 case R6_OPC_SDBBP:
23211 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23212 gen_helper_do_semihosting(cpu_env);
23213 } else {
23214 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23215 generate_exception_end(ctx, EXCP_RI);
23216 } else {
23217 generate_exception_end(ctx, EXCP_DBp);
23220 break;
23221 #if defined(TARGET_MIPS64)
23222 case OPC_DLSA:
23223 check_mips_64(ctx);
23224 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
23225 break;
23226 case R6_OPC_DCLO:
23227 case R6_OPC_DCLZ:
23228 if (rt == 0 && sa == 1) {
23229 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
23230 We need additionally to check other fields */
23231 check_mips_64(ctx);
23232 gen_cl(ctx, op1, rd, rs);
23233 } else {
23234 generate_exception_end(ctx, EXCP_RI);
23236 break;
23237 case OPC_DMULT:
23238 case OPC_DMULTU:
23239 case OPC_DDIV:
23240 case OPC_DDIVU:
23242 op2 = MASK_R6_MULDIV(ctx->opcode);
23243 switch (op2) {
23244 case R6_OPC_DMUL:
23245 case R6_OPC_DMUH:
23246 case R6_OPC_DMULU:
23247 case R6_OPC_DMUHU:
23248 case R6_OPC_DDIV:
23249 case R6_OPC_DMOD:
23250 case R6_OPC_DDIVU:
23251 case R6_OPC_DMODU:
23252 check_mips_64(ctx);
23253 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23254 break;
23255 default:
23256 MIPS_INVAL("special_r6 muldiv");
23257 generate_exception_end(ctx, EXCP_RI);
23258 break;
23260 break;
23261 #endif
23262 default: /* Invalid */
23263 MIPS_INVAL("special_r6");
23264 generate_exception_end(ctx, EXCP_RI);
23265 break;
23269 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23271 int rs, rt, rd, sa;
23272 uint32_t op1;
23274 rs = (ctx->opcode >> 21) & 0x1f;
23275 rt = (ctx->opcode >> 16) & 0x1f;
23276 rd = (ctx->opcode >> 11) & 0x1f;
23277 sa = (ctx->opcode >> 6) & 0x1f;
23279 op1 = MASK_SPECIAL(ctx->opcode);
23280 switch (op1) {
23281 case OPC_MOVN: /* Conditional move */
23282 case OPC_MOVZ:
23283 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
23284 INSN_LOONGSON2E | INSN_LOONGSON2F);
23285 gen_cond_move(ctx, op1, rd, rs, rt);
23286 break;
23287 case OPC_MFHI: /* Move from HI/LO */
23288 case OPC_MFLO:
23289 gen_HILO(ctx, op1, rs & 3, rd);
23290 break;
23291 case OPC_MTHI:
23292 case OPC_MTLO: /* Move to HI/LO */
23293 gen_HILO(ctx, op1, rd & 3, rs);
23294 break;
23295 case OPC_MOVCI:
23296 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
23297 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23298 check_cp1_enabled(ctx);
23299 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23300 (ctx->opcode >> 16) & 1);
23301 } else {
23302 generate_exception_err(ctx, EXCP_CpU, 1);
23304 break;
23305 case OPC_MULT:
23306 case OPC_MULTU:
23307 if (sa) {
23308 check_insn(ctx, INSN_VR54XX);
23309 op1 = MASK_MUL_VR54XX(ctx->opcode);
23310 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23311 } else {
23312 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23314 break;
23315 case OPC_DIV:
23316 case OPC_DIVU:
23317 gen_muldiv(ctx, op1, 0, rs, rt);
23318 break;
23319 #if defined(TARGET_MIPS64)
23320 case OPC_DMULT:
23321 case OPC_DMULTU:
23322 case OPC_DDIV:
23323 case OPC_DDIVU:
23324 check_insn(ctx, ISA_MIPS3);
23325 check_mips_64(ctx);
23326 gen_muldiv(ctx, op1, 0, rs, rt);
23327 break;
23328 #endif
23329 case OPC_JR:
23330 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23331 break;
23332 case OPC_SPIM:
23333 #ifdef MIPS_STRICT_STANDARD
23334 MIPS_INVAL("SPIM");
23335 generate_exception_end(ctx, EXCP_RI);
23336 #else
23337 /* Implemented as RI exception for now. */
23338 MIPS_INVAL("spim (unofficial)");
23339 generate_exception_end(ctx, EXCP_RI);
23340 #endif
23341 break;
23342 default: /* Invalid */
23343 MIPS_INVAL("special_legacy");
23344 generate_exception_end(ctx, EXCP_RI);
23345 break;
23349 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23351 int rs, rt, rd, sa;
23352 uint32_t op1;
23354 rs = (ctx->opcode >> 21) & 0x1f;
23355 rt = (ctx->opcode >> 16) & 0x1f;
23356 rd = (ctx->opcode >> 11) & 0x1f;
23357 sa = (ctx->opcode >> 6) & 0x1f;
23359 op1 = MASK_SPECIAL(ctx->opcode);
23360 switch (op1) {
23361 case OPC_SLL: /* Shift with immediate */
23362 if (sa == 5 && rd == 0 &&
23363 rs == 0 && rt == 0) { /* PAUSE */
23364 if ((ctx->insn_flags & ISA_MIPS32R6) &&
23365 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23366 generate_exception_end(ctx, EXCP_RI);
23367 break;
23370 /* Fallthrough */
23371 case OPC_SRA:
23372 gen_shift_imm(ctx, op1, rd, rt, sa);
23373 break;
23374 case OPC_SRL:
23375 switch ((ctx->opcode >> 21) & 0x1f) {
23376 case 1:
23377 /* rotr is decoded as srl on non-R2 CPUs */
23378 if (ctx->insn_flags & ISA_MIPS32R2) {
23379 op1 = OPC_ROTR;
23381 /* Fallthrough */
23382 case 0:
23383 gen_shift_imm(ctx, op1, rd, rt, sa);
23384 break;
23385 default:
23386 generate_exception_end(ctx, EXCP_RI);
23387 break;
23389 break;
23390 case OPC_ADD:
23391 case OPC_ADDU:
23392 case OPC_SUB:
23393 case OPC_SUBU:
23394 gen_arith(ctx, op1, rd, rs, rt);
23395 break;
23396 case OPC_SLLV: /* Shifts */
23397 case OPC_SRAV:
23398 gen_shift(ctx, op1, rd, rs, rt);
23399 break;
23400 case OPC_SRLV:
23401 switch ((ctx->opcode >> 6) & 0x1f) {
23402 case 1:
23403 /* rotrv is decoded as srlv on non-R2 CPUs */
23404 if (ctx->insn_flags & ISA_MIPS32R2) {
23405 op1 = OPC_ROTRV;
23407 /* Fallthrough */
23408 case 0:
23409 gen_shift(ctx, op1, rd, rs, rt);
23410 break;
23411 default:
23412 generate_exception_end(ctx, EXCP_RI);
23413 break;
23415 break;
23416 case OPC_SLT: /* Set on less than */
23417 case OPC_SLTU:
23418 gen_slt(ctx, op1, rd, rs, rt);
23419 break;
23420 case OPC_AND: /* Logic*/
23421 case OPC_OR:
23422 case OPC_NOR:
23423 case OPC_XOR:
23424 gen_logic(ctx, op1, rd, rs, rt);
23425 break;
23426 case OPC_JALR:
23427 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23428 break;
23429 case OPC_TGE: /* Traps */
23430 case OPC_TGEU:
23431 case OPC_TLT:
23432 case OPC_TLTU:
23433 case OPC_TEQ:
23434 case OPC_TNE:
23435 check_insn(ctx, ISA_MIPS2);
23436 gen_trap(ctx, op1, rs, rt, -1);
23437 break;
23438 case OPC_LSA: /* OPC_PMON */
23439 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23440 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23441 decode_opc_special_r6(env, ctx);
23442 } else {
23443 /* Pmon entry point, also R4010 selsl */
23444 #ifdef MIPS_STRICT_STANDARD
23445 MIPS_INVAL("PMON / selsl");
23446 generate_exception_end(ctx, EXCP_RI);
23447 #else
23448 gen_helper_0e0i(pmon, sa);
23449 #endif
23451 break;
23452 case OPC_SYSCALL:
23453 generate_exception_end(ctx, EXCP_SYSCALL);
23454 break;
23455 case OPC_BREAK:
23456 generate_exception_end(ctx, EXCP_BREAK);
23457 break;
23458 case OPC_SYNC:
23459 check_insn(ctx, ISA_MIPS2);
23460 gen_sync(extract32(ctx->opcode, 6, 5));
23461 break;
23463 #if defined(TARGET_MIPS64)
23464 /* MIPS64 specific opcodes */
23465 case OPC_DSLL:
23466 case OPC_DSRA:
23467 case OPC_DSLL32:
23468 case OPC_DSRA32:
23469 check_insn(ctx, ISA_MIPS3);
23470 check_mips_64(ctx);
23471 gen_shift_imm(ctx, op1, rd, rt, sa);
23472 break;
23473 case OPC_DSRL:
23474 switch ((ctx->opcode >> 21) & 0x1f) {
23475 case 1:
23476 /* drotr is decoded as dsrl on non-R2 CPUs */
23477 if (ctx->insn_flags & ISA_MIPS32R2) {
23478 op1 = OPC_DROTR;
23480 /* Fallthrough */
23481 case 0:
23482 check_insn(ctx, ISA_MIPS3);
23483 check_mips_64(ctx);
23484 gen_shift_imm(ctx, op1, rd, rt, sa);
23485 break;
23486 default:
23487 generate_exception_end(ctx, EXCP_RI);
23488 break;
23490 break;
23491 case OPC_DSRL32:
23492 switch ((ctx->opcode >> 21) & 0x1f) {
23493 case 1:
23494 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23495 if (ctx->insn_flags & ISA_MIPS32R2) {
23496 op1 = OPC_DROTR32;
23498 /* Fallthrough */
23499 case 0:
23500 check_insn(ctx, ISA_MIPS3);
23501 check_mips_64(ctx);
23502 gen_shift_imm(ctx, op1, rd, rt, sa);
23503 break;
23504 default:
23505 generate_exception_end(ctx, EXCP_RI);
23506 break;
23508 break;
23509 case OPC_DADD:
23510 case OPC_DADDU:
23511 case OPC_DSUB:
23512 case OPC_DSUBU:
23513 check_insn(ctx, ISA_MIPS3);
23514 check_mips_64(ctx);
23515 gen_arith(ctx, op1, rd, rs, rt);
23516 break;
23517 case OPC_DSLLV:
23518 case OPC_DSRAV:
23519 check_insn(ctx, ISA_MIPS3);
23520 check_mips_64(ctx);
23521 gen_shift(ctx, op1, rd, rs, rt);
23522 break;
23523 case OPC_DSRLV:
23524 switch ((ctx->opcode >> 6) & 0x1f) {
23525 case 1:
23526 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23527 if (ctx->insn_flags & ISA_MIPS32R2) {
23528 op1 = OPC_DROTRV;
23530 /* Fallthrough */
23531 case 0:
23532 check_insn(ctx, ISA_MIPS3);
23533 check_mips_64(ctx);
23534 gen_shift(ctx, op1, rd, rs, rt);
23535 break;
23536 default:
23537 generate_exception_end(ctx, EXCP_RI);
23538 break;
23540 break;
23541 case OPC_DLSA:
23542 if ((ctx->insn_flags & ISA_MIPS32R6) ||
23543 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
23544 decode_opc_special_r6(env, ctx);
23546 break;
23547 #endif
23548 default:
23549 if (ctx->insn_flags & ISA_MIPS32R6) {
23550 decode_opc_special_r6(env, ctx);
23551 } else {
23552 decode_opc_special_legacy(env, ctx);
23557 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23559 int rs, rt, rd;
23560 uint32_t op1;
23562 check_insn_opc_removed(ctx, ISA_MIPS32R6);
23564 rs = (ctx->opcode >> 21) & 0x1f;
23565 rt = (ctx->opcode >> 16) & 0x1f;
23566 rd = (ctx->opcode >> 11) & 0x1f;
23568 op1 = MASK_SPECIAL2(ctx->opcode);
23569 switch (op1) {
23570 case OPC_MADD: /* Multiply and add/sub */
23571 case OPC_MADDU:
23572 case OPC_MSUB:
23573 case OPC_MSUBU:
23574 check_insn(ctx, ISA_MIPS32);
23575 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23576 break;
23577 case OPC_MUL:
23578 gen_arith(ctx, op1, rd, rs, rt);
23579 break;
23580 case OPC_DIV_G_2F:
23581 case OPC_DIVU_G_2F:
23582 case OPC_MULT_G_2F:
23583 case OPC_MULTU_G_2F:
23584 case OPC_MOD_G_2F:
23585 case OPC_MODU_G_2F:
23586 check_insn(ctx, INSN_LOONGSON2F);
23587 gen_loongson_integer(ctx, op1, rd, rs, rt);
23588 break;
23589 case OPC_CLO:
23590 case OPC_CLZ:
23591 check_insn(ctx, ISA_MIPS32);
23592 gen_cl(ctx, op1, rd, rs);
23593 break;
23594 case OPC_SDBBP:
23595 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23596 gen_helper_do_semihosting(cpu_env);
23597 } else {
23598 /* XXX: not clear which exception should be raised
23599 * when in debug mode...
23601 check_insn(ctx, ISA_MIPS32);
23602 generate_exception_end(ctx, EXCP_DBp);
23604 break;
23605 #if defined(TARGET_MIPS64)
23606 case OPC_DCLO:
23607 case OPC_DCLZ:
23608 check_insn(ctx, ISA_MIPS64);
23609 check_mips_64(ctx);
23610 gen_cl(ctx, op1, rd, rs);
23611 break;
23612 case OPC_DMULT_G_2F:
23613 case OPC_DMULTU_G_2F:
23614 case OPC_DDIV_G_2F:
23615 case OPC_DDIVU_G_2F:
23616 case OPC_DMOD_G_2F:
23617 case OPC_DMODU_G_2F:
23618 check_insn(ctx, INSN_LOONGSON2F);
23619 gen_loongson_integer(ctx, op1, rd, rs, rt);
23620 break;
23621 #endif
23622 default: /* Invalid */
23623 MIPS_INVAL("special2_legacy");
23624 generate_exception_end(ctx, EXCP_RI);
23625 break;
23629 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23631 int rs, rt, rd, sa;
23632 uint32_t op1, op2;
23633 int16_t imm;
23635 rs = (ctx->opcode >> 21) & 0x1f;
23636 rt = (ctx->opcode >> 16) & 0x1f;
23637 rd = (ctx->opcode >> 11) & 0x1f;
23638 sa = (ctx->opcode >> 6) & 0x1f;
23639 imm = (int16_t)ctx->opcode >> 7;
23641 op1 = MASK_SPECIAL3(ctx->opcode);
23642 switch (op1) {
23643 case R6_OPC_PREF:
23644 if (rt >= 24) {
23645 /* hint codes 24-31 are reserved and signal RI */
23646 generate_exception_end(ctx, EXCP_RI);
23648 /* Treat as NOP. */
23649 break;
23650 case R6_OPC_CACHE:
23651 check_cp0_enabled(ctx);
23652 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23653 gen_cache_operation(ctx, rt, rs, imm);
23655 break;
23656 case R6_OPC_SC:
23657 gen_st_cond(ctx, op1, rt, rs, imm);
23658 break;
23659 case R6_OPC_LL:
23660 gen_ld(ctx, op1, rt, rs, imm);
23661 break;
23662 case OPC_BSHFL:
23664 if (rd == 0) {
23665 /* Treat as NOP. */
23666 break;
23668 op2 = MASK_BSHFL(ctx->opcode);
23669 switch (op2) {
23670 case OPC_ALIGN:
23671 case OPC_ALIGN_END:
23672 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23673 break;
23674 case OPC_BITSWAP:
23675 gen_bitswap(ctx, op2, rd, rt);
23676 break;
23679 break;
23680 #if defined(TARGET_MIPS64)
23681 case R6_OPC_SCD:
23682 gen_st_cond(ctx, op1, rt, rs, imm);
23683 break;
23684 case R6_OPC_LLD:
23685 gen_ld(ctx, op1, rt, rs, imm);
23686 break;
23687 case OPC_DBSHFL:
23688 check_mips_64(ctx);
23690 if (rd == 0) {
23691 /* Treat as NOP. */
23692 break;
23694 op2 = MASK_DBSHFL(ctx->opcode);
23695 switch (op2) {
23696 case OPC_DALIGN:
23697 case OPC_DALIGN_END:
23698 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23699 break;
23700 case OPC_DBITSWAP:
23701 gen_bitswap(ctx, op2, rd, rt);
23702 break;
23706 break;
23707 #endif
23708 default: /* Invalid */
23709 MIPS_INVAL("special3_r6");
23710 generate_exception_end(ctx, EXCP_RI);
23711 break;
23715 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23717 int rs, rt, rd;
23718 uint32_t op1, op2;
23720 rs = (ctx->opcode >> 21) & 0x1f;
23721 rt = (ctx->opcode >> 16) & 0x1f;
23722 rd = (ctx->opcode >> 11) & 0x1f;
23724 op1 = MASK_SPECIAL3(ctx->opcode);
23725 switch (op1) {
23726 case OPC_DIV_G_2E:
23727 case OPC_DIVU_G_2E:
23728 case OPC_MOD_G_2E:
23729 case OPC_MODU_G_2E:
23730 case OPC_MULT_G_2E:
23731 case OPC_MULTU_G_2E:
23732 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23733 * the same mask and op1. */
23734 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
23735 op2 = MASK_ADDUH_QB(ctx->opcode);
23736 switch (op2) {
23737 case OPC_ADDUH_QB:
23738 case OPC_ADDUH_R_QB:
23739 case OPC_ADDQH_PH:
23740 case OPC_ADDQH_R_PH:
23741 case OPC_ADDQH_W:
23742 case OPC_ADDQH_R_W:
23743 case OPC_SUBUH_QB:
23744 case OPC_SUBUH_R_QB:
23745 case OPC_SUBQH_PH:
23746 case OPC_SUBQH_R_PH:
23747 case OPC_SUBQH_W:
23748 case OPC_SUBQH_R_W:
23749 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23750 break;
23751 case OPC_MUL_PH:
23752 case OPC_MUL_S_PH:
23753 case OPC_MULQ_S_W:
23754 case OPC_MULQ_RS_W:
23755 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23756 break;
23757 default:
23758 MIPS_INVAL("MASK ADDUH.QB");
23759 generate_exception_end(ctx, EXCP_RI);
23760 break;
23762 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23763 gen_loongson_integer(ctx, op1, rd, rs, rt);
23764 } else {
23765 generate_exception_end(ctx, EXCP_RI);
23767 break;
23768 case OPC_LX_DSP:
23769 op2 = MASK_LX(ctx->opcode);
23770 switch (op2) {
23771 #if defined(TARGET_MIPS64)
23772 case OPC_LDX:
23773 #endif
23774 case OPC_LBUX:
23775 case OPC_LHX:
23776 case OPC_LWX:
23777 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23778 break;
23779 default: /* Invalid */
23780 MIPS_INVAL("MASK LX");
23781 generate_exception_end(ctx, EXCP_RI);
23782 break;
23784 break;
23785 case OPC_ABSQ_S_PH_DSP:
23786 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23787 switch (op2) {
23788 case OPC_ABSQ_S_QB:
23789 case OPC_ABSQ_S_PH:
23790 case OPC_ABSQ_S_W:
23791 case OPC_PRECEQ_W_PHL:
23792 case OPC_PRECEQ_W_PHR:
23793 case OPC_PRECEQU_PH_QBL:
23794 case OPC_PRECEQU_PH_QBR:
23795 case OPC_PRECEQU_PH_QBLA:
23796 case OPC_PRECEQU_PH_QBRA:
23797 case OPC_PRECEU_PH_QBL:
23798 case OPC_PRECEU_PH_QBR:
23799 case OPC_PRECEU_PH_QBLA:
23800 case OPC_PRECEU_PH_QBRA:
23801 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23802 break;
23803 case OPC_BITREV:
23804 case OPC_REPL_QB:
23805 case OPC_REPLV_QB:
23806 case OPC_REPL_PH:
23807 case OPC_REPLV_PH:
23808 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23809 break;
23810 default:
23811 MIPS_INVAL("MASK ABSQ_S.PH");
23812 generate_exception_end(ctx, EXCP_RI);
23813 break;
23815 break;
23816 case OPC_ADDU_QB_DSP:
23817 op2 = MASK_ADDU_QB(ctx->opcode);
23818 switch (op2) {
23819 case OPC_ADDQ_PH:
23820 case OPC_ADDQ_S_PH:
23821 case OPC_ADDQ_S_W:
23822 case OPC_ADDU_QB:
23823 case OPC_ADDU_S_QB:
23824 case OPC_ADDU_PH:
23825 case OPC_ADDU_S_PH:
23826 case OPC_SUBQ_PH:
23827 case OPC_SUBQ_S_PH:
23828 case OPC_SUBQ_S_W:
23829 case OPC_SUBU_QB:
23830 case OPC_SUBU_S_QB:
23831 case OPC_SUBU_PH:
23832 case OPC_SUBU_S_PH:
23833 case OPC_ADDSC:
23834 case OPC_ADDWC:
23835 case OPC_MODSUB:
23836 case OPC_RADDU_W_QB:
23837 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23838 break;
23839 case OPC_MULEU_S_PH_QBL:
23840 case OPC_MULEU_S_PH_QBR:
23841 case OPC_MULQ_RS_PH:
23842 case OPC_MULEQ_S_W_PHL:
23843 case OPC_MULEQ_S_W_PHR:
23844 case OPC_MULQ_S_PH:
23845 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23846 break;
23847 default: /* Invalid */
23848 MIPS_INVAL("MASK ADDU.QB");
23849 generate_exception_end(ctx, EXCP_RI);
23850 break;
23853 break;
23854 case OPC_CMPU_EQ_QB_DSP:
23855 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
23856 switch (op2) {
23857 case OPC_PRECR_SRA_PH_W:
23858 case OPC_PRECR_SRA_R_PH_W:
23859 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
23860 break;
23861 case OPC_PRECR_QB_PH:
23862 case OPC_PRECRQ_QB_PH:
23863 case OPC_PRECRQ_PH_W:
23864 case OPC_PRECRQ_RS_PH_W:
23865 case OPC_PRECRQU_S_QB_PH:
23866 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23867 break;
23868 case OPC_CMPU_EQ_QB:
23869 case OPC_CMPU_LT_QB:
23870 case OPC_CMPU_LE_QB:
23871 case OPC_CMP_EQ_PH:
23872 case OPC_CMP_LT_PH:
23873 case OPC_CMP_LE_PH:
23874 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
23875 break;
23876 case OPC_CMPGU_EQ_QB:
23877 case OPC_CMPGU_LT_QB:
23878 case OPC_CMPGU_LE_QB:
23879 case OPC_CMPGDU_EQ_QB:
23880 case OPC_CMPGDU_LT_QB:
23881 case OPC_CMPGDU_LE_QB:
23882 case OPC_PICK_QB:
23883 case OPC_PICK_PH:
23884 case OPC_PACKRL_PH:
23885 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
23886 break;
23887 default: /* Invalid */
23888 MIPS_INVAL("MASK CMPU.EQ.QB");
23889 generate_exception_end(ctx, EXCP_RI);
23890 break;
23892 break;
23893 case OPC_SHLL_QB_DSP:
23894 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
23895 break;
23896 case OPC_DPA_W_PH_DSP:
23897 op2 = MASK_DPA_W_PH(ctx->opcode);
23898 switch (op2) {
23899 case OPC_DPAU_H_QBL:
23900 case OPC_DPAU_H_QBR:
23901 case OPC_DPSU_H_QBL:
23902 case OPC_DPSU_H_QBR:
23903 case OPC_DPA_W_PH:
23904 case OPC_DPAX_W_PH:
23905 case OPC_DPAQ_S_W_PH:
23906 case OPC_DPAQX_S_W_PH:
23907 case OPC_DPAQX_SA_W_PH:
23908 case OPC_DPS_W_PH:
23909 case OPC_DPSX_W_PH:
23910 case OPC_DPSQ_S_W_PH:
23911 case OPC_DPSQX_S_W_PH:
23912 case OPC_DPSQX_SA_W_PH:
23913 case OPC_MULSAQ_S_W_PH:
23914 case OPC_DPAQ_SA_L_W:
23915 case OPC_DPSQ_SA_L_W:
23916 case OPC_MAQ_S_W_PHL:
23917 case OPC_MAQ_S_W_PHR:
23918 case OPC_MAQ_SA_W_PHL:
23919 case OPC_MAQ_SA_W_PHR:
23920 case OPC_MULSA_W_PH:
23921 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
23922 break;
23923 default: /* Invalid */
23924 MIPS_INVAL("MASK DPAW.PH");
23925 generate_exception_end(ctx, EXCP_RI);
23926 break;
23928 break;
23929 case OPC_INSV_DSP:
23930 op2 = MASK_INSV(ctx->opcode);
23931 switch (op2) {
23932 case OPC_INSV:
23933 check_dsp(ctx);
23935 TCGv t0, t1;
23937 if (rt == 0) {
23938 break;
23941 t0 = tcg_temp_new();
23942 t1 = tcg_temp_new();
23944 gen_load_gpr(t0, rt);
23945 gen_load_gpr(t1, rs);
23947 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
23949 tcg_temp_free(t0);
23950 tcg_temp_free(t1);
23951 break;
23953 default: /* Invalid */
23954 MIPS_INVAL("MASK INSV");
23955 generate_exception_end(ctx, EXCP_RI);
23956 break;
23958 break;
23959 case OPC_APPEND_DSP:
23960 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
23961 break;
23962 case OPC_EXTR_W_DSP:
23963 op2 = MASK_EXTR_W(ctx->opcode);
23964 switch (op2) {
23965 case OPC_EXTR_W:
23966 case OPC_EXTR_R_W:
23967 case OPC_EXTR_RS_W:
23968 case OPC_EXTR_S_H:
23969 case OPC_EXTRV_S_H:
23970 case OPC_EXTRV_W:
23971 case OPC_EXTRV_R_W:
23972 case OPC_EXTRV_RS_W:
23973 case OPC_EXTP:
23974 case OPC_EXTPV:
23975 case OPC_EXTPDP:
23976 case OPC_EXTPDPV:
23977 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
23978 break;
23979 case OPC_RDDSP:
23980 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
23981 break;
23982 case OPC_SHILO:
23983 case OPC_SHILOV:
23984 case OPC_MTHLIP:
23985 case OPC_WRDSP:
23986 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
23987 break;
23988 default: /* Invalid */
23989 MIPS_INVAL("MASK EXTR.W");
23990 generate_exception_end(ctx, EXCP_RI);
23991 break;
23993 break;
23994 #if defined(TARGET_MIPS64)
23995 case OPC_DDIV_G_2E:
23996 case OPC_DDIVU_G_2E:
23997 case OPC_DMULT_G_2E:
23998 case OPC_DMULTU_G_2E:
23999 case OPC_DMOD_G_2E:
24000 case OPC_DMODU_G_2E:
24001 check_insn(ctx, INSN_LOONGSON2E);
24002 gen_loongson_integer(ctx, op1, rd, rs, rt);
24003 break;
24004 case OPC_ABSQ_S_QH_DSP:
24005 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24006 switch (op2) {
24007 case OPC_PRECEQ_L_PWL:
24008 case OPC_PRECEQ_L_PWR:
24009 case OPC_PRECEQ_PW_QHL:
24010 case OPC_PRECEQ_PW_QHR:
24011 case OPC_PRECEQ_PW_QHLA:
24012 case OPC_PRECEQ_PW_QHRA:
24013 case OPC_PRECEQU_QH_OBL:
24014 case OPC_PRECEQU_QH_OBR:
24015 case OPC_PRECEQU_QH_OBLA:
24016 case OPC_PRECEQU_QH_OBRA:
24017 case OPC_PRECEU_QH_OBL:
24018 case OPC_PRECEU_QH_OBR:
24019 case OPC_PRECEU_QH_OBLA:
24020 case OPC_PRECEU_QH_OBRA:
24021 case OPC_ABSQ_S_OB:
24022 case OPC_ABSQ_S_PW:
24023 case OPC_ABSQ_S_QH:
24024 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24025 break;
24026 case OPC_REPL_OB:
24027 case OPC_REPL_PW:
24028 case OPC_REPL_QH:
24029 case OPC_REPLV_OB:
24030 case OPC_REPLV_PW:
24031 case OPC_REPLV_QH:
24032 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24033 break;
24034 default: /* Invalid */
24035 MIPS_INVAL("MASK ABSQ_S.QH");
24036 generate_exception_end(ctx, EXCP_RI);
24037 break;
24039 break;
24040 case OPC_ADDU_OB_DSP:
24041 op2 = MASK_ADDU_OB(ctx->opcode);
24042 switch (op2) {
24043 case OPC_RADDU_L_OB:
24044 case OPC_SUBQ_PW:
24045 case OPC_SUBQ_S_PW:
24046 case OPC_SUBQ_QH:
24047 case OPC_SUBQ_S_QH:
24048 case OPC_SUBU_OB:
24049 case OPC_SUBU_S_OB:
24050 case OPC_SUBU_QH:
24051 case OPC_SUBU_S_QH:
24052 case OPC_SUBUH_OB:
24053 case OPC_SUBUH_R_OB:
24054 case OPC_ADDQ_PW:
24055 case OPC_ADDQ_S_PW:
24056 case OPC_ADDQ_QH:
24057 case OPC_ADDQ_S_QH:
24058 case OPC_ADDU_OB:
24059 case OPC_ADDU_S_OB:
24060 case OPC_ADDU_QH:
24061 case OPC_ADDU_S_QH:
24062 case OPC_ADDUH_OB:
24063 case OPC_ADDUH_R_OB:
24064 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24065 break;
24066 case OPC_MULEQ_S_PW_QHL:
24067 case OPC_MULEQ_S_PW_QHR:
24068 case OPC_MULEU_S_QH_OBL:
24069 case OPC_MULEU_S_QH_OBR:
24070 case OPC_MULQ_RS_QH:
24071 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24072 break;
24073 default: /* Invalid */
24074 MIPS_INVAL("MASK ADDU.OB");
24075 generate_exception_end(ctx, EXCP_RI);
24076 break;
24078 break;
24079 case OPC_CMPU_EQ_OB_DSP:
24080 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24081 switch (op2) {
24082 case OPC_PRECR_SRA_QH_PW:
24083 case OPC_PRECR_SRA_R_QH_PW:
24084 /* Return value is rt. */
24085 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24086 break;
24087 case OPC_PRECR_OB_QH:
24088 case OPC_PRECRQ_OB_QH:
24089 case OPC_PRECRQ_PW_L:
24090 case OPC_PRECRQ_QH_PW:
24091 case OPC_PRECRQ_RS_QH_PW:
24092 case OPC_PRECRQU_S_OB_QH:
24093 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24094 break;
24095 case OPC_CMPU_EQ_OB:
24096 case OPC_CMPU_LT_OB:
24097 case OPC_CMPU_LE_OB:
24098 case OPC_CMP_EQ_QH:
24099 case OPC_CMP_LT_QH:
24100 case OPC_CMP_LE_QH:
24101 case OPC_CMP_EQ_PW:
24102 case OPC_CMP_LT_PW:
24103 case OPC_CMP_LE_PW:
24104 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24105 break;
24106 case OPC_CMPGDU_EQ_OB:
24107 case OPC_CMPGDU_LT_OB:
24108 case OPC_CMPGDU_LE_OB:
24109 case OPC_CMPGU_EQ_OB:
24110 case OPC_CMPGU_LT_OB:
24111 case OPC_CMPGU_LE_OB:
24112 case OPC_PACKRL_PW:
24113 case OPC_PICK_OB:
24114 case OPC_PICK_PW:
24115 case OPC_PICK_QH:
24116 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24117 break;
24118 default: /* Invalid */
24119 MIPS_INVAL("MASK CMPU_EQ.OB");
24120 generate_exception_end(ctx, EXCP_RI);
24121 break;
24123 break;
24124 case OPC_DAPPEND_DSP:
24125 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24126 break;
24127 case OPC_DEXTR_W_DSP:
24128 op2 = MASK_DEXTR_W(ctx->opcode);
24129 switch (op2) {
24130 case OPC_DEXTP:
24131 case OPC_DEXTPDP:
24132 case OPC_DEXTPDPV:
24133 case OPC_DEXTPV:
24134 case OPC_DEXTR_L:
24135 case OPC_DEXTR_R_L:
24136 case OPC_DEXTR_RS_L:
24137 case OPC_DEXTR_W:
24138 case OPC_DEXTR_R_W:
24139 case OPC_DEXTR_RS_W:
24140 case OPC_DEXTR_S_H:
24141 case OPC_DEXTRV_L:
24142 case OPC_DEXTRV_R_L:
24143 case OPC_DEXTRV_RS_L:
24144 case OPC_DEXTRV_S_H:
24145 case OPC_DEXTRV_W:
24146 case OPC_DEXTRV_R_W:
24147 case OPC_DEXTRV_RS_W:
24148 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24149 break;
24150 case OPC_DMTHLIP:
24151 case OPC_DSHILO:
24152 case OPC_DSHILOV:
24153 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24154 break;
24155 default: /* Invalid */
24156 MIPS_INVAL("MASK EXTR.W");
24157 generate_exception_end(ctx, EXCP_RI);
24158 break;
24160 break;
24161 case OPC_DPAQ_W_QH_DSP:
24162 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24163 switch (op2) {
24164 case OPC_DPAU_H_OBL:
24165 case OPC_DPAU_H_OBR:
24166 case OPC_DPSU_H_OBL:
24167 case OPC_DPSU_H_OBR:
24168 case OPC_DPA_W_QH:
24169 case OPC_DPAQ_S_W_QH:
24170 case OPC_DPS_W_QH:
24171 case OPC_DPSQ_S_W_QH:
24172 case OPC_MULSAQ_S_W_QH:
24173 case OPC_DPAQ_SA_L_PW:
24174 case OPC_DPSQ_SA_L_PW:
24175 case OPC_MULSAQ_S_L_PW:
24176 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24177 break;
24178 case OPC_MAQ_S_W_QHLL:
24179 case OPC_MAQ_S_W_QHLR:
24180 case OPC_MAQ_S_W_QHRL:
24181 case OPC_MAQ_S_W_QHRR:
24182 case OPC_MAQ_SA_W_QHLL:
24183 case OPC_MAQ_SA_W_QHLR:
24184 case OPC_MAQ_SA_W_QHRL:
24185 case OPC_MAQ_SA_W_QHRR:
24186 case OPC_MAQ_S_L_PWL:
24187 case OPC_MAQ_S_L_PWR:
24188 case OPC_DMADD:
24189 case OPC_DMADDU:
24190 case OPC_DMSUB:
24191 case OPC_DMSUBU:
24192 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24193 break;
24194 default: /* Invalid */
24195 MIPS_INVAL("MASK DPAQ.W.QH");
24196 generate_exception_end(ctx, EXCP_RI);
24197 break;
24199 break;
24200 case OPC_DINSV_DSP:
24201 op2 = MASK_INSV(ctx->opcode);
24202 switch (op2) {
24203 case OPC_DINSV:
24205 TCGv t0, t1;
24207 if (rt == 0) {
24208 break;
24210 check_dsp(ctx);
24212 t0 = tcg_temp_new();
24213 t1 = tcg_temp_new();
24215 gen_load_gpr(t0, rt);
24216 gen_load_gpr(t1, rs);
24218 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24220 tcg_temp_free(t0);
24221 tcg_temp_free(t1);
24222 break;
24224 default: /* Invalid */
24225 MIPS_INVAL("MASK DINSV");
24226 generate_exception_end(ctx, EXCP_RI);
24227 break;
24229 break;
24230 case OPC_SHLL_OB_DSP:
24231 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24232 break;
24233 #endif
24234 default: /* Invalid */
24235 MIPS_INVAL("special3_legacy");
24236 generate_exception_end(ctx, EXCP_RI);
24237 break;
24241 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24243 int rs, rt, rd, sa;
24244 uint32_t op1, op2;
24245 int16_t imm;
24247 rs = (ctx->opcode >> 21) & 0x1f;
24248 rt = (ctx->opcode >> 16) & 0x1f;
24249 rd = (ctx->opcode >> 11) & 0x1f;
24250 sa = (ctx->opcode >> 6) & 0x1f;
24251 imm = sextract32(ctx->opcode, 7, 9);
24253 op1 = MASK_SPECIAL3(ctx->opcode);
24256 * EVA loads and stores overlap Loongson 2E instructions decoded by
24257 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24258 * EVA is absent.
24260 if (ctx->eva) {
24261 switch (op1) {
24262 case OPC_LWLE:
24263 case OPC_LWRE:
24264 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24265 /* fall through */
24266 case OPC_LBUE:
24267 case OPC_LHUE:
24268 case OPC_LBE:
24269 case OPC_LHE:
24270 case OPC_LLE:
24271 case OPC_LWE:
24272 check_cp0_enabled(ctx);
24273 gen_ld(ctx, op1, rt, rs, imm);
24274 return;
24275 case OPC_SWLE:
24276 case OPC_SWRE:
24277 check_insn_opc_removed(ctx, ISA_MIPS32R6);
24278 /* fall through */
24279 case OPC_SBE:
24280 case OPC_SHE:
24281 case OPC_SWE:
24282 check_cp0_enabled(ctx);
24283 gen_st(ctx, op1, rt, rs, imm);
24284 return;
24285 case OPC_SCE:
24286 check_cp0_enabled(ctx);
24287 gen_st_cond(ctx, op1, rt, rs, imm);
24288 return;
24289 case OPC_CACHEE:
24290 check_cp0_enabled(ctx);
24291 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24292 gen_cache_operation(ctx, rt, rs, imm);
24294 /* Treat as NOP. */
24295 return;
24296 case OPC_PREFE:
24297 check_cp0_enabled(ctx);
24298 /* Treat as NOP. */
24299 return;
24303 switch (op1) {
24304 case OPC_EXT:
24305 case OPC_INS:
24306 check_insn(ctx, ISA_MIPS32R2);
24307 gen_bitops(ctx, op1, rt, rs, sa, rd);
24308 break;
24309 case OPC_BSHFL:
24310 op2 = MASK_BSHFL(ctx->opcode);
24311 switch (op2) {
24312 case OPC_ALIGN:
24313 case OPC_ALIGN_END:
24314 case OPC_BITSWAP:
24315 check_insn(ctx, ISA_MIPS32R6);
24316 decode_opc_special3_r6(env, ctx);
24317 break;
24318 default:
24319 check_insn(ctx, ISA_MIPS32R2);
24320 gen_bshfl(ctx, op2, rt, rd);
24321 break;
24323 break;
24324 #if defined(TARGET_MIPS64)
24325 case OPC_DEXTM:
24326 case OPC_DEXTU:
24327 case OPC_DEXT:
24328 case OPC_DINSM:
24329 case OPC_DINSU:
24330 case OPC_DINS:
24331 check_insn(ctx, ISA_MIPS64R2);
24332 check_mips_64(ctx);
24333 gen_bitops(ctx, op1, rt, rs, sa, rd);
24334 break;
24335 case OPC_DBSHFL:
24336 op2 = MASK_DBSHFL(ctx->opcode);
24337 switch (op2) {
24338 case OPC_DALIGN:
24339 case OPC_DALIGN_END:
24340 case OPC_DBITSWAP:
24341 check_insn(ctx, ISA_MIPS32R6);
24342 decode_opc_special3_r6(env, ctx);
24343 break;
24344 default:
24345 check_insn(ctx, ISA_MIPS64R2);
24346 check_mips_64(ctx);
24347 op2 = MASK_DBSHFL(ctx->opcode);
24348 gen_bshfl(ctx, op2, rt, rd);
24349 break;
24351 break;
24352 #endif
24353 case OPC_RDHWR:
24354 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24355 break;
24356 case OPC_FORK:
24357 check_mt(ctx);
24359 TCGv t0 = tcg_temp_new();
24360 TCGv t1 = tcg_temp_new();
24362 gen_load_gpr(t0, rt);
24363 gen_load_gpr(t1, rs);
24364 gen_helper_fork(t0, t1);
24365 tcg_temp_free(t0);
24366 tcg_temp_free(t1);
24368 break;
24369 case OPC_YIELD:
24370 check_mt(ctx);
24372 TCGv t0 = tcg_temp_new();
24374 gen_load_gpr(t0, rs);
24375 gen_helper_yield(t0, cpu_env, t0);
24376 gen_store_gpr(t0, rd);
24377 tcg_temp_free(t0);
24379 break;
24380 default:
24381 if (ctx->insn_flags & ISA_MIPS32R6) {
24382 decode_opc_special3_r6(env, ctx);
24383 } else {
24384 decode_opc_special3_legacy(env, ctx);
24389 /* MIPS SIMD Architecture (MSA) */
24390 static inline int check_msa_access(DisasContext *ctx)
24392 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
24393 !(ctx->hflags & MIPS_HFLAG_F64))) {
24394 generate_exception_end(ctx, EXCP_RI);
24395 return 0;
24398 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
24399 if (ctx->insn_flags & ASE_MSA) {
24400 generate_exception_end(ctx, EXCP_MSADIS);
24401 return 0;
24402 } else {
24403 generate_exception_end(ctx, EXCP_RI);
24404 return 0;
24407 return 1;
24410 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
24412 /* generates tcg ops to check if any element is 0 */
24413 /* Note this function only works with MSA_WRLEN = 128 */
24414 uint64_t eval_zero_or_big = 0;
24415 uint64_t eval_big = 0;
24416 TCGv_i64 t0 = tcg_temp_new_i64();
24417 TCGv_i64 t1 = tcg_temp_new_i64();
24418 switch (df) {
24419 case DF_BYTE:
24420 eval_zero_or_big = 0x0101010101010101ULL;
24421 eval_big = 0x8080808080808080ULL;
24422 break;
24423 case DF_HALF:
24424 eval_zero_or_big = 0x0001000100010001ULL;
24425 eval_big = 0x8000800080008000ULL;
24426 break;
24427 case DF_WORD:
24428 eval_zero_or_big = 0x0000000100000001ULL;
24429 eval_big = 0x8000000080000000ULL;
24430 break;
24431 case DF_DOUBLE:
24432 eval_zero_or_big = 0x0000000000000001ULL;
24433 eval_big = 0x8000000000000000ULL;
24434 break;
24436 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
24437 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
24438 tcg_gen_andi_i64(t0, t0, eval_big);
24439 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
24440 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
24441 tcg_gen_andi_i64(t1, t1, eval_big);
24442 tcg_gen_or_i64(t0, t0, t1);
24443 /* if all bits are zero then all elements are not zero */
24444 /* if some bit is non-zero then some element is zero */
24445 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
24446 tcg_gen_trunc_i64_tl(tresult, t0);
24447 tcg_temp_free_i64(t0);
24448 tcg_temp_free_i64(t1);
24451 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
24453 uint8_t df = (ctx->opcode >> 21) & 0x3;
24454 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24455 int64_t s16 = (int16_t)ctx->opcode;
24457 check_msa_access(ctx);
24459 if (ctx->hflags & MIPS_HFLAG_BMASK) {
24460 generate_exception_end(ctx, EXCP_RI);
24461 return;
24463 switch (op1) {
24464 case OPC_BZ_V:
24465 case OPC_BNZ_V:
24467 TCGv_i64 t0 = tcg_temp_new_i64();
24468 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
24469 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
24470 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
24471 tcg_gen_trunc_i64_tl(bcond, t0);
24472 tcg_temp_free_i64(t0);
24474 break;
24475 case OPC_BZ_B:
24476 case OPC_BZ_H:
24477 case OPC_BZ_W:
24478 case OPC_BZ_D:
24479 gen_check_zero_element(bcond, df, wt);
24480 break;
24481 case OPC_BNZ_B:
24482 case OPC_BNZ_H:
24483 case OPC_BNZ_W:
24484 case OPC_BNZ_D:
24485 gen_check_zero_element(bcond, df, wt);
24486 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
24487 break;
24490 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
24492 ctx->hflags |= MIPS_HFLAG_BC;
24493 ctx->hflags |= MIPS_HFLAG_BDS32;
24496 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
24498 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
24499 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
24500 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24501 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24503 TCGv_i32 twd = tcg_const_i32(wd);
24504 TCGv_i32 tws = tcg_const_i32(ws);
24505 TCGv_i32 ti8 = tcg_const_i32(i8);
24507 switch (MASK_MSA_I8(ctx->opcode)) {
24508 case OPC_ANDI_B:
24509 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
24510 break;
24511 case OPC_ORI_B:
24512 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
24513 break;
24514 case OPC_NORI_B:
24515 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
24516 break;
24517 case OPC_XORI_B:
24518 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
24519 break;
24520 case OPC_BMNZI_B:
24521 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
24522 break;
24523 case OPC_BMZI_B:
24524 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
24525 break;
24526 case OPC_BSELI_B:
24527 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
24528 break;
24529 case OPC_SHF_B:
24530 case OPC_SHF_H:
24531 case OPC_SHF_W:
24533 uint8_t df = (ctx->opcode >> 24) & 0x3;
24534 if (df == DF_DOUBLE) {
24535 generate_exception_end(ctx, EXCP_RI);
24536 } else {
24537 TCGv_i32 tdf = tcg_const_i32(df);
24538 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
24539 tcg_temp_free_i32(tdf);
24542 break;
24543 default:
24544 MIPS_INVAL("MSA instruction");
24545 generate_exception_end(ctx, EXCP_RI);
24546 break;
24549 tcg_temp_free_i32(twd);
24550 tcg_temp_free_i32(tws);
24551 tcg_temp_free_i32(ti8);
24554 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
24556 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24557 uint8_t df = (ctx->opcode >> 21) & 0x3;
24558 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
24559 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
24560 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24561 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24563 TCGv_i32 tdf = tcg_const_i32(df);
24564 TCGv_i32 twd = tcg_const_i32(wd);
24565 TCGv_i32 tws = tcg_const_i32(ws);
24566 TCGv_i32 timm = tcg_temp_new_i32();
24567 tcg_gen_movi_i32(timm, u5);
24569 switch (MASK_MSA_I5(ctx->opcode)) {
24570 case OPC_ADDVI_df:
24571 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
24572 break;
24573 case OPC_SUBVI_df:
24574 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
24575 break;
24576 case OPC_MAXI_S_df:
24577 tcg_gen_movi_i32(timm, s5);
24578 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
24579 break;
24580 case OPC_MAXI_U_df:
24581 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
24582 break;
24583 case OPC_MINI_S_df:
24584 tcg_gen_movi_i32(timm, s5);
24585 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
24586 break;
24587 case OPC_MINI_U_df:
24588 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
24589 break;
24590 case OPC_CEQI_df:
24591 tcg_gen_movi_i32(timm, s5);
24592 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
24593 break;
24594 case OPC_CLTI_S_df:
24595 tcg_gen_movi_i32(timm, s5);
24596 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
24597 break;
24598 case OPC_CLTI_U_df:
24599 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
24600 break;
24601 case OPC_CLEI_S_df:
24602 tcg_gen_movi_i32(timm, s5);
24603 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
24604 break;
24605 case OPC_CLEI_U_df:
24606 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
24607 break;
24608 case OPC_LDI_df:
24610 int32_t s10 = sextract32(ctx->opcode, 11, 10);
24611 tcg_gen_movi_i32(timm, s10);
24612 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
24614 break;
24615 default:
24616 MIPS_INVAL("MSA instruction");
24617 generate_exception_end(ctx, EXCP_RI);
24618 break;
24621 tcg_temp_free_i32(tdf);
24622 tcg_temp_free_i32(twd);
24623 tcg_temp_free_i32(tws);
24624 tcg_temp_free_i32(timm);
24627 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
24629 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24630 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
24631 uint32_t df = 0, m = 0;
24632 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24633 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24635 TCGv_i32 tdf;
24636 TCGv_i32 tm;
24637 TCGv_i32 twd;
24638 TCGv_i32 tws;
24640 if ((dfm & 0x40) == 0x00) {
24641 m = dfm & 0x3f;
24642 df = DF_DOUBLE;
24643 } else if ((dfm & 0x60) == 0x40) {
24644 m = dfm & 0x1f;
24645 df = DF_WORD;
24646 } else if ((dfm & 0x70) == 0x60) {
24647 m = dfm & 0x0f;
24648 df = DF_HALF;
24649 } else if ((dfm & 0x78) == 0x70) {
24650 m = dfm & 0x7;
24651 df = DF_BYTE;
24652 } else {
24653 generate_exception_end(ctx, EXCP_RI);
24654 return;
24657 tdf = tcg_const_i32(df);
24658 tm = tcg_const_i32(m);
24659 twd = tcg_const_i32(wd);
24660 tws = tcg_const_i32(ws);
24662 switch (MASK_MSA_BIT(ctx->opcode)) {
24663 case OPC_SLLI_df:
24664 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
24665 break;
24666 case OPC_SRAI_df:
24667 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
24668 break;
24669 case OPC_SRLI_df:
24670 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
24671 break;
24672 case OPC_BCLRI_df:
24673 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
24674 break;
24675 case OPC_BSETI_df:
24676 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
24677 break;
24678 case OPC_BNEGI_df:
24679 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
24680 break;
24681 case OPC_BINSLI_df:
24682 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
24683 break;
24684 case OPC_BINSRI_df:
24685 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
24686 break;
24687 case OPC_SAT_S_df:
24688 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
24689 break;
24690 case OPC_SAT_U_df:
24691 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
24692 break;
24693 case OPC_SRARI_df:
24694 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
24695 break;
24696 case OPC_SRLRI_df:
24697 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
24698 break;
24699 default:
24700 MIPS_INVAL("MSA instruction");
24701 generate_exception_end(ctx, EXCP_RI);
24702 break;
24705 tcg_temp_free_i32(tdf);
24706 tcg_temp_free_i32(tm);
24707 tcg_temp_free_i32(twd);
24708 tcg_temp_free_i32(tws);
24711 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
24713 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
24714 uint8_t df = (ctx->opcode >> 21) & 0x3;
24715 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
24716 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24717 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24719 TCGv_i32 tdf = tcg_const_i32(df);
24720 TCGv_i32 twd = tcg_const_i32(wd);
24721 TCGv_i32 tws = tcg_const_i32(ws);
24722 TCGv_i32 twt = tcg_const_i32(wt);
24724 switch (MASK_MSA_3R(ctx->opcode)) {
24725 case OPC_SLL_df:
24726 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
24727 break;
24728 case OPC_ADDV_df:
24729 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
24730 break;
24731 case OPC_CEQ_df:
24732 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
24733 break;
24734 case OPC_ADD_A_df:
24735 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
24736 break;
24737 case OPC_SUBS_S_df:
24738 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
24739 break;
24740 case OPC_MULV_df:
24741 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
24742 break;
24743 case OPC_SLD_df:
24744 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
24745 break;
24746 case OPC_VSHF_df:
24747 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
24748 break;
24749 case OPC_SRA_df:
24750 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
24751 break;
24752 case OPC_SUBV_df:
24753 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
24754 break;
24755 case OPC_ADDS_A_df:
24756 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
24757 break;
24758 case OPC_SUBS_U_df:
24759 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
24760 break;
24761 case OPC_MADDV_df:
24762 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
24763 break;
24764 case OPC_SPLAT_df:
24765 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
24766 break;
24767 case OPC_SRAR_df:
24768 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
24769 break;
24770 case OPC_SRL_df:
24771 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
24772 break;
24773 case OPC_MAX_S_df:
24774 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
24775 break;
24776 case OPC_CLT_S_df:
24777 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
24778 break;
24779 case OPC_ADDS_S_df:
24780 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
24781 break;
24782 case OPC_SUBSUS_U_df:
24783 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
24784 break;
24785 case OPC_MSUBV_df:
24786 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
24787 break;
24788 case OPC_PCKEV_df:
24789 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
24790 break;
24791 case OPC_SRLR_df:
24792 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
24793 break;
24794 case OPC_BCLR_df:
24795 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
24796 break;
24797 case OPC_MAX_U_df:
24798 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
24799 break;
24800 case OPC_CLT_U_df:
24801 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
24802 break;
24803 case OPC_ADDS_U_df:
24804 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
24805 break;
24806 case OPC_SUBSUU_S_df:
24807 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
24808 break;
24809 case OPC_PCKOD_df:
24810 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
24811 break;
24812 case OPC_BSET_df:
24813 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
24814 break;
24815 case OPC_MIN_S_df:
24816 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
24817 break;
24818 case OPC_CLE_S_df:
24819 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
24820 break;
24821 case OPC_AVE_S_df:
24822 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
24823 break;
24824 case OPC_ASUB_S_df:
24825 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
24826 break;
24827 case OPC_DIV_S_df:
24828 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
24829 break;
24830 case OPC_ILVL_df:
24831 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
24832 break;
24833 case OPC_BNEG_df:
24834 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
24835 break;
24836 case OPC_MIN_U_df:
24837 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
24838 break;
24839 case OPC_CLE_U_df:
24840 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
24841 break;
24842 case OPC_AVE_U_df:
24843 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
24844 break;
24845 case OPC_ASUB_U_df:
24846 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
24847 break;
24848 case OPC_DIV_U_df:
24849 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
24850 break;
24851 case OPC_ILVR_df:
24852 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
24853 break;
24854 case OPC_BINSL_df:
24855 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
24856 break;
24857 case OPC_MAX_A_df:
24858 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
24859 break;
24860 case OPC_AVER_S_df:
24861 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
24862 break;
24863 case OPC_MOD_S_df:
24864 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
24865 break;
24866 case OPC_ILVEV_df:
24867 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
24868 break;
24869 case OPC_BINSR_df:
24870 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
24871 break;
24872 case OPC_MIN_A_df:
24873 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
24874 break;
24875 case OPC_AVER_U_df:
24876 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
24877 break;
24878 case OPC_MOD_U_df:
24879 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
24880 break;
24881 case OPC_ILVOD_df:
24882 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
24883 break;
24885 case OPC_DOTP_S_df:
24886 case OPC_DOTP_U_df:
24887 case OPC_DPADD_S_df:
24888 case OPC_DPADD_U_df:
24889 case OPC_DPSUB_S_df:
24890 case OPC_HADD_S_df:
24891 case OPC_DPSUB_U_df:
24892 case OPC_HADD_U_df:
24893 case OPC_HSUB_S_df:
24894 case OPC_HSUB_U_df:
24895 if (df == DF_BYTE) {
24896 generate_exception_end(ctx, EXCP_RI);
24897 break;
24899 switch (MASK_MSA_3R(ctx->opcode)) {
24900 case OPC_DOTP_S_df:
24901 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
24902 break;
24903 case OPC_DOTP_U_df:
24904 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
24905 break;
24906 case OPC_DPADD_S_df:
24907 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
24908 break;
24909 case OPC_DPADD_U_df:
24910 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
24911 break;
24912 case OPC_DPSUB_S_df:
24913 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
24914 break;
24915 case OPC_HADD_S_df:
24916 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
24917 break;
24918 case OPC_DPSUB_U_df:
24919 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
24920 break;
24921 case OPC_HADD_U_df:
24922 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
24923 break;
24924 case OPC_HSUB_S_df:
24925 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
24926 break;
24927 case OPC_HSUB_U_df:
24928 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
24929 break;
24931 break;
24932 default:
24933 MIPS_INVAL("MSA instruction");
24934 generate_exception_end(ctx, EXCP_RI);
24935 break;
24937 tcg_temp_free_i32(twd);
24938 tcg_temp_free_i32(tws);
24939 tcg_temp_free_i32(twt);
24940 tcg_temp_free_i32(tdf);
24943 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
24945 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
24946 uint8_t source = (ctx->opcode >> 11) & 0x1f;
24947 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
24948 TCGv telm = tcg_temp_new();
24949 TCGv_i32 tsr = tcg_const_i32(source);
24950 TCGv_i32 tdt = tcg_const_i32(dest);
24952 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
24953 case OPC_CTCMSA:
24954 gen_load_gpr(telm, source);
24955 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
24956 break;
24957 case OPC_CFCMSA:
24958 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
24959 gen_store_gpr(telm, dest);
24960 break;
24961 case OPC_MOVE_V:
24962 gen_helper_msa_move_v(cpu_env, tdt, tsr);
24963 break;
24964 default:
24965 MIPS_INVAL("MSA instruction");
24966 generate_exception_end(ctx, EXCP_RI);
24967 break;
24970 tcg_temp_free(telm);
24971 tcg_temp_free_i32(tdt);
24972 tcg_temp_free_i32(tsr);
24975 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
24976 uint32_t n)
24978 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
24979 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
24980 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
24982 TCGv_i32 tws = tcg_const_i32(ws);
24983 TCGv_i32 twd = tcg_const_i32(wd);
24984 TCGv_i32 tn = tcg_const_i32(n);
24985 TCGv_i32 tdf = tcg_const_i32(df);
24987 switch (MASK_MSA_ELM(ctx->opcode)) {
24988 case OPC_SLDI_df:
24989 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
24990 break;
24991 case OPC_SPLATI_df:
24992 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
24993 break;
24994 case OPC_INSVE_df:
24995 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
24996 break;
24997 case OPC_COPY_S_df:
24998 case OPC_COPY_U_df:
24999 case OPC_INSERT_df:
25000 #if !defined(TARGET_MIPS64)
25001 /* Double format valid only for MIPS64 */
25002 if (df == DF_DOUBLE) {
25003 generate_exception_end(ctx, EXCP_RI);
25004 break;
25006 #endif
25007 switch (MASK_MSA_ELM(ctx->opcode)) {
25008 case OPC_COPY_S_df:
25009 if (likely(wd != 0)) {
25010 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
25012 break;
25013 case OPC_COPY_U_df:
25014 if (likely(wd != 0)) {
25015 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
25017 break;
25018 case OPC_INSERT_df:
25019 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
25020 break;
25022 break;
25023 default:
25024 MIPS_INVAL("MSA instruction");
25025 generate_exception_end(ctx, EXCP_RI);
25027 tcg_temp_free_i32(twd);
25028 tcg_temp_free_i32(tws);
25029 tcg_temp_free_i32(tn);
25030 tcg_temp_free_i32(tdf);
25033 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
25035 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
25036 uint32_t df = 0, n = 0;
25038 if ((dfn & 0x30) == 0x00) {
25039 n = dfn & 0x0f;
25040 df = DF_BYTE;
25041 } else if ((dfn & 0x38) == 0x20) {
25042 n = dfn & 0x07;
25043 df = DF_HALF;
25044 } else if ((dfn & 0x3c) == 0x30) {
25045 n = dfn & 0x03;
25046 df = DF_WORD;
25047 } else if ((dfn & 0x3e) == 0x38) {
25048 n = dfn & 0x01;
25049 df = DF_DOUBLE;
25050 } else if (dfn == 0x3E) {
25051 /* CTCMSA, CFCMSA, MOVE.V */
25052 gen_msa_elm_3e(env, ctx);
25053 return;
25054 } else {
25055 generate_exception_end(ctx, EXCP_RI);
25056 return;
25059 gen_msa_elm_df(env, ctx, df, n);
25062 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
25064 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
25065 uint8_t df = (ctx->opcode >> 21) & 0x1;
25066 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25067 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25068 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25070 TCGv_i32 twd = tcg_const_i32(wd);
25071 TCGv_i32 tws = tcg_const_i32(ws);
25072 TCGv_i32 twt = tcg_const_i32(wt);
25073 TCGv_i32 tdf = tcg_temp_new_i32();
25075 /* adjust df value for floating-point instruction */
25076 tcg_gen_movi_i32(tdf, df + 2);
25078 switch (MASK_MSA_3RF(ctx->opcode)) {
25079 case OPC_FCAF_df:
25080 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
25081 break;
25082 case OPC_FADD_df:
25083 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
25084 break;
25085 case OPC_FCUN_df:
25086 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
25087 break;
25088 case OPC_FSUB_df:
25089 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
25090 break;
25091 case OPC_FCOR_df:
25092 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
25093 break;
25094 case OPC_FCEQ_df:
25095 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
25096 break;
25097 case OPC_FMUL_df:
25098 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
25099 break;
25100 case OPC_FCUNE_df:
25101 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
25102 break;
25103 case OPC_FCUEQ_df:
25104 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
25105 break;
25106 case OPC_FDIV_df:
25107 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
25108 break;
25109 case OPC_FCNE_df:
25110 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
25111 break;
25112 case OPC_FCLT_df:
25113 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
25114 break;
25115 case OPC_FMADD_df:
25116 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
25117 break;
25118 case OPC_MUL_Q_df:
25119 tcg_gen_movi_i32(tdf, df + 1);
25120 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
25121 break;
25122 case OPC_FCULT_df:
25123 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
25124 break;
25125 case OPC_FMSUB_df:
25126 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
25127 break;
25128 case OPC_MADD_Q_df:
25129 tcg_gen_movi_i32(tdf, df + 1);
25130 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
25131 break;
25132 case OPC_FCLE_df:
25133 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
25134 break;
25135 case OPC_MSUB_Q_df:
25136 tcg_gen_movi_i32(tdf, df + 1);
25137 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
25138 break;
25139 case OPC_FCULE_df:
25140 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
25141 break;
25142 case OPC_FEXP2_df:
25143 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
25144 break;
25145 case OPC_FSAF_df:
25146 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
25147 break;
25148 case OPC_FEXDO_df:
25149 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
25150 break;
25151 case OPC_FSUN_df:
25152 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
25153 break;
25154 case OPC_FSOR_df:
25155 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
25156 break;
25157 case OPC_FSEQ_df:
25158 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
25159 break;
25160 case OPC_FTQ_df:
25161 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
25162 break;
25163 case OPC_FSUNE_df:
25164 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
25165 break;
25166 case OPC_FSUEQ_df:
25167 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
25168 break;
25169 case OPC_FSNE_df:
25170 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
25171 break;
25172 case OPC_FSLT_df:
25173 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
25174 break;
25175 case OPC_FMIN_df:
25176 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
25177 break;
25178 case OPC_MULR_Q_df:
25179 tcg_gen_movi_i32(tdf, df + 1);
25180 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
25181 break;
25182 case OPC_FSULT_df:
25183 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
25184 break;
25185 case OPC_FMIN_A_df:
25186 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
25187 break;
25188 case OPC_MADDR_Q_df:
25189 tcg_gen_movi_i32(tdf, df + 1);
25190 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
25191 break;
25192 case OPC_FSLE_df:
25193 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
25194 break;
25195 case OPC_FMAX_df:
25196 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
25197 break;
25198 case OPC_MSUBR_Q_df:
25199 tcg_gen_movi_i32(tdf, df + 1);
25200 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
25201 break;
25202 case OPC_FSULE_df:
25203 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
25204 break;
25205 case OPC_FMAX_A_df:
25206 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
25207 break;
25208 default:
25209 MIPS_INVAL("MSA instruction");
25210 generate_exception_end(ctx, EXCP_RI);
25211 break;
25214 tcg_temp_free_i32(twd);
25215 tcg_temp_free_i32(tws);
25216 tcg_temp_free_i32(twt);
25217 tcg_temp_free_i32(tdf);
25220 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
25222 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25223 (op & (0x7 << 18)))
25224 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25225 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25226 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25227 uint8_t df = (ctx->opcode >> 16) & 0x3;
25228 TCGv_i32 twd = tcg_const_i32(wd);
25229 TCGv_i32 tws = tcg_const_i32(ws);
25230 TCGv_i32 twt = tcg_const_i32(wt);
25231 TCGv_i32 tdf = tcg_const_i32(df);
25233 switch (MASK_MSA_2R(ctx->opcode)) {
25234 case OPC_FILL_df:
25235 #if !defined(TARGET_MIPS64)
25236 /* Double format valid only for MIPS64 */
25237 if (df == DF_DOUBLE) {
25238 generate_exception_end(ctx, EXCP_RI);
25239 break;
25241 #endif
25242 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
25243 break;
25244 case OPC_PCNT_df:
25245 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
25246 break;
25247 case OPC_NLOC_df:
25248 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
25249 break;
25250 case OPC_NLZC_df:
25251 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
25252 break;
25253 default:
25254 MIPS_INVAL("MSA instruction");
25255 generate_exception_end(ctx, EXCP_RI);
25256 break;
25259 tcg_temp_free_i32(twd);
25260 tcg_temp_free_i32(tws);
25261 tcg_temp_free_i32(twt);
25262 tcg_temp_free_i32(tdf);
25265 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
25267 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
25268 (op & (0xf << 17)))
25269 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25270 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25271 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25272 uint8_t df = (ctx->opcode >> 16) & 0x1;
25273 TCGv_i32 twd = tcg_const_i32(wd);
25274 TCGv_i32 tws = tcg_const_i32(ws);
25275 TCGv_i32 twt = tcg_const_i32(wt);
25276 /* adjust df value for floating-point instruction */
25277 TCGv_i32 tdf = tcg_const_i32(df + 2);
25279 switch (MASK_MSA_2RF(ctx->opcode)) {
25280 case OPC_FCLASS_df:
25281 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
25282 break;
25283 case OPC_FTRUNC_S_df:
25284 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
25285 break;
25286 case OPC_FTRUNC_U_df:
25287 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
25288 break;
25289 case OPC_FSQRT_df:
25290 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
25291 break;
25292 case OPC_FRSQRT_df:
25293 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
25294 break;
25295 case OPC_FRCP_df:
25296 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
25297 break;
25298 case OPC_FRINT_df:
25299 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
25300 break;
25301 case OPC_FLOG2_df:
25302 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
25303 break;
25304 case OPC_FEXUPL_df:
25305 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
25306 break;
25307 case OPC_FEXUPR_df:
25308 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
25309 break;
25310 case OPC_FFQL_df:
25311 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
25312 break;
25313 case OPC_FFQR_df:
25314 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
25315 break;
25316 case OPC_FTINT_S_df:
25317 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
25318 break;
25319 case OPC_FTINT_U_df:
25320 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
25321 break;
25322 case OPC_FFINT_S_df:
25323 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
25324 break;
25325 case OPC_FFINT_U_df:
25326 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
25327 break;
25330 tcg_temp_free_i32(twd);
25331 tcg_temp_free_i32(tws);
25332 tcg_temp_free_i32(twt);
25333 tcg_temp_free_i32(tdf);
25336 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
25338 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
25339 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
25340 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
25341 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25342 TCGv_i32 twd = tcg_const_i32(wd);
25343 TCGv_i32 tws = tcg_const_i32(ws);
25344 TCGv_i32 twt = tcg_const_i32(wt);
25346 switch (MASK_MSA_VEC(ctx->opcode)) {
25347 case OPC_AND_V:
25348 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
25349 break;
25350 case OPC_OR_V:
25351 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
25352 break;
25353 case OPC_NOR_V:
25354 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
25355 break;
25356 case OPC_XOR_V:
25357 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
25358 break;
25359 case OPC_BMNZ_V:
25360 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
25361 break;
25362 case OPC_BMZ_V:
25363 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
25364 break;
25365 case OPC_BSEL_V:
25366 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
25367 break;
25368 default:
25369 MIPS_INVAL("MSA instruction");
25370 generate_exception_end(ctx, EXCP_RI);
25371 break;
25374 tcg_temp_free_i32(twd);
25375 tcg_temp_free_i32(tws);
25376 tcg_temp_free_i32(twt);
25379 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
25381 switch (MASK_MSA_VEC(ctx->opcode)) {
25382 case OPC_AND_V:
25383 case OPC_OR_V:
25384 case OPC_NOR_V:
25385 case OPC_XOR_V:
25386 case OPC_BMNZ_V:
25387 case OPC_BMZ_V:
25388 case OPC_BSEL_V:
25389 gen_msa_vec_v(env, ctx);
25390 break;
25391 case OPC_MSA_2R:
25392 gen_msa_2r(env, ctx);
25393 break;
25394 case OPC_MSA_2RF:
25395 gen_msa_2rf(env, ctx);
25396 break;
25397 default:
25398 MIPS_INVAL("MSA instruction");
25399 generate_exception_end(ctx, EXCP_RI);
25400 break;
25404 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
25406 uint32_t opcode = ctx->opcode;
25407 check_insn(ctx, ASE_MSA);
25408 check_msa_access(ctx);
25410 switch (MASK_MSA_MINOR(opcode)) {
25411 case OPC_MSA_I8_00:
25412 case OPC_MSA_I8_01:
25413 case OPC_MSA_I8_02:
25414 gen_msa_i8(env, ctx);
25415 break;
25416 case OPC_MSA_I5_06:
25417 case OPC_MSA_I5_07:
25418 gen_msa_i5(env, ctx);
25419 break;
25420 case OPC_MSA_BIT_09:
25421 case OPC_MSA_BIT_0A:
25422 gen_msa_bit(env, ctx);
25423 break;
25424 case OPC_MSA_3R_0D:
25425 case OPC_MSA_3R_0E:
25426 case OPC_MSA_3R_0F:
25427 case OPC_MSA_3R_10:
25428 case OPC_MSA_3R_11:
25429 case OPC_MSA_3R_12:
25430 case OPC_MSA_3R_13:
25431 case OPC_MSA_3R_14:
25432 case OPC_MSA_3R_15:
25433 gen_msa_3r(env, ctx);
25434 break;
25435 case OPC_MSA_ELM:
25436 gen_msa_elm(env, ctx);
25437 break;
25438 case OPC_MSA_3RF_1A:
25439 case OPC_MSA_3RF_1B:
25440 case OPC_MSA_3RF_1C:
25441 gen_msa_3rf(env, ctx);
25442 break;
25443 case OPC_MSA_VEC:
25444 gen_msa_vec(env, ctx);
25445 break;
25446 case OPC_LD_B:
25447 case OPC_LD_H:
25448 case OPC_LD_W:
25449 case OPC_LD_D:
25450 case OPC_ST_B:
25451 case OPC_ST_H:
25452 case OPC_ST_W:
25453 case OPC_ST_D:
25455 int32_t s10 = sextract32(ctx->opcode, 16, 10);
25456 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
25457 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
25458 uint8_t df = (ctx->opcode >> 0) & 0x3;
25460 TCGv_i32 twd = tcg_const_i32(wd);
25461 TCGv taddr = tcg_temp_new();
25462 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
25464 switch (MASK_MSA_MINOR(opcode)) {
25465 case OPC_LD_B:
25466 gen_helper_msa_ld_b(cpu_env, twd, taddr);
25467 break;
25468 case OPC_LD_H:
25469 gen_helper_msa_ld_h(cpu_env, twd, taddr);
25470 break;
25471 case OPC_LD_W:
25472 gen_helper_msa_ld_w(cpu_env, twd, taddr);
25473 break;
25474 case OPC_LD_D:
25475 gen_helper_msa_ld_d(cpu_env, twd, taddr);
25476 break;
25477 case OPC_ST_B:
25478 gen_helper_msa_st_b(cpu_env, twd, taddr);
25479 break;
25480 case OPC_ST_H:
25481 gen_helper_msa_st_h(cpu_env, twd, taddr);
25482 break;
25483 case OPC_ST_W:
25484 gen_helper_msa_st_w(cpu_env, twd, taddr);
25485 break;
25486 case OPC_ST_D:
25487 gen_helper_msa_st_d(cpu_env, twd, taddr);
25488 break;
25491 tcg_temp_free_i32(twd);
25492 tcg_temp_free(taddr);
25494 break;
25495 default:
25496 MIPS_INVAL("MSA instruction");
25497 generate_exception_end(ctx, EXCP_RI);
25498 break;
25503 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25505 int32_t offset;
25506 int rs, rt, rd, sa;
25507 uint32_t op, op1;
25508 int16_t imm;
25510 /* make sure instructions are on a word boundary */
25511 if (ctx->base.pc_next & 0x3) {
25512 env->CP0_BadVAddr = ctx->base.pc_next;
25513 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25514 return;
25517 /* Handle blikely not taken case */
25518 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25519 TCGLabel *l1 = gen_new_label();
25521 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25522 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25523 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25524 gen_set_label(l1);
25527 op = MASK_OP_MAJOR(ctx->opcode);
25528 rs = (ctx->opcode >> 21) & 0x1f;
25529 rt = (ctx->opcode >> 16) & 0x1f;
25530 rd = (ctx->opcode >> 11) & 0x1f;
25531 sa = (ctx->opcode >> 6) & 0x1f;
25532 imm = (int16_t)ctx->opcode;
25533 switch (op) {
25534 case OPC_SPECIAL:
25535 decode_opc_special(env, ctx);
25536 break;
25537 case OPC_SPECIAL2:
25538 decode_opc_special2_legacy(env, ctx);
25539 break;
25540 case OPC_SPECIAL3:
25541 decode_opc_special3(env, ctx);
25542 break;
25543 case OPC_REGIMM:
25544 op1 = MASK_REGIMM(ctx->opcode);
25545 switch (op1) {
25546 case OPC_BLTZL: /* REGIMM branches */
25547 case OPC_BGEZL:
25548 case OPC_BLTZALL:
25549 case OPC_BGEZALL:
25550 check_insn(ctx, ISA_MIPS2);
25551 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25552 /* Fallthrough */
25553 case OPC_BLTZ:
25554 case OPC_BGEZ:
25555 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25556 break;
25557 case OPC_BLTZAL:
25558 case OPC_BGEZAL:
25559 if (ctx->insn_flags & ISA_MIPS32R6) {
25560 if (rs == 0) {
25561 /* OPC_NAL, OPC_BAL */
25562 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
25563 } else {
25564 generate_exception_end(ctx, EXCP_RI);
25566 } else {
25567 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
25569 break;
25570 case OPC_TGEI: /* REGIMM traps */
25571 case OPC_TGEIU:
25572 case OPC_TLTI:
25573 case OPC_TLTIU:
25574 case OPC_TEQI:
25576 case OPC_TNEI:
25577 check_insn(ctx, ISA_MIPS2);
25578 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25579 gen_trap(ctx, op1, rs, -1, imm);
25580 break;
25581 case OPC_SIGRIE:
25582 check_insn(ctx, ISA_MIPS32R6);
25583 generate_exception_end(ctx, EXCP_RI);
25584 break;
25585 case OPC_SYNCI:
25586 check_insn(ctx, ISA_MIPS32R2);
25587 /* Break the TB to be able to sync copied instructions
25588 immediately */
25589 ctx->base.is_jmp = DISAS_STOP;
25590 break;
25591 case OPC_BPOSGE32: /* MIPS DSP branch */
25592 #if defined(TARGET_MIPS64)
25593 case OPC_BPOSGE64:
25594 #endif
25595 check_dsp(ctx);
25596 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
25597 break;
25598 #if defined(TARGET_MIPS64)
25599 case OPC_DAHI:
25600 check_insn(ctx, ISA_MIPS32R6);
25601 check_mips_64(ctx);
25602 if (rs != 0) {
25603 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
25605 break;
25606 case OPC_DATI:
25607 check_insn(ctx, ISA_MIPS32R6);
25608 check_mips_64(ctx);
25609 if (rs != 0) {
25610 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
25612 break;
25613 #endif
25614 default: /* Invalid */
25615 MIPS_INVAL("regimm");
25616 generate_exception_end(ctx, EXCP_RI);
25617 break;
25619 break;
25620 case OPC_CP0:
25621 check_cp0_enabled(ctx);
25622 op1 = MASK_CP0(ctx->opcode);
25623 switch (op1) {
25624 case OPC_MFC0:
25625 case OPC_MTC0:
25626 case OPC_MFTR:
25627 case OPC_MTTR:
25628 case OPC_MFHC0:
25629 case OPC_MTHC0:
25630 #if defined(TARGET_MIPS64)
25631 case OPC_DMFC0:
25632 case OPC_DMTC0:
25633 #endif
25634 #ifndef CONFIG_USER_ONLY
25635 gen_cp0(env, ctx, op1, rt, rd);
25636 #endif /* !CONFIG_USER_ONLY */
25637 break;
25638 case OPC_C0:
25639 case OPC_C0_1:
25640 case OPC_C0_2:
25641 case OPC_C0_3:
25642 case OPC_C0_4:
25643 case OPC_C0_5:
25644 case OPC_C0_6:
25645 case OPC_C0_7:
25646 case OPC_C0_8:
25647 case OPC_C0_9:
25648 case OPC_C0_A:
25649 case OPC_C0_B:
25650 case OPC_C0_C:
25651 case OPC_C0_D:
25652 case OPC_C0_E:
25653 case OPC_C0_F:
25654 #ifndef CONFIG_USER_ONLY
25655 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
25656 #endif /* !CONFIG_USER_ONLY */
25657 break;
25658 case OPC_MFMC0:
25659 #ifndef CONFIG_USER_ONLY
25661 uint32_t op2;
25662 TCGv t0 = tcg_temp_new();
25664 op2 = MASK_MFMC0(ctx->opcode);
25665 switch (op2) {
25666 case OPC_DMT:
25667 check_cp0_mt(ctx);
25668 gen_helper_dmt(t0);
25669 gen_store_gpr(t0, rt);
25670 break;
25671 case OPC_EMT:
25672 check_cp0_mt(ctx);
25673 gen_helper_emt(t0);
25674 gen_store_gpr(t0, rt);
25675 break;
25676 case OPC_DVPE:
25677 check_cp0_mt(ctx);
25678 gen_helper_dvpe(t0, cpu_env);
25679 gen_store_gpr(t0, rt);
25680 break;
25681 case OPC_EVPE:
25682 check_cp0_mt(ctx);
25683 gen_helper_evpe(t0, cpu_env);
25684 gen_store_gpr(t0, rt);
25685 break;
25686 case OPC_DVP:
25687 check_insn(ctx, ISA_MIPS32R6);
25688 if (ctx->vp) {
25689 gen_helper_dvp(t0, cpu_env);
25690 gen_store_gpr(t0, rt);
25692 break;
25693 case OPC_EVP:
25694 check_insn(ctx, ISA_MIPS32R6);
25695 if (ctx->vp) {
25696 gen_helper_evp(t0, cpu_env);
25697 gen_store_gpr(t0, rt);
25699 break;
25700 case OPC_DI:
25701 check_insn(ctx, ISA_MIPS32R2);
25702 save_cpu_state(ctx, 1);
25703 gen_helper_di(t0, cpu_env);
25704 gen_store_gpr(t0, rt);
25705 /* Stop translation as we may have switched
25706 the execution mode. */
25707 ctx->base.is_jmp = DISAS_STOP;
25708 break;
25709 case OPC_EI:
25710 check_insn(ctx, ISA_MIPS32R2);
25711 save_cpu_state(ctx, 1);
25712 gen_helper_ei(t0, cpu_env);
25713 gen_store_gpr(t0, rt);
25714 /* DISAS_STOP isn't sufficient, we need to ensure we break
25715 out of translated code to check for pending interrupts */
25716 gen_save_pc(ctx->base.pc_next + 4);
25717 ctx->base.is_jmp = DISAS_EXIT;
25718 break;
25719 default: /* Invalid */
25720 MIPS_INVAL("mfmc0");
25721 generate_exception_end(ctx, EXCP_RI);
25722 break;
25724 tcg_temp_free(t0);
25726 #endif /* !CONFIG_USER_ONLY */
25727 break;
25728 case OPC_RDPGPR:
25729 check_insn(ctx, ISA_MIPS32R2);
25730 gen_load_srsgpr(rt, rd);
25731 break;
25732 case OPC_WRPGPR:
25733 check_insn(ctx, ISA_MIPS32R2);
25734 gen_store_srsgpr(rt, rd);
25735 break;
25736 default:
25737 MIPS_INVAL("cp0");
25738 generate_exception_end(ctx, EXCP_RI);
25739 break;
25741 break;
25742 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
25743 if (ctx->insn_flags & ISA_MIPS32R6) {
25744 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
25745 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25746 } else {
25747 /* OPC_ADDI */
25748 /* Arithmetic with immediate opcode */
25749 gen_arith_imm(ctx, op, rt, rs, imm);
25751 break;
25752 case OPC_ADDIU:
25753 gen_arith_imm(ctx, op, rt, rs, imm);
25754 break;
25755 case OPC_SLTI: /* Set on less than with immediate opcode */
25756 case OPC_SLTIU:
25757 gen_slt_imm(ctx, op, rt, rs, imm);
25758 break;
25759 case OPC_ANDI: /* Arithmetic with immediate opcode */
25760 case OPC_LUI: /* OPC_AUI */
25761 case OPC_ORI:
25762 case OPC_XORI:
25763 gen_logic_imm(ctx, op, rt, rs, imm);
25764 break;
25765 case OPC_J: /* Jump */
25766 case OPC_JAL:
25767 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25768 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25769 break;
25770 /* Branch */
25771 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
25772 if (ctx->insn_flags & ISA_MIPS32R6) {
25773 if (rt == 0) {
25774 generate_exception_end(ctx, EXCP_RI);
25775 break;
25777 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
25778 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25779 } else {
25780 /* OPC_BLEZL */
25781 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25783 break;
25784 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
25785 if (ctx->insn_flags & ISA_MIPS32R6) {
25786 if (rt == 0) {
25787 generate_exception_end(ctx, EXCP_RI);
25788 break;
25790 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
25791 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25792 } else {
25793 /* OPC_BGTZL */
25794 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25796 break;
25797 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
25798 if (rt == 0) {
25799 /* OPC_BLEZ */
25800 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25801 } else {
25802 check_insn(ctx, ISA_MIPS32R6);
25803 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
25804 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25806 break;
25807 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
25808 if (rt == 0) {
25809 /* OPC_BGTZ */
25810 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25811 } else {
25812 check_insn(ctx, ISA_MIPS32R6);
25813 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
25814 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25816 break;
25817 case OPC_BEQL:
25818 case OPC_BNEL:
25819 check_insn(ctx, ISA_MIPS2);
25820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25821 /* Fallthrough */
25822 case OPC_BEQ:
25823 case OPC_BNE:
25824 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
25825 break;
25826 case OPC_LL: /* Load and stores */
25827 check_insn(ctx, ISA_MIPS2);
25828 /* Fallthrough */
25829 case OPC_LWL:
25830 case OPC_LWR:
25831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25832 /* Fallthrough */
25833 case OPC_LB:
25834 case OPC_LH:
25835 case OPC_LW:
25836 case OPC_LWPC:
25837 case OPC_LBU:
25838 case OPC_LHU:
25839 gen_ld(ctx, op, rt, rs, imm);
25840 break;
25841 case OPC_SWL:
25842 case OPC_SWR:
25843 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25844 /* fall through */
25845 case OPC_SB:
25846 case OPC_SH:
25847 case OPC_SW:
25848 gen_st(ctx, op, rt, rs, imm);
25849 break;
25850 case OPC_SC:
25851 check_insn(ctx, ISA_MIPS2);
25852 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25853 gen_st_cond(ctx, op, rt, rs, imm);
25854 break;
25855 case OPC_CACHE:
25856 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25857 check_cp0_enabled(ctx);
25858 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
25859 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25860 gen_cache_operation(ctx, rt, rs, imm);
25862 /* Treat as NOP. */
25863 break;
25864 case OPC_PREF:
25865 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25866 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
25867 /* Treat as NOP. */
25868 break;
25870 /* Floating point (COP1). */
25871 case OPC_LWC1:
25872 case OPC_LDC1:
25873 case OPC_SWC1:
25874 case OPC_SDC1:
25875 gen_cop1_ldst(ctx, op, rt, rs, imm);
25876 break;
25878 case OPC_CP1:
25879 op1 = MASK_CP1(ctx->opcode);
25881 switch (op1) {
25882 case OPC_MFHC1:
25883 case OPC_MTHC1:
25884 check_cp1_enabled(ctx);
25885 check_insn(ctx, ISA_MIPS32R2);
25886 /* fall through */
25887 case OPC_MFC1:
25888 case OPC_CFC1:
25889 case OPC_MTC1:
25890 case OPC_CTC1:
25891 check_cp1_enabled(ctx);
25892 gen_cp1(ctx, op1, rt, rd);
25893 break;
25894 #if defined(TARGET_MIPS64)
25895 case OPC_DMFC1:
25896 case OPC_DMTC1:
25897 check_cp1_enabled(ctx);
25898 check_insn(ctx, ISA_MIPS3);
25899 check_mips_64(ctx);
25900 gen_cp1(ctx, op1, rt, rd);
25901 break;
25902 #endif
25903 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25904 check_cp1_enabled(ctx);
25905 if (ctx->insn_flags & ISA_MIPS32R6) {
25906 /* OPC_BC1EQZ */
25907 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25908 rt, imm << 2, 4);
25909 } else {
25910 /* OPC_BC1ANY2 */
25911 check_cop1x(ctx);
25912 check_insn(ctx, ASE_MIPS3D);
25913 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25914 (rt >> 2) & 0x7, imm << 2);
25916 break;
25917 case OPC_BC1NEZ:
25918 check_cp1_enabled(ctx);
25919 check_insn(ctx, ISA_MIPS32R6);
25920 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25921 rt, imm << 2, 4);
25922 break;
25923 case OPC_BC1ANY4:
25924 check_cp1_enabled(ctx);
25925 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25926 check_cop1x(ctx);
25927 check_insn(ctx, ASE_MIPS3D);
25928 /* fall through */
25929 case OPC_BC1:
25930 check_cp1_enabled(ctx);
25931 check_insn_opc_removed(ctx, ISA_MIPS32R6);
25932 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25933 (rt >> 2) & 0x7, imm << 2);
25934 break;
25935 case OPC_PS_FMT:
25936 check_ps(ctx);
25937 /* fall through */
25938 case OPC_S_FMT:
25939 case OPC_D_FMT:
25940 check_cp1_enabled(ctx);
25941 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25942 (imm >> 8) & 0x7);
25943 break;
25944 case OPC_W_FMT:
25945 case OPC_L_FMT:
25947 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25948 check_cp1_enabled(ctx);
25949 if (ctx->insn_flags & ISA_MIPS32R6) {
25950 switch (r6_op) {
25951 case R6_OPC_CMP_AF_S:
25952 case R6_OPC_CMP_UN_S:
25953 case R6_OPC_CMP_EQ_S:
25954 case R6_OPC_CMP_UEQ_S:
25955 case R6_OPC_CMP_LT_S:
25956 case R6_OPC_CMP_ULT_S:
25957 case R6_OPC_CMP_LE_S:
25958 case R6_OPC_CMP_ULE_S:
25959 case R6_OPC_CMP_SAF_S:
25960 case R6_OPC_CMP_SUN_S:
25961 case R6_OPC_CMP_SEQ_S:
25962 case R6_OPC_CMP_SEUQ_S:
25963 case R6_OPC_CMP_SLT_S:
25964 case R6_OPC_CMP_SULT_S:
25965 case R6_OPC_CMP_SLE_S:
25966 case R6_OPC_CMP_SULE_S:
25967 case R6_OPC_CMP_OR_S:
25968 case R6_OPC_CMP_UNE_S:
25969 case R6_OPC_CMP_NE_S:
25970 case R6_OPC_CMP_SOR_S:
25971 case R6_OPC_CMP_SUNE_S:
25972 case R6_OPC_CMP_SNE_S:
25973 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25974 break;
25975 case R6_OPC_CMP_AF_D:
25976 case R6_OPC_CMP_UN_D:
25977 case R6_OPC_CMP_EQ_D:
25978 case R6_OPC_CMP_UEQ_D:
25979 case R6_OPC_CMP_LT_D:
25980 case R6_OPC_CMP_ULT_D:
25981 case R6_OPC_CMP_LE_D:
25982 case R6_OPC_CMP_ULE_D:
25983 case R6_OPC_CMP_SAF_D:
25984 case R6_OPC_CMP_SUN_D:
25985 case R6_OPC_CMP_SEQ_D:
25986 case R6_OPC_CMP_SEUQ_D:
25987 case R6_OPC_CMP_SLT_D:
25988 case R6_OPC_CMP_SULT_D:
25989 case R6_OPC_CMP_SLE_D:
25990 case R6_OPC_CMP_SULE_D:
25991 case R6_OPC_CMP_OR_D:
25992 case R6_OPC_CMP_UNE_D:
25993 case R6_OPC_CMP_NE_D:
25994 case R6_OPC_CMP_SOR_D:
25995 case R6_OPC_CMP_SUNE_D:
25996 case R6_OPC_CMP_SNE_D:
25997 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25998 break;
25999 default:
26000 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
26001 rt, rd, sa, (imm >> 8) & 0x7);
26003 break;
26005 } else {
26006 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
26007 (imm >> 8) & 0x7);
26009 break;
26011 case OPC_BZ_V:
26012 case OPC_BNZ_V:
26013 case OPC_BZ_B:
26014 case OPC_BZ_H:
26015 case OPC_BZ_W:
26016 case OPC_BZ_D:
26017 case OPC_BNZ_B:
26018 case OPC_BNZ_H:
26019 case OPC_BNZ_W:
26020 case OPC_BNZ_D:
26021 check_insn(ctx, ASE_MSA);
26022 gen_msa_branch(env, ctx, op1);
26023 break;
26024 default:
26025 MIPS_INVAL("cp1");
26026 generate_exception_end(ctx, EXCP_RI);
26027 break;
26029 break;
26031 /* Compact branches [R6] and COP2 [non-R6] */
26032 case OPC_BC: /* OPC_LWC2 */
26033 case OPC_BALC: /* OPC_SWC2 */
26034 if (ctx->insn_flags & ISA_MIPS32R6) {
26035 /* OPC_BC, OPC_BALC */
26036 gen_compute_compact_branch(ctx, op, 0, 0,
26037 sextract32(ctx->opcode << 2, 0, 28));
26038 } else {
26039 /* OPC_LWC2, OPC_SWC2 */
26040 /* COP2: Not implemented. */
26041 generate_exception_err(ctx, EXCP_CpU, 2);
26043 break;
26044 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
26045 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
26046 if (ctx->insn_flags & ISA_MIPS32R6) {
26047 if (rs != 0) {
26048 /* OPC_BEQZC, OPC_BNEZC */
26049 gen_compute_compact_branch(ctx, op, rs, 0,
26050 sextract32(ctx->opcode << 2, 0, 23));
26051 } else {
26052 /* OPC_JIC, OPC_JIALC */
26053 gen_compute_compact_branch(ctx, op, 0, rt, imm);
26055 } else {
26056 /* OPC_LWC2, OPC_SWC2 */
26057 /* COP2: Not implemented. */
26058 generate_exception_err(ctx, EXCP_CpU, 2);
26060 break;
26061 case OPC_CP2:
26062 check_insn(ctx, INSN_LOONGSON2F);
26063 /* Note that these instructions use different fields. */
26064 gen_loongson_multimedia(ctx, sa, rd, rt);
26065 break;
26067 case OPC_CP3:
26068 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26069 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
26070 check_cp1_enabled(ctx);
26071 op1 = MASK_CP3(ctx->opcode);
26072 switch (op1) {
26073 case OPC_LUXC1:
26074 case OPC_SUXC1:
26075 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26076 /* Fallthrough */
26077 case OPC_LWXC1:
26078 case OPC_LDXC1:
26079 case OPC_SWXC1:
26080 case OPC_SDXC1:
26081 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26082 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
26083 break;
26084 case OPC_PREFX:
26085 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26086 /* Treat as NOP. */
26087 break;
26088 case OPC_ALNV_PS:
26089 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
26090 /* Fallthrough */
26091 case OPC_MADD_S:
26092 case OPC_MADD_D:
26093 case OPC_MADD_PS:
26094 case OPC_MSUB_S:
26095 case OPC_MSUB_D:
26096 case OPC_MSUB_PS:
26097 case OPC_NMADD_S:
26098 case OPC_NMADD_D:
26099 case OPC_NMADD_PS:
26100 case OPC_NMSUB_S:
26101 case OPC_NMSUB_D:
26102 case OPC_NMSUB_PS:
26103 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
26104 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
26105 break;
26106 default:
26107 MIPS_INVAL("cp3");
26108 generate_exception_end(ctx, EXCP_RI);
26109 break;
26111 } else {
26112 generate_exception_err(ctx, EXCP_CpU, 1);
26114 break;
26116 #if defined(TARGET_MIPS64)
26117 /* MIPS64 opcodes */
26118 case OPC_LDL:
26119 case OPC_LDR:
26120 case OPC_LLD:
26121 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26122 /* fall through */
26123 case OPC_LWU:
26124 case OPC_LD:
26125 check_insn(ctx, ISA_MIPS3);
26126 check_mips_64(ctx);
26127 gen_ld(ctx, op, rt, rs, imm);
26128 break;
26129 case OPC_SDL:
26130 case OPC_SDR:
26131 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26132 /* fall through */
26133 case OPC_SD:
26134 check_insn(ctx, ISA_MIPS3);
26135 check_mips_64(ctx);
26136 gen_st(ctx, op, rt, rs, imm);
26137 break;
26138 case OPC_SCD:
26139 check_insn_opc_removed(ctx, ISA_MIPS32R6);
26140 check_insn(ctx, ISA_MIPS3);
26141 check_mips_64(ctx);
26142 gen_st_cond(ctx, op, rt, rs, imm);
26143 break;
26144 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
26145 if (ctx->insn_flags & ISA_MIPS32R6) {
26146 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
26147 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26148 } else {
26149 /* OPC_DADDI */
26150 check_insn(ctx, ISA_MIPS3);
26151 check_mips_64(ctx);
26152 gen_arith_imm(ctx, op, rt, rs, imm);
26154 break;
26155 case OPC_DADDIU:
26156 check_insn(ctx, ISA_MIPS3);
26157 check_mips_64(ctx);
26158 gen_arith_imm(ctx, op, rt, rs, imm);
26159 break;
26160 #else
26161 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
26162 if (ctx->insn_flags & ISA_MIPS32R6) {
26163 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
26164 } else {
26165 MIPS_INVAL("major opcode");
26166 generate_exception_end(ctx, EXCP_RI);
26168 break;
26169 #endif
26170 case OPC_DAUI: /* OPC_JALX */
26171 if (ctx->insn_flags & ISA_MIPS32R6) {
26172 #if defined(TARGET_MIPS64)
26173 /* OPC_DAUI */
26174 check_mips_64(ctx);
26175 if (rs == 0) {
26176 generate_exception(ctx, EXCP_RI);
26177 } else if (rt != 0) {
26178 TCGv t0 = tcg_temp_new();
26179 gen_load_gpr(t0, rs);
26180 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
26181 tcg_temp_free(t0);
26183 #else
26184 generate_exception_end(ctx, EXCP_RI);
26185 MIPS_INVAL("major opcode");
26186 #endif
26187 } else {
26188 /* OPC_JALX */
26189 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
26190 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
26191 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
26193 break;
26194 case OPC_MSA: /* OPC_MDMX */
26195 /* MDMX: Not implemented. */
26196 gen_msa(env, ctx);
26197 break;
26198 case OPC_PCREL:
26199 check_insn(ctx, ISA_MIPS32R6);
26200 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
26201 break;
26202 default: /* Invalid */
26203 MIPS_INVAL("major opcode");
26204 generate_exception_end(ctx, EXCP_RI);
26205 break;
26209 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
26211 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26212 CPUMIPSState *env = cs->env_ptr;
26214 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
26215 ctx->saved_pc = -1;
26216 ctx->insn_flags = env->insn_flags;
26217 ctx->CP0_Config1 = env->CP0_Config1;
26218 ctx->CP0_Config2 = env->CP0_Config2;
26219 ctx->CP0_Config3 = env->CP0_Config3;
26220 ctx->CP0_Config5 = env->CP0_Config5;
26221 ctx->btarget = 0;
26222 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
26223 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
26224 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
26225 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
26226 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
26227 ctx->PAMask = env->PAMask;
26228 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
26229 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
26230 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
26231 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
26232 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
26233 /* Restore delay slot state from the tb context. */
26234 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
26235 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
26236 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
26237 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
26238 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
26239 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
26240 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
26241 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
26242 restore_cpu_state(env, ctx);
26243 #ifdef CONFIG_USER_ONLY
26244 ctx->mem_idx = MIPS_HFLAG_UM;
26245 #else
26246 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
26247 #endif
26248 ctx->default_tcg_memop_mask = (ctx->insn_flags & ISA_MIPS32R6) ?
26249 MO_UNALN : MO_ALIGN;
26251 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
26252 ctx->hflags);
26255 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
26259 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
26261 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26263 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
26264 ctx->btarget);
26267 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
26268 const CPUBreakpoint *bp)
26270 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26272 save_cpu_state(ctx, 1);
26273 ctx->base.is_jmp = DISAS_NORETURN;
26274 gen_helper_raise_exception_debug(cpu_env);
26275 /* The address covered by the breakpoint must be included in
26276 [tb->pc, tb->pc + tb->size) in order to for it to be
26277 properly cleared -- thus we increment the PC here so that
26278 the logic setting tb->size below does the right thing. */
26279 ctx->base.pc_next += 4;
26280 return true;
26283 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
26285 CPUMIPSState *env = cs->env_ptr;
26286 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26287 int insn_bytes;
26288 int is_slot;
26290 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
26291 if (ctx->insn_flags & ISA_NANOMIPS32) {
26292 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26293 insn_bytes = decode_nanomips_opc(env, ctx);
26294 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
26295 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
26296 insn_bytes = 4;
26297 decode_opc(env, ctx);
26298 } else if (ctx->insn_flags & ASE_MICROMIPS) {
26299 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26300 insn_bytes = decode_micromips_opc(env, ctx);
26301 } else if (ctx->insn_flags & ASE_MIPS16) {
26302 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
26303 insn_bytes = decode_mips16_opc(env, ctx);
26304 } else {
26305 generate_exception_end(ctx, EXCP_RI);
26306 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
26307 return;
26310 if (ctx->hflags & MIPS_HFLAG_BMASK) {
26311 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
26312 MIPS_HFLAG_FBNSLOT))) {
26313 /* force to generate branch as there is neither delay nor
26314 forbidden slot */
26315 is_slot = 1;
26317 if ((ctx->hflags & MIPS_HFLAG_M16) &&
26318 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
26319 /* Force to generate branch as microMIPS R6 doesn't restrict
26320 branches in the forbidden slot. */
26321 is_slot = 1;
26324 if (is_slot) {
26325 gen_branch(ctx, insn_bytes);
26327 ctx->base.pc_next += insn_bytes;
26329 if (ctx->base.is_jmp != DISAS_NEXT) {
26330 return;
26332 /* Execute a branch and its delay slot as a single instruction.
26333 This is what GDB expects and is consistent with what the
26334 hardware does (e.g. if a delay slot instruction faults, the
26335 reported PC is the PC of the branch). */
26336 if (ctx->base.singlestep_enabled &&
26337 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
26338 ctx->base.is_jmp = DISAS_TOO_MANY;
26340 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
26341 ctx->base.is_jmp = DISAS_TOO_MANY;
26345 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
26347 DisasContext *ctx = container_of(dcbase, DisasContext, base);
26349 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
26350 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
26351 gen_helper_raise_exception_debug(cpu_env);
26352 } else {
26353 switch (ctx->base.is_jmp) {
26354 case DISAS_STOP:
26355 gen_save_pc(ctx->base.pc_next);
26356 tcg_gen_lookup_and_goto_ptr();
26357 break;
26358 case DISAS_NEXT:
26359 case DISAS_TOO_MANY:
26360 save_cpu_state(ctx, 0);
26361 gen_goto_tb(ctx, 0, ctx->base.pc_next);
26362 break;
26363 case DISAS_EXIT:
26364 tcg_gen_exit_tb(NULL, 0);
26365 break;
26366 case DISAS_NORETURN:
26367 break;
26368 default:
26369 g_assert_not_reached();
26374 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
26376 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
26377 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
26380 static const TranslatorOps mips_tr_ops = {
26381 .init_disas_context = mips_tr_init_disas_context,
26382 .tb_start = mips_tr_tb_start,
26383 .insn_start = mips_tr_insn_start,
26384 .breakpoint_check = mips_tr_breakpoint_check,
26385 .translate_insn = mips_tr_translate_insn,
26386 .tb_stop = mips_tr_tb_stop,
26387 .disas_log = mips_tr_disas_log,
26390 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
26392 DisasContext ctx;
26394 translator_loop(&mips_tr_ops, &ctx.base, cs, tb);
26397 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
26398 int flags)
26400 int i;
26401 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
26403 #define printfpr(fp) \
26404 do { \
26405 if (is_fpu64) \
26406 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26407 " fd:%13g fs:%13g psu: %13g\n", \
26408 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
26409 (double)(fp)->fd, \
26410 (double)(fp)->fs[FP_ENDIAN_IDX], \
26411 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
26412 else { \
26413 fpr_t tmp; \
26414 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
26415 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
26416 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
26417 " fd:%13g fs:%13g psu:%13g\n", \
26418 tmp.w[FP_ENDIAN_IDX], tmp.d, \
26419 (double)tmp.fd, \
26420 (double)tmp.fs[FP_ENDIAN_IDX], \
26421 (double)tmp.fs[!FP_ENDIAN_IDX]); \
26423 } while(0)
26426 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
26427 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
26428 get_float_exception_flags(&env->active_fpu.fp_status));
26429 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
26430 fpu_fprintf(f, "%3s: ", fregnames[i]);
26431 printfpr(&env->active_fpu.fpr[i]);
26434 #undef printfpr
26437 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
26438 int flags)
26440 MIPSCPU *cpu = MIPS_CPU(cs);
26441 CPUMIPSState *env = &cpu->env;
26442 int i;
26444 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
26445 " LO=0x" TARGET_FMT_lx " ds %04x "
26446 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
26447 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
26448 env->hflags, env->btarget, env->bcond);
26449 for (i = 0; i < 32; i++) {
26450 if ((i & 3) == 0)
26451 cpu_fprintf(f, "GPR%02d:", i);
26452 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
26453 if ((i & 3) == 3)
26454 cpu_fprintf(f, "\n");
26457 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
26458 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
26459 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
26460 PRIx64 "\n",
26461 env->CP0_Config0, env->CP0_Config1, env->lladdr);
26462 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
26463 env->CP0_Config2, env->CP0_Config3);
26464 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
26465 env->CP0_Config4, env->CP0_Config5);
26466 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
26467 fpu_dump_state(env, f, cpu_fprintf, flags);
26471 void mips_tcg_init(void)
26473 int i;
26475 cpu_gpr[0] = NULL;
26476 for (i = 1; i < 32; i++)
26477 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
26478 offsetof(CPUMIPSState, active_tc.gpr[i]),
26479 regnames[i]);
26481 for (i = 0; i < 32; i++) {
26482 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
26483 msa_wr_d[i * 2] =
26484 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
26485 /* The scalar floating-point unit (FPU) registers are mapped on
26486 * the MSA vector registers. */
26487 fpu_f64[i] = msa_wr_d[i * 2];
26488 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
26489 msa_wr_d[i * 2 + 1] =
26490 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
26493 cpu_PC = tcg_global_mem_new(cpu_env,
26494 offsetof(CPUMIPSState, active_tc.PC), "PC");
26495 for (i = 0; i < MIPS_DSP_ACC; i++) {
26496 cpu_HI[i] = tcg_global_mem_new(cpu_env,
26497 offsetof(CPUMIPSState, active_tc.HI[i]),
26498 regnames_HI[i]);
26499 cpu_LO[i] = tcg_global_mem_new(cpu_env,
26500 offsetof(CPUMIPSState, active_tc.LO[i]),
26501 regnames_LO[i]);
26503 cpu_dspctrl = tcg_global_mem_new(cpu_env,
26504 offsetof(CPUMIPSState, active_tc.DSPControl),
26505 "DSPControl");
26506 bcond = tcg_global_mem_new(cpu_env,
26507 offsetof(CPUMIPSState, bcond), "bcond");
26508 btarget = tcg_global_mem_new(cpu_env,
26509 offsetof(CPUMIPSState, btarget), "btarget");
26510 hflags = tcg_global_mem_new_i32(cpu_env,
26511 offsetof(CPUMIPSState, hflags), "hflags");
26513 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
26514 offsetof(CPUMIPSState, active_fpu.fcr0),
26515 "fcr0");
26516 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
26517 offsetof(CPUMIPSState, active_fpu.fcr31),
26518 "fcr31");
26521 #include "translate_init.inc.c"
26523 void cpu_mips_realize_env(CPUMIPSState *env)
26525 env->exception_base = (int32_t)0xBFC00000;
26527 #ifndef CONFIG_USER_ONLY
26528 mmu_init(env, env->cpu_model);
26529 #endif
26530 fpu_init(env, env->cpu_model);
26531 mvp_init(env, env->cpu_model);
26534 bool cpu_supports_cps_smp(const char *cpu_type)
26536 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26537 return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
26540 bool cpu_supports_isa(const char *cpu_type, unsigned int isa)
26542 const MIPSCPUClass *mcc = MIPS_CPU_CLASS(object_class_by_name(cpu_type));
26543 return (mcc->cpu_def->insn_flags & isa) != 0;
26546 void cpu_set_exception_base(int vp_index, target_ulong address)
26548 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
26549 vp->env.exception_base = address;
26552 void cpu_state_reset(CPUMIPSState *env)
26554 MIPSCPU *cpu = mips_env_get_cpu(env);
26555 CPUState *cs = CPU(cpu);
26557 /* Reset registers to their default values */
26558 env->CP0_PRid = env->cpu_model->CP0_PRid;
26559 env->CP0_Config0 = env->cpu_model->CP0_Config0;
26560 #ifdef TARGET_WORDS_BIGENDIAN
26561 env->CP0_Config0 |= (1 << CP0C0_BE);
26562 #endif
26563 env->CP0_Config1 = env->cpu_model->CP0_Config1;
26564 env->CP0_Config2 = env->cpu_model->CP0_Config2;
26565 env->CP0_Config3 = env->cpu_model->CP0_Config3;
26566 env->CP0_Config4 = env->cpu_model->CP0_Config4;
26567 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
26568 env->CP0_Config5 = env->cpu_model->CP0_Config5;
26569 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
26570 env->CP0_Config6 = env->cpu_model->CP0_Config6;
26571 env->CP0_Config7 = env->cpu_model->CP0_Config7;
26572 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
26573 << env->cpu_model->CP0_LLAddr_shift;
26574 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
26575 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
26576 env->CCRes = env->cpu_model->CCRes;
26577 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
26578 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
26579 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
26580 env->current_tc = 0;
26581 env->SEGBITS = env->cpu_model->SEGBITS;
26582 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
26583 #if defined(TARGET_MIPS64)
26584 if (env->cpu_model->insn_flags & ISA_MIPS3) {
26585 env->SEGMask |= 3ULL << 62;
26587 #endif
26588 env->PABITS = env->cpu_model->PABITS;
26589 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
26590 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
26591 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
26592 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
26593 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
26594 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
26595 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
26596 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
26597 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
26598 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
26599 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
26600 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
26601 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
26602 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
26603 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
26604 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
26605 env->msair = env->cpu_model->MSAIR;
26606 env->insn_flags = env->cpu_model->insn_flags;
26608 #if defined(CONFIG_USER_ONLY)
26609 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
26610 # ifdef TARGET_MIPS64
26611 /* Enable 64-bit register mode. */
26612 env->CP0_Status |= (1 << CP0St_PX);
26613 # endif
26614 # ifdef TARGET_ABI_MIPSN64
26615 /* Enable 64-bit address mode. */
26616 env->CP0_Status |= (1 << CP0St_UX);
26617 # endif
26618 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
26619 hardware registers. */
26620 env->CP0_HWREna |= 0x0000000F;
26621 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
26622 env->CP0_Status |= (1 << CP0St_CU1);
26624 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
26625 env->CP0_Status |= (1 << CP0St_MX);
26627 # if defined(TARGET_MIPS64)
26628 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
26629 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
26630 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
26631 env->CP0_Status |= (1 << CP0St_FR);
26633 # endif
26634 #else
26635 if (env->hflags & MIPS_HFLAG_BMASK) {
26636 /* If the exception was raised from a delay slot,
26637 come back to the jump. */
26638 env->CP0_ErrorEPC = (env->active_tc.PC
26639 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
26640 } else {
26641 env->CP0_ErrorEPC = env->active_tc.PC;
26643 env->active_tc.PC = env->exception_base;
26644 env->CP0_Random = env->tlb->nb_tlb - 1;
26645 env->tlb->tlb_in_use = env->tlb->nb_tlb;
26646 env->CP0_Wired = 0;
26647 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
26648 env->CP0_EBase = (cs->cpu_index & 0x3FF);
26649 if (mips_um_ksegs_enabled()) {
26650 env->CP0_EBase |= 0x40000000;
26651 } else {
26652 env->CP0_EBase |= (int32_t)0x80000000;
26654 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
26655 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
26657 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
26658 0x3ff : 0xff;
26659 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
26660 /* vectored interrupts not implemented, timer on int 7,
26661 no performance counters. */
26662 env->CP0_IntCtl = 0xe0000000;
26664 int i;
26666 for (i = 0; i < 7; i++) {
26667 env->CP0_WatchLo[i] = 0;
26668 env->CP0_WatchHi[i] = 0x80000000;
26670 env->CP0_WatchLo[7] = 0;
26671 env->CP0_WatchHi[7] = 0;
26673 /* Count register increments in debug mode, EJTAG version 1 */
26674 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
26676 cpu_mips_store_count(env, 1);
26678 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
26679 int i;
26681 /* Only TC0 on VPE 0 starts as active. */
26682 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
26683 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
26684 env->tcs[i].CP0_TCHalt = 1;
26686 env->active_tc.CP0_TCHalt = 1;
26687 cs->halted = 1;
26689 if (cs->cpu_index == 0) {
26690 /* VPE0 starts up enabled. */
26691 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
26692 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
26694 /* TC0 starts up unhalted. */
26695 cs->halted = 0;
26696 env->active_tc.CP0_TCHalt = 0;
26697 env->tcs[0].CP0_TCHalt = 0;
26698 /* With thread 0 active. */
26699 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
26700 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
26705 * Configure default legacy segmentation control. We use this regardless of
26706 * whether segmentation control is presented to the guest.
26708 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
26709 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
26710 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
26711 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
26712 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
26713 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26714 (2 << CP0SC_C);
26715 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
26716 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
26717 (3 << CP0SC_C)) << 16;
26718 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
26719 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26720 (1 << CP0SC_EU) | (2 << CP0SC_C);
26721 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
26722 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
26723 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
26724 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
26725 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
26726 #endif
26727 if ((env->insn_flags & ISA_MIPS32R6) &&
26728 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
26729 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
26730 env->CP0_Status |= (1 << CP0St_FR);
26733 if (env->insn_flags & ISA_MIPS32R6) {
26734 /* PTW = 1 */
26735 env->CP0_PWSize = 0x40;
26736 /* GDI = 12 */
26737 /* UDI = 12 */
26738 /* MDI = 12 */
26739 /* PRI = 12 */
26740 /* PTEI = 2 */
26741 env->CP0_PWField = 0x0C30C302;
26742 } else {
26743 /* GDI = 0 */
26744 /* UDI = 0 */
26745 /* MDI = 0 */
26746 /* PRI = 0 */
26747 /* PTEI = 2 */
26748 env->CP0_PWField = 0x02;
26751 if (env->CP0_Config3 & (1 << CP0C3_ISA) & (1 << (CP0C3_ISA + 1))) {
26752 /* microMIPS on reset when Config3.ISA is 3 */
26753 env->hflags |= MIPS_HFLAG_M16;
26756 /* MSA */
26757 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
26758 msa_reset(env);
26761 compute_hflags(env);
26762 restore_fp_status(env);
26763 restore_pamask(env);
26764 cs->exception_index = EXCP_NONE;
26766 if (semihosting_get_argc()) {
26767 /* UHI interface can be used to obtain argc and argv */
26768 env->active_tc.gpr[4] = -1;
26772 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
26773 target_ulong *data)
26775 env->active_tc.PC = data[0];
26776 env->hflags &= ~MIPS_HFLAG_BMASK;
26777 env->hflags |= data[1];
26778 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
26779 case MIPS_HFLAG_BR:
26780 break;
26781 case MIPS_HFLAG_BC:
26782 case MIPS_HFLAG_BL:
26783 case MIPS_HFLAG_B:
26784 env->btarget = data[2];
26785 break;