docker: Fix test-mingw
[qemu/ar7.git] / target / mips / translate.c
blobd16d879df7386f4c028aa48902d20081047235c7
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/log.h"
41 #define MIPS_DEBUG_DISAS 0
43 /* MIPS major opcodes */
44 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
46 enum {
47 /* indirect opcode tables */
48 OPC_SPECIAL = (0x00 << 26),
49 OPC_REGIMM = (0x01 << 26),
50 OPC_CP0 = (0x10 << 26),
51 OPC_CP1 = (0x11 << 26),
52 OPC_CP2 = (0x12 << 26),
53 OPC_CP3 = (0x13 << 26),
54 OPC_SPECIAL2 = (0x1C << 26),
55 OPC_SPECIAL3 = (0x1F << 26),
56 /* arithmetic with immediate */
57 OPC_ADDI = (0x08 << 26),
58 OPC_ADDIU = (0x09 << 26),
59 OPC_SLTI = (0x0A << 26),
60 OPC_SLTIU = (0x0B << 26),
61 /* logic with immediate */
62 OPC_ANDI = (0x0C << 26),
63 OPC_ORI = (0x0D << 26),
64 OPC_XORI = (0x0E << 26),
65 OPC_LUI = (0x0F << 26),
66 /* arithmetic with immediate */
67 OPC_DADDI = (0x18 << 26),
68 OPC_DADDIU = (0x19 << 26),
69 /* Jump and branches */
70 OPC_J = (0x02 << 26),
71 OPC_JAL = (0x03 << 26),
72 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
73 OPC_BEQL = (0x14 << 26),
74 OPC_BNE = (0x05 << 26),
75 OPC_BNEL = (0x15 << 26),
76 OPC_BLEZ = (0x06 << 26),
77 OPC_BLEZL = (0x16 << 26),
78 OPC_BGTZ = (0x07 << 26),
79 OPC_BGTZL = (0x17 << 26),
80 OPC_JALX = (0x1D << 26),
81 OPC_DAUI = (0x1D << 26),
82 /* Load and stores */
83 OPC_LDL = (0x1A << 26),
84 OPC_LDR = (0x1B << 26),
85 OPC_LB = (0x20 << 26),
86 OPC_LH = (0x21 << 26),
87 OPC_LWL = (0x22 << 26),
88 OPC_LW = (0x23 << 26),
89 OPC_LWPC = OPC_LW | 0x5,
90 OPC_LBU = (0x24 << 26),
91 OPC_LHU = (0x25 << 26),
92 OPC_LWR = (0x26 << 26),
93 OPC_LWU = (0x27 << 26),
94 OPC_SB = (0x28 << 26),
95 OPC_SH = (0x29 << 26),
96 OPC_SWL = (0x2A << 26),
97 OPC_SW = (0x2B << 26),
98 OPC_SDL = (0x2C << 26),
99 OPC_SDR = (0x2D << 26),
100 OPC_SWR = (0x2E << 26),
101 OPC_LL = (0x30 << 26),
102 OPC_LLD = (0x34 << 26),
103 OPC_LD = (0x37 << 26),
104 OPC_LDPC = OPC_LD | 0x5,
105 OPC_SC = (0x38 << 26),
106 OPC_SCD = (0x3C << 26),
107 OPC_SD = (0x3F << 26),
108 /* Floating point load/store */
109 OPC_LWC1 = (0x31 << 26),
110 OPC_LWC2 = (0x32 << 26),
111 OPC_LDC1 = (0x35 << 26),
112 OPC_LDC2 = (0x36 << 26),
113 OPC_SWC1 = (0x39 << 26),
114 OPC_SWC2 = (0x3A << 26),
115 OPC_SDC1 = (0x3D << 26),
116 OPC_SDC2 = (0x3E << 26),
117 /* Compact Branches */
118 OPC_BLEZALC = (0x06 << 26),
119 OPC_BGEZALC = (0x06 << 26),
120 OPC_BGEUC = (0x06 << 26),
121 OPC_BGTZALC = (0x07 << 26),
122 OPC_BLTZALC = (0x07 << 26),
123 OPC_BLTUC = (0x07 << 26),
124 OPC_BOVC = (0x08 << 26),
125 OPC_BEQZALC = (0x08 << 26),
126 OPC_BEQC = (0x08 << 26),
127 OPC_BLEZC = (0x16 << 26),
128 OPC_BGEZC = (0x16 << 26),
129 OPC_BGEC = (0x16 << 26),
130 OPC_BGTZC = (0x17 << 26),
131 OPC_BLTZC = (0x17 << 26),
132 OPC_BLTC = (0x17 << 26),
133 OPC_BNVC = (0x18 << 26),
134 OPC_BNEZALC = (0x18 << 26),
135 OPC_BNEC = (0x18 << 26),
136 OPC_BC = (0x32 << 26),
137 OPC_BEQZC = (0x36 << 26),
138 OPC_JIC = (0x36 << 26),
139 OPC_BALC = (0x3A << 26),
140 OPC_BNEZC = (0x3E << 26),
141 OPC_JIALC = (0x3E << 26),
142 /* MDMX ASE specific */
143 OPC_MDMX = (0x1E << 26),
144 /* MSA ASE, same as MDMX */
145 OPC_MSA = OPC_MDMX,
146 /* Cache and prefetch */
147 OPC_CACHE = (0x2F << 26),
148 OPC_PREF = (0x33 << 26),
149 /* PC-relative address computation / loads */
150 OPC_PCREL = (0x3B << 26),
153 /* PC-relative address computation / loads */
154 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
155 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
156 enum {
157 /* Instructions determined by bits 19 and 20 */
158 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
159 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
160 OPC_LWUPC = OPC_PCREL | (2 << 19),
162 /* Instructions determined by bits 16 ... 20 */
163 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
164 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
166 /* Other */
167 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
170 /* MIPS special opcodes */
171 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
173 enum {
174 /* Shifts */
175 OPC_SLL = 0x00 | OPC_SPECIAL,
176 /* NOP is SLL r0, r0, 0 */
177 /* SSNOP is SLL r0, r0, 1 */
178 /* EHB is SLL r0, r0, 3 */
179 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
180 OPC_ROTR = OPC_SRL | (1 << 21),
181 OPC_SRA = 0x03 | OPC_SPECIAL,
182 OPC_SLLV = 0x04 | OPC_SPECIAL,
183 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
184 OPC_ROTRV = OPC_SRLV | (1 << 6),
185 OPC_SRAV = 0x07 | OPC_SPECIAL,
186 OPC_DSLLV = 0x14 | OPC_SPECIAL,
187 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
188 OPC_DROTRV = OPC_DSRLV | (1 << 6),
189 OPC_DSRAV = 0x17 | OPC_SPECIAL,
190 OPC_DSLL = 0x38 | OPC_SPECIAL,
191 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
192 OPC_DROTR = OPC_DSRL | (1 << 21),
193 OPC_DSRA = 0x3B | OPC_SPECIAL,
194 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
195 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
196 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
197 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
198 /* Multiplication / division */
199 OPC_MULT = 0x18 | OPC_SPECIAL,
200 OPC_MULTU = 0x19 | OPC_SPECIAL,
201 OPC_DIV = 0x1A | OPC_SPECIAL,
202 OPC_DIVU = 0x1B | OPC_SPECIAL,
203 OPC_DMULT = 0x1C | OPC_SPECIAL,
204 OPC_DMULTU = 0x1D | OPC_SPECIAL,
205 OPC_DDIV = 0x1E | OPC_SPECIAL,
206 OPC_DDIVU = 0x1F | OPC_SPECIAL,
208 /* 2 registers arithmetic / logic */
209 OPC_ADD = 0x20 | OPC_SPECIAL,
210 OPC_ADDU = 0x21 | OPC_SPECIAL,
211 OPC_SUB = 0x22 | OPC_SPECIAL,
212 OPC_SUBU = 0x23 | OPC_SPECIAL,
213 OPC_AND = 0x24 | OPC_SPECIAL,
214 OPC_OR = 0x25 | OPC_SPECIAL,
215 OPC_XOR = 0x26 | OPC_SPECIAL,
216 OPC_NOR = 0x27 | OPC_SPECIAL,
217 OPC_SLT = 0x2A | OPC_SPECIAL,
218 OPC_SLTU = 0x2B | OPC_SPECIAL,
219 OPC_DADD = 0x2C | OPC_SPECIAL,
220 OPC_DADDU = 0x2D | OPC_SPECIAL,
221 OPC_DSUB = 0x2E | OPC_SPECIAL,
222 OPC_DSUBU = 0x2F | OPC_SPECIAL,
223 /* Jumps */
224 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
225 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
226 /* Traps */
227 OPC_TGE = 0x30 | OPC_SPECIAL,
228 OPC_TGEU = 0x31 | OPC_SPECIAL,
229 OPC_TLT = 0x32 | OPC_SPECIAL,
230 OPC_TLTU = 0x33 | OPC_SPECIAL,
231 OPC_TEQ = 0x34 | OPC_SPECIAL,
232 OPC_TNE = 0x36 | OPC_SPECIAL,
233 /* HI / LO registers load & stores */
234 OPC_MFHI = 0x10 | OPC_SPECIAL,
235 OPC_MTHI = 0x11 | OPC_SPECIAL,
236 OPC_MFLO = 0x12 | OPC_SPECIAL,
237 OPC_MTLO = 0x13 | OPC_SPECIAL,
238 /* Conditional moves */
239 OPC_MOVZ = 0x0A | OPC_SPECIAL,
240 OPC_MOVN = 0x0B | OPC_SPECIAL,
242 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
243 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
245 OPC_MOVCI = 0x01 | OPC_SPECIAL,
247 /* Special */
248 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
249 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
250 OPC_BREAK = 0x0D | OPC_SPECIAL,
251 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
252 OPC_SYNC = 0x0F | OPC_SPECIAL,
254 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
255 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
256 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
257 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
260 /* R6 Multiply and Divide instructions have the same Opcode
261 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
262 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
264 enum {
265 R6_OPC_MUL = OPC_MULT | (2 << 6),
266 R6_OPC_MUH = OPC_MULT | (3 << 6),
267 R6_OPC_MULU = OPC_MULTU | (2 << 6),
268 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
269 R6_OPC_DIV = OPC_DIV | (2 << 6),
270 R6_OPC_MOD = OPC_DIV | (3 << 6),
271 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
272 R6_OPC_MODU = OPC_DIVU | (3 << 6),
274 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
275 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
276 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
277 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
278 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
279 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
280 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
281 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
283 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
284 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
285 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
286 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
287 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
289 OPC_LSA = 0x05 | OPC_SPECIAL,
290 OPC_DLSA = 0x15 | OPC_SPECIAL,
293 /* Multiplication variants of the vr54xx. */
294 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
296 enum {
297 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
298 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
299 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
300 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
301 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
302 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
303 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
304 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
305 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
306 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
307 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
308 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
309 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
310 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
313 /* REGIMM (rt field) opcodes */
314 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
316 enum {
317 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
318 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
319 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
320 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
321 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
322 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
323 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
324 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
325 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
326 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
327 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
328 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
329 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
330 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
331 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
332 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
334 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
335 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
338 /* Special2 opcodes */
339 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
341 enum {
342 /* Multiply & xxx operations */
343 OPC_MADD = 0x00 | OPC_SPECIAL2,
344 OPC_MADDU = 0x01 | OPC_SPECIAL2,
345 OPC_MUL = 0x02 | OPC_SPECIAL2,
346 OPC_MSUB = 0x04 | OPC_SPECIAL2,
347 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
348 /* Loongson 2F */
349 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
350 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
351 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
352 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
353 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
354 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
355 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
356 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
357 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
358 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
359 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
360 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
361 /* Misc */
362 OPC_CLZ = 0x20 | OPC_SPECIAL2,
363 OPC_CLO = 0x21 | OPC_SPECIAL2,
364 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
365 OPC_DCLO = 0x25 | OPC_SPECIAL2,
366 /* Special */
367 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
370 /* Special3 opcodes */
371 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
373 enum {
374 OPC_EXT = 0x00 | OPC_SPECIAL3,
375 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
376 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
377 OPC_DEXT = 0x03 | OPC_SPECIAL3,
378 OPC_INS = 0x04 | OPC_SPECIAL3,
379 OPC_DINSM = 0x05 | OPC_SPECIAL3,
380 OPC_DINSU = 0x06 | OPC_SPECIAL3,
381 OPC_DINS = 0x07 | OPC_SPECIAL3,
382 OPC_FORK = 0x08 | OPC_SPECIAL3,
383 OPC_YIELD = 0x09 | OPC_SPECIAL3,
384 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
385 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
386 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
388 /* Loongson 2E */
389 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
390 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
391 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
392 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
393 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
394 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
395 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
396 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
397 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
398 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
399 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
400 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
402 /* MIPS DSP Load */
403 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
404 /* MIPS DSP Arithmetic */
405 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
406 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
407 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
408 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
409 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
410 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
411 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
412 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
413 /* MIPS DSP GPR-Based Shift Sub-class */
414 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
415 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
416 /* MIPS DSP Multiply Sub-class insns */
417 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
418 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
419 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
420 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
421 /* DSP Bit/Manipulation Sub-class */
422 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
423 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
424 /* MIPS DSP Append Sub-class */
425 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
426 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
427 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
428 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
429 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
431 /* EVA */
432 OPC_LWLE = 0x19 | OPC_SPECIAL3,
433 OPC_LWRE = 0x1A | OPC_SPECIAL3,
434 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
435 OPC_SBE = 0x1C | OPC_SPECIAL3,
436 OPC_SHE = 0x1D | OPC_SPECIAL3,
437 OPC_SCE = 0x1E | OPC_SPECIAL3,
438 OPC_SWE = 0x1F | OPC_SPECIAL3,
439 OPC_SWLE = 0x21 | OPC_SPECIAL3,
440 OPC_SWRE = 0x22 | OPC_SPECIAL3,
441 OPC_PREFE = 0x23 | OPC_SPECIAL3,
442 OPC_LBUE = 0x28 | OPC_SPECIAL3,
443 OPC_LHUE = 0x29 | OPC_SPECIAL3,
444 OPC_LBE = 0x2C | OPC_SPECIAL3,
445 OPC_LHE = 0x2D | OPC_SPECIAL3,
446 OPC_LLE = 0x2E | OPC_SPECIAL3,
447 OPC_LWE = 0x2F | OPC_SPECIAL3,
449 /* R6 */
450 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
451 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
452 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
453 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
454 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
455 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
458 /* BSHFL opcodes */
459 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
461 enum {
462 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
463 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
464 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
465 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
466 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
467 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
470 /* DBSHFL opcodes */
471 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
473 enum {
474 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
475 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
476 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
477 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
478 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
481 /* MIPS DSP REGIMM opcodes */
482 enum {
483 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
484 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
487 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
488 /* MIPS DSP Load */
489 enum {
490 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
491 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
492 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
493 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
496 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
497 enum {
498 /* MIPS DSP Arithmetic Sub-class */
499 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
500 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
501 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
502 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
503 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
506 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
507 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
508 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
509 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
513 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
514 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
515 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
516 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
517 /* MIPS DSP Multiply Sub-class insns */
518 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
519 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
521 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
522 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
526 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
527 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
528 enum {
529 /* MIPS DSP Arithmetic Sub-class */
530 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
531 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
532 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
533 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
542 /* MIPS DSP Multiply Sub-class insns */
543 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
544 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
545 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
546 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
549 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
550 enum {
551 /* MIPS DSP Arithmetic Sub-class */
552 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
553 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
554 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
555 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
565 /* DSP Bit/Manipulation Sub-class */
566 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
569 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
573 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
574 enum {
575 /* MIPS DSP Arithmetic Sub-class */
576 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
577 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
578 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
579 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
583 /* DSP Compare-Pick Sub-class */
584 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
585 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
587 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
601 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
602 enum {
603 /* MIPS DSP GPR-Based Shift Sub-class */
604 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
605 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
606 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
607 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
628 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
629 enum {
630 /* MIPS DSP Multiply Sub-class insns */
631 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
632 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
633 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
634 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
645 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
648 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
655 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
656 enum {
657 /* DSP Bit/Manipulation Sub-class */
658 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
661 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
662 enum {
663 /* MIPS DSP Append Sub-class */
664 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
665 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
666 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
669 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
670 enum {
671 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
672 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
673 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
674 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
675 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
684 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
685 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
686 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
687 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
688 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
691 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
692 enum {
693 /* MIPS DSP Arithmetic Sub-class */
694 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
695 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
696 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
697 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
711 /* DSP Bit/Manipulation Sub-class */
712 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
715 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
720 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
721 enum {
722 /* MIPS DSP Multiply Sub-class insns */
723 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
724 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
725 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
726 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
728 /* MIPS DSP Arithmetic Sub-class */
729 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
730 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
731 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
732 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
740 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
741 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
742 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
752 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
753 enum {
754 /* DSP Compare-Pick Sub-class */
755 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
758 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
774 /* MIPS DSP Arithmetic Sub-class */
775 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
778 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
785 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
786 enum {
787 /* DSP Append Sub-class */
788 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
789 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
790 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
791 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
794 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
795 enum {
796 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
797 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
798 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
799 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
800 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
801 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
820 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
821 enum {
822 /* DSP Bit/Manipulation Sub-class */
823 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
826 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
827 enum {
828 /* MIPS DSP Multiply Sub-class insns */
829 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
830 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
831 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
832 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
857 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
858 enum {
859 /* MIPS DSP GPR-Based Shift Sub-class */
860 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
861 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
862 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
863 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
888 /* Coprocessor 0 (rs field) */
889 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
891 enum {
892 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
893 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
894 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
895 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
896 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
897 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
898 OPC_MFTR = (0x08 << 21) | OPC_CP0,
899 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
900 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
901 OPC_MTTR = (0x0C << 21) | OPC_CP0,
902 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
903 OPC_C0 = (0x10 << 21) | OPC_CP0,
904 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
905 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
908 /* MFMC0 opcodes */
909 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
911 enum {
912 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
913 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
914 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
915 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
916 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
917 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
918 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
919 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
922 /* Coprocessor 0 (with rs == C0) */
923 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
925 enum {
926 OPC_TLBR = 0x01 | OPC_C0,
927 OPC_TLBWI = 0x02 | OPC_C0,
928 OPC_TLBINV = 0x03 | OPC_C0,
929 OPC_TLBINVF = 0x04 | OPC_C0,
930 OPC_TLBWR = 0x06 | OPC_C0,
931 OPC_TLBP = 0x08 | OPC_C0,
932 OPC_RFE = 0x10 | OPC_C0,
933 OPC_ERET = 0x18 | OPC_C0,
934 OPC_DERET = 0x1F | OPC_C0,
935 OPC_WAIT = 0x20 | OPC_C0,
938 /* Coprocessor 1 (rs field) */
939 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
941 /* Values for the fmt field in FP instructions */
942 enum {
943 /* 0 - 15 are reserved */
944 FMT_S = 16, /* single fp */
945 FMT_D = 17, /* double fp */
946 FMT_E = 18, /* extended fp */
947 FMT_Q = 19, /* quad fp */
948 FMT_W = 20, /* 32-bit fixed */
949 FMT_L = 21, /* 64-bit fixed */
950 FMT_PS = 22, /* paired single fp */
951 /* 23 - 31 are reserved */
954 enum {
955 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
956 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
957 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
958 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
959 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
960 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
961 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
962 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
963 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
964 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
965 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
966 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
967 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
968 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
969 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
970 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
971 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
972 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
973 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
974 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
975 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
976 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
977 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
978 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
979 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
980 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
981 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
982 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
983 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
984 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
987 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
988 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
990 enum {
991 OPC_BC1F = (0x00 << 16) | OPC_BC1,
992 OPC_BC1T = (0x01 << 16) | OPC_BC1,
993 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
994 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
997 enum {
998 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
999 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1002 enum {
1003 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1004 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1007 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
1009 enum {
1010 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1011 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1012 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1013 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1014 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1015 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1016 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1017 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1018 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1019 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1020 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1023 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1025 enum {
1026 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1027 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1028 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1029 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1030 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1031 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1032 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1033 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1035 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1036 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1037 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1038 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1039 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1040 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1041 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1042 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1044 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1045 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1046 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1047 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1048 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1049 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1050 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1051 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1053 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1054 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1055 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1056 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1057 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1058 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1059 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1060 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1062 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1063 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1064 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1065 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1066 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1067 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1069 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1070 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1071 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1072 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1073 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1074 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1076 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1077 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1078 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1079 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1080 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1081 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1083 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1084 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1085 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1086 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1087 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1088 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1090 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1091 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1092 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1093 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1094 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1095 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1097 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1098 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1099 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1100 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1101 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1102 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1104 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1105 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1106 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1107 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1108 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1109 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1111 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1112 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1113 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1114 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1115 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1116 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1120 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1122 enum {
1123 OPC_LWXC1 = 0x00 | OPC_CP3,
1124 OPC_LDXC1 = 0x01 | OPC_CP3,
1125 OPC_LUXC1 = 0x05 | OPC_CP3,
1126 OPC_SWXC1 = 0x08 | OPC_CP3,
1127 OPC_SDXC1 = 0x09 | OPC_CP3,
1128 OPC_SUXC1 = 0x0D | OPC_CP3,
1129 OPC_PREFX = 0x0F | OPC_CP3,
1130 OPC_ALNV_PS = 0x1E | OPC_CP3,
1131 OPC_MADD_S = 0x20 | OPC_CP3,
1132 OPC_MADD_D = 0x21 | OPC_CP3,
1133 OPC_MADD_PS = 0x26 | OPC_CP3,
1134 OPC_MSUB_S = 0x28 | OPC_CP3,
1135 OPC_MSUB_D = 0x29 | OPC_CP3,
1136 OPC_MSUB_PS = 0x2E | OPC_CP3,
1137 OPC_NMADD_S = 0x30 | OPC_CP3,
1138 OPC_NMADD_D = 0x31 | OPC_CP3,
1139 OPC_NMADD_PS= 0x36 | OPC_CP3,
1140 OPC_NMSUB_S = 0x38 | OPC_CP3,
1141 OPC_NMSUB_D = 0x39 | OPC_CP3,
1142 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1145 /* MSA Opcodes */
1146 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1147 enum {
1148 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1149 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1150 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1151 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1152 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1153 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1154 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1155 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1156 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1157 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1158 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1159 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1160 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1161 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1162 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1163 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1164 OPC_MSA_ELM = 0x19 | OPC_MSA,
1165 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1166 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1167 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1168 OPC_MSA_VEC = 0x1E | OPC_MSA,
1170 /* MI10 instruction */
1171 OPC_LD_B = (0x20) | OPC_MSA,
1172 OPC_LD_H = (0x21) | OPC_MSA,
1173 OPC_LD_W = (0x22) | OPC_MSA,
1174 OPC_LD_D = (0x23) | OPC_MSA,
1175 OPC_ST_B = (0x24) | OPC_MSA,
1176 OPC_ST_H = (0x25) | OPC_MSA,
1177 OPC_ST_W = (0x26) | OPC_MSA,
1178 OPC_ST_D = (0x27) | OPC_MSA,
1181 enum {
1182 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1183 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1184 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1185 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1186 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1187 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1188 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1189 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1190 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1191 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1192 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1193 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1194 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1196 /* I8 instruction */
1197 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1198 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1199 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1200 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1201 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1202 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1203 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1204 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1205 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1206 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1208 /* VEC/2R/2RF instruction */
1209 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1210 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1211 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1212 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1213 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1214 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1215 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1217 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1218 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1220 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1221 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1222 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1223 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1224 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1226 /* 2RF instruction df(bit 16) = _w, _d */
1227 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1228 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1229 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1230 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1231 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1232 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1233 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1234 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1235 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1236 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1237 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1238 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1239 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1240 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1241 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1242 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1244 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1245 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1246 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1247 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1248 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1249 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1250 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1251 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1252 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1253 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1254 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1255 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1256 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1257 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1258 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1259 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1260 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1261 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1262 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1263 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1264 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1265 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1266 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1267 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1268 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1269 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1270 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1271 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1272 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1273 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1274 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1275 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1276 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1277 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1278 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1279 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1280 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1281 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1282 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1283 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1284 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1285 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1286 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1287 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1288 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1289 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1290 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1291 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1292 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1293 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1294 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1295 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1296 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1297 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1298 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1299 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1300 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1301 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1302 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1303 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1304 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1305 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1306 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1307 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1309 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1310 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1311 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1312 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1313 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1314 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1315 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1316 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1317 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1318 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1320 /* 3RF instruction _df(bit 21) = _w, _d */
1321 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1322 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1323 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1324 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1325 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1326 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1327 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1328 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1329 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1330 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1331 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1332 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1333 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1334 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1335 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1337 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1338 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1339 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1340 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1341 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1342 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1343 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1344 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1345 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1346 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1347 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1348 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1349 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1350 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1351 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1352 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1353 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1354 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1355 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1356 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1357 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1358 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1359 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1360 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1361 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1363 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1364 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1365 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1366 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1367 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1368 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1369 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1370 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1371 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1372 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1373 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1374 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1375 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1378 /* global register indices */
1379 static TCGv_env cpu_env;
1380 static TCGv cpu_gpr[32], cpu_PC;
1381 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1382 static TCGv cpu_dspctrl, btarget, bcond;
1383 static TCGv_i32 hflags;
1384 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1385 static TCGv_i64 fpu_f64[32];
1386 static TCGv_i64 msa_wr_d[64];
1388 #include "exec/gen-icount.h"
1390 #define gen_helper_0e0i(name, arg) do { \
1391 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1392 gen_helper_##name(cpu_env, helper_tmp); \
1393 tcg_temp_free_i32(helper_tmp); \
1394 } while(0)
1396 #define gen_helper_0e1i(name, arg1, arg2) do { \
1397 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1398 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1399 tcg_temp_free_i32(helper_tmp); \
1400 } while(0)
1402 #define gen_helper_1e0i(name, ret, arg1) do { \
1403 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1404 gen_helper_##name(ret, cpu_env, helper_tmp); \
1405 tcg_temp_free_i32(helper_tmp); \
1406 } while(0)
1408 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1409 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1410 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1411 tcg_temp_free_i32(helper_tmp); \
1412 } while(0)
1414 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1415 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1416 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1417 tcg_temp_free_i32(helper_tmp); \
1418 } while(0)
1420 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1421 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1422 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1423 tcg_temp_free_i32(helper_tmp); \
1424 } while(0)
1426 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1427 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1428 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1429 tcg_temp_free_i32(helper_tmp); \
1430 } while(0)
1432 typedef struct DisasContext {
1433 struct TranslationBlock *tb;
1434 target_ulong pc, saved_pc;
1435 uint32_t opcode;
1436 int singlestep_enabled;
1437 int insn_flags;
1438 int32_t CP0_Config1;
1439 /* Routine used to access memory */
1440 int mem_idx;
1441 TCGMemOp default_tcg_memop_mask;
1442 uint32_t hflags, saved_hflags;
1443 int bstate;
1444 target_ulong btarget;
1445 bool ulri;
1446 int kscrexist;
1447 bool rxi;
1448 int ie;
1449 bool bi;
1450 bool bp;
1451 uint64_t PAMask;
1452 bool mvh;
1453 bool eva;
1454 bool sc;
1455 int CP0_LLAddr_shift;
1456 bool ps;
1457 bool vp;
1458 bool cmgcr;
1459 bool mrp;
1460 bool nan2008;
1461 bool abs2008;
1462 } DisasContext;
1464 enum {
1465 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1466 * exception condition */
1467 BS_STOP = 1, /* We want to stop translation for any reason */
1468 BS_BRANCH = 2, /* We reached a branch condition */
1469 BS_EXCP = 3, /* We reached an exception condition */
1472 static const char * const regnames[] = {
1473 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1474 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1475 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1476 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1479 static const char * const regnames_HI[] = {
1480 "HI0", "HI1", "HI2", "HI3",
1483 static const char * const regnames_LO[] = {
1484 "LO0", "LO1", "LO2", "LO3",
1487 static const char * const fregnames[] = {
1488 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1489 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1490 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1491 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1494 static const char * const msaregnames[] = {
1495 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
1496 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
1497 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
1498 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
1499 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
1500 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
1501 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
1502 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
1503 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
1504 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
1505 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
1506 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
1507 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
1508 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
1509 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
1510 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
1513 #define LOG_DISAS(...) \
1514 do { \
1515 if (MIPS_DEBUG_DISAS) { \
1516 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1518 } while (0)
1520 #define MIPS_INVAL(op) \
1521 do { \
1522 if (MIPS_DEBUG_DISAS) { \
1523 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1524 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
1525 ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
1526 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
1528 } while (0)
1530 /* General purpose registers moves. */
1531 static inline void gen_load_gpr (TCGv t, int reg)
1533 if (reg == 0)
1534 tcg_gen_movi_tl(t, 0);
1535 else
1536 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1539 static inline void gen_store_gpr (TCGv t, int reg)
1541 if (reg != 0)
1542 tcg_gen_mov_tl(cpu_gpr[reg], t);
1545 /* Moves to/from shadow registers. */
1546 static inline void gen_load_srsgpr (int from, int to)
1548 TCGv t0 = tcg_temp_new();
1550 if (from == 0)
1551 tcg_gen_movi_tl(t0, 0);
1552 else {
1553 TCGv_i32 t2 = tcg_temp_new_i32();
1554 TCGv_ptr addr = tcg_temp_new_ptr();
1556 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1557 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1558 tcg_gen_andi_i32(t2, t2, 0xf);
1559 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1560 tcg_gen_ext_i32_ptr(addr, t2);
1561 tcg_gen_add_ptr(addr, cpu_env, addr);
1563 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1564 tcg_temp_free_ptr(addr);
1565 tcg_temp_free_i32(t2);
1567 gen_store_gpr(t0, to);
1568 tcg_temp_free(t0);
1571 static inline void gen_store_srsgpr (int from, int to)
1573 if (to != 0) {
1574 TCGv t0 = tcg_temp_new();
1575 TCGv_i32 t2 = tcg_temp_new_i32();
1576 TCGv_ptr addr = tcg_temp_new_ptr();
1578 gen_load_gpr(t0, from);
1579 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1580 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1581 tcg_gen_andi_i32(t2, t2, 0xf);
1582 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1583 tcg_gen_ext_i32_ptr(addr, t2);
1584 tcg_gen_add_ptr(addr, cpu_env, addr);
1586 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1587 tcg_temp_free_ptr(addr);
1588 tcg_temp_free_i32(t2);
1589 tcg_temp_free(t0);
1593 /* Tests */
1594 static inline void gen_save_pc(target_ulong pc)
1596 tcg_gen_movi_tl(cpu_PC, pc);
1599 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1601 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1602 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1603 gen_save_pc(ctx->pc);
1604 ctx->saved_pc = ctx->pc;
1606 if (ctx->hflags != ctx->saved_hflags) {
1607 tcg_gen_movi_i32(hflags, ctx->hflags);
1608 ctx->saved_hflags = ctx->hflags;
1609 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1610 case MIPS_HFLAG_BR:
1611 break;
1612 case MIPS_HFLAG_BC:
1613 case MIPS_HFLAG_BL:
1614 case MIPS_HFLAG_B:
1615 tcg_gen_movi_tl(btarget, ctx->btarget);
1616 break;
1621 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1623 ctx->saved_hflags = ctx->hflags;
1624 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1625 case MIPS_HFLAG_BR:
1626 break;
1627 case MIPS_HFLAG_BC:
1628 case MIPS_HFLAG_BL:
1629 case MIPS_HFLAG_B:
1630 ctx->btarget = env->btarget;
1631 break;
1635 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
1637 TCGv_i32 texcp = tcg_const_i32(excp);
1638 TCGv_i32 terr = tcg_const_i32(err);
1639 save_cpu_state(ctx, 1);
1640 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1641 tcg_temp_free_i32(terr);
1642 tcg_temp_free_i32(texcp);
1643 ctx->bstate = BS_EXCP;
1646 static inline void generate_exception(DisasContext *ctx, int excp)
1648 gen_helper_0e0i(raise_exception, excp);
1651 static inline void generate_exception_end(DisasContext *ctx, int excp)
1653 generate_exception_err(ctx, excp, 0);
1656 /* Floating point register moves. */
1657 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1659 if (ctx->hflags & MIPS_HFLAG_FRE) {
1660 generate_exception(ctx, EXCP_RI);
1662 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1665 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1667 TCGv_i64 t64;
1668 if (ctx->hflags & MIPS_HFLAG_FRE) {
1669 generate_exception(ctx, EXCP_RI);
1671 t64 = tcg_temp_new_i64();
1672 tcg_gen_extu_i32_i64(t64, t);
1673 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1674 tcg_temp_free_i64(t64);
1677 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1679 if (ctx->hflags & MIPS_HFLAG_F64) {
1680 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1681 } else {
1682 gen_load_fpr32(ctx, t, reg | 1);
1686 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1688 if (ctx->hflags & MIPS_HFLAG_F64) {
1689 TCGv_i64 t64 = tcg_temp_new_i64();
1690 tcg_gen_extu_i32_i64(t64, t);
1691 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1692 tcg_temp_free_i64(t64);
1693 } else {
1694 gen_store_fpr32(ctx, t, reg | 1);
1698 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1700 if (ctx->hflags & MIPS_HFLAG_F64) {
1701 tcg_gen_mov_i64(t, fpu_f64[reg]);
1702 } else {
1703 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1707 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1709 if (ctx->hflags & MIPS_HFLAG_F64) {
1710 tcg_gen_mov_i64(fpu_f64[reg], t);
1711 } else {
1712 TCGv_i64 t0;
1713 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1714 t0 = tcg_temp_new_i64();
1715 tcg_gen_shri_i64(t0, t, 32);
1716 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1717 tcg_temp_free_i64(t0);
1721 static inline int get_fp_bit (int cc)
1723 if (cc)
1724 return 24 + cc;
1725 else
1726 return 23;
1729 /* Addresses computation */
1730 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1732 tcg_gen_add_tl(ret, arg0, arg1);
1734 #if defined(TARGET_MIPS64)
1735 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1736 tcg_gen_ext32s_i64(ret, ret);
1738 #endif
1741 /* Addresses computation (translation time) */
1742 static target_long addr_add(DisasContext *ctx, target_long base,
1743 target_long offset)
1745 target_long sum = base + offset;
1747 #if defined(TARGET_MIPS64)
1748 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1749 sum = (int32_t)sum;
1751 #endif
1752 return sum;
1755 /* Sign-extract the low 32-bits to a target_long. */
1756 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
1758 #if defined(TARGET_MIPS64)
1759 tcg_gen_ext32s_i64(ret, arg);
1760 #else
1761 tcg_gen_extrl_i64_i32(ret, arg);
1762 #endif
1765 /* Sign-extract the high 32-bits to a target_long. */
1766 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
1768 #if defined(TARGET_MIPS64)
1769 tcg_gen_sari_i64(ret, arg, 32);
1770 #else
1771 tcg_gen_extrh_i64_i32(ret, arg);
1772 #endif
1775 static inline void check_cp0_enabled(DisasContext *ctx)
1777 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1778 generate_exception_err(ctx, EXCP_CpU, 0);
1781 static inline void check_cp1_enabled(DisasContext *ctx)
1783 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1784 generate_exception_err(ctx, EXCP_CpU, 1);
1787 /* Verify that the processor is running with COP1X instructions enabled.
1788 This is associated with the nabla symbol in the MIPS32 and MIPS64
1789 opcode tables. */
1791 static inline void check_cop1x(DisasContext *ctx)
1793 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1794 generate_exception_end(ctx, EXCP_RI);
1797 /* Verify that the processor is running with 64-bit floating-point
1798 operations enabled. */
1800 static inline void check_cp1_64bitmode(DisasContext *ctx)
1802 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1803 generate_exception_end(ctx, EXCP_RI);
1807 * Verify if floating point register is valid; an operation is not defined
1808 * if bit 0 of any register specification is set and the FR bit in the
1809 * Status register equals zero, since the register numbers specify an
1810 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1811 * in the Status register equals one, both even and odd register numbers
1812 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1814 * Multiple 64 bit wide registers can be checked by calling
1815 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1817 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1819 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1820 generate_exception_end(ctx, EXCP_RI);
1823 /* Verify that the processor is running with DSP instructions enabled.
1824 This is enabled by CP0 Status register MX(24) bit.
1827 static inline void check_dsp(DisasContext *ctx)
1829 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1830 if (ctx->insn_flags & ASE_DSP) {
1831 generate_exception_end(ctx, EXCP_DSPDIS);
1832 } else {
1833 generate_exception_end(ctx, EXCP_RI);
1838 static inline void check_dspr2(DisasContext *ctx)
1840 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1841 if (ctx->insn_flags & ASE_DSP) {
1842 generate_exception_end(ctx, EXCP_DSPDIS);
1843 } else {
1844 generate_exception_end(ctx, EXCP_RI);
1849 /* This code generates a "reserved instruction" exception if the
1850 CPU does not support the instruction set corresponding to flags. */
1851 static inline void check_insn(DisasContext *ctx, int flags)
1853 if (unlikely(!(ctx->insn_flags & flags))) {
1854 generate_exception_end(ctx, EXCP_RI);
1858 /* This code generates a "reserved instruction" exception if the
1859 CPU has corresponding flag set which indicates that the instruction
1860 has been removed. */
1861 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1863 if (unlikely(ctx->insn_flags & flags)) {
1864 generate_exception_end(ctx, EXCP_RI);
1868 /* This code generates a "reserved instruction" exception if the
1869 CPU does not support 64-bit paired-single (PS) floating point data type */
1870 static inline void check_ps(DisasContext *ctx)
1872 if (unlikely(!ctx->ps)) {
1873 generate_exception(ctx, EXCP_RI);
1875 check_cp1_64bitmode(ctx);
1878 #ifdef TARGET_MIPS64
1879 /* This code generates a "reserved instruction" exception if 64-bit
1880 instructions are not enabled. */
1881 static inline void check_mips_64(DisasContext *ctx)
1883 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1884 generate_exception_end(ctx, EXCP_RI);
1886 #endif
1888 #ifndef CONFIG_USER_ONLY
1889 static inline void check_mvh(DisasContext *ctx)
1891 if (unlikely(!ctx->mvh)) {
1892 generate_exception(ctx, EXCP_RI);
1895 #endif
1897 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1898 calling interface for 32 and 64-bit FPRs. No sense in changing
1899 all callers for gen_load_fpr32 when we need the CTX parameter for
1900 this one use. */
1901 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1902 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1903 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1904 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1905 int ft, int fs, int cc) \
1907 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1908 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1909 switch (ifmt) { \
1910 case FMT_PS: \
1911 check_ps(ctx); \
1912 break; \
1913 case FMT_D: \
1914 if (abs) { \
1915 check_cop1x(ctx); \
1917 check_cp1_registers(ctx, fs | ft); \
1918 break; \
1919 case FMT_S: \
1920 if (abs) { \
1921 check_cop1x(ctx); \
1923 break; \
1925 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1926 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1927 switch (n) { \
1928 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1929 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1930 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1931 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1932 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1933 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1934 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1935 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1936 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1937 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1938 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1939 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1940 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1941 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1942 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1943 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1944 default: abort(); \
1946 tcg_temp_free_i##bits (fp0); \
1947 tcg_temp_free_i##bits (fp1); \
1950 FOP_CONDS(, 0, d, FMT_D, 64)
1951 FOP_CONDS(abs, 1, d, FMT_D, 64)
1952 FOP_CONDS(, 0, s, FMT_S, 32)
1953 FOP_CONDS(abs, 1, s, FMT_S, 32)
1954 FOP_CONDS(, 0, ps, FMT_PS, 64)
1955 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1956 #undef FOP_CONDS
1958 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1959 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1960 int ft, int fs, int fd) \
1962 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1963 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1964 if (ifmt == FMT_D) { \
1965 check_cp1_registers(ctx, fs | ft | fd); \
1967 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1968 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1969 switch (n) { \
1970 case 0: \
1971 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1972 break; \
1973 case 1: \
1974 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1975 break; \
1976 case 2: \
1977 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1978 break; \
1979 case 3: \
1980 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1981 break; \
1982 case 4: \
1983 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1984 break; \
1985 case 5: \
1986 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1987 break; \
1988 case 6: \
1989 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1990 break; \
1991 case 7: \
1992 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1993 break; \
1994 case 8: \
1995 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1996 break; \
1997 case 9: \
1998 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1999 break; \
2000 case 10: \
2001 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
2002 break; \
2003 case 11: \
2004 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
2005 break; \
2006 case 12: \
2007 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
2008 break; \
2009 case 13: \
2010 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
2011 break; \
2012 case 14: \
2013 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
2014 break; \
2015 case 15: \
2016 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
2017 break; \
2018 case 17: \
2019 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
2020 break; \
2021 case 18: \
2022 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
2023 break; \
2024 case 19: \
2025 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
2026 break; \
2027 case 25: \
2028 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
2029 break; \
2030 case 26: \
2031 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2032 break; \
2033 case 27: \
2034 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2035 break; \
2036 default: \
2037 abort(); \
2039 STORE; \
2040 tcg_temp_free_i ## bits (fp0); \
2041 tcg_temp_free_i ## bits (fp1); \
2044 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2045 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2046 #undef FOP_CONDNS
2047 #undef gen_ldcmp_fpr32
2048 #undef gen_ldcmp_fpr64
2050 /* load/store instructions. */
2051 #ifdef CONFIG_USER_ONLY
2052 #define OP_LD_ATOMIC(insn,fname) \
2053 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2054 DisasContext *ctx) \
2056 TCGv t0 = tcg_temp_new(); \
2057 tcg_gen_mov_tl(t0, arg1); \
2058 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2059 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2060 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2061 tcg_temp_free(t0); \
2063 #else
2064 #define OP_LD_ATOMIC(insn,fname) \
2065 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2066 DisasContext *ctx) \
2068 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2070 #endif
2071 OP_LD_ATOMIC(ll,ld32s);
2072 #if defined(TARGET_MIPS64)
2073 OP_LD_ATOMIC(lld,ld64);
2074 #endif
2075 #undef OP_LD_ATOMIC
2077 #ifdef CONFIG_USER_ONLY
2078 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2079 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2080 DisasContext *ctx) \
2082 TCGv t0 = tcg_temp_new(); \
2083 TCGLabel *l1 = gen_new_label(); \
2084 TCGLabel *l2 = gen_new_label(); \
2086 tcg_gen_andi_tl(t0, arg2, almask); \
2087 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
2088 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
2089 generate_exception(ctx, EXCP_AdES); \
2090 gen_set_label(l1); \
2091 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2092 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
2093 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
2094 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
2095 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
2096 generate_exception_end(ctx, EXCP_SC); \
2097 gen_set_label(l2); \
2098 tcg_gen_movi_tl(t0, 0); \
2099 gen_store_gpr(t0, rt); \
2100 tcg_temp_free(t0); \
2102 #else
2103 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
2104 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, int mem_idx, \
2105 DisasContext *ctx) \
2107 TCGv t0 = tcg_temp_new(); \
2108 gen_helper_1e2i(insn, t0, arg1, arg2, mem_idx); \
2109 gen_store_gpr(t0, rt); \
2110 tcg_temp_free(t0); \
2112 #endif
2113 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
2114 #if defined(TARGET_MIPS64)
2115 OP_ST_ATOMIC(scd,st64,ld64,0x7);
2116 #endif
2117 #undef OP_ST_ATOMIC
2119 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
2120 int base, int16_t offset)
2122 if (base == 0) {
2123 tcg_gen_movi_tl(addr, offset);
2124 } else if (offset == 0) {
2125 gen_load_gpr(addr, base);
2126 } else {
2127 tcg_gen_movi_tl(addr, offset);
2128 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2132 static target_ulong pc_relative_pc (DisasContext *ctx)
2134 target_ulong pc = ctx->pc;
2136 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2137 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2139 pc -= branch_bytes;
2142 pc &= ~(target_ulong)3;
2143 return pc;
2146 /* Load */
2147 static void gen_ld(DisasContext *ctx, uint32_t opc,
2148 int rt, int base, int16_t offset)
2150 TCGv t0, t1, t2;
2151 int mem_idx = ctx->mem_idx;
2153 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
2154 /* Loongson CPU uses a load to zero register for prefetch.
2155 We emulate it as a NOP. On other CPU we must perform the
2156 actual memory access. */
2157 return;
2160 t0 = tcg_temp_new();
2161 gen_base_offset_addr(ctx, t0, base, offset);
2163 switch (opc) {
2164 #if defined(TARGET_MIPS64)
2165 case OPC_LWU:
2166 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2167 ctx->default_tcg_memop_mask);
2168 gen_store_gpr(t0, rt);
2169 break;
2170 case OPC_LD:
2171 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2172 ctx->default_tcg_memop_mask);
2173 gen_store_gpr(t0, rt);
2174 break;
2175 case OPC_LLD:
2176 case R6_OPC_LLD:
2177 op_ld_lld(t0, t0, mem_idx, ctx);
2178 gen_store_gpr(t0, rt);
2179 break;
2180 case OPC_LDL:
2181 t1 = tcg_temp_new();
2182 /* Do a byte access to possibly trigger a page
2183 fault with the unaligned address. */
2184 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2185 tcg_gen_andi_tl(t1, t0, 7);
2186 #ifndef TARGET_WORDS_BIGENDIAN
2187 tcg_gen_xori_tl(t1, t1, 7);
2188 #endif
2189 tcg_gen_shli_tl(t1, t1, 3);
2190 tcg_gen_andi_tl(t0, t0, ~7);
2191 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2192 tcg_gen_shl_tl(t0, t0, t1);
2193 t2 = tcg_const_tl(-1);
2194 tcg_gen_shl_tl(t2, t2, t1);
2195 gen_load_gpr(t1, rt);
2196 tcg_gen_andc_tl(t1, t1, t2);
2197 tcg_temp_free(t2);
2198 tcg_gen_or_tl(t0, t0, t1);
2199 tcg_temp_free(t1);
2200 gen_store_gpr(t0, rt);
2201 break;
2202 case OPC_LDR:
2203 t1 = tcg_temp_new();
2204 /* Do a byte access to possibly trigger a page
2205 fault with the unaligned address. */
2206 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2207 tcg_gen_andi_tl(t1, t0, 7);
2208 #ifdef TARGET_WORDS_BIGENDIAN
2209 tcg_gen_xori_tl(t1, t1, 7);
2210 #endif
2211 tcg_gen_shli_tl(t1, t1, 3);
2212 tcg_gen_andi_tl(t0, t0, ~7);
2213 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2214 tcg_gen_shr_tl(t0, t0, t1);
2215 tcg_gen_xori_tl(t1, t1, 63);
2216 t2 = tcg_const_tl(0xfffffffffffffffeull);
2217 tcg_gen_shl_tl(t2, t2, t1);
2218 gen_load_gpr(t1, rt);
2219 tcg_gen_and_tl(t1, t1, t2);
2220 tcg_temp_free(t2);
2221 tcg_gen_or_tl(t0, t0, t1);
2222 tcg_temp_free(t1);
2223 gen_store_gpr(t0, rt);
2224 break;
2225 case OPC_LDPC:
2226 t1 = tcg_const_tl(pc_relative_pc(ctx));
2227 gen_op_addr_add(ctx, t0, t0, t1);
2228 tcg_temp_free(t1);
2229 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2230 gen_store_gpr(t0, rt);
2231 break;
2232 #endif
2233 case OPC_LWPC:
2234 t1 = tcg_const_tl(pc_relative_pc(ctx));
2235 gen_op_addr_add(ctx, t0, t0, t1);
2236 tcg_temp_free(t1);
2237 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2238 gen_store_gpr(t0, rt);
2239 break;
2240 case OPC_LWE:
2241 mem_idx = MIPS_HFLAG_UM;
2242 /* fall through */
2243 case OPC_LW:
2244 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2245 ctx->default_tcg_memop_mask);
2246 gen_store_gpr(t0, rt);
2247 break;
2248 case OPC_LHE:
2249 mem_idx = MIPS_HFLAG_UM;
2250 /* fall through */
2251 case OPC_LH:
2252 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2253 ctx->default_tcg_memop_mask);
2254 gen_store_gpr(t0, rt);
2255 break;
2256 case OPC_LHUE:
2257 mem_idx = MIPS_HFLAG_UM;
2258 /* fall through */
2259 case OPC_LHU:
2260 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2261 ctx->default_tcg_memop_mask);
2262 gen_store_gpr(t0, rt);
2263 break;
2264 case OPC_LBE:
2265 mem_idx = MIPS_HFLAG_UM;
2266 /* fall through */
2267 case OPC_LB:
2268 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2269 gen_store_gpr(t0, rt);
2270 break;
2271 case OPC_LBUE:
2272 mem_idx = MIPS_HFLAG_UM;
2273 /* fall through */
2274 case OPC_LBU:
2275 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2276 gen_store_gpr(t0, rt);
2277 break;
2278 case OPC_LWLE:
2279 mem_idx = MIPS_HFLAG_UM;
2280 /* fall through */
2281 case OPC_LWL:
2282 t1 = tcg_temp_new();
2283 /* Do a byte access to possibly trigger a page
2284 fault with the unaligned address. */
2285 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2286 tcg_gen_andi_tl(t1, t0, 3);
2287 #ifndef TARGET_WORDS_BIGENDIAN
2288 tcg_gen_xori_tl(t1, t1, 3);
2289 #endif
2290 tcg_gen_shli_tl(t1, t1, 3);
2291 tcg_gen_andi_tl(t0, t0, ~3);
2292 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2293 tcg_gen_shl_tl(t0, t0, t1);
2294 t2 = tcg_const_tl(-1);
2295 tcg_gen_shl_tl(t2, t2, t1);
2296 gen_load_gpr(t1, rt);
2297 tcg_gen_andc_tl(t1, t1, t2);
2298 tcg_temp_free(t2);
2299 tcg_gen_or_tl(t0, t0, t1);
2300 tcg_temp_free(t1);
2301 tcg_gen_ext32s_tl(t0, t0);
2302 gen_store_gpr(t0, rt);
2303 break;
2304 case OPC_LWRE:
2305 mem_idx = MIPS_HFLAG_UM;
2306 /* fall through */
2307 case OPC_LWR:
2308 t1 = tcg_temp_new();
2309 /* Do a byte access to possibly trigger a page
2310 fault with the unaligned address. */
2311 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2312 tcg_gen_andi_tl(t1, t0, 3);
2313 #ifdef TARGET_WORDS_BIGENDIAN
2314 tcg_gen_xori_tl(t1, t1, 3);
2315 #endif
2316 tcg_gen_shli_tl(t1, t1, 3);
2317 tcg_gen_andi_tl(t0, t0, ~3);
2318 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2319 tcg_gen_shr_tl(t0, t0, t1);
2320 tcg_gen_xori_tl(t1, t1, 31);
2321 t2 = tcg_const_tl(0xfffffffeull);
2322 tcg_gen_shl_tl(t2, t2, t1);
2323 gen_load_gpr(t1, rt);
2324 tcg_gen_and_tl(t1, t1, t2);
2325 tcg_temp_free(t2);
2326 tcg_gen_or_tl(t0, t0, t1);
2327 tcg_temp_free(t1);
2328 tcg_gen_ext32s_tl(t0, t0);
2329 gen_store_gpr(t0, rt);
2330 break;
2331 case OPC_LLE:
2332 mem_idx = MIPS_HFLAG_UM;
2333 /* fall through */
2334 case OPC_LL:
2335 case R6_OPC_LL:
2336 op_ld_ll(t0, t0, mem_idx, ctx);
2337 gen_store_gpr(t0, rt);
2338 break;
2340 tcg_temp_free(t0);
2343 /* Store */
2344 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
2345 int base, int16_t offset)
2347 TCGv t0 = tcg_temp_new();
2348 TCGv t1 = tcg_temp_new();
2349 int mem_idx = ctx->mem_idx;
2351 gen_base_offset_addr(ctx, t0, base, offset);
2352 gen_load_gpr(t1, rt);
2353 switch (opc) {
2354 #if defined(TARGET_MIPS64)
2355 case OPC_SD:
2356 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2357 ctx->default_tcg_memop_mask);
2358 break;
2359 case OPC_SDL:
2360 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2361 break;
2362 case OPC_SDR:
2363 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2364 break;
2365 #endif
2366 case OPC_SWE:
2367 mem_idx = MIPS_HFLAG_UM;
2368 /* fall through */
2369 case OPC_SW:
2370 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2371 ctx->default_tcg_memop_mask);
2372 break;
2373 case OPC_SHE:
2374 mem_idx = MIPS_HFLAG_UM;
2375 /* fall through */
2376 case OPC_SH:
2377 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2378 ctx->default_tcg_memop_mask);
2379 break;
2380 case OPC_SBE:
2381 mem_idx = MIPS_HFLAG_UM;
2382 /* fall through */
2383 case OPC_SB:
2384 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2385 break;
2386 case OPC_SWLE:
2387 mem_idx = MIPS_HFLAG_UM;
2388 /* fall through */
2389 case OPC_SWL:
2390 gen_helper_0e2i(swl, t1, t0, mem_idx);
2391 break;
2392 case OPC_SWRE:
2393 mem_idx = MIPS_HFLAG_UM;
2394 /* fall through */
2395 case OPC_SWR:
2396 gen_helper_0e2i(swr, t1, t0, mem_idx);
2397 break;
2399 tcg_temp_free(t0);
2400 tcg_temp_free(t1);
2404 /* Store conditional */
2405 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2406 int base, int16_t offset)
2408 TCGv t0, t1;
2409 int mem_idx = ctx->mem_idx;
2411 #ifdef CONFIG_USER_ONLY
2412 t0 = tcg_temp_local_new();
2413 t1 = tcg_temp_local_new();
2414 #else
2415 t0 = tcg_temp_new();
2416 t1 = tcg_temp_new();
2417 #endif
2418 gen_base_offset_addr(ctx, t0, base, offset);
2419 gen_load_gpr(t1, rt);
2420 switch (opc) {
2421 #if defined(TARGET_MIPS64)
2422 case OPC_SCD:
2423 case R6_OPC_SCD:
2424 op_st_scd(t1, t0, rt, mem_idx, ctx);
2425 break;
2426 #endif
2427 case OPC_SCE:
2428 mem_idx = MIPS_HFLAG_UM;
2429 /* fall through */
2430 case OPC_SC:
2431 case R6_OPC_SC:
2432 op_st_sc(t1, t0, rt, mem_idx, ctx);
2433 break;
2435 tcg_temp_free(t1);
2436 tcg_temp_free(t0);
2439 /* Load and store */
2440 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2441 int base, int16_t offset)
2443 TCGv t0 = tcg_temp_new();
2445 gen_base_offset_addr(ctx, t0, base, offset);
2446 /* Don't do NOP if destination is zero: we must perform the actual
2447 memory access. */
2448 switch (opc) {
2449 case OPC_LWC1:
2451 TCGv_i32 fp0 = tcg_temp_new_i32();
2452 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2453 ctx->default_tcg_memop_mask);
2454 gen_store_fpr32(ctx, fp0, ft);
2455 tcg_temp_free_i32(fp0);
2457 break;
2458 case OPC_SWC1:
2460 TCGv_i32 fp0 = tcg_temp_new_i32();
2461 gen_load_fpr32(ctx, fp0, ft);
2462 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2463 ctx->default_tcg_memop_mask);
2464 tcg_temp_free_i32(fp0);
2466 break;
2467 case OPC_LDC1:
2469 TCGv_i64 fp0 = tcg_temp_new_i64();
2470 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2471 ctx->default_tcg_memop_mask);
2472 gen_store_fpr64(ctx, fp0, ft);
2473 tcg_temp_free_i64(fp0);
2475 break;
2476 case OPC_SDC1:
2478 TCGv_i64 fp0 = tcg_temp_new_i64();
2479 gen_load_fpr64(ctx, fp0, ft);
2480 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2481 ctx->default_tcg_memop_mask);
2482 tcg_temp_free_i64(fp0);
2484 break;
2485 default:
2486 MIPS_INVAL("flt_ldst");
2487 generate_exception_end(ctx, EXCP_RI);
2488 goto out;
2490 out:
2491 tcg_temp_free(t0);
2494 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2495 int rs, int16_t imm)
2497 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2498 check_cp1_enabled(ctx);
2499 switch (op) {
2500 case OPC_LDC1:
2501 case OPC_SDC1:
2502 check_insn(ctx, ISA_MIPS2);
2503 /* Fallthrough */
2504 default:
2505 gen_flt_ldst(ctx, op, rt, rs, imm);
2507 } else {
2508 generate_exception_err(ctx, EXCP_CpU, 1);
2512 /* Arithmetic with immediate operand */
2513 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2514 int rt, int rs, int16_t imm)
2516 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2518 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2519 /* If no destination, treat it as a NOP.
2520 For addi, we must generate the overflow exception when needed. */
2521 return;
2523 switch (opc) {
2524 case OPC_ADDI:
2526 TCGv t0 = tcg_temp_local_new();
2527 TCGv t1 = tcg_temp_new();
2528 TCGv t2 = tcg_temp_new();
2529 TCGLabel *l1 = gen_new_label();
2531 gen_load_gpr(t1, rs);
2532 tcg_gen_addi_tl(t0, t1, uimm);
2533 tcg_gen_ext32s_tl(t0, t0);
2535 tcg_gen_xori_tl(t1, t1, ~uimm);
2536 tcg_gen_xori_tl(t2, t0, uimm);
2537 tcg_gen_and_tl(t1, t1, t2);
2538 tcg_temp_free(t2);
2539 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2540 tcg_temp_free(t1);
2541 /* operands of same sign, result different sign */
2542 generate_exception(ctx, EXCP_OVERFLOW);
2543 gen_set_label(l1);
2544 tcg_gen_ext32s_tl(t0, t0);
2545 gen_store_gpr(t0, rt);
2546 tcg_temp_free(t0);
2548 break;
2549 case OPC_ADDIU:
2550 if (rs != 0) {
2551 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2552 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2553 } else {
2554 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2556 break;
2557 #if defined(TARGET_MIPS64)
2558 case OPC_DADDI:
2560 TCGv t0 = tcg_temp_local_new();
2561 TCGv t1 = tcg_temp_new();
2562 TCGv t2 = tcg_temp_new();
2563 TCGLabel *l1 = gen_new_label();
2565 gen_load_gpr(t1, rs);
2566 tcg_gen_addi_tl(t0, t1, uimm);
2568 tcg_gen_xori_tl(t1, t1, ~uimm);
2569 tcg_gen_xori_tl(t2, t0, uimm);
2570 tcg_gen_and_tl(t1, t1, t2);
2571 tcg_temp_free(t2);
2572 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2573 tcg_temp_free(t1);
2574 /* operands of same sign, result different sign */
2575 generate_exception(ctx, EXCP_OVERFLOW);
2576 gen_set_label(l1);
2577 gen_store_gpr(t0, rt);
2578 tcg_temp_free(t0);
2580 break;
2581 case OPC_DADDIU:
2582 if (rs != 0) {
2583 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2584 } else {
2585 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2587 break;
2588 #endif
2592 /* Logic with immediate operand */
2593 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2594 int rt, int rs, int16_t imm)
2596 target_ulong uimm;
2598 if (rt == 0) {
2599 /* If no destination, treat it as a NOP. */
2600 return;
2602 uimm = (uint16_t)imm;
2603 switch (opc) {
2604 case OPC_ANDI:
2605 if (likely(rs != 0))
2606 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2607 else
2608 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2609 break;
2610 case OPC_ORI:
2611 if (rs != 0)
2612 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2613 else
2614 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2615 break;
2616 case OPC_XORI:
2617 if (likely(rs != 0))
2618 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2619 else
2620 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2621 break;
2622 case OPC_LUI:
2623 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2624 /* OPC_AUI */
2625 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2626 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2627 } else {
2628 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2630 break;
2632 default:
2633 break;
2637 /* Set on less than with immediate operand */
2638 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2639 int rt, int rs, int16_t imm)
2641 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2642 TCGv t0;
2644 if (rt == 0) {
2645 /* If no destination, treat it as a NOP. */
2646 return;
2648 t0 = tcg_temp_new();
2649 gen_load_gpr(t0, rs);
2650 switch (opc) {
2651 case OPC_SLTI:
2652 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2653 break;
2654 case OPC_SLTIU:
2655 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2656 break;
2658 tcg_temp_free(t0);
2661 /* Shifts with immediate operand */
2662 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2663 int rt, int rs, int16_t imm)
2665 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2666 TCGv t0;
2668 if (rt == 0) {
2669 /* If no destination, treat it as a NOP. */
2670 return;
2673 t0 = tcg_temp_new();
2674 gen_load_gpr(t0, rs);
2675 switch (opc) {
2676 case OPC_SLL:
2677 tcg_gen_shli_tl(t0, t0, uimm);
2678 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2679 break;
2680 case OPC_SRA:
2681 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2682 break;
2683 case OPC_SRL:
2684 if (uimm != 0) {
2685 tcg_gen_ext32u_tl(t0, t0);
2686 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2687 } else {
2688 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2690 break;
2691 case OPC_ROTR:
2692 if (uimm != 0) {
2693 TCGv_i32 t1 = tcg_temp_new_i32();
2695 tcg_gen_trunc_tl_i32(t1, t0);
2696 tcg_gen_rotri_i32(t1, t1, uimm);
2697 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2698 tcg_temp_free_i32(t1);
2699 } else {
2700 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2702 break;
2703 #if defined(TARGET_MIPS64)
2704 case OPC_DSLL:
2705 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2706 break;
2707 case OPC_DSRA:
2708 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2709 break;
2710 case OPC_DSRL:
2711 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2712 break;
2713 case OPC_DROTR:
2714 if (uimm != 0) {
2715 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2716 } else {
2717 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2719 break;
2720 case OPC_DSLL32:
2721 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2722 break;
2723 case OPC_DSRA32:
2724 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2725 break;
2726 case OPC_DSRL32:
2727 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2728 break;
2729 case OPC_DROTR32:
2730 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2731 break;
2732 #endif
2734 tcg_temp_free(t0);
2737 /* Arithmetic */
2738 static void gen_arith(DisasContext *ctx, uint32_t opc,
2739 int rd, int rs, int rt)
2741 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2742 && opc != OPC_DADD && opc != OPC_DSUB) {
2743 /* If no destination, treat it as a NOP.
2744 For add & sub, we must generate the overflow exception when needed. */
2745 return;
2748 switch (opc) {
2749 case OPC_ADD:
2751 TCGv t0 = tcg_temp_local_new();
2752 TCGv t1 = tcg_temp_new();
2753 TCGv t2 = tcg_temp_new();
2754 TCGLabel *l1 = gen_new_label();
2756 gen_load_gpr(t1, rs);
2757 gen_load_gpr(t2, rt);
2758 tcg_gen_add_tl(t0, t1, t2);
2759 tcg_gen_ext32s_tl(t0, t0);
2760 tcg_gen_xor_tl(t1, t1, t2);
2761 tcg_gen_xor_tl(t2, t0, t2);
2762 tcg_gen_andc_tl(t1, t2, t1);
2763 tcg_temp_free(t2);
2764 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2765 tcg_temp_free(t1);
2766 /* operands of same sign, result different sign */
2767 generate_exception(ctx, EXCP_OVERFLOW);
2768 gen_set_label(l1);
2769 gen_store_gpr(t0, rd);
2770 tcg_temp_free(t0);
2772 break;
2773 case OPC_ADDU:
2774 if (rs != 0 && rt != 0) {
2775 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2776 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2777 } else if (rs == 0 && rt != 0) {
2778 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2779 } else if (rs != 0 && rt == 0) {
2780 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2781 } else {
2782 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2784 break;
2785 case OPC_SUB:
2787 TCGv t0 = tcg_temp_local_new();
2788 TCGv t1 = tcg_temp_new();
2789 TCGv t2 = tcg_temp_new();
2790 TCGLabel *l1 = gen_new_label();
2792 gen_load_gpr(t1, rs);
2793 gen_load_gpr(t2, rt);
2794 tcg_gen_sub_tl(t0, t1, t2);
2795 tcg_gen_ext32s_tl(t0, t0);
2796 tcg_gen_xor_tl(t2, t1, t2);
2797 tcg_gen_xor_tl(t1, t0, t1);
2798 tcg_gen_and_tl(t1, t1, t2);
2799 tcg_temp_free(t2);
2800 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2801 tcg_temp_free(t1);
2802 /* operands of different sign, first operand and result different sign */
2803 generate_exception(ctx, EXCP_OVERFLOW);
2804 gen_set_label(l1);
2805 gen_store_gpr(t0, rd);
2806 tcg_temp_free(t0);
2808 break;
2809 case OPC_SUBU:
2810 if (rs != 0 && rt != 0) {
2811 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2812 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2813 } else if (rs == 0 && rt != 0) {
2814 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2815 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2816 } else if (rs != 0 && rt == 0) {
2817 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2818 } else {
2819 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2821 break;
2822 #if defined(TARGET_MIPS64)
2823 case OPC_DADD:
2825 TCGv t0 = tcg_temp_local_new();
2826 TCGv t1 = tcg_temp_new();
2827 TCGv t2 = tcg_temp_new();
2828 TCGLabel *l1 = gen_new_label();
2830 gen_load_gpr(t1, rs);
2831 gen_load_gpr(t2, rt);
2832 tcg_gen_add_tl(t0, t1, t2);
2833 tcg_gen_xor_tl(t1, t1, t2);
2834 tcg_gen_xor_tl(t2, t0, t2);
2835 tcg_gen_andc_tl(t1, t2, t1);
2836 tcg_temp_free(t2);
2837 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2838 tcg_temp_free(t1);
2839 /* operands of same sign, result different sign */
2840 generate_exception(ctx, EXCP_OVERFLOW);
2841 gen_set_label(l1);
2842 gen_store_gpr(t0, rd);
2843 tcg_temp_free(t0);
2845 break;
2846 case OPC_DADDU:
2847 if (rs != 0 && rt != 0) {
2848 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2849 } else if (rs == 0 && rt != 0) {
2850 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2851 } else if (rs != 0 && rt == 0) {
2852 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2853 } else {
2854 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2856 break;
2857 case OPC_DSUB:
2859 TCGv t0 = tcg_temp_local_new();
2860 TCGv t1 = tcg_temp_new();
2861 TCGv t2 = tcg_temp_new();
2862 TCGLabel *l1 = gen_new_label();
2864 gen_load_gpr(t1, rs);
2865 gen_load_gpr(t2, rt);
2866 tcg_gen_sub_tl(t0, t1, t2);
2867 tcg_gen_xor_tl(t2, t1, t2);
2868 tcg_gen_xor_tl(t1, t0, t1);
2869 tcg_gen_and_tl(t1, t1, t2);
2870 tcg_temp_free(t2);
2871 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2872 tcg_temp_free(t1);
2873 /* operands of different sign, first operand and result different sign */
2874 generate_exception(ctx, EXCP_OVERFLOW);
2875 gen_set_label(l1);
2876 gen_store_gpr(t0, rd);
2877 tcg_temp_free(t0);
2879 break;
2880 case OPC_DSUBU:
2881 if (rs != 0 && rt != 0) {
2882 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2883 } else if (rs == 0 && rt != 0) {
2884 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2885 } else if (rs != 0 && rt == 0) {
2886 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2887 } else {
2888 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2890 break;
2891 #endif
2892 case OPC_MUL:
2893 if (likely(rs != 0 && rt != 0)) {
2894 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2895 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2896 } else {
2897 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2899 break;
2903 /* Conditional move */
2904 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2905 int rd, int rs, int rt)
2907 TCGv t0, t1, t2;
2909 if (rd == 0) {
2910 /* If no destination, treat it as a NOP. */
2911 return;
2914 t0 = tcg_temp_new();
2915 gen_load_gpr(t0, rt);
2916 t1 = tcg_const_tl(0);
2917 t2 = tcg_temp_new();
2918 gen_load_gpr(t2, rs);
2919 switch (opc) {
2920 case OPC_MOVN:
2921 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2922 break;
2923 case OPC_MOVZ:
2924 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2925 break;
2926 case OPC_SELNEZ:
2927 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2928 break;
2929 case OPC_SELEQZ:
2930 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2931 break;
2933 tcg_temp_free(t2);
2934 tcg_temp_free(t1);
2935 tcg_temp_free(t0);
2938 /* Logic */
2939 static void gen_logic(DisasContext *ctx, uint32_t opc,
2940 int rd, int rs, int rt)
2942 if (rd == 0) {
2943 /* If no destination, treat it as a NOP. */
2944 return;
2947 switch (opc) {
2948 case OPC_AND:
2949 if (likely(rs != 0 && rt != 0)) {
2950 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2951 } else {
2952 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2954 break;
2955 case OPC_NOR:
2956 if (rs != 0 && rt != 0) {
2957 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2958 } else if (rs == 0 && rt != 0) {
2959 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2960 } else if (rs != 0 && rt == 0) {
2961 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2962 } else {
2963 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2965 break;
2966 case OPC_OR:
2967 if (likely(rs != 0 && rt != 0)) {
2968 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2969 } else if (rs == 0 && rt != 0) {
2970 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2971 } else if (rs != 0 && rt == 0) {
2972 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2973 } else {
2974 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2976 break;
2977 case OPC_XOR:
2978 if (likely(rs != 0 && rt != 0)) {
2979 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2980 } else if (rs == 0 && rt != 0) {
2981 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2982 } else if (rs != 0 && rt == 0) {
2983 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2984 } else {
2985 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2987 break;
2991 /* Set on lower than */
2992 static void gen_slt(DisasContext *ctx, uint32_t opc,
2993 int rd, int rs, int rt)
2995 TCGv t0, t1;
2997 if (rd == 0) {
2998 /* If no destination, treat it as a NOP. */
2999 return;
3002 t0 = tcg_temp_new();
3003 t1 = tcg_temp_new();
3004 gen_load_gpr(t0, rs);
3005 gen_load_gpr(t1, rt);
3006 switch (opc) {
3007 case OPC_SLT:
3008 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3009 break;
3010 case OPC_SLTU:
3011 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3012 break;
3014 tcg_temp_free(t0);
3015 tcg_temp_free(t1);
3018 /* Shifts */
3019 static void gen_shift(DisasContext *ctx, uint32_t opc,
3020 int rd, int rs, int rt)
3022 TCGv t0, t1;
3024 if (rd == 0) {
3025 /* If no destination, treat it as a NOP.
3026 For add & sub, we must generate the overflow exception when needed. */
3027 return;
3030 t0 = tcg_temp_new();
3031 t1 = tcg_temp_new();
3032 gen_load_gpr(t0, rs);
3033 gen_load_gpr(t1, rt);
3034 switch (opc) {
3035 case OPC_SLLV:
3036 tcg_gen_andi_tl(t0, t0, 0x1f);
3037 tcg_gen_shl_tl(t0, t1, t0);
3038 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3039 break;
3040 case OPC_SRAV:
3041 tcg_gen_andi_tl(t0, t0, 0x1f);
3042 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3043 break;
3044 case OPC_SRLV:
3045 tcg_gen_ext32u_tl(t1, t1);
3046 tcg_gen_andi_tl(t0, t0, 0x1f);
3047 tcg_gen_shr_tl(t0, t1, t0);
3048 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3049 break;
3050 case OPC_ROTRV:
3052 TCGv_i32 t2 = tcg_temp_new_i32();
3053 TCGv_i32 t3 = tcg_temp_new_i32();
3055 tcg_gen_trunc_tl_i32(t2, t0);
3056 tcg_gen_trunc_tl_i32(t3, t1);
3057 tcg_gen_andi_i32(t2, t2, 0x1f);
3058 tcg_gen_rotr_i32(t2, t3, t2);
3059 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3060 tcg_temp_free_i32(t2);
3061 tcg_temp_free_i32(t3);
3063 break;
3064 #if defined(TARGET_MIPS64)
3065 case OPC_DSLLV:
3066 tcg_gen_andi_tl(t0, t0, 0x3f);
3067 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3068 break;
3069 case OPC_DSRAV:
3070 tcg_gen_andi_tl(t0, t0, 0x3f);
3071 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3072 break;
3073 case OPC_DSRLV:
3074 tcg_gen_andi_tl(t0, t0, 0x3f);
3075 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3076 break;
3077 case OPC_DROTRV:
3078 tcg_gen_andi_tl(t0, t0, 0x3f);
3079 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3080 break;
3081 #endif
3083 tcg_temp_free(t0);
3084 tcg_temp_free(t1);
3087 /* Arithmetic on HI/LO registers */
3088 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3090 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3091 /* Treat as NOP. */
3092 return;
3095 if (acc != 0) {
3096 check_dsp(ctx);
3099 switch (opc) {
3100 case OPC_MFHI:
3101 #if defined(TARGET_MIPS64)
3102 if (acc != 0) {
3103 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3104 } else
3105 #endif
3107 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3109 break;
3110 case OPC_MFLO:
3111 #if defined(TARGET_MIPS64)
3112 if (acc != 0) {
3113 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3114 } else
3115 #endif
3117 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3119 break;
3120 case OPC_MTHI:
3121 if (reg != 0) {
3122 #if defined(TARGET_MIPS64)
3123 if (acc != 0) {
3124 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3125 } else
3126 #endif
3128 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3130 } else {
3131 tcg_gen_movi_tl(cpu_HI[acc], 0);
3133 break;
3134 case OPC_MTLO:
3135 if (reg != 0) {
3136 #if defined(TARGET_MIPS64)
3137 if (acc != 0) {
3138 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3139 } else
3140 #endif
3142 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3144 } else {
3145 tcg_gen_movi_tl(cpu_LO[acc], 0);
3147 break;
3151 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3152 TCGMemOp memop)
3154 TCGv t0 = tcg_const_tl(addr);
3155 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3156 gen_store_gpr(t0, reg);
3157 tcg_temp_free(t0);
3160 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3161 int rs)
3163 target_long offset;
3164 target_long addr;
3166 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3167 case OPC_ADDIUPC:
3168 if (rs != 0) {
3169 offset = sextract32(ctx->opcode << 2, 0, 21);
3170 addr = addr_add(ctx, pc, offset);
3171 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3173 break;
3174 case R6_OPC_LWPC:
3175 offset = sextract32(ctx->opcode << 2, 0, 21);
3176 addr = addr_add(ctx, pc, offset);
3177 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3178 break;
3179 #if defined(TARGET_MIPS64)
3180 case OPC_LWUPC:
3181 check_mips_64(ctx);
3182 offset = sextract32(ctx->opcode << 2, 0, 21);
3183 addr = addr_add(ctx, pc, offset);
3184 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3185 break;
3186 #endif
3187 default:
3188 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3189 case OPC_AUIPC:
3190 if (rs != 0) {
3191 offset = sextract32(ctx->opcode, 0, 16) << 16;
3192 addr = addr_add(ctx, pc, offset);
3193 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3195 break;
3196 case OPC_ALUIPC:
3197 if (rs != 0) {
3198 offset = sextract32(ctx->opcode, 0, 16) << 16;
3199 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3200 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3202 break;
3203 #if defined(TARGET_MIPS64)
3204 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3205 case R6_OPC_LDPC + (1 << 16):
3206 case R6_OPC_LDPC + (2 << 16):
3207 case R6_OPC_LDPC + (3 << 16):
3208 check_mips_64(ctx);
3209 offset = sextract32(ctx->opcode << 3, 0, 21);
3210 addr = addr_add(ctx, (pc & ~0x7), offset);
3211 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3212 break;
3213 #endif
3214 default:
3215 MIPS_INVAL("OPC_PCREL");
3216 generate_exception_end(ctx, EXCP_RI);
3217 break;
3219 break;
3223 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3225 TCGv t0, t1;
3227 if (rd == 0) {
3228 /* Treat as NOP. */
3229 return;
3232 t0 = tcg_temp_new();
3233 t1 = tcg_temp_new();
3235 gen_load_gpr(t0, rs);
3236 gen_load_gpr(t1, rt);
3238 switch (opc) {
3239 case R6_OPC_DIV:
3241 TCGv t2 = tcg_temp_new();
3242 TCGv t3 = tcg_temp_new();
3243 tcg_gen_ext32s_tl(t0, t0);
3244 tcg_gen_ext32s_tl(t1, t1);
3245 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3246 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3247 tcg_gen_and_tl(t2, t2, t3);
3248 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3249 tcg_gen_or_tl(t2, t2, t3);
3250 tcg_gen_movi_tl(t3, 0);
3251 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3252 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3253 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3254 tcg_temp_free(t3);
3255 tcg_temp_free(t2);
3257 break;
3258 case R6_OPC_MOD:
3260 TCGv t2 = tcg_temp_new();
3261 TCGv t3 = tcg_temp_new();
3262 tcg_gen_ext32s_tl(t0, t0);
3263 tcg_gen_ext32s_tl(t1, t1);
3264 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3265 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3266 tcg_gen_and_tl(t2, t2, t3);
3267 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3268 tcg_gen_or_tl(t2, t2, t3);
3269 tcg_gen_movi_tl(t3, 0);
3270 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3271 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3272 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3273 tcg_temp_free(t3);
3274 tcg_temp_free(t2);
3276 break;
3277 case R6_OPC_DIVU:
3279 TCGv t2 = tcg_const_tl(0);
3280 TCGv t3 = tcg_const_tl(1);
3281 tcg_gen_ext32u_tl(t0, t0);
3282 tcg_gen_ext32u_tl(t1, t1);
3283 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3284 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3285 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3286 tcg_temp_free(t3);
3287 tcg_temp_free(t2);
3289 break;
3290 case R6_OPC_MODU:
3292 TCGv t2 = tcg_const_tl(0);
3293 TCGv t3 = tcg_const_tl(1);
3294 tcg_gen_ext32u_tl(t0, t0);
3295 tcg_gen_ext32u_tl(t1, t1);
3296 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3297 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3298 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3299 tcg_temp_free(t3);
3300 tcg_temp_free(t2);
3302 break;
3303 case R6_OPC_MUL:
3305 TCGv_i32 t2 = tcg_temp_new_i32();
3306 TCGv_i32 t3 = tcg_temp_new_i32();
3307 tcg_gen_trunc_tl_i32(t2, t0);
3308 tcg_gen_trunc_tl_i32(t3, t1);
3309 tcg_gen_mul_i32(t2, t2, t3);
3310 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3311 tcg_temp_free_i32(t2);
3312 tcg_temp_free_i32(t3);
3314 break;
3315 case R6_OPC_MUH:
3317 TCGv_i32 t2 = tcg_temp_new_i32();
3318 TCGv_i32 t3 = tcg_temp_new_i32();
3319 tcg_gen_trunc_tl_i32(t2, t0);
3320 tcg_gen_trunc_tl_i32(t3, t1);
3321 tcg_gen_muls2_i32(t2, t3, t2, t3);
3322 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3323 tcg_temp_free_i32(t2);
3324 tcg_temp_free_i32(t3);
3326 break;
3327 case R6_OPC_MULU:
3329 TCGv_i32 t2 = tcg_temp_new_i32();
3330 TCGv_i32 t3 = tcg_temp_new_i32();
3331 tcg_gen_trunc_tl_i32(t2, t0);
3332 tcg_gen_trunc_tl_i32(t3, t1);
3333 tcg_gen_mul_i32(t2, t2, t3);
3334 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3335 tcg_temp_free_i32(t2);
3336 tcg_temp_free_i32(t3);
3338 break;
3339 case R6_OPC_MUHU:
3341 TCGv_i32 t2 = tcg_temp_new_i32();
3342 TCGv_i32 t3 = tcg_temp_new_i32();
3343 tcg_gen_trunc_tl_i32(t2, t0);
3344 tcg_gen_trunc_tl_i32(t3, t1);
3345 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3346 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3347 tcg_temp_free_i32(t2);
3348 tcg_temp_free_i32(t3);
3350 break;
3351 #if defined(TARGET_MIPS64)
3352 case R6_OPC_DDIV:
3354 TCGv t2 = tcg_temp_new();
3355 TCGv t3 = tcg_temp_new();
3356 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3357 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3358 tcg_gen_and_tl(t2, t2, t3);
3359 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3360 tcg_gen_or_tl(t2, t2, t3);
3361 tcg_gen_movi_tl(t3, 0);
3362 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3363 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3364 tcg_temp_free(t3);
3365 tcg_temp_free(t2);
3367 break;
3368 case R6_OPC_DMOD:
3370 TCGv t2 = tcg_temp_new();
3371 TCGv t3 = tcg_temp_new();
3372 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3373 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3374 tcg_gen_and_tl(t2, t2, t3);
3375 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3376 tcg_gen_or_tl(t2, t2, t3);
3377 tcg_gen_movi_tl(t3, 0);
3378 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3379 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3380 tcg_temp_free(t3);
3381 tcg_temp_free(t2);
3383 break;
3384 case R6_OPC_DDIVU:
3386 TCGv t2 = tcg_const_tl(0);
3387 TCGv t3 = tcg_const_tl(1);
3388 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3389 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3390 tcg_temp_free(t3);
3391 tcg_temp_free(t2);
3393 break;
3394 case R6_OPC_DMODU:
3396 TCGv t2 = tcg_const_tl(0);
3397 TCGv t3 = tcg_const_tl(1);
3398 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3399 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3400 tcg_temp_free(t3);
3401 tcg_temp_free(t2);
3403 break;
3404 case R6_OPC_DMUL:
3405 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3406 break;
3407 case R6_OPC_DMUH:
3409 TCGv t2 = tcg_temp_new();
3410 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3411 tcg_temp_free(t2);
3413 break;
3414 case R6_OPC_DMULU:
3415 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3416 break;
3417 case R6_OPC_DMUHU:
3419 TCGv t2 = tcg_temp_new();
3420 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3421 tcg_temp_free(t2);
3423 break;
3424 #endif
3425 default:
3426 MIPS_INVAL("r6 mul/div");
3427 generate_exception_end(ctx, EXCP_RI);
3428 goto out;
3430 out:
3431 tcg_temp_free(t0);
3432 tcg_temp_free(t1);
3435 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3436 int acc, int rs, int rt)
3438 TCGv t0, t1;
3440 t0 = tcg_temp_new();
3441 t1 = tcg_temp_new();
3443 gen_load_gpr(t0, rs);
3444 gen_load_gpr(t1, rt);
3446 if (acc != 0) {
3447 check_dsp(ctx);
3450 switch (opc) {
3451 case OPC_DIV:
3453 TCGv t2 = tcg_temp_new();
3454 TCGv t3 = tcg_temp_new();
3455 tcg_gen_ext32s_tl(t0, t0);
3456 tcg_gen_ext32s_tl(t1, t1);
3457 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3458 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3459 tcg_gen_and_tl(t2, t2, t3);
3460 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3461 tcg_gen_or_tl(t2, t2, t3);
3462 tcg_gen_movi_tl(t3, 0);
3463 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3464 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3465 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3466 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3467 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3468 tcg_temp_free(t3);
3469 tcg_temp_free(t2);
3471 break;
3472 case OPC_DIVU:
3474 TCGv t2 = tcg_const_tl(0);
3475 TCGv t3 = tcg_const_tl(1);
3476 tcg_gen_ext32u_tl(t0, t0);
3477 tcg_gen_ext32u_tl(t1, t1);
3478 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3479 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3480 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3481 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3482 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3483 tcg_temp_free(t3);
3484 tcg_temp_free(t2);
3486 break;
3487 case OPC_MULT:
3489 TCGv_i32 t2 = tcg_temp_new_i32();
3490 TCGv_i32 t3 = tcg_temp_new_i32();
3491 tcg_gen_trunc_tl_i32(t2, t0);
3492 tcg_gen_trunc_tl_i32(t3, t1);
3493 tcg_gen_muls2_i32(t2, t3, t2, t3);
3494 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3495 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3496 tcg_temp_free_i32(t2);
3497 tcg_temp_free_i32(t3);
3499 break;
3500 case OPC_MULTU:
3502 TCGv_i32 t2 = tcg_temp_new_i32();
3503 TCGv_i32 t3 = tcg_temp_new_i32();
3504 tcg_gen_trunc_tl_i32(t2, t0);
3505 tcg_gen_trunc_tl_i32(t3, t1);
3506 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3507 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3508 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3509 tcg_temp_free_i32(t2);
3510 tcg_temp_free_i32(t3);
3512 break;
3513 #if defined(TARGET_MIPS64)
3514 case OPC_DDIV:
3516 TCGv t2 = tcg_temp_new();
3517 TCGv t3 = tcg_temp_new();
3518 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3519 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3520 tcg_gen_and_tl(t2, t2, t3);
3521 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3522 tcg_gen_or_tl(t2, t2, t3);
3523 tcg_gen_movi_tl(t3, 0);
3524 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3525 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3526 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3527 tcg_temp_free(t3);
3528 tcg_temp_free(t2);
3530 break;
3531 case OPC_DDIVU:
3533 TCGv t2 = tcg_const_tl(0);
3534 TCGv t3 = tcg_const_tl(1);
3535 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3536 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3537 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3538 tcg_temp_free(t3);
3539 tcg_temp_free(t2);
3541 break;
3542 case OPC_DMULT:
3543 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3544 break;
3545 case OPC_DMULTU:
3546 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3547 break;
3548 #endif
3549 case OPC_MADD:
3551 TCGv_i64 t2 = tcg_temp_new_i64();
3552 TCGv_i64 t3 = tcg_temp_new_i64();
3554 tcg_gen_ext_tl_i64(t2, t0);
3555 tcg_gen_ext_tl_i64(t3, t1);
3556 tcg_gen_mul_i64(t2, t2, t3);
3557 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3558 tcg_gen_add_i64(t2, t2, t3);
3559 tcg_temp_free_i64(t3);
3560 gen_move_low32(cpu_LO[acc], t2);
3561 gen_move_high32(cpu_HI[acc], t2);
3562 tcg_temp_free_i64(t2);
3564 break;
3565 case OPC_MADDU:
3567 TCGv_i64 t2 = tcg_temp_new_i64();
3568 TCGv_i64 t3 = tcg_temp_new_i64();
3570 tcg_gen_ext32u_tl(t0, t0);
3571 tcg_gen_ext32u_tl(t1, t1);
3572 tcg_gen_extu_tl_i64(t2, t0);
3573 tcg_gen_extu_tl_i64(t3, t1);
3574 tcg_gen_mul_i64(t2, t2, t3);
3575 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3576 tcg_gen_add_i64(t2, t2, t3);
3577 tcg_temp_free_i64(t3);
3578 gen_move_low32(cpu_LO[acc], t2);
3579 gen_move_high32(cpu_HI[acc], t2);
3580 tcg_temp_free_i64(t2);
3582 break;
3583 case OPC_MSUB:
3585 TCGv_i64 t2 = tcg_temp_new_i64();
3586 TCGv_i64 t3 = tcg_temp_new_i64();
3588 tcg_gen_ext_tl_i64(t2, t0);
3589 tcg_gen_ext_tl_i64(t3, t1);
3590 tcg_gen_mul_i64(t2, t2, t3);
3591 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3592 tcg_gen_sub_i64(t2, t3, t2);
3593 tcg_temp_free_i64(t3);
3594 gen_move_low32(cpu_LO[acc], t2);
3595 gen_move_high32(cpu_HI[acc], t2);
3596 tcg_temp_free_i64(t2);
3598 break;
3599 case OPC_MSUBU:
3601 TCGv_i64 t2 = tcg_temp_new_i64();
3602 TCGv_i64 t3 = tcg_temp_new_i64();
3604 tcg_gen_ext32u_tl(t0, t0);
3605 tcg_gen_ext32u_tl(t1, t1);
3606 tcg_gen_extu_tl_i64(t2, t0);
3607 tcg_gen_extu_tl_i64(t3, t1);
3608 tcg_gen_mul_i64(t2, t2, t3);
3609 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3610 tcg_gen_sub_i64(t2, t3, t2);
3611 tcg_temp_free_i64(t3);
3612 gen_move_low32(cpu_LO[acc], t2);
3613 gen_move_high32(cpu_HI[acc], t2);
3614 tcg_temp_free_i64(t2);
3616 break;
3617 default:
3618 MIPS_INVAL("mul/div");
3619 generate_exception_end(ctx, EXCP_RI);
3620 goto out;
3622 out:
3623 tcg_temp_free(t0);
3624 tcg_temp_free(t1);
3627 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3628 int rd, int rs, int rt)
3630 TCGv t0 = tcg_temp_new();
3631 TCGv t1 = tcg_temp_new();
3633 gen_load_gpr(t0, rs);
3634 gen_load_gpr(t1, rt);
3636 switch (opc) {
3637 case OPC_VR54XX_MULS:
3638 gen_helper_muls(t0, cpu_env, t0, t1);
3639 break;
3640 case OPC_VR54XX_MULSU:
3641 gen_helper_mulsu(t0, cpu_env, t0, t1);
3642 break;
3643 case OPC_VR54XX_MACC:
3644 gen_helper_macc(t0, cpu_env, t0, t1);
3645 break;
3646 case OPC_VR54XX_MACCU:
3647 gen_helper_maccu(t0, cpu_env, t0, t1);
3648 break;
3649 case OPC_VR54XX_MSAC:
3650 gen_helper_msac(t0, cpu_env, t0, t1);
3651 break;
3652 case OPC_VR54XX_MSACU:
3653 gen_helper_msacu(t0, cpu_env, t0, t1);
3654 break;
3655 case OPC_VR54XX_MULHI:
3656 gen_helper_mulhi(t0, cpu_env, t0, t1);
3657 break;
3658 case OPC_VR54XX_MULHIU:
3659 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3660 break;
3661 case OPC_VR54XX_MULSHI:
3662 gen_helper_mulshi(t0, cpu_env, t0, t1);
3663 break;
3664 case OPC_VR54XX_MULSHIU:
3665 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3666 break;
3667 case OPC_VR54XX_MACCHI:
3668 gen_helper_macchi(t0, cpu_env, t0, t1);
3669 break;
3670 case OPC_VR54XX_MACCHIU:
3671 gen_helper_macchiu(t0, cpu_env, t0, t1);
3672 break;
3673 case OPC_VR54XX_MSACHI:
3674 gen_helper_msachi(t0, cpu_env, t0, t1);
3675 break;
3676 case OPC_VR54XX_MSACHIU:
3677 gen_helper_msachiu(t0, cpu_env, t0, t1);
3678 break;
3679 default:
3680 MIPS_INVAL("mul vr54xx");
3681 generate_exception_end(ctx, EXCP_RI);
3682 goto out;
3684 gen_store_gpr(t0, rd);
3686 out:
3687 tcg_temp_free(t0);
3688 tcg_temp_free(t1);
3691 static void gen_cl (DisasContext *ctx, uint32_t opc,
3692 int rd, int rs)
3694 TCGv t0;
3696 if (rd == 0) {
3697 /* Treat as NOP. */
3698 return;
3700 t0 = cpu_gpr[rd];
3701 gen_load_gpr(t0, rs);
3703 switch (opc) {
3704 case OPC_CLO:
3705 case R6_OPC_CLO:
3706 #if defined(TARGET_MIPS64)
3707 case OPC_DCLO:
3708 case R6_OPC_DCLO:
3709 #endif
3710 tcg_gen_not_tl(t0, t0);
3711 break;
3714 switch (opc) {
3715 case OPC_CLO:
3716 case R6_OPC_CLO:
3717 case OPC_CLZ:
3718 case R6_OPC_CLZ:
3719 tcg_gen_ext32u_tl(t0, t0);
3720 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3721 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3722 break;
3723 #if defined(TARGET_MIPS64)
3724 case OPC_DCLO:
3725 case R6_OPC_DCLO:
3726 case OPC_DCLZ:
3727 case R6_OPC_DCLZ:
3728 tcg_gen_clzi_i64(t0, t0, 64);
3729 break;
3730 #endif
3734 /* Godson integer instructions */
3735 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3736 int rd, int rs, int rt)
3738 TCGv t0, t1;
3740 if (rd == 0) {
3741 /* Treat as NOP. */
3742 return;
3745 switch (opc) {
3746 case OPC_MULT_G_2E:
3747 case OPC_MULT_G_2F:
3748 case OPC_MULTU_G_2E:
3749 case OPC_MULTU_G_2F:
3750 #if defined(TARGET_MIPS64)
3751 case OPC_DMULT_G_2E:
3752 case OPC_DMULT_G_2F:
3753 case OPC_DMULTU_G_2E:
3754 case OPC_DMULTU_G_2F:
3755 #endif
3756 t0 = tcg_temp_new();
3757 t1 = tcg_temp_new();
3758 break;
3759 default:
3760 t0 = tcg_temp_local_new();
3761 t1 = tcg_temp_local_new();
3762 break;
3765 gen_load_gpr(t0, rs);
3766 gen_load_gpr(t1, rt);
3768 switch (opc) {
3769 case OPC_MULT_G_2E:
3770 case OPC_MULT_G_2F:
3771 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3772 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3773 break;
3774 case OPC_MULTU_G_2E:
3775 case OPC_MULTU_G_2F:
3776 tcg_gen_ext32u_tl(t0, t0);
3777 tcg_gen_ext32u_tl(t1, t1);
3778 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3779 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3780 break;
3781 case OPC_DIV_G_2E:
3782 case OPC_DIV_G_2F:
3784 TCGLabel *l1 = gen_new_label();
3785 TCGLabel *l2 = gen_new_label();
3786 TCGLabel *l3 = gen_new_label();
3787 tcg_gen_ext32s_tl(t0, t0);
3788 tcg_gen_ext32s_tl(t1, t1);
3789 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3790 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3791 tcg_gen_br(l3);
3792 gen_set_label(l1);
3793 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3794 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3795 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3796 tcg_gen_br(l3);
3797 gen_set_label(l2);
3798 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3799 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3800 gen_set_label(l3);
3802 break;
3803 case OPC_DIVU_G_2E:
3804 case OPC_DIVU_G_2F:
3806 TCGLabel *l1 = gen_new_label();
3807 TCGLabel *l2 = gen_new_label();
3808 tcg_gen_ext32u_tl(t0, t0);
3809 tcg_gen_ext32u_tl(t1, t1);
3810 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3811 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3812 tcg_gen_br(l2);
3813 gen_set_label(l1);
3814 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3815 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3816 gen_set_label(l2);
3818 break;
3819 case OPC_MOD_G_2E:
3820 case OPC_MOD_G_2F:
3822 TCGLabel *l1 = gen_new_label();
3823 TCGLabel *l2 = gen_new_label();
3824 TCGLabel *l3 = gen_new_label();
3825 tcg_gen_ext32u_tl(t0, t0);
3826 tcg_gen_ext32u_tl(t1, t1);
3827 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3828 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3829 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3830 gen_set_label(l1);
3831 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3832 tcg_gen_br(l3);
3833 gen_set_label(l2);
3834 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3835 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3836 gen_set_label(l3);
3838 break;
3839 case OPC_MODU_G_2E:
3840 case OPC_MODU_G_2F:
3842 TCGLabel *l1 = gen_new_label();
3843 TCGLabel *l2 = gen_new_label();
3844 tcg_gen_ext32u_tl(t0, t0);
3845 tcg_gen_ext32u_tl(t1, t1);
3846 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3847 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3848 tcg_gen_br(l2);
3849 gen_set_label(l1);
3850 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3851 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3852 gen_set_label(l2);
3854 break;
3855 #if defined(TARGET_MIPS64)
3856 case OPC_DMULT_G_2E:
3857 case OPC_DMULT_G_2F:
3858 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3859 break;
3860 case OPC_DMULTU_G_2E:
3861 case OPC_DMULTU_G_2F:
3862 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3863 break;
3864 case OPC_DDIV_G_2E:
3865 case OPC_DDIV_G_2F:
3867 TCGLabel *l1 = gen_new_label();
3868 TCGLabel *l2 = gen_new_label();
3869 TCGLabel *l3 = gen_new_label();
3870 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3871 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3872 tcg_gen_br(l3);
3873 gen_set_label(l1);
3874 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3875 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3876 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3877 tcg_gen_br(l3);
3878 gen_set_label(l2);
3879 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3880 gen_set_label(l3);
3882 break;
3883 case OPC_DDIVU_G_2E:
3884 case OPC_DDIVU_G_2F:
3886 TCGLabel *l1 = gen_new_label();
3887 TCGLabel *l2 = gen_new_label();
3888 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3889 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3890 tcg_gen_br(l2);
3891 gen_set_label(l1);
3892 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3893 gen_set_label(l2);
3895 break;
3896 case OPC_DMOD_G_2E:
3897 case OPC_DMOD_G_2F:
3899 TCGLabel *l1 = gen_new_label();
3900 TCGLabel *l2 = gen_new_label();
3901 TCGLabel *l3 = gen_new_label();
3902 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3903 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3904 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3905 gen_set_label(l1);
3906 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3907 tcg_gen_br(l3);
3908 gen_set_label(l2);
3909 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3910 gen_set_label(l3);
3912 break;
3913 case OPC_DMODU_G_2E:
3914 case OPC_DMODU_G_2F:
3916 TCGLabel *l1 = gen_new_label();
3917 TCGLabel *l2 = gen_new_label();
3918 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3919 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3920 tcg_gen_br(l2);
3921 gen_set_label(l1);
3922 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3923 gen_set_label(l2);
3925 break;
3926 #endif
3929 tcg_temp_free(t0);
3930 tcg_temp_free(t1);
3933 /* Loongson multimedia instructions */
3934 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3936 uint32_t opc, shift_max;
3937 TCGv_i64 t0, t1;
3939 opc = MASK_LMI(ctx->opcode);
3940 switch (opc) {
3941 case OPC_ADD_CP2:
3942 case OPC_SUB_CP2:
3943 case OPC_DADD_CP2:
3944 case OPC_DSUB_CP2:
3945 t0 = tcg_temp_local_new_i64();
3946 t1 = tcg_temp_local_new_i64();
3947 break;
3948 default:
3949 t0 = tcg_temp_new_i64();
3950 t1 = tcg_temp_new_i64();
3951 break;
3954 check_cp1_enabled(ctx);
3955 gen_load_fpr64(ctx, t0, rs);
3956 gen_load_fpr64(ctx, t1, rt);
3958 #define LMI_HELPER(UP, LO) \
3959 case OPC_##UP: gen_helper_##LO(t0, t0, t1); break
3960 #define LMI_HELPER_1(UP, LO) \
3961 case OPC_##UP: gen_helper_##LO(t0, t0); break
3962 #define LMI_DIRECT(UP, LO, OP) \
3963 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); break
3965 switch (opc) {
3966 LMI_HELPER(PADDSH, paddsh);
3967 LMI_HELPER(PADDUSH, paddush);
3968 LMI_HELPER(PADDH, paddh);
3969 LMI_HELPER(PADDW, paddw);
3970 LMI_HELPER(PADDSB, paddsb);
3971 LMI_HELPER(PADDUSB, paddusb);
3972 LMI_HELPER(PADDB, paddb);
3974 LMI_HELPER(PSUBSH, psubsh);
3975 LMI_HELPER(PSUBUSH, psubush);
3976 LMI_HELPER(PSUBH, psubh);
3977 LMI_HELPER(PSUBW, psubw);
3978 LMI_HELPER(PSUBSB, psubsb);
3979 LMI_HELPER(PSUBUSB, psubusb);
3980 LMI_HELPER(PSUBB, psubb);
3982 LMI_HELPER(PSHUFH, pshufh);
3983 LMI_HELPER(PACKSSWH, packsswh);
3984 LMI_HELPER(PACKSSHB, packsshb);
3985 LMI_HELPER(PACKUSHB, packushb);
3987 LMI_HELPER(PUNPCKLHW, punpcklhw);
3988 LMI_HELPER(PUNPCKHHW, punpckhhw);
3989 LMI_HELPER(PUNPCKLBH, punpcklbh);
3990 LMI_HELPER(PUNPCKHBH, punpckhbh);
3991 LMI_HELPER(PUNPCKLWD, punpcklwd);
3992 LMI_HELPER(PUNPCKHWD, punpckhwd);
3994 LMI_HELPER(PAVGH, pavgh);
3995 LMI_HELPER(PAVGB, pavgb);
3996 LMI_HELPER(PMAXSH, pmaxsh);
3997 LMI_HELPER(PMINSH, pminsh);
3998 LMI_HELPER(PMAXUB, pmaxub);
3999 LMI_HELPER(PMINUB, pminub);
4001 LMI_HELPER(PCMPEQW, pcmpeqw);
4002 LMI_HELPER(PCMPGTW, pcmpgtw);
4003 LMI_HELPER(PCMPEQH, pcmpeqh);
4004 LMI_HELPER(PCMPGTH, pcmpgth);
4005 LMI_HELPER(PCMPEQB, pcmpeqb);
4006 LMI_HELPER(PCMPGTB, pcmpgtb);
4008 LMI_HELPER(PSLLW, psllw);
4009 LMI_HELPER(PSLLH, psllh);
4010 LMI_HELPER(PSRLW, psrlw);
4011 LMI_HELPER(PSRLH, psrlh);
4012 LMI_HELPER(PSRAW, psraw);
4013 LMI_HELPER(PSRAH, psrah);
4015 LMI_HELPER(PMULLH, pmullh);
4016 LMI_HELPER(PMULHH, pmulhh);
4017 LMI_HELPER(PMULHUH, pmulhuh);
4018 LMI_HELPER(PMADDHW, pmaddhw);
4020 LMI_HELPER(PASUBUB, pasubub);
4021 LMI_HELPER_1(BIADD, biadd);
4022 LMI_HELPER_1(PMOVMSKB, pmovmskb);
4024 LMI_DIRECT(PADDD, paddd, add);
4025 LMI_DIRECT(PSUBD, psubd, sub);
4026 LMI_DIRECT(XOR_CP2, xor, xor);
4027 LMI_DIRECT(NOR_CP2, nor, nor);
4028 LMI_DIRECT(AND_CP2, and, and);
4029 LMI_DIRECT(OR_CP2, or, or);
4031 case OPC_PANDN:
4032 tcg_gen_andc_i64(t0, t1, t0);
4033 break;
4035 case OPC_PINSRH_0:
4036 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4037 break;
4038 case OPC_PINSRH_1:
4039 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4040 break;
4041 case OPC_PINSRH_2:
4042 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4043 break;
4044 case OPC_PINSRH_3:
4045 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4046 break;
4048 case OPC_PEXTRH:
4049 tcg_gen_andi_i64(t1, t1, 3);
4050 tcg_gen_shli_i64(t1, t1, 4);
4051 tcg_gen_shr_i64(t0, t0, t1);
4052 tcg_gen_ext16u_i64(t0, t0);
4053 break;
4055 case OPC_ADDU_CP2:
4056 tcg_gen_add_i64(t0, t0, t1);
4057 tcg_gen_ext32s_i64(t0, t0);
4058 break;
4059 case OPC_SUBU_CP2:
4060 tcg_gen_sub_i64(t0, t0, t1);
4061 tcg_gen_ext32s_i64(t0, t0);
4062 break;
4064 case OPC_SLL_CP2:
4065 shift_max = 32;
4066 goto do_shift;
4067 case OPC_SRL_CP2:
4068 shift_max = 32;
4069 goto do_shift;
4070 case OPC_SRA_CP2:
4071 shift_max = 32;
4072 goto do_shift;
4073 case OPC_DSLL_CP2:
4074 shift_max = 64;
4075 goto do_shift;
4076 case OPC_DSRL_CP2:
4077 shift_max = 64;
4078 goto do_shift;
4079 case OPC_DSRA_CP2:
4080 shift_max = 64;
4081 goto do_shift;
4082 do_shift:
4083 /* Make sure shift count isn't TCG undefined behaviour. */
4084 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4086 switch (opc) {
4087 case OPC_SLL_CP2:
4088 case OPC_DSLL_CP2:
4089 tcg_gen_shl_i64(t0, t0, t1);
4090 break;
4091 case OPC_SRA_CP2:
4092 case OPC_DSRA_CP2:
4093 /* Since SRA is UndefinedResult without sign-extended inputs,
4094 we can treat SRA and DSRA the same. */
4095 tcg_gen_sar_i64(t0, t0, t1);
4096 break;
4097 case OPC_SRL_CP2:
4098 /* We want to shift in zeros for SRL; zero-extend first. */
4099 tcg_gen_ext32u_i64(t0, t0);
4100 /* FALLTHRU */
4101 case OPC_DSRL_CP2:
4102 tcg_gen_shr_i64(t0, t0, t1);
4103 break;
4106 if (shift_max == 32) {
4107 tcg_gen_ext32s_i64(t0, t0);
4110 /* Shifts larger than MAX produce zero. */
4111 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4112 tcg_gen_neg_i64(t1, t1);
4113 tcg_gen_and_i64(t0, t0, t1);
4114 break;
4116 case OPC_ADD_CP2:
4117 case OPC_DADD_CP2:
4119 TCGv_i64 t2 = tcg_temp_new_i64();
4120 TCGLabel *lab = gen_new_label();
4122 tcg_gen_mov_i64(t2, t0);
4123 tcg_gen_add_i64(t0, t1, t2);
4124 if (opc == OPC_ADD_CP2) {
4125 tcg_gen_ext32s_i64(t0, t0);
4127 tcg_gen_xor_i64(t1, t1, t2);
4128 tcg_gen_xor_i64(t2, t2, t0);
4129 tcg_gen_andc_i64(t1, t2, t1);
4130 tcg_temp_free_i64(t2);
4131 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4132 generate_exception(ctx, EXCP_OVERFLOW);
4133 gen_set_label(lab);
4134 break;
4137 case OPC_SUB_CP2:
4138 case OPC_DSUB_CP2:
4140 TCGv_i64 t2 = tcg_temp_new_i64();
4141 TCGLabel *lab = gen_new_label();
4143 tcg_gen_mov_i64(t2, t0);
4144 tcg_gen_sub_i64(t0, t1, t2);
4145 if (opc == OPC_SUB_CP2) {
4146 tcg_gen_ext32s_i64(t0, t0);
4148 tcg_gen_xor_i64(t1, t1, t2);
4149 tcg_gen_xor_i64(t2, t2, t0);
4150 tcg_gen_and_i64(t1, t1, t2);
4151 tcg_temp_free_i64(t2);
4152 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4153 generate_exception(ctx, EXCP_OVERFLOW);
4154 gen_set_label(lab);
4155 break;
4158 case OPC_PMULUW:
4159 tcg_gen_ext32u_i64(t0, t0);
4160 tcg_gen_ext32u_i64(t1, t1);
4161 tcg_gen_mul_i64(t0, t0, t1);
4162 break;
4164 case OPC_SEQU_CP2:
4165 case OPC_SEQ_CP2:
4166 case OPC_SLTU_CP2:
4167 case OPC_SLT_CP2:
4168 case OPC_SLEU_CP2:
4169 case OPC_SLE_CP2:
4170 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
4171 FD field is the CC field? */
4172 default:
4173 MIPS_INVAL("loongson_cp2");
4174 generate_exception_end(ctx, EXCP_RI);
4175 return;
4178 #undef LMI_HELPER
4179 #undef LMI_DIRECT
4181 gen_store_fpr64(ctx, t0, rd);
4183 tcg_temp_free_i64(t0);
4184 tcg_temp_free_i64(t1);
4187 /* Traps */
4188 static void gen_trap (DisasContext *ctx, uint32_t opc,
4189 int rs, int rt, int16_t imm)
4191 int cond;
4192 TCGv t0 = tcg_temp_new();
4193 TCGv t1 = tcg_temp_new();
4195 cond = 0;
4196 /* Load needed operands */
4197 switch (opc) {
4198 case OPC_TEQ:
4199 case OPC_TGE:
4200 case OPC_TGEU:
4201 case OPC_TLT:
4202 case OPC_TLTU:
4203 case OPC_TNE:
4204 /* Compare two registers */
4205 if (rs != rt) {
4206 gen_load_gpr(t0, rs);
4207 gen_load_gpr(t1, rt);
4208 cond = 1;
4210 break;
4211 case OPC_TEQI:
4212 case OPC_TGEI:
4213 case OPC_TGEIU:
4214 case OPC_TLTI:
4215 case OPC_TLTIU:
4216 case OPC_TNEI:
4217 /* Compare register to immediate */
4218 if (rs != 0 || imm != 0) {
4219 gen_load_gpr(t0, rs);
4220 tcg_gen_movi_tl(t1, (int32_t)imm);
4221 cond = 1;
4223 break;
4225 if (cond == 0) {
4226 switch (opc) {
4227 case OPC_TEQ: /* rs == rs */
4228 case OPC_TEQI: /* r0 == 0 */
4229 case OPC_TGE: /* rs >= rs */
4230 case OPC_TGEI: /* r0 >= 0 */
4231 case OPC_TGEU: /* rs >= rs unsigned */
4232 case OPC_TGEIU: /* r0 >= 0 unsigned */
4233 /* Always trap */
4234 generate_exception_end(ctx, EXCP_TRAP);
4235 break;
4236 case OPC_TLT: /* rs < rs */
4237 case OPC_TLTI: /* r0 < 0 */
4238 case OPC_TLTU: /* rs < rs unsigned */
4239 case OPC_TLTIU: /* r0 < 0 unsigned */
4240 case OPC_TNE: /* rs != rs */
4241 case OPC_TNEI: /* r0 != 0 */
4242 /* Never trap: treat as NOP. */
4243 break;
4245 } else {
4246 TCGLabel *l1 = gen_new_label();
4248 switch (opc) {
4249 case OPC_TEQ:
4250 case OPC_TEQI:
4251 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4252 break;
4253 case OPC_TGE:
4254 case OPC_TGEI:
4255 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4256 break;
4257 case OPC_TGEU:
4258 case OPC_TGEIU:
4259 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4260 break;
4261 case OPC_TLT:
4262 case OPC_TLTI:
4263 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4264 break;
4265 case OPC_TLTU:
4266 case OPC_TLTIU:
4267 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4268 break;
4269 case OPC_TNE:
4270 case OPC_TNEI:
4271 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4272 break;
4274 generate_exception(ctx, EXCP_TRAP);
4275 gen_set_label(l1);
4277 tcg_temp_free(t0);
4278 tcg_temp_free(t1);
4281 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
4283 if (unlikely(ctx->singlestep_enabled)) {
4284 return false;
4287 #ifndef CONFIG_USER_ONLY
4288 return (ctx->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4289 #else
4290 return true;
4291 #endif
4294 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4296 if (use_goto_tb(ctx, dest)) {
4297 tcg_gen_goto_tb(n);
4298 gen_save_pc(dest);
4299 tcg_gen_exit_tb((uintptr_t)ctx->tb + n);
4300 } else {
4301 gen_save_pc(dest);
4302 if (ctx->singlestep_enabled) {
4303 save_cpu_state(ctx, 0);
4304 gen_helper_raise_exception_debug(cpu_env);
4306 tcg_gen_lookup_and_goto_ptr(cpu_PC);
4310 /* Branches (before delay slot) */
4311 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4312 int insn_bytes,
4313 int rs, int rt, int32_t offset,
4314 int delayslot_size)
4316 target_ulong btgt = -1;
4317 int blink = 0;
4318 int bcond_compute = 0;
4319 TCGv t0 = tcg_temp_new();
4320 TCGv t1 = tcg_temp_new();
4322 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4323 #ifdef MIPS_DEBUG_DISAS
4324 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4325 TARGET_FMT_lx "\n", ctx->pc);
4326 #endif
4327 generate_exception_end(ctx, EXCP_RI);
4328 goto out;
4331 /* Load needed operands */
4332 switch (opc) {
4333 case OPC_BEQ:
4334 case OPC_BEQL:
4335 case OPC_BNE:
4336 case OPC_BNEL:
4337 /* Compare two registers */
4338 if (rs != rt) {
4339 gen_load_gpr(t0, rs);
4340 gen_load_gpr(t1, rt);
4341 bcond_compute = 1;
4343 btgt = ctx->pc + insn_bytes + offset;
4344 break;
4345 case OPC_BGEZ:
4346 case OPC_BGEZAL:
4347 case OPC_BGEZALL:
4348 case OPC_BGEZL:
4349 case OPC_BGTZ:
4350 case OPC_BGTZL:
4351 case OPC_BLEZ:
4352 case OPC_BLEZL:
4353 case OPC_BLTZ:
4354 case OPC_BLTZAL:
4355 case OPC_BLTZALL:
4356 case OPC_BLTZL:
4357 /* Compare to zero */
4358 if (rs != 0) {
4359 gen_load_gpr(t0, rs);
4360 bcond_compute = 1;
4362 btgt = ctx->pc + insn_bytes + offset;
4363 break;
4364 case OPC_BPOSGE32:
4365 #if defined(TARGET_MIPS64)
4366 case OPC_BPOSGE64:
4367 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4368 #else
4369 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4370 #endif
4371 bcond_compute = 1;
4372 btgt = ctx->pc + insn_bytes + offset;
4373 break;
4374 case OPC_J:
4375 case OPC_JAL:
4376 case OPC_JALX:
4377 /* Jump to immediate */
4378 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4379 break;
4380 case OPC_JR:
4381 case OPC_JALR:
4382 /* Jump to register */
4383 if (offset != 0 && offset != 16) {
4384 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4385 others are reserved. */
4386 MIPS_INVAL("jump hint");
4387 generate_exception_end(ctx, EXCP_RI);
4388 goto out;
4390 gen_load_gpr(btarget, rs);
4391 break;
4392 default:
4393 MIPS_INVAL("branch/jump");
4394 generate_exception_end(ctx, EXCP_RI);
4395 goto out;
4397 if (bcond_compute == 0) {
4398 /* No condition to be computed */
4399 switch (opc) {
4400 case OPC_BEQ: /* rx == rx */
4401 case OPC_BEQL: /* rx == rx likely */
4402 case OPC_BGEZ: /* 0 >= 0 */
4403 case OPC_BGEZL: /* 0 >= 0 likely */
4404 case OPC_BLEZ: /* 0 <= 0 */
4405 case OPC_BLEZL: /* 0 <= 0 likely */
4406 /* Always take */
4407 ctx->hflags |= MIPS_HFLAG_B;
4408 break;
4409 case OPC_BGEZAL: /* 0 >= 0 */
4410 case OPC_BGEZALL: /* 0 >= 0 likely */
4411 /* Always take and link */
4412 blink = 31;
4413 ctx->hflags |= MIPS_HFLAG_B;
4414 break;
4415 case OPC_BNE: /* rx != rx */
4416 case OPC_BGTZ: /* 0 > 0 */
4417 case OPC_BLTZ: /* 0 < 0 */
4418 /* Treat as NOP. */
4419 goto out;
4420 case OPC_BLTZAL: /* 0 < 0 */
4421 /* Handle as an unconditional branch to get correct delay
4422 slot checking. */
4423 blink = 31;
4424 btgt = ctx->pc + insn_bytes + delayslot_size;
4425 ctx->hflags |= MIPS_HFLAG_B;
4426 break;
4427 case OPC_BLTZALL: /* 0 < 0 likely */
4428 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4429 /* Skip the instruction in the delay slot */
4430 ctx->pc += 4;
4431 goto out;
4432 case OPC_BNEL: /* rx != rx likely */
4433 case OPC_BGTZL: /* 0 > 0 likely */
4434 case OPC_BLTZL: /* 0 < 0 likely */
4435 /* Skip the instruction in the delay slot */
4436 ctx->pc += 4;
4437 goto out;
4438 case OPC_J:
4439 ctx->hflags |= MIPS_HFLAG_B;
4440 break;
4441 case OPC_JALX:
4442 ctx->hflags |= MIPS_HFLAG_BX;
4443 /* Fallthrough */
4444 case OPC_JAL:
4445 blink = 31;
4446 ctx->hflags |= MIPS_HFLAG_B;
4447 break;
4448 case OPC_JR:
4449 ctx->hflags |= MIPS_HFLAG_BR;
4450 break;
4451 case OPC_JALR:
4452 blink = rt;
4453 ctx->hflags |= MIPS_HFLAG_BR;
4454 break;
4455 default:
4456 MIPS_INVAL("branch/jump");
4457 generate_exception_end(ctx, EXCP_RI);
4458 goto out;
4460 } else {
4461 switch (opc) {
4462 case OPC_BEQ:
4463 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4464 goto not_likely;
4465 case OPC_BEQL:
4466 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4467 goto likely;
4468 case OPC_BNE:
4469 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4470 goto not_likely;
4471 case OPC_BNEL:
4472 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4473 goto likely;
4474 case OPC_BGEZ:
4475 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4476 goto not_likely;
4477 case OPC_BGEZL:
4478 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4479 goto likely;
4480 case OPC_BGEZAL:
4481 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4482 blink = 31;
4483 goto not_likely;
4484 case OPC_BGEZALL:
4485 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4486 blink = 31;
4487 goto likely;
4488 case OPC_BGTZ:
4489 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4490 goto not_likely;
4491 case OPC_BGTZL:
4492 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4493 goto likely;
4494 case OPC_BLEZ:
4495 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4496 goto not_likely;
4497 case OPC_BLEZL:
4498 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4499 goto likely;
4500 case OPC_BLTZ:
4501 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4502 goto not_likely;
4503 case OPC_BLTZL:
4504 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4505 goto likely;
4506 case OPC_BPOSGE32:
4507 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4508 goto not_likely;
4509 #if defined(TARGET_MIPS64)
4510 case OPC_BPOSGE64:
4511 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4512 goto not_likely;
4513 #endif
4514 case OPC_BLTZAL:
4515 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4516 blink = 31;
4517 not_likely:
4518 ctx->hflags |= MIPS_HFLAG_BC;
4519 break;
4520 case OPC_BLTZALL:
4521 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4522 blink = 31;
4523 likely:
4524 ctx->hflags |= MIPS_HFLAG_BL;
4525 break;
4526 default:
4527 MIPS_INVAL("conditional branch/jump");
4528 generate_exception_end(ctx, EXCP_RI);
4529 goto out;
4533 ctx->btarget = btgt;
4535 switch (delayslot_size) {
4536 case 2:
4537 ctx->hflags |= MIPS_HFLAG_BDS16;
4538 break;
4539 case 4:
4540 ctx->hflags |= MIPS_HFLAG_BDS32;
4541 break;
4544 if (blink > 0) {
4545 int post_delay = insn_bytes + delayslot_size;
4546 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4548 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4551 out:
4552 if (insn_bytes == 2)
4553 ctx->hflags |= MIPS_HFLAG_B16;
4554 tcg_temp_free(t0);
4555 tcg_temp_free(t1);
4558 /* special3 bitfield operations */
4559 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4560 int rs, int lsb, int msb)
4562 TCGv t0 = tcg_temp_new();
4563 TCGv t1 = tcg_temp_new();
4565 gen_load_gpr(t1, rs);
4566 switch (opc) {
4567 case OPC_EXT:
4568 if (lsb + msb > 31) {
4569 goto fail;
4571 if (msb != 31) {
4572 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4573 } else {
4574 /* The two checks together imply that lsb == 0,
4575 so this is a simple sign-extension. */
4576 tcg_gen_ext32s_tl(t0, t1);
4578 break;
4579 #if defined(TARGET_MIPS64)
4580 case OPC_DEXTU:
4581 lsb += 32;
4582 goto do_dext;
4583 case OPC_DEXTM:
4584 msb += 32;
4585 goto do_dext;
4586 case OPC_DEXT:
4587 do_dext:
4588 if (lsb + msb > 63) {
4589 goto fail;
4591 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4592 break;
4593 #endif
4594 case OPC_INS:
4595 if (lsb > msb) {
4596 goto fail;
4598 gen_load_gpr(t0, rt);
4599 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4600 tcg_gen_ext32s_tl(t0, t0);
4601 break;
4602 #if defined(TARGET_MIPS64)
4603 case OPC_DINSU:
4604 lsb += 32;
4605 /* FALLTHRU */
4606 case OPC_DINSM:
4607 msb += 32;
4608 /* FALLTHRU */
4609 case OPC_DINS:
4610 if (lsb > msb) {
4611 goto fail;
4613 gen_load_gpr(t0, rt);
4614 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4615 break;
4616 #endif
4617 default:
4618 fail:
4619 MIPS_INVAL("bitops");
4620 generate_exception_end(ctx, EXCP_RI);
4621 tcg_temp_free(t0);
4622 tcg_temp_free(t1);
4623 return;
4625 gen_store_gpr(t0, rt);
4626 tcg_temp_free(t0);
4627 tcg_temp_free(t1);
4630 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4632 TCGv t0;
4634 if (rd == 0) {
4635 /* If no destination, treat it as a NOP. */
4636 return;
4639 t0 = tcg_temp_new();
4640 gen_load_gpr(t0, rt);
4641 switch (op2) {
4642 case OPC_WSBH:
4644 TCGv t1 = tcg_temp_new();
4645 TCGv t2 = tcg_const_tl(0x00FF00FF);
4647 tcg_gen_shri_tl(t1, t0, 8);
4648 tcg_gen_and_tl(t1, t1, t2);
4649 tcg_gen_and_tl(t0, t0, t2);
4650 tcg_gen_shli_tl(t0, t0, 8);
4651 tcg_gen_or_tl(t0, t0, t1);
4652 tcg_temp_free(t2);
4653 tcg_temp_free(t1);
4654 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4656 break;
4657 case OPC_SEB:
4658 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4659 break;
4660 case OPC_SEH:
4661 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4662 break;
4663 #if defined(TARGET_MIPS64)
4664 case OPC_DSBH:
4666 TCGv t1 = tcg_temp_new();
4667 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
4669 tcg_gen_shri_tl(t1, t0, 8);
4670 tcg_gen_and_tl(t1, t1, t2);
4671 tcg_gen_and_tl(t0, t0, t2);
4672 tcg_gen_shli_tl(t0, t0, 8);
4673 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4674 tcg_temp_free(t2);
4675 tcg_temp_free(t1);
4677 break;
4678 case OPC_DSHD:
4680 TCGv t1 = tcg_temp_new();
4681 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
4683 tcg_gen_shri_tl(t1, t0, 16);
4684 tcg_gen_and_tl(t1, t1, t2);
4685 tcg_gen_and_tl(t0, t0, t2);
4686 tcg_gen_shli_tl(t0, t0, 16);
4687 tcg_gen_or_tl(t0, t0, t1);
4688 tcg_gen_shri_tl(t1, t0, 32);
4689 tcg_gen_shli_tl(t0, t0, 32);
4690 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4691 tcg_temp_free(t2);
4692 tcg_temp_free(t1);
4694 break;
4695 #endif
4696 default:
4697 MIPS_INVAL("bsfhl");
4698 generate_exception_end(ctx, EXCP_RI);
4699 tcg_temp_free(t0);
4700 return;
4702 tcg_temp_free(t0);
4705 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
4706 int imm2)
4708 TCGv t0;
4709 TCGv t1;
4710 if (rd == 0) {
4711 /* Treat as NOP. */
4712 return;
4714 t0 = tcg_temp_new();
4715 t1 = tcg_temp_new();
4716 gen_load_gpr(t0, rs);
4717 gen_load_gpr(t1, rt);
4718 tcg_gen_shli_tl(t0, t0, imm2 + 1);
4719 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
4720 if (opc == OPC_LSA) {
4721 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4724 tcg_temp_free(t1);
4725 tcg_temp_free(t0);
4727 return;
4730 static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
4731 int bp)
4733 TCGv t0;
4734 if (rd == 0) {
4735 /* Treat as NOP. */
4736 return;
4738 t0 = tcg_temp_new();
4739 gen_load_gpr(t0, rt);
4740 if (bp == 0) {
4741 switch (opc) {
4742 case OPC_ALIGN:
4743 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4744 break;
4745 #if defined(TARGET_MIPS64)
4746 case OPC_DALIGN:
4747 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4748 break;
4749 #endif
4751 } else {
4752 TCGv t1 = tcg_temp_new();
4753 gen_load_gpr(t1, rs);
4754 switch (opc) {
4755 case OPC_ALIGN:
4757 TCGv_i64 t2 = tcg_temp_new_i64();
4758 tcg_gen_concat_tl_i64(t2, t1, t0);
4759 tcg_gen_shri_i64(t2, t2, 8 * (4 - bp));
4760 gen_move_low32(cpu_gpr[rd], t2);
4761 tcg_temp_free_i64(t2);
4763 break;
4764 #if defined(TARGET_MIPS64)
4765 case OPC_DALIGN:
4766 tcg_gen_shli_tl(t0, t0, 8 * bp);
4767 tcg_gen_shri_tl(t1, t1, 8 * (8 - bp));
4768 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4769 break;
4770 #endif
4772 tcg_temp_free(t1);
4775 tcg_temp_free(t0);
4778 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4780 TCGv t0;
4781 if (rd == 0) {
4782 /* Treat as NOP. */
4783 return;
4785 t0 = tcg_temp_new();
4786 gen_load_gpr(t0, rt);
4787 switch (opc) {
4788 case OPC_BITSWAP:
4789 gen_helper_bitswap(cpu_gpr[rd], t0);
4790 break;
4791 #if defined(TARGET_MIPS64)
4792 case OPC_DBITSWAP:
4793 gen_helper_dbitswap(cpu_gpr[rd], t0);
4794 break;
4795 #endif
4797 tcg_temp_free(t0);
4800 #ifndef CONFIG_USER_ONLY
4801 /* CP0 (MMU and control) */
4802 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4804 TCGv_i64 t0 = tcg_temp_new_i64();
4805 TCGv_i64 t1 = tcg_temp_new_i64();
4807 tcg_gen_ext_tl_i64(t0, arg);
4808 tcg_gen_ld_i64(t1, cpu_env, off);
4809 #if defined(TARGET_MIPS64)
4810 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4811 #else
4812 tcg_gen_concat32_i64(t1, t1, t0);
4813 #endif
4814 tcg_gen_st_i64(t1, cpu_env, off);
4815 tcg_temp_free_i64(t1);
4816 tcg_temp_free_i64(t0);
4819 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4821 TCGv_i64 t0 = tcg_temp_new_i64();
4822 TCGv_i64 t1 = tcg_temp_new_i64();
4824 tcg_gen_ext_tl_i64(t0, arg);
4825 tcg_gen_ld_i64(t1, cpu_env, off);
4826 tcg_gen_concat32_i64(t1, t1, t0);
4827 tcg_gen_st_i64(t1, cpu_env, off);
4828 tcg_temp_free_i64(t1);
4829 tcg_temp_free_i64(t0);
4832 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4834 TCGv_i64 t0 = tcg_temp_new_i64();
4836 tcg_gen_ld_i64(t0, cpu_env, off);
4837 #if defined(TARGET_MIPS64)
4838 tcg_gen_shri_i64(t0, t0, 30);
4839 #else
4840 tcg_gen_shri_i64(t0, t0, 32);
4841 #endif
4842 gen_move_low32(arg, t0);
4843 tcg_temp_free_i64(t0);
4846 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4848 TCGv_i64 t0 = tcg_temp_new_i64();
4850 tcg_gen_ld_i64(t0, cpu_env, off);
4851 tcg_gen_shri_i64(t0, t0, 32 + shift);
4852 gen_move_low32(arg, t0);
4853 tcg_temp_free_i64(t0);
4856 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4858 TCGv_i32 t0 = tcg_temp_new_i32();
4860 tcg_gen_ld_i32(t0, cpu_env, off);
4861 tcg_gen_ext_i32_tl(arg, t0);
4862 tcg_temp_free_i32(t0);
4865 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4867 tcg_gen_ld_tl(arg, cpu_env, off);
4868 tcg_gen_ext32s_tl(arg, arg);
4871 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4873 TCGv_i32 t0 = tcg_temp_new_i32();
4875 tcg_gen_trunc_tl_i32(t0, arg);
4876 tcg_gen_st_i32(t0, cpu_env, off);
4877 tcg_temp_free_i32(t0);
4880 #define CP0_CHECK(c) \
4881 do { \
4882 if (!(c)) { \
4883 goto cp0_unimplemented; \
4885 } while (0)
4887 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4889 const char *rn = "invalid";
4891 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4893 switch (reg) {
4894 case 2:
4895 switch (sel) {
4896 case 0:
4897 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4898 rn = "EntryLo0";
4899 break;
4900 default:
4901 goto cp0_unimplemented;
4903 break;
4904 case 3:
4905 switch (sel) {
4906 case 0:
4907 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4908 rn = "EntryLo1";
4909 break;
4910 default:
4911 goto cp0_unimplemented;
4913 break;
4914 case 17:
4915 switch (sel) {
4916 case 0:
4917 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, lladdr),
4918 ctx->CP0_LLAddr_shift);
4919 rn = "LLAddr";
4920 break;
4921 case 1:
4922 CP0_CHECK(ctx->mrp);
4923 gen_helper_mfhc0_maar(arg, cpu_env);
4924 rn = "MAAR";
4925 break;
4926 default:
4927 goto cp0_unimplemented;
4929 break;
4930 case 28:
4931 switch (sel) {
4932 case 0:
4933 case 2:
4934 case 4:
4935 case 6:
4936 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4937 rn = "TagLo";
4938 break;
4939 default:
4940 goto cp0_unimplemented;
4942 break;
4943 default:
4944 goto cp0_unimplemented;
4946 trace_mips_translate_c0("mfhc0", rn, reg, sel);
4947 return;
4949 cp0_unimplemented:
4950 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n", rn, reg, sel);
4951 tcg_gen_movi_tl(arg, 0);
4954 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4956 const char *rn = "invalid";
4957 uint64_t mask = ctx->PAMask >> 36;
4959 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4961 switch (reg) {
4962 case 2:
4963 switch (sel) {
4964 case 0:
4965 tcg_gen_andi_tl(arg, arg, mask);
4966 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4967 rn = "EntryLo0";
4968 break;
4969 default:
4970 goto cp0_unimplemented;
4972 break;
4973 case 3:
4974 switch (sel) {
4975 case 0:
4976 tcg_gen_andi_tl(arg, arg, mask);
4977 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4978 rn = "EntryLo1";
4979 break;
4980 default:
4981 goto cp0_unimplemented;
4983 break;
4984 case 17:
4985 switch (sel) {
4986 case 0:
4987 /* LLAddr is read-only (the only exception is bit 0 if LLB is
4988 supported); the CP0_LLAddr_rw_bitmask does not seem to be
4989 relevant for modern MIPS cores supporting MTHC0, therefore
4990 treating MTHC0 to LLAddr as NOP. */
4991 rn = "LLAddr";
4992 break;
4993 case 1:
4994 CP0_CHECK(ctx->mrp);
4995 gen_helper_mthc0_maar(cpu_env, arg);
4996 rn = "MAAR";
4997 break;
4998 default:
4999 goto cp0_unimplemented;
5001 break;
5002 case 28:
5003 switch (sel) {
5004 case 0:
5005 case 2:
5006 case 4:
5007 case 6:
5008 tcg_gen_andi_tl(arg, arg, mask);
5009 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5010 rn = "TagLo";
5011 break;
5012 default:
5013 goto cp0_unimplemented;
5015 break;
5016 default:
5017 goto cp0_unimplemented;
5019 trace_mips_translate_c0("mthc0", rn, reg, sel);
5021 cp0_unimplemented:
5022 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n", rn, reg, sel);
5025 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5027 if (ctx->insn_flags & ISA_MIPS32R6) {
5028 tcg_gen_movi_tl(arg, 0);
5029 } else {
5030 tcg_gen_movi_tl(arg, ~0);
5034 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5036 const char *rn = "invalid";
5038 if (sel != 0)
5039 check_insn(ctx, ISA_MIPS32);
5041 switch (reg) {
5042 case 0:
5043 switch (sel) {
5044 case 0:
5045 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5046 rn = "Index";
5047 break;
5048 case 1:
5049 CP0_CHECK(ctx->insn_flags & ASE_MT);
5050 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5051 rn = "MVPControl";
5052 break;
5053 case 2:
5054 CP0_CHECK(ctx->insn_flags & ASE_MT);
5055 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5056 rn = "MVPConf0";
5057 break;
5058 case 3:
5059 CP0_CHECK(ctx->insn_flags & ASE_MT);
5060 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5061 rn = "MVPConf1";
5062 break;
5063 case 4:
5064 CP0_CHECK(ctx->vp);
5065 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5066 rn = "VPControl";
5067 break;
5068 default:
5069 goto cp0_unimplemented;
5071 break;
5072 case 1:
5073 switch (sel) {
5074 case 0:
5075 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5076 gen_helper_mfc0_random(arg, cpu_env);
5077 rn = "Random";
5078 break;
5079 case 1:
5080 CP0_CHECK(ctx->insn_flags & ASE_MT);
5081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5082 rn = "VPEControl";
5083 break;
5084 case 2:
5085 CP0_CHECK(ctx->insn_flags & ASE_MT);
5086 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5087 rn = "VPEConf0";
5088 break;
5089 case 3:
5090 CP0_CHECK(ctx->insn_flags & ASE_MT);
5091 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5092 rn = "VPEConf1";
5093 break;
5094 case 4:
5095 CP0_CHECK(ctx->insn_flags & ASE_MT);
5096 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5097 rn = "YQMask";
5098 break;
5099 case 5:
5100 CP0_CHECK(ctx->insn_flags & ASE_MT);
5101 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5102 rn = "VPESchedule";
5103 break;
5104 case 6:
5105 CP0_CHECK(ctx->insn_flags & ASE_MT);
5106 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5107 rn = "VPEScheFBack";
5108 break;
5109 case 7:
5110 CP0_CHECK(ctx->insn_flags & ASE_MT);
5111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5112 rn = "VPEOpt";
5113 break;
5114 default:
5115 goto cp0_unimplemented;
5117 break;
5118 case 2:
5119 switch (sel) {
5120 case 0:
5122 TCGv_i64 tmp = tcg_temp_new_i64();
5123 tcg_gen_ld_i64(tmp, cpu_env,
5124 offsetof(CPUMIPSState, CP0_EntryLo0));
5125 #if defined(TARGET_MIPS64)
5126 if (ctx->rxi) {
5127 /* Move RI/XI fields to bits 31:30 */
5128 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5129 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5131 #endif
5132 gen_move_low32(arg, tmp);
5133 tcg_temp_free_i64(tmp);
5135 rn = "EntryLo0";
5136 break;
5137 case 1:
5138 CP0_CHECK(ctx->insn_flags & ASE_MT);
5139 gen_helper_mfc0_tcstatus(arg, cpu_env);
5140 rn = "TCStatus";
5141 break;
5142 case 2:
5143 CP0_CHECK(ctx->insn_flags & ASE_MT);
5144 gen_helper_mfc0_tcbind(arg, cpu_env);
5145 rn = "TCBind";
5146 break;
5147 case 3:
5148 CP0_CHECK(ctx->insn_flags & ASE_MT);
5149 gen_helper_mfc0_tcrestart(arg, cpu_env);
5150 rn = "TCRestart";
5151 break;
5152 case 4:
5153 CP0_CHECK(ctx->insn_flags & ASE_MT);
5154 gen_helper_mfc0_tchalt(arg, cpu_env);
5155 rn = "TCHalt";
5156 break;
5157 case 5:
5158 CP0_CHECK(ctx->insn_flags & ASE_MT);
5159 gen_helper_mfc0_tccontext(arg, cpu_env);
5160 rn = "TCContext";
5161 break;
5162 case 6:
5163 CP0_CHECK(ctx->insn_flags & ASE_MT);
5164 gen_helper_mfc0_tcschedule(arg, cpu_env);
5165 rn = "TCSchedule";
5166 break;
5167 case 7:
5168 CP0_CHECK(ctx->insn_flags & ASE_MT);
5169 gen_helper_mfc0_tcschefback(arg, cpu_env);
5170 rn = "TCScheFBack";
5171 break;
5172 default:
5173 goto cp0_unimplemented;
5175 break;
5176 case 3:
5177 switch (sel) {
5178 case 0:
5180 TCGv_i64 tmp = tcg_temp_new_i64();
5181 tcg_gen_ld_i64(tmp, cpu_env,
5182 offsetof(CPUMIPSState, CP0_EntryLo1));
5183 #if defined(TARGET_MIPS64)
5184 if (ctx->rxi) {
5185 /* Move RI/XI fields to bits 31:30 */
5186 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5187 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5189 #endif
5190 gen_move_low32(arg, tmp);
5191 tcg_temp_free_i64(tmp);
5193 rn = "EntryLo1";
5194 break;
5195 case 1:
5196 CP0_CHECK(ctx->vp);
5197 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5198 rn = "GlobalNumber";
5199 break;
5200 default:
5201 goto cp0_unimplemented;
5203 break;
5204 case 4:
5205 switch (sel) {
5206 case 0:
5207 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5208 tcg_gen_ext32s_tl(arg, arg);
5209 rn = "Context";
5210 break;
5211 case 1:
5212 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
5213 rn = "ContextConfig";
5214 goto cp0_unimplemented;
5215 case 2:
5216 CP0_CHECK(ctx->ulri);
5217 tcg_gen_ld_tl(arg, cpu_env,
5218 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5219 tcg_gen_ext32s_tl(arg, arg);
5220 rn = "UserLocal";
5221 break;
5222 default:
5223 goto cp0_unimplemented;
5225 break;
5226 case 5:
5227 switch (sel) {
5228 case 0:
5229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5230 rn = "PageMask";
5231 break;
5232 case 1:
5233 check_insn(ctx, ISA_MIPS32R2);
5234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5235 rn = "PageGrain";
5236 break;
5237 case 2:
5238 CP0_CHECK(ctx->sc);
5239 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5240 tcg_gen_ext32s_tl(arg, arg);
5241 rn = "SegCtl0";
5242 break;
5243 case 3:
5244 CP0_CHECK(ctx->sc);
5245 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5246 tcg_gen_ext32s_tl(arg, arg);
5247 rn = "SegCtl1";
5248 break;
5249 case 4:
5250 CP0_CHECK(ctx->sc);
5251 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5252 tcg_gen_ext32s_tl(arg, arg);
5253 rn = "SegCtl2";
5254 break;
5255 default:
5256 goto cp0_unimplemented;
5258 break;
5259 case 6:
5260 switch (sel) {
5261 case 0:
5262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5263 rn = "Wired";
5264 break;
5265 case 1:
5266 check_insn(ctx, ISA_MIPS32R2);
5267 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5268 rn = "SRSConf0";
5269 break;
5270 case 2:
5271 check_insn(ctx, ISA_MIPS32R2);
5272 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5273 rn = "SRSConf1";
5274 break;
5275 case 3:
5276 check_insn(ctx, ISA_MIPS32R2);
5277 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5278 rn = "SRSConf2";
5279 break;
5280 case 4:
5281 check_insn(ctx, ISA_MIPS32R2);
5282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5283 rn = "SRSConf3";
5284 break;
5285 case 5:
5286 check_insn(ctx, ISA_MIPS32R2);
5287 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5288 rn = "SRSConf4";
5289 break;
5290 default:
5291 goto cp0_unimplemented;
5293 break;
5294 case 7:
5295 switch (sel) {
5296 case 0:
5297 check_insn(ctx, ISA_MIPS32R2);
5298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5299 rn = "HWREna";
5300 break;
5301 default:
5302 goto cp0_unimplemented;
5304 break;
5305 case 8:
5306 switch (sel) {
5307 case 0:
5308 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5309 tcg_gen_ext32s_tl(arg, arg);
5310 rn = "BadVAddr";
5311 break;
5312 case 1:
5313 CP0_CHECK(ctx->bi);
5314 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5315 rn = "BadInstr";
5316 break;
5317 case 2:
5318 CP0_CHECK(ctx->bp);
5319 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5320 rn = "BadInstrP";
5321 break;
5322 default:
5323 goto cp0_unimplemented;
5325 break;
5326 case 9:
5327 switch (sel) {
5328 case 0:
5329 /* Mark as an IO operation because we read the time. */
5330 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5331 gen_io_start();
5333 gen_helper_mfc0_count(arg, cpu_env);
5334 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5335 gen_io_end();
5337 /* Break the TB to be able to take timer interrupts immediately
5338 after reading count. BS_STOP isn't sufficient, we need to ensure
5339 we break completely out of translated code. */
5340 gen_save_pc(ctx->pc + 4);
5341 ctx->bstate = BS_EXCP;
5342 rn = "Count";
5343 break;
5344 /* 6,7 are implementation dependent */
5345 default:
5346 goto cp0_unimplemented;
5348 break;
5349 case 10:
5350 switch (sel) {
5351 case 0:
5352 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5353 tcg_gen_ext32s_tl(arg, arg);
5354 rn = "EntryHi";
5355 break;
5356 default:
5357 goto cp0_unimplemented;
5359 break;
5360 case 11:
5361 switch (sel) {
5362 case 0:
5363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5364 rn = "Compare";
5365 break;
5366 /* 6,7 are implementation dependent */
5367 default:
5368 goto cp0_unimplemented;
5370 break;
5371 case 12:
5372 switch (sel) {
5373 case 0:
5374 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5375 rn = "Status";
5376 break;
5377 case 1:
5378 check_insn(ctx, ISA_MIPS32R2);
5379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5380 rn = "IntCtl";
5381 break;
5382 case 2:
5383 check_insn(ctx, ISA_MIPS32R2);
5384 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5385 rn = "SRSCtl";
5386 break;
5387 case 3:
5388 check_insn(ctx, ISA_MIPS32R2);
5389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5390 rn = "SRSMap";
5391 break;
5392 default:
5393 goto cp0_unimplemented;
5395 break;
5396 case 13:
5397 switch (sel) {
5398 case 0:
5399 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5400 rn = "Cause";
5401 break;
5402 default:
5403 goto cp0_unimplemented;
5405 break;
5406 case 14:
5407 switch (sel) {
5408 case 0:
5409 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5410 tcg_gen_ext32s_tl(arg, arg);
5411 rn = "EPC";
5412 break;
5413 default:
5414 goto cp0_unimplemented;
5416 break;
5417 case 15:
5418 switch (sel) {
5419 case 0:
5420 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5421 rn = "PRid";
5422 break;
5423 case 1:
5424 check_insn(ctx, ISA_MIPS32R2);
5425 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
5426 tcg_gen_ext32s_tl(arg, arg);
5427 rn = "EBase";
5428 break;
5429 case 3:
5430 check_insn(ctx, ISA_MIPS32R2);
5431 CP0_CHECK(ctx->cmgcr);
5432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5433 tcg_gen_ext32s_tl(arg, arg);
5434 rn = "CMGCRBase";
5435 break;
5436 default:
5437 goto cp0_unimplemented;
5439 break;
5440 case 16:
5441 switch (sel) {
5442 case 0:
5443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5444 rn = "Config";
5445 break;
5446 case 1:
5447 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5448 rn = "Config1";
5449 break;
5450 case 2:
5451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5452 rn = "Config2";
5453 break;
5454 case 3:
5455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5456 rn = "Config3";
5457 break;
5458 case 4:
5459 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5460 rn = "Config4";
5461 break;
5462 case 5:
5463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5464 rn = "Config5";
5465 break;
5466 /* 6,7 are implementation dependent */
5467 case 6:
5468 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5469 rn = "Config6";
5470 break;
5471 case 7:
5472 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5473 rn = "Config7";
5474 break;
5475 default:
5476 goto cp0_unimplemented;
5478 break;
5479 case 17:
5480 switch (sel) {
5481 case 0:
5482 gen_helper_mfc0_lladdr(arg, cpu_env);
5483 rn = "LLAddr";
5484 break;
5485 case 1:
5486 CP0_CHECK(ctx->mrp);
5487 gen_helper_mfc0_maar(arg, cpu_env);
5488 rn = "MAAR";
5489 break;
5490 case 2:
5491 CP0_CHECK(ctx->mrp);
5492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5493 rn = "MAARI";
5494 break;
5495 default:
5496 goto cp0_unimplemented;
5498 break;
5499 case 18:
5500 switch (sel) {
5501 case 0 ... 7:
5502 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5503 rn = "WatchLo";
5504 break;
5505 default:
5506 goto cp0_unimplemented;
5508 break;
5509 case 19:
5510 switch (sel) {
5511 case 0 ...7:
5512 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5513 rn = "WatchHi";
5514 break;
5515 default:
5516 goto cp0_unimplemented;
5518 break;
5519 case 20:
5520 switch (sel) {
5521 case 0:
5522 #if defined(TARGET_MIPS64)
5523 check_insn(ctx, ISA_MIPS3);
5524 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5525 tcg_gen_ext32s_tl(arg, arg);
5526 rn = "XContext";
5527 break;
5528 #endif
5529 default:
5530 goto cp0_unimplemented;
5532 break;
5533 case 21:
5534 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5535 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
5536 switch (sel) {
5537 case 0:
5538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5539 rn = "Framemask";
5540 break;
5541 default:
5542 goto cp0_unimplemented;
5544 break;
5545 case 22:
5546 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5547 rn = "'Diagnostic"; /* implementation dependent */
5548 break;
5549 case 23:
5550 switch (sel) {
5551 case 0:
5552 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5553 rn = "Debug";
5554 break;
5555 case 1:
5556 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5557 rn = "TraceControl";
5558 goto cp0_unimplemented;
5559 case 2:
5560 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5561 rn = "TraceControl2";
5562 goto cp0_unimplemented;
5563 case 3:
5564 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5565 rn = "UserTraceData";
5566 goto cp0_unimplemented;
5567 case 4:
5568 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5569 rn = "TraceBPC";
5570 goto cp0_unimplemented;
5571 default:
5572 goto cp0_unimplemented;
5574 break;
5575 case 24:
5576 switch (sel) {
5577 case 0:
5578 /* EJTAG support */
5579 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5580 tcg_gen_ext32s_tl(arg, arg);
5581 rn = "DEPC";
5582 break;
5583 default:
5584 goto cp0_unimplemented;
5586 break;
5587 case 25:
5588 switch (sel) {
5589 case 0:
5590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5591 rn = "Performance0";
5592 break;
5593 case 1:
5594 // gen_helper_mfc0_performance1(arg);
5595 rn = "Performance1";
5596 goto cp0_unimplemented;
5597 case 2:
5598 // gen_helper_mfc0_performance2(arg);
5599 rn = "Performance2";
5600 goto cp0_unimplemented;
5601 case 3:
5602 // gen_helper_mfc0_performance3(arg);
5603 rn = "Performance3";
5604 goto cp0_unimplemented;
5605 case 4:
5606 // gen_helper_mfc0_performance4(arg);
5607 rn = "Performance4";
5608 goto cp0_unimplemented;
5609 case 5:
5610 // gen_helper_mfc0_performance5(arg);
5611 rn = "Performance5";
5612 goto cp0_unimplemented;
5613 case 6:
5614 // gen_helper_mfc0_performance6(arg);
5615 rn = "Performance6";
5616 goto cp0_unimplemented;
5617 case 7:
5618 // gen_helper_mfc0_performance7(arg);
5619 rn = "Performance7";
5620 goto cp0_unimplemented;
5621 default:
5622 goto cp0_unimplemented;
5624 break;
5625 case 26:
5626 switch (sel) {
5627 case 0:
5628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5629 rn = "ErrCtl";
5630 break;
5631 default:
5632 goto cp0_unimplemented;
5634 break;
5635 case 27:
5636 switch (sel) {
5637 case 0 ... 3:
5638 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5639 rn = "CacheErr";
5640 break;
5641 default:
5642 goto cp0_unimplemented;
5644 break;
5645 case 28:
5646 switch (sel) {
5647 case 0:
5648 case 2:
5649 case 4:
5650 case 6:
5652 TCGv_i64 tmp = tcg_temp_new_i64();
5653 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
5654 gen_move_low32(arg, tmp);
5655 tcg_temp_free_i64(tmp);
5657 rn = "TagLo";
5658 break;
5659 case 1:
5660 case 3:
5661 case 5:
5662 case 7:
5663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5664 rn = "DataLo";
5665 break;
5666 default:
5667 goto cp0_unimplemented;
5669 break;
5670 case 29:
5671 switch (sel) {
5672 case 0:
5673 case 2:
5674 case 4:
5675 case 6:
5676 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5677 rn = "TagHi";
5678 break;
5679 case 1:
5680 case 3:
5681 case 5:
5682 case 7:
5683 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5684 rn = "DataHi";
5685 break;
5686 default:
5687 goto cp0_unimplemented;
5689 break;
5690 case 30:
5691 switch (sel) {
5692 case 0:
5693 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5694 tcg_gen_ext32s_tl(arg, arg);
5695 rn = "ErrorEPC";
5696 break;
5697 default:
5698 goto cp0_unimplemented;
5700 break;
5701 case 31:
5702 switch (sel) {
5703 case 0:
5704 /* EJTAG support */
5705 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5706 rn = "DESAVE";
5707 break;
5708 case 2 ... 7:
5709 CP0_CHECK(ctx->kscrexist & (1 << sel));
5710 tcg_gen_ld_tl(arg, cpu_env,
5711 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5712 tcg_gen_ext32s_tl(arg, arg);
5713 rn = "KScratch";
5714 break;
5715 default:
5716 goto cp0_unimplemented;
5718 break;
5719 default:
5720 goto cp0_unimplemented;
5722 trace_mips_translate_c0("mfc0", rn, reg, sel);
5723 return;
5725 cp0_unimplemented:
5726 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5727 gen_mfc0_unimplemented(ctx, arg);
5730 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5732 const char *rn = "invalid";
5734 if (sel != 0)
5735 check_insn(ctx, ISA_MIPS32);
5737 if (ctx->tb->cflags & CF_USE_ICOUNT) {
5738 gen_io_start();
5741 switch (reg) {
5742 case 0:
5743 switch (sel) {
5744 case 0:
5745 gen_helper_mtc0_index(cpu_env, arg);
5746 rn = "Index";
5747 break;
5748 case 1:
5749 CP0_CHECK(ctx->insn_flags & ASE_MT);
5750 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5751 rn = "MVPControl";
5752 break;
5753 case 2:
5754 CP0_CHECK(ctx->insn_flags & ASE_MT);
5755 /* ignored */
5756 rn = "MVPConf0";
5757 break;
5758 case 3:
5759 CP0_CHECK(ctx->insn_flags & ASE_MT);
5760 /* ignored */
5761 rn = "MVPConf1";
5762 break;
5763 case 4:
5764 CP0_CHECK(ctx->vp);
5765 /* ignored */
5766 rn = "VPControl";
5767 break;
5768 default:
5769 goto cp0_unimplemented;
5771 break;
5772 case 1:
5773 switch (sel) {
5774 case 0:
5775 /* ignored */
5776 rn = "Random";
5777 break;
5778 case 1:
5779 CP0_CHECK(ctx->insn_flags & ASE_MT);
5780 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5781 rn = "VPEControl";
5782 break;
5783 case 2:
5784 CP0_CHECK(ctx->insn_flags & ASE_MT);
5785 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5786 rn = "VPEConf0";
5787 break;
5788 case 3:
5789 CP0_CHECK(ctx->insn_flags & ASE_MT);
5790 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5791 rn = "VPEConf1";
5792 break;
5793 case 4:
5794 CP0_CHECK(ctx->insn_flags & ASE_MT);
5795 gen_helper_mtc0_yqmask(cpu_env, arg);
5796 rn = "YQMask";
5797 break;
5798 case 5:
5799 CP0_CHECK(ctx->insn_flags & ASE_MT);
5800 tcg_gen_st_tl(arg, cpu_env,
5801 offsetof(CPUMIPSState, CP0_VPESchedule));
5802 rn = "VPESchedule";
5803 break;
5804 case 6:
5805 CP0_CHECK(ctx->insn_flags & ASE_MT);
5806 tcg_gen_st_tl(arg, cpu_env,
5807 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5808 rn = "VPEScheFBack";
5809 break;
5810 case 7:
5811 CP0_CHECK(ctx->insn_flags & ASE_MT);
5812 gen_helper_mtc0_vpeopt(cpu_env, arg);
5813 rn = "VPEOpt";
5814 break;
5815 default:
5816 goto cp0_unimplemented;
5818 break;
5819 case 2:
5820 switch (sel) {
5821 case 0:
5822 gen_helper_mtc0_entrylo0(cpu_env, arg);
5823 rn = "EntryLo0";
5824 break;
5825 case 1:
5826 CP0_CHECK(ctx->insn_flags & ASE_MT);
5827 gen_helper_mtc0_tcstatus(cpu_env, arg);
5828 rn = "TCStatus";
5829 break;
5830 case 2:
5831 CP0_CHECK(ctx->insn_flags & ASE_MT);
5832 gen_helper_mtc0_tcbind(cpu_env, arg);
5833 rn = "TCBind";
5834 break;
5835 case 3:
5836 CP0_CHECK(ctx->insn_flags & ASE_MT);
5837 gen_helper_mtc0_tcrestart(cpu_env, arg);
5838 rn = "TCRestart";
5839 break;
5840 case 4:
5841 CP0_CHECK(ctx->insn_flags & ASE_MT);
5842 gen_helper_mtc0_tchalt(cpu_env, arg);
5843 rn = "TCHalt";
5844 break;
5845 case 5:
5846 CP0_CHECK(ctx->insn_flags & ASE_MT);
5847 gen_helper_mtc0_tccontext(cpu_env, arg);
5848 rn = "TCContext";
5849 break;
5850 case 6:
5851 CP0_CHECK(ctx->insn_flags & ASE_MT);
5852 gen_helper_mtc0_tcschedule(cpu_env, arg);
5853 rn = "TCSchedule";
5854 break;
5855 case 7:
5856 CP0_CHECK(ctx->insn_flags & ASE_MT);
5857 gen_helper_mtc0_tcschefback(cpu_env, arg);
5858 rn = "TCScheFBack";
5859 break;
5860 default:
5861 goto cp0_unimplemented;
5863 break;
5864 case 3:
5865 switch (sel) {
5866 case 0:
5867 gen_helper_mtc0_entrylo1(cpu_env, arg);
5868 rn = "EntryLo1";
5869 break;
5870 case 1:
5871 CP0_CHECK(ctx->vp);
5872 /* ignored */
5873 rn = "GlobalNumber";
5874 break;
5875 default:
5876 goto cp0_unimplemented;
5878 break;
5879 case 4:
5880 switch (sel) {
5881 case 0:
5882 gen_helper_mtc0_context(cpu_env, arg);
5883 rn = "Context";
5884 break;
5885 case 1:
5886 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5887 rn = "ContextConfig";
5888 goto cp0_unimplemented;
5889 case 2:
5890 CP0_CHECK(ctx->ulri);
5891 tcg_gen_st_tl(arg, cpu_env,
5892 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5893 rn = "UserLocal";
5894 break;
5895 default:
5896 goto cp0_unimplemented;
5898 break;
5899 case 5:
5900 switch (sel) {
5901 case 0:
5902 gen_helper_mtc0_pagemask(cpu_env, arg);
5903 rn = "PageMask";
5904 break;
5905 case 1:
5906 check_insn(ctx, ISA_MIPS32R2);
5907 gen_helper_mtc0_pagegrain(cpu_env, arg);
5908 rn = "PageGrain";
5909 ctx->bstate = BS_STOP;
5910 break;
5911 case 2:
5912 CP0_CHECK(ctx->sc);
5913 gen_helper_mtc0_segctl0(cpu_env, arg);
5914 rn = "SegCtl0";
5915 break;
5916 case 3:
5917 CP0_CHECK(ctx->sc);
5918 gen_helper_mtc0_segctl1(cpu_env, arg);
5919 rn = "SegCtl1";
5920 break;
5921 case 4:
5922 CP0_CHECK(ctx->sc);
5923 gen_helper_mtc0_segctl2(cpu_env, arg);
5924 rn = "SegCtl2";
5925 break;
5926 default:
5927 goto cp0_unimplemented;
5929 break;
5930 case 6:
5931 switch (sel) {
5932 case 0:
5933 gen_helper_mtc0_wired(cpu_env, arg);
5934 rn = "Wired";
5935 break;
5936 case 1:
5937 check_insn(ctx, ISA_MIPS32R2);
5938 gen_helper_mtc0_srsconf0(cpu_env, arg);
5939 rn = "SRSConf0";
5940 break;
5941 case 2:
5942 check_insn(ctx, ISA_MIPS32R2);
5943 gen_helper_mtc0_srsconf1(cpu_env, arg);
5944 rn = "SRSConf1";
5945 break;
5946 case 3:
5947 check_insn(ctx, ISA_MIPS32R2);
5948 gen_helper_mtc0_srsconf2(cpu_env, arg);
5949 rn = "SRSConf2";
5950 break;
5951 case 4:
5952 check_insn(ctx, ISA_MIPS32R2);
5953 gen_helper_mtc0_srsconf3(cpu_env, arg);
5954 rn = "SRSConf3";
5955 break;
5956 case 5:
5957 check_insn(ctx, ISA_MIPS32R2);
5958 gen_helper_mtc0_srsconf4(cpu_env, arg);
5959 rn = "SRSConf4";
5960 break;
5961 default:
5962 goto cp0_unimplemented;
5964 break;
5965 case 7:
5966 switch (sel) {
5967 case 0:
5968 check_insn(ctx, ISA_MIPS32R2);
5969 gen_helper_mtc0_hwrena(cpu_env, arg);
5970 ctx->bstate = BS_STOP;
5971 rn = "HWREna";
5972 break;
5973 default:
5974 goto cp0_unimplemented;
5976 break;
5977 case 8:
5978 switch (sel) {
5979 case 0:
5980 /* ignored */
5981 rn = "BadVAddr";
5982 break;
5983 case 1:
5984 /* ignored */
5985 rn = "BadInstr";
5986 break;
5987 case 2:
5988 /* ignored */
5989 rn = "BadInstrP";
5990 break;
5991 default:
5992 goto cp0_unimplemented;
5994 break;
5995 case 9:
5996 switch (sel) {
5997 case 0:
5998 gen_helper_mtc0_count(cpu_env, arg);
5999 rn = "Count";
6000 break;
6001 /* 6,7 are implementation dependent */
6002 default:
6003 goto cp0_unimplemented;
6005 break;
6006 case 10:
6007 switch (sel) {
6008 case 0:
6009 gen_helper_mtc0_entryhi(cpu_env, arg);
6010 rn = "EntryHi";
6011 break;
6012 default:
6013 goto cp0_unimplemented;
6015 break;
6016 case 11:
6017 switch (sel) {
6018 case 0:
6019 gen_helper_mtc0_compare(cpu_env, arg);
6020 rn = "Compare";
6021 break;
6022 /* 6,7 are implementation dependent */
6023 default:
6024 goto cp0_unimplemented;
6026 break;
6027 case 12:
6028 switch (sel) {
6029 case 0:
6030 save_cpu_state(ctx, 1);
6031 gen_helper_mtc0_status(cpu_env, arg);
6032 /* BS_STOP isn't good enough here, hflags may have changed. */
6033 gen_save_pc(ctx->pc + 4);
6034 ctx->bstate = BS_EXCP;
6035 rn = "Status";
6036 break;
6037 case 1:
6038 check_insn(ctx, ISA_MIPS32R2);
6039 gen_helper_mtc0_intctl(cpu_env, arg);
6040 /* Stop translation as we may have switched the execution mode */
6041 ctx->bstate = BS_STOP;
6042 rn = "IntCtl";
6043 break;
6044 case 2:
6045 check_insn(ctx, ISA_MIPS32R2);
6046 gen_helper_mtc0_srsctl(cpu_env, arg);
6047 /* Stop translation as we may have switched the execution mode */
6048 ctx->bstate = BS_STOP;
6049 rn = "SRSCtl";
6050 break;
6051 case 3:
6052 check_insn(ctx, ISA_MIPS32R2);
6053 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6054 /* Stop translation as we may have switched the execution mode */
6055 ctx->bstate = BS_STOP;
6056 rn = "SRSMap";
6057 break;
6058 default:
6059 goto cp0_unimplemented;
6061 break;
6062 case 13:
6063 switch (sel) {
6064 case 0:
6065 save_cpu_state(ctx, 1);
6066 gen_helper_mtc0_cause(cpu_env, arg);
6067 /* Stop translation as we may have triggered an interrupt. BS_STOP
6068 * isn't sufficient, we need to ensure we break out of translated
6069 * code to check for pending interrupts. */
6070 gen_save_pc(ctx->pc + 4);
6071 ctx->bstate = BS_EXCP;
6072 rn = "Cause";
6073 break;
6074 default:
6075 goto cp0_unimplemented;
6077 break;
6078 case 14:
6079 switch (sel) {
6080 case 0:
6081 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6082 rn = "EPC";
6083 break;
6084 default:
6085 goto cp0_unimplemented;
6087 break;
6088 case 15:
6089 switch (sel) {
6090 case 0:
6091 /* ignored */
6092 rn = "PRid";
6093 break;
6094 case 1:
6095 check_insn(ctx, ISA_MIPS32R2);
6096 gen_helper_mtc0_ebase(cpu_env, arg);
6097 rn = "EBase";
6098 break;
6099 default:
6100 goto cp0_unimplemented;
6102 break;
6103 case 16:
6104 switch (sel) {
6105 case 0:
6106 gen_helper_mtc0_config0(cpu_env, arg);
6107 rn = "Config";
6108 /* Stop translation as we may have switched the execution mode */
6109 ctx->bstate = BS_STOP;
6110 break;
6111 case 1:
6112 /* ignored, read only */
6113 rn = "Config1";
6114 break;
6115 case 2:
6116 gen_helper_mtc0_config2(cpu_env, arg);
6117 rn = "Config2";
6118 /* Stop translation as we may have switched the execution mode */
6119 ctx->bstate = BS_STOP;
6120 break;
6121 case 3:
6122 gen_helper_mtc0_config3(cpu_env, arg);
6123 rn = "Config3";
6124 /* Stop translation as we may have switched the execution mode */
6125 ctx->bstate = BS_STOP;
6126 break;
6127 case 4:
6128 gen_helper_mtc0_config4(cpu_env, arg);
6129 rn = "Config4";
6130 ctx->bstate = BS_STOP;
6131 break;
6132 case 5:
6133 gen_helper_mtc0_config5(cpu_env, arg);
6134 rn = "Config5";
6135 /* Stop translation as we may have switched the execution mode */
6136 ctx->bstate = BS_STOP;
6137 break;
6138 /* 6,7 are implementation dependent */
6139 case 6:
6140 /* ignored */
6141 rn = "Config6";
6142 break;
6143 case 7:
6144 /* ignored */
6145 rn = "Config7";
6146 break;
6147 default:
6148 rn = "Invalid config selector";
6149 goto cp0_unimplemented;
6151 break;
6152 case 17:
6153 switch (sel) {
6154 case 0:
6155 gen_helper_mtc0_lladdr(cpu_env, arg);
6156 rn = "LLAddr";
6157 break;
6158 case 1:
6159 CP0_CHECK(ctx->mrp);
6160 gen_helper_mtc0_maar(cpu_env, arg);
6161 rn = "MAAR";
6162 break;
6163 case 2:
6164 CP0_CHECK(ctx->mrp);
6165 gen_helper_mtc0_maari(cpu_env, arg);
6166 rn = "MAARI";
6167 break;
6168 default:
6169 goto cp0_unimplemented;
6171 break;
6172 case 18:
6173 switch (sel) {
6174 case 0 ... 7:
6175 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6176 rn = "WatchLo";
6177 break;
6178 default:
6179 goto cp0_unimplemented;
6181 break;
6182 case 19:
6183 switch (sel) {
6184 case 0 ... 7:
6185 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6186 rn = "WatchHi";
6187 break;
6188 default:
6189 goto cp0_unimplemented;
6191 break;
6192 case 20:
6193 switch (sel) {
6194 case 0:
6195 #if defined(TARGET_MIPS64)
6196 check_insn(ctx, ISA_MIPS3);
6197 gen_helper_mtc0_xcontext(cpu_env, arg);
6198 rn = "XContext";
6199 break;
6200 #endif
6201 default:
6202 goto cp0_unimplemented;
6204 break;
6205 case 21:
6206 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6207 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6208 switch (sel) {
6209 case 0:
6210 gen_helper_mtc0_framemask(cpu_env, arg);
6211 rn = "Framemask";
6212 break;
6213 default:
6214 goto cp0_unimplemented;
6216 break;
6217 case 22:
6218 /* ignored */
6219 rn = "Diagnostic"; /* implementation dependent */
6220 break;
6221 case 23:
6222 switch (sel) {
6223 case 0:
6224 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6225 /* BS_STOP isn't good enough here, hflags may have changed. */
6226 gen_save_pc(ctx->pc + 4);
6227 ctx->bstate = BS_EXCP;
6228 rn = "Debug";
6229 break;
6230 case 1:
6231 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6232 rn = "TraceControl";
6233 /* Stop translation as we may have switched the execution mode */
6234 ctx->bstate = BS_STOP;
6235 goto cp0_unimplemented;
6236 case 2:
6237 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6238 rn = "TraceControl2";
6239 /* Stop translation as we may have switched the execution mode */
6240 ctx->bstate = BS_STOP;
6241 goto cp0_unimplemented;
6242 case 3:
6243 /* Stop translation as we may have switched the execution mode */
6244 ctx->bstate = BS_STOP;
6245 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6246 rn = "UserTraceData";
6247 /* Stop translation as we may have switched the execution mode */
6248 ctx->bstate = BS_STOP;
6249 goto cp0_unimplemented;
6250 case 4:
6251 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6252 /* Stop translation as we may have switched the execution mode */
6253 ctx->bstate = BS_STOP;
6254 rn = "TraceBPC";
6255 goto cp0_unimplemented;
6256 default:
6257 goto cp0_unimplemented;
6259 break;
6260 case 24:
6261 switch (sel) {
6262 case 0:
6263 /* EJTAG support */
6264 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6265 rn = "DEPC";
6266 break;
6267 default:
6268 goto cp0_unimplemented;
6270 break;
6271 case 25:
6272 switch (sel) {
6273 case 0:
6274 gen_helper_mtc0_performance0(cpu_env, arg);
6275 rn = "Performance0";
6276 break;
6277 case 1:
6278 // gen_helper_mtc0_performance1(arg);
6279 rn = "Performance1";
6280 goto cp0_unimplemented;
6281 case 2:
6282 // gen_helper_mtc0_performance2(arg);
6283 rn = "Performance2";
6284 goto cp0_unimplemented;
6285 case 3:
6286 // gen_helper_mtc0_performance3(arg);
6287 rn = "Performance3";
6288 goto cp0_unimplemented;
6289 case 4:
6290 // gen_helper_mtc0_performance4(arg);
6291 rn = "Performance4";
6292 goto cp0_unimplemented;
6293 case 5:
6294 // gen_helper_mtc0_performance5(arg);
6295 rn = "Performance5";
6296 goto cp0_unimplemented;
6297 case 6:
6298 // gen_helper_mtc0_performance6(arg);
6299 rn = "Performance6";
6300 goto cp0_unimplemented;
6301 case 7:
6302 // gen_helper_mtc0_performance7(arg);
6303 rn = "Performance7";
6304 goto cp0_unimplemented;
6305 default:
6306 goto cp0_unimplemented;
6308 break;
6309 case 26:
6310 switch (sel) {
6311 case 0:
6312 gen_helper_mtc0_errctl(cpu_env, arg);
6313 ctx->bstate = BS_STOP;
6314 rn = "ErrCtl";
6315 break;
6316 default:
6317 goto cp0_unimplemented;
6319 break;
6320 case 27:
6321 switch (sel) {
6322 case 0 ... 3:
6323 /* ignored */
6324 rn = "CacheErr";
6325 break;
6326 default:
6327 goto cp0_unimplemented;
6329 break;
6330 case 28:
6331 switch (sel) {
6332 case 0:
6333 case 2:
6334 case 4:
6335 case 6:
6336 gen_helper_mtc0_taglo(cpu_env, arg);
6337 rn = "TagLo";
6338 break;
6339 case 1:
6340 case 3:
6341 case 5:
6342 case 7:
6343 gen_helper_mtc0_datalo(cpu_env, arg);
6344 rn = "DataLo";
6345 break;
6346 default:
6347 goto cp0_unimplemented;
6349 break;
6350 case 29:
6351 switch (sel) {
6352 case 0:
6353 case 2:
6354 case 4:
6355 case 6:
6356 gen_helper_mtc0_taghi(cpu_env, arg);
6357 rn = "TagHi";
6358 break;
6359 case 1:
6360 case 3:
6361 case 5:
6362 case 7:
6363 gen_helper_mtc0_datahi(cpu_env, arg);
6364 rn = "DataHi";
6365 break;
6366 default:
6367 rn = "invalid sel";
6368 goto cp0_unimplemented;
6370 break;
6371 case 30:
6372 switch (sel) {
6373 case 0:
6374 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6375 rn = "ErrorEPC";
6376 break;
6377 default:
6378 goto cp0_unimplemented;
6380 break;
6381 case 31:
6382 switch (sel) {
6383 case 0:
6384 /* EJTAG support */
6385 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6386 rn = "DESAVE";
6387 break;
6388 case 2 ... 7:
6389 CP0_CHECK(ctx->kscrexist & (1 << sel));
6390 tcg_gen_st_tl(arg, cpu_env,
6391 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6392 rn = "KScratch";
6393 break;
6394 default:
6395 goto cp0_unimplemented;
6397 break;
6398 default:
6399 goto cp0_unimplemented;
6401 trace_mips_translate_c0("mtc0", rn, reg, sel);
6403 /* For simplicity assume that all writes can cause interrupts. */
6404 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6405 gen_io_end();
6406 /* BS_STOP isn't sufficient, we need to ensure we break out of
6407 * translated code to check for pending interrupts. */
6408 gen_save_pc(ctx->pc + 4);
6409 ctx->bstate = BS_EXCP;
6411 return;
6413 cp0_unimplemented:
6414 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6417 #if defined(TARGET_MIPS64)
6418 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6420 const char *rn = "invalid";
6422 if (sel != 0)
6423 check_insn(ctx, ISA_MIPS64);
6425 switch (reg) {
6426 case 0:
6427 switch (sel) {
6428 case 0:
6429 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6430 rn = "Index";
6431 break;
6432 case 1:
6433 CP0_CHECK(ctx->insn_flags & ASE_MT);
6434 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
6435 rn = "MVPControl";
6436 break;
6437 case 2:
6438 CP0_CHECK(ctx->insn_flags & ASE_MT);
6439 gen_helper_mfc0_mvpconf0(arg, cpu_env);
6440 rn = "MVPConf0";
6441 break;
6442 case 3:
6443 CP0_CHECK(ctx->insn_flags & ASE_MT);
6444 gen_helper_mfc0_mvpconf1(arg, cpu_env);
6445 rn = "MVPConf1";
6446 break;
6447 case 4:
6448 CP0_CHECK(ctx->vp);
6449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6450 rn = "VPControl";
6451 break;
6452 default:
6453 goto cp0_unimplemented;
6455 break;
6456 case 1:
6457 switch (sel) {
6458 case 0:
6459 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6460 gen_helper_mfc0_random(arg, cpu_env);
6461 rn = "Random";
6462 break;
6463 case 1:
6464 CP0_CHECK(ctx->insn_flags & ASE_MT);
6465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6466 rn = "VPEControl";
6467 break;
6468 case 2:
6469 CP0_CHECK(ctx->insn_flags & ASE_MT);
6470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6471 rn = "VPEConf0";
6472 break;
6473 case 3:
6474 CP0_CHECK(ctx->insn_flags & ASE_MT);
6475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6476 rn = "VPEConf1";
6477 break;
6478 case 4:
6479 CP0_CHECK(ctx->insn_flags & ASE_MT);
6480 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
6481 rn = "YQMask";
6482 break;
6483 case 5:
6484 CP0_CHECK(ctx->insn_flags & ASE_MT);
6485 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6486 rn = "VPESchedule";
6487 break;
6488 case 6:
6489 CP0_CHECK(ctx->insn_flags & ASE_MT);
6490 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6491 rn = "VPEScheFBack";
6492 break;
6493 case 7:
6494 CP0_CHECK(ctx->insn_flags & ASE_MT);
6495 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6496 rn = "VPEOpt";
6497 break;
6498 default:
6499 goto cp0_unimplemented;
6501 break;
6502 case 2:
6503 switch (sel) {
6504 case 0:
6505 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
6506 rn = "EntryLo0";
6507 break;
6508 case 1:
6509 CP0_CHECK(ctx->insn_flags & ASE_MT);
6510 gen_helper_mfc0_tcstatus(arg, cpu_env);
6511 rn = "TCStatus";
6512 break;
6513 case 2:
6514 CP0_CHECK(ctx->insn_flags & ASE_MT);
6515 gen_helper_mfc0_tcbind(arg, cpu_env);
6516 rn = "TCBind";
6517 break;
6518 case 3:
6519 CP0_CHECK(ctx->insn_flags & ASE_MT);
6520 gen_helper_dmfc0_tcrestart(arg, cpu_env);
6521 rn = "TCRestart";
6522 break;
6523 case 4:
6524 CP0_CHECK(ctx->insn_flags & ASE_MT);
6525 gen_helper_dmfc0_tchalt(arg, cpu_env);
6526 rn = "TCHalt";
6527 break;
6528 case 5:
6529 CP0_CHECK(ctx->insn_flags & ASE_MT);
6530 gen_helper_dmfc0_tccontext(arg, cpu_env);
6531 rn = "TCContext";
6532 break;
6533 case 6:
6534 CP0_CHECK(ctx->insn_flags & ASE_MT);
6535 gen_helper_dmfc0_tcschedule(arg, cpu_env);
6536 rn = "TCSchedule";
6537 break;
6538 case 7:
6539 CP0_CHECK(ctx->insn_flags & ASE_MT);
6540 gen_helper_dmfc0_tcschefback(arg, cpu_env);
6541 rn = "TCScheFBack";
6542 break;
6543 default:
6544 goto cp0_unimplemented;
6546 break;
6547 case 3:
6548 switch (sel) {
6549 case 0:
6550 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6551 rn = "EntryLo1";
6552 break;
6553 case 1:
6554 CP0_CHECK(ctx->vp);
6555 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6556 rn = "GlobalNumber";
6557 break;
6558 default:
6559 goto cp0_unimplemented;
6561 break;
6562 case 4:
6563 switch (sel) {
6564 case 0:
6565 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6566 rn = "Context";
6567 break;
6568 case 1:
6569 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
6570 rn = "ContextConfig";
6571 goto cp0_unimplemented;
6572 case 2:
6573 CP0_CHECK(ctx->ulri);
6574 tcg_gen_ld_tl(arg, cpu_env,
6575 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6576 rn = "UserLocal";
6577 break;
6578 default:
6579 goto cp0_unimplemented;
6581 break;
6582 case 5:
6583 switch (sel) {
6584 case 0:
6585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6586 rn = "PageMask";
6587 break;
6588 case 1:
6589 check_insn(ctx, ISA_MIPS32R2);
6590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6591 rn = "PageGrain";
6592 break;
6593 case 2:
6594 CP0_CHECK(ctx->sc);
6595 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6596 rn = "SegCtl0";
6597 break;
6598 case 3:
6599 CP0_CHECK(ctx->sc);
6600 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6601 rn = "SegCtl1";
6602 break;
6603 case 4:
6604 CP0_CHECK(ctx->sc);
6605 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6606 rn = "SegCtl2";
6607 break;
6608 default:
6609 goto cp0_unimplemented;
6611 break;
6612 case 6:
6613 switch (sel) {
6614 case 0:
6615 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6616 rn = "Wired";
6617 break;
6618 case 1:
6619 check_insn(ctx, ISA_MIPS32R2);
6620 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6621 rn = "SRSConf0";
6622 break;
6623 case 2:
6624 check_insn(ctx, ISA_MIPS32R2);
6625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6626 rn = "SRSConf1";
6627 break;
6628 case 3:
6629 check_insn(ctx, ISA_MIPS32R2);
6630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6631 rn = "SRSConf2";
6632 break;
6633 case 4:
6634 check_insn(ctx, ISA_MIPS32R2);
6635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6636 rn = "SRSConf3";
6637 break;
6638 case 5:
6639 check_insn(ctx, ISA_MIPS32R2);
6640 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6641 rn = "SRSConf4";
6642 break;
6643 default:
6644 goto cp0_unimplemented;
6646 break;
6647 case 7:
6648 switch (sel) {
6649 case 0:
6650 check_insn(ctx, ISA_MIPS32R2);
6651 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6652 rn = "HWREna";
6653 break;
6654 default:
6655 goto cp0_unimplemented;
6657 break;
6658 case 8:
6659 switch (sel) {
6660 case 0:
6661 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6662 rn = "BadVAddr";
6663 break;
6664 case 1:
6665 CP0_CHECK(ctx->bi);
6666 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6667 rn = "BadInstr";
6668 break;
6669 case 2:
6670 CP0_CHECK(ctx->bp);
6671 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6672 rn = "BadInstrP";
6673 break;
6674 default:
6675 goto cp0_unimplemented;
6677 break;
6678 case 9:
6679 switch (sel) {
6680 case 0:
6681 /* Mark as an IO operation because we read the time. */
6682 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6683 gen_io_start();
6685 gen_helper_mfc0_count(arg, cpu_env);
6686 if (ctx->tb->cflags & CF_USE_ICOUNT) {
6687 gen_io_end();
6689 /* Break the TB to be able to take timer interrupts immediately
6690 after reading count. BS_STOP isn't sufficient, we need to ensure
6691 we break completely out of translated code. */
6692 gen_save_pc(ctx->pc + 4);
6693 ctx->bstate = BS_EXCP;
6694 rn = "Count";
6695 break;
6696 /* 6,7 are implementation dependent */
6697 default:
6698 goto cp0_unimplemented;
6700 break;
6701 case 10:
6702 switch (sel) {
6703 case 0:
6704 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6705 rn = "EntryHi";
6706 break;
6707 default:
6708 goto cp0_unimplemented;
6710 break;
6711 case 11:
6712 switch (sel) {
6713 case 0:
6714 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6715 rn = "Compare";
6716 break;
6717 /* 6,7 are implementation dependent */
6718 default:
6719 goto cp0_unimplemented;
6721 break;
6722 case 12:
6723 switch (sel) {
6724 case 0:
6725 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6726 rn = "Status";
6727 break;
6728 case 1:
6729 check_insn(ctx, ISA_MIPS32R2);
6730 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6731 rn = "IntCtl";
6732 break;
6733 case 2:
6734 check_insn(ctx, ISA_MIPS32R2);
6735 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6736 rn = "SRSCtl";
6737 break;
6738 case 3:
6739 check_insn(ctx, ISA_MIPS32R2);
6740 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6741 rn = "SRSMap";
6742 break;
6743 default:
6744 goto cp0_unimplemented;
6746 break;
6747 case 13:
6748 switch (sel) {
6749 case 0:
6750 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6751 rn = "Cause";
6752 break;
6753 default:
6754 goto cp0_unimplemented;
6756 break;
6757 case 14:
6758 switch (sel) {
6759 case 0:
6760 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6761 rn = "EPC";
6762 break;
6763 default:
6764 goto cp0_unimplemented;
6766 break;
6767 case 15:
6768 switch (sel) {
6769 case 0:
6770 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6771 rn = "PRid";
6772 break;
6773 case 1:
6774 check_insn(ctx, ISA_MIPS32R2);
6775 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6776 rn = "EBase";
6777 break;
6778 case 3:
6779 check_insn(ctx, ISA_MIPS32R2);
6780 CP0_CHECK(ctx->cmgcr);
6781 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6782 rn = "CMGCRBase";
6783 break;
6784 default:
6785 goto cp0_unimplemented;
6787 break;
6788 case 16:
6789 switch (sel) {
6790 case 0:
6791 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6792 rn = "Config";
6793 break;
6794 case 1:
6795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6796 rn = "Config1";
6797 break;
6798 case 2:
6799 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6800 rn = "Config2";
6801 break;
6802 case 3:
6803 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6804 rn = "Config3";
6805 break;
6806 case 4:
6807 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6808 rn = "Config4";
6809 break;
6810 case 5:
6811 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6812 rn = "Config5";
6813 break;
6814 /* 6,7 are implementation dependent */
6815 case 6:
6816 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6817 rn = "Config6";
6818 break;
6819 case 7:
6820 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6821 rn = "Config7";
6822 break;
6823 default:
6824 goto cp0_unimplemented;
6826 break;
6827 case 17:
6828 switch (sel) {
6829 case 0:
6830 gen_helper_dmfc0_lladdr(arg, cpu_env);
6831 rn = "LLAddr";
6832 break;
6833 case 1:
6834 CP0_CHECK(ctx->mrp);
6835 gen_helper_dmfc0_maar(arg, cpu_env);
6836 rn = "MAAR";
6837 break;
6838 case 2:
6839 CP0_CHECK(ctx->mrp);
6840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6841 rn = "MAARI";
6842 break;
6843 default:
6844 goto cp0_unimplemented;
6846 break;
6847 case 18:
6848 switch (sel) {
6849 case 0 ... 7:
6850 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6851 rn = "WatchLo";
6852 break;
6853 default:
6854 goto cp0_unimplemented;
6856 break;
6857 case 19:
6858 switch (sel) {
6859 case 0 ... 7:
6860 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6861 rn = "WatchHi";
6862 break;
6863 default:
6864 goto cp0_unimplemented;
6866 break;
6867 case 20:
6868 switch (sel) {
6869 case 0:
6870 check_insn(ctx, ISA_MIPS3);
6871 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6872 rn = "XContext";
6873 break;
6874 default:
6875 goto cp0_unimplemented;
6877 break;
6878 case 21:
6879 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6880 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
6881 switch (sel) {
6882 case 0:
6883 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6884 rn = "Framemask";
6885 break;
6886 default:
6887 goto cp0_unimplemented;
6889 break;
6890 case 22:
6891 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6892 rn = "'Diagnostic"; /* implementation dependent */
6893 break;
6894 case 23:
6895 switch (sel) {
6896 case 0:
6897 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6898 rn = "Debug";
6899 break;
6900 case 1:
6901 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6902 rn = "TraceControl";
6903 goto cp0_unimplemented;
6904 case 2:
6905 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6906 rn = "TraceControl2";
6907 goto cp0_unimplemented;
6908 case 3:
6909 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6910 rn = "UserTraceData";
6911 goto cp0_unimplemented;
6912 case 4:
6913 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6914 rn = "TraceBPC";
6915 goto cp0_unimplemented;
6916 default:
6917 goto cp0_unimplemented;
6919 break;
6920 case 24:
6921 switch (sel) {
6922 case 0:
6923 /* EJTAG support */
6924 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6925 rn = "DEPC";
6926 break;
6927 default:
6928 goto cp0_unimplemented;
6930 break;
6931 case 25:
6932 switch (sel) {
6933 case 0:
6934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6935 rn = "Performance0";
6936 break;
6937 case 1:
6938 // gen_helper_dmfc0_performance1(arg);
6939 rn = "Performance1";
6940 goto cp0_unimplemented;
6941 case 2:
6942 // gen_helper_dmfc0_performance2(arg);
6943 rn = "Performance2";
6944 goto cp0_unimplemented;
6945 case 3:
6946 // gen_helper_dmfc0_performance3(arg);
6947 rn = "Performance3";
6948 goto cp0_unimplemented;
6949 case 4:
6950 // gen_helper_dmfc0_performance4(arg);
6951 rn = "Performance4";
6952 goto cp0_unimplemented;
6953 case 5:
6954 // gen_helper_dmfc0_performance5(arg);
6955 rn = "Performance5";
6956 goto cp0_unimplemented;
6957 case 6:
6958 // gen_helper_dmfc0_performance6(arg);
6959 rn = "Performance6";
6960 goto cp0_unimplemented;
6961 case 7:
6962 // gen_helper_dmfc0_performance7(arg);
6963 rn = "Performance7";
6964 goto cp0_unimplemented;
6965 default:
6966 goto cp0_unimplemented;
6968 break;
6969 case 26:
6970 switch (sel) {
6971 case 0:
6972 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6973 rn = "ErrCtl";
6974 break;
6975 default:
6976 goto cp0_unimplemented;
6978 break;
6979 case 27:
6980 switch (sel) {
6981 /* ignored */
6982 case 0 ... 3:
6983 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6984 rn = "CacheErr";
6985 break;
6986 default:
6987 goto cp0_unimplemented;
6989 break;
6990 case 28:
6991 switch (sel) {
6992 case 0:
6993 case 2:
6994 case 4:
6995 case 6:
6996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6997 rn = "TagLo";
6998 break;
6999 case 1:
7000 case 3:
7001 case 5:
7002 case 7:
7003 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7004 rn = "DataLo";
7005 break;
7006 default:
7007 goto cp0_unimplemented;
7009 break;
7010 case 29:
7011 switch (sel) {
7012 case 0:
7013 case 2:
7014 case 4:
7015 case 6:
7016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7017 rn = "TagHi";
7018 break;
7019 case 1:
7020 case 3:
7021 case 5:
7022 case 7:
7023 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7024 rn = "DataHi";
7025 break;
7026 default:
7027 goto cp0_unimplemented;
7029 break;
7030 case 30:
7031 switch (sel) {
7032 case 0:
7033 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7034 rn = "ErrorEPC";
7035 break;
7036 default:
7037 goto cp0_unimplemented;
7039 break;
7040 case 31:
7041 switch (sel) {
7042 case 0:
7043 /* EJTAG support */
7044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7045 rn = "DESAVE";
7046 break;
7047 case 2 ... 7:
7048 CP0_CHECK(ctx->kscrexist & (1 << sel));
7049 tcg_gen_ld_tl(arg, cpu_env,
7050 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7051 rn = "KScratch";
7052 break;
7053 default:
7054 goto cp0_unimplemented;
7056 break;
7057 default:
7058 goto cp0_unimplemented;
7060 trace_mips_translate_c0("dmfc0", rn, reg, sel);
7061 return;
7063 cp0_unimplemented:
7064 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
7065 gen_mfc0_unimplemented(ctx, arg);
7068 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7070 const char *rn = "invalid";
7072 if (sel != 0)
7073 check_insn(ctx, ISA_MIPS64);
7075 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7076 gen_io_start();
7079 switch (reg) {
7080 case 0:
7081 switch (sel) {
7082 case 0:
7083 gen_helper_mtc0_index(cpu_env, arg);
7084 rn = "Index";
7085 break;
7086 case 1:
7087 CP0_CHECK(ctx->insn_flags & ASE_MT);
7088 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
7089 rn = "MVPControl";
7090 break;
7091 case 2:
7092 CP0_CHECK(ctx->insn_flags & ASE_MT);
7093 /* ignored */
7094 rn = "MVPConf0";
7095 break;
7096 case 3:
7097 CP0_CHECK(ctx->insn_flags & ASE_MT);
7098 /* ignored */
7099 rn = "MVPConf1";
7100 break;
7101 case 4:
7102 CP0_CHECK(ctx->vp);
7103 /* ignored */
7104 rn = "VPControl";
7105 break;
7106 default:
7107 goto cp0_unimplemented;
7109 break;
7110 case 1:
7111 switch (sel) {
7112 case 0:
7113 /* ignored */
7114 rn = "Random";
7115 break;
7116 case 1:
7117 CP0_CHECK(ctx->insn_flags & ASE_MT);
7118 gen_helper_mtc0_vpecontrol(cpu_env, arg);
7119 rn = "VPEControl";
7120 break;
7121 case 2:
7122 CP0_CHECK(ctx->insn_flags & ASE_MT);
7123 gen_helper_mtc0_vpeconf0(cpu_env, arg);
7124 rn = "VPEConf0";
7125 break;
7126 case 3:
7127 CP0_CHECK(ctx->insn_flags & ASE_MT);
7128 gen_helper_mtc0_vpeconf1(cpu_env, arg);
7129 rn = "VPEConf1";
7130 break;
7131 case 4:
7132 CP0_CHECK(ctx->insn_flags & ASE_MT);
7133 gen_helper_mtc0_yqmask(cpu_env, arg);
7134 rn = "YQMask";
7135 break;
7136 case 5:
7137 CP0_CHECK(ctx->insn_flags & ASE_MT);
7138 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
7139 rn = "VPESchedule";
7140 break;
7141 case 6:
7142 CP0_CHECK(ctx->insn_flags & ASE_MT);
7143 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7144 rn = "VPEScheFBack";
7145 break;
7146 case 7:
7147 CP0_CHECK(ctx->insn_flags & ASE_MT);
7148 gen_helper_mtc0_vpeopt(cpu_env, arg);
7149 rn = "VPEOpt";
7150 break;
7151 default:
7152 goto cp0_unimplemented;
7154 break;
7155 case 2:
7156 switch (sel) {
7157 case 0:
7158 gen_helper_dmtc0_entrylo0(cpu_env, arg);
7159 rn = "EntryLo0";
7160 break;
7161 case 1:
7162 CP0_CHECK(ctx->insn_flags & ASE_MT);
7163 gen_helper_mtc0_tcstatus(cpu_env, arg);
7164 rn = "TCStatus";
7165 break;
7166 case 2:
7167 CP0_CHECK(ctx->insn_flags & ASE_MT);
7168 gen_helper_mtc0_tcbind(cpu_env, arg);
7169 rn = "TCBind";
7170 break;
7171 case 3:
7172 CP0_CHECK(ctx->insn_flags & ASE_MT);
7173 gen_helper_mtc0_tcrestart(cpu_env, arg);
7174 rn = "TCRestart";
7175 break;
7176 case 4:
7177 CP0_CHECK(ctx->insn_flags & ASE_MT);
7178 gen_helper_mtc0_tchalt(cpu_env, arg);
7179 rn = "TCHalt";
7180 break;
7181 case 5:
7182 CP0_CHECK(ctx->insn_flags & ASE_MT);
7183 gen_helper_mtc0_tccontext(cpu_env, arg);
7184 rn = "TCContext";
7185 break;
7186 case 6:
7187 CP0_CHECK(ctx->insn_flags & ASE_MT);
7188 gen_helper_mtc0_tcschedule(cpu_env, arg);
7189 rn = "TCSchedule";
7190 break;
7191 case 7:
7192 CP0_CHECK(ctx->insn_flags & ASE_MT);
7193 gen_helper_mtc0_tcschefback(cpu_env, arg);
7194 rn = "TCScheFBack";
7195 break;
7196 default:
7197 goto cp0_unimplemented;
7199 break;
7200 case 3:
7201 switch (sel) {
7202 case 0:
7203 gen_helper_dmtc0_entrylo1(cpu_env, arg);
7204 rn = "EntryLo1";
7205 break;
7206 case 1:
7207 CP0_CHECK(ctx->vp);
7208 /* ignored */
7209 rn = "GlobalNumber";
7210 break;
7211 default:
7212 goto cp0_unimplemented;
7214 break;
7215 case 4:
7216 switch (sel) {
7217 case 0:
7218 gen_helper_mtc0_context(cpu_env, arg);
7219 rn = "Context";
7220 break;
7221 case 1:
7222 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
7223 rn = "ContextConfig";
7224 goto cp0_unimplemented;
7225 case 2:
7226 CP0_CHECK(ctx->ulri);
7227 tcg_gen_st_tl(arg, cpu_env,
7228 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7229 rn = "UserLocal";
7230 break;
7231 default:
7232 goto cp0_unimplemented;
7234 break;
7235 case 5:
7236 switch (sel) {
7237 case 0:
7238 gen_helper_mtc0_pagemask(cpu_env, arg);
7239 rn = "PageMask";
7240 break;
7241 case 1:
7242 check_insn(ctx, ISA_MIPS32R2);
7243 gen_helper_mtc0_pagegrain(cpu_env, arg);
7244 rn = "PageGrain";
7245 break;
7246 case 2:
7247 CP0_CHECK(ctx->sc);
7248 gen_helper_mtc0_segctl0(cpu_env, arg);
7249 rn = "SegCtl0";
7250 break;
7251 case 3:
7252 CP0_CHECK(ctx->sc);
7253 gen_helper_mtc0_segctl1(cpu_env, arg);
7254 rn = "SegCtl1";
7255 break;
7256 case 4:
7257 CP0_CHECK(ctx->sc);
7258 gen_helper_mtc0_segctl2(cpu_env, arg);
7259 rn = "SegCtl2";
7260 break;
7261 default:
7262 goto cp0_unimplemented;
7264 break;
7265 case 6:
7266 switch (sel) {
7267 case 0:
7268 gen_helper_mtc0_wired(cpu_env, arg);
7269 rn = "Wired";
7270 break;
7271 case 1:
7272 check_insn(ctx, ISA_MIPS32R2);
7273 gen_helper_mtc0_srsconf0(cpu_env, arg);
7274 rn = "SRSConf0";
7275 break;
7276 case 2:
7277 check_insn(ctx, ISA_MIPS32R2);
7278 gen_helper_mtc0_srsconf1(cpu_env, arg);
7279 rn = "SRSConf1";
7280 break;
7281 case 3:
7282 check_insn(ctx, ISA_MIPS32R2);
7283 gen_helper_mtc0_srsconf2(cpu_env, arg);
7284 rn = "SRSConf2";
7285 break;
7286 case 4:
7287 check_insn(ctx, ISA_MIPS32R2);
7288 gen_helper_mtc0_srsconf3(cpu_env, arg);
7289 rn = "SRSConf3";
7290 break;
7291 case 5:
7292 check_insn(ctx, ISA_MIPS32R2);
7293 gen_helper_mtc0_srsconf4(cpu_env, arg);
7294 rn = "SRSConf4";
7295 break;
7296 default:
7297 goto cp0_unimplemented;
7299 break;
7300 case 7:
7301 switch (sel) {
7302 case 0:
7303 check_insn(ctx, ISA_MIPS32R2);
7304 gen_helper_mtc0_hwrena(cpu_env, arg);
7305 ctx->bstate = BS_STOP;
7306 rn = "HWREna";
7307 break;
7308 default:
7309 goto cp0_unimplemented;
7311 break;
7312 case 8:
7313 switch (sel) {
7314 case 0:
7315 /* ignored */
7316 rn = "BadVAddr";
7317 break;
7318 case 1:
7319 /* ignored */
7320 rn = "BadInstr";
7321 break;
7322 case 2:
7323 /* ignored */
7324 rn = "BadInstrP";
7325 break;
7326 default:
7327 goto cp0_unimplemented;
7329 break;
7330 case 9:
7331 switch (sel) {
7332 case 0:
7333 gen_helper_mtc0_count(cpu_env, arg);
7334 rn = "Count";
7335 break;
7336 /* 6,7 are implementation dependent */
7337 default:
7338 goto cp0_unimplemented;
7340 /* Stop translation as we may have switched the execution mode */
7341 ctx->bstate = BS_STOP;
7342 break;
7343 case 10:
7344 switch (sel) {
7345 case 0:
7346 gen_helper_mtc0_entryhi(cpu_env, arg);
7347 rn = "EntryHi";
7348 break;
7349 default:
7350 goto cp0_unimplemented;
7352 break;
7353 case 11:
7354 switch (sel) {
7355 case 0:
7356 gen_helper_mtc0_compare(cpu_env, arg);
7357 rn = "Compare";
7358 break;
7359 /* 6,7 are implementation dependent */
7360 default:
7361 goto cp0_unimplemented;
7363 /* Stop translation as we may have switched the execution mode */
7364 ctx->bstate = BS_STOP;
7365 break;
7366 case 12:
7367 switch (sel) {
7368 case 0:
7369 save_cpu_state(ctx, 1);
7370 gen_helper_mtc0_status(cpu_env, arg);
7371 /* BS_STOP isn't good enough here, hflags may have changed. */
7372 gen_save_pc(ctx->pc + 4);
7373 ctx->bstate = BS_EXCP;
7374 rn = "Status";
7375 break;
7376 case 1:
7377 check_insn(ctx, ISA_MIPS32R2);
7378 gen_helper_mtc0_intctl(cpu_env, arg);
7379 /* Stop translation as we may have switched the execution mode */
7380 ctx->bstate = BS_STOP;
7381 rn = "IntCtl";
7382 break;
7383 case 2:
7384 check_insn(ctx, ISA_MIPS32R2);
7385 gen_helper_mtc0_srsctl(cpu_env, arg);
7386 /* Stop translation as we may have switched the execution mode */
7387 ctx->bstate = BS_STOP;
7388 rn = "SRSCtl";
7389 break;
7390 case 3:
7391 check_insn(ctx, ISA_MIPS32R2);
7392 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7393 /* Stop translation as we may have switched the execution mode */
7394 ctx->bstate = BS_STOP;
7395 rn = "SRSMap";
7396 break;
7397 default:
7398 goto cp0_unimplemented;
7400 break;
7401 case 13:
7402 switch (sel) {
7403 case 0:
7404 save_cpu_state(ctx, 1);
7405 gen_helper_mtc0_cause(cpu_env, arg);
7406 /* Stop translation as we may have triggered an intetrupt. BS_STOP
7407 * isn't sufficient, we need to ensure we break out of translated
7408 * code to check for pending interrupts. */
7409 gen_save_pc(ctx->pc + 4);
7410 ctx->bstate = BS_EXCP;
7411 rn = "Cause";
7412 break;
7413 default:
7414 goto cp0_unimplemented;
7416 break;
7417 case 14:
7418 switch (sel) {
7419 case 0:
7420 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7421 rn = "EPC";
7422 break;
7423 default:
7424 goto cp0_unimplemented;
7426 break;
7427 case 15:
7428 switch (sel) {
7429 case 0:
7430 /* ignored */
7431 rn = "PRid";
7432 break;
7433 case 1:
7434 check_insn(ctx, ISA_MIPS32R2);
7435 gen_helper_mtc0_ebase(cpu_env, arg);
7436 rn = "EBase";
7437 break;
7438 default:
7439 goto cp0_unimplemented;
7441 break;
7442 case 16:
7443 switch (sel) {
7444 case 0:
7445 gen_helper_mtc0_config0(cpu_env, arg);
7446 rn = "Config";
7447 /* Stop translation as we may have switched the execution mode */
7448 ctx->bstate = BS_STOP;
7449 break;
7450 case 1:
7451 /* ignored, read only */
7452 rn = "Config1";
7453 break;
7454 case 2:
7455 gen_helper_mtc0_config2(cpu_env, arg);
7456 rn = "Config2";
7457 /* Stop translation as we may have switched the execution mode */
7458 ctx->bstate = BS_STOP;
7459 break;
7460 case 3:
7461 gen_helper_mtc0_config3(cpu_env, arg);
7462 rn = "Config3";
7463 /* Stop translation as we may have switched the execution mode */
7464 ctx->bstate = BS_STOP;
7465 break;
7466 case 4:
7467 /* currently ignored */
7468 rn = "Config4";
7469 break;
7470 case 5:
7471 gen_helper_mtc0_config5(cpu_env, arg);
7472 rn = "Config5";
7473 /* Stop translation as we may have switched the execution mode */
7474 ctx->bstate = BS_STOP;
7475 break;
7476 /* 6,7 are implementation dependent */
7477 default:
7478 rn = "Invalid config selector";
7479 goto cp0_unimplemented;
7481 break;
7482 case 17:
7483 switch (sel) {
7484 case 0:
7485 gen_helper_mtc0_lladdr(cpu_env, arg);
7486 rn = "LLAddr";
7487 break;
7488 case 1:
7489 CP0_CHECK(ctx->mrp);
7490 gen_helper_mtc0_maar(cpu_env, arg);
7491 rn = "MAAR";
7492 break;
7493 case 2:
7494 CP0_CHECK(ctx->mrp);
7495 gen_helper_mtc0_maari(cpu_env, arg);
7496 rn = "MAARI";
7497 break;
7498 default:
7499 goto cp0_unimplemented;
7501 break;
7502 case 18:
7503 switch (sel) {
7504 case 0 ... 7:
7505 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7506 rn = "WatchLo";
7507 break;
7508 default:
7509 goto cp0_unimplemented;
7511 break;
7512 case 19:
7513 switch (sel) {
7514 case 0 ... 7:
7515 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7516 rn = "WatchHi";
7517 break;
7518 default:
7519 goto cp0_unimplemented;
7521 break;
7522 case 20:
7523 switch (sel) {
7524 case 0:
7525 check_insn(ctx, ISA_MIPS3);
7526 gen_helper_mtc0_xcontext(cpu_env, arg);
7527 rn = "XContext";
7528 break;
7529 default:
7530 goto cp0_unimplemented;
7532 break;
7533 case 21:
7534 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7535 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7536 switch (sel) {
7537 case 0:
7538 gen_helper_mtc0_framemask(cpu_env, arg);
7539 rn = "Framemask";
7540 break;
7541 default:
7542 goto cp0_unimplemented;
7544 break;
7545 case 22:
7546 /* ignored */
7547 rn = "Diagnostic"; /* implementation dependent */
7548 break;
7549 case 23:
7550 switch (sel) {
7551 case 0:
7552 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7553 /* BS_STOP isn't good enough here, hflags may have changed. */
7554 gen_save_pc(ctx->pc + 4);
7555 ctx->bstate = BS_EXCP;
7556 rn = "Debug";
7557 break;
7558 case 1:
7559 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
7560 /* Stop translation as we may have switched the execution mode */
7561 ctx->bstate = BS_STOP;
7562 rn = "TraceControl";
7563 goto cp0_unimplemented;
7564 case 2:
7565 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
7566 /* Stop translation as we may have switched the execution mode */
7567 ctx->bstate = BS_STOP;
7568 rn = "TraceControl2";
7569 goto cp0_unimplemented;
7570 case 3:
7571 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
7572 /* Stop translation as we may have switched the execution mode */
7573 ctx->bstate = BS_STOP;
7574 rn = "UserTraceData";
7575 goto cp0_unimplemented;
7576 case 4:
7577 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
7578 /* Stop translation as we may have switched the execution mode */
7579 ctx->bstate = BS_STOP;
7580 rn = "TraceBPC";
7581 goto cp0_unimplemented;
7582 default:
7583 goto cp0_unimplemented;
7585 break;
7586 case 24:
7587 switch (sel) {
7588 case 0:
7589 /* EJTAG support */
7590 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7591 rn = "DEPC";
7592 break;
7593 default:
7594 goto cp0_unimplemented;
7596 break;
7597 case 25:
7598 switch (sel) {
7599 case 0:
7600 gen_helper_mtc0_performance0(cpu_env, arg);
7601 rn = "Performance0";
7602 break;
7603 case 1:
7604 // gen_helper_mtc0_performance1(cpu_env, arg);
7605 rn = "Performance1";
7606 goto cp0_unimplemented;
7607 case 2:
7608 // gen_helper_mtc0_performance2(cpu_env, arg);
7609 rn = "Performance2";
7610 goto cp0_unimplemented;
7611 case 3:
7612 // gen_helper_mtc0_performance3(cpu_env, arg);
7613 rn = "Performance3";
7614 goto cp0_unimplemented;
7615 case 4:
7616 // gen_helper_mtc0_performance4(cpu_env, arg);
7617 rn = "Performance4";
7618 goto cp0_unimplemented;
7619 case 5:
7620 // gen_helper_mtc0_performance5(cpu_env, arg);
7621 rn = "Performance5";
7622 goto cp0_unimplemented;
7623 case 6:
7624 // gen_helper_mtc0_performance6(cpu_env, arg);
7625 rn = "Performance6";
7626 goto cp0_unimplemented;
7627 case 7:
7628 // gen_helper_mtc0_performance7(cpu_env, arg);
7629 rn = "Performance7";
7630 goto cp0_unimplemented;
7631 default:
7632 goto cp0_unimplemented;
7634 break;
7635 case 26:
7636 switch (sel) {
7637 case 0:
7638 gen_helper_mtc0_errctl(cpu_env, arg);
7639 ctx->bstate = BS_STOP;
7640 rn = "ErrCtl";
7641 break;
7642 default:
7643 goto cp0_unimplemented;
7645 break;
7646 case 27:
7647 switch (sel) {
7648 case 0 ... 3:
7649 /* ignored */
7650 rn = "CacheErr";
7651 break;
7652 default:
7653 goto cp0_unimplemented;
7655 break;
7656 case 28:
7657 switch (sel) {
7658 case 0:
7659 case 2:
7660 case 4:
7661 case 6:
7662 gen_helper_mtc0_taglo(cpu_env, arg);
7663 rn = "TagLo";
7664 break;
7665 case 1:
7666 case 3:
7667 case 5:
7668 case 7:
7669 gen_helper_mtc0_datalo(cpu_env, arg);
7670 rn = "DataLo";
7671 break;
7672 default:
7673 goto cp0_unimplemented;
7675 break;
7676 case 29:
7677 switch (sel) {
7678 case 0:
7679 case 2:
7680 case 4:
7681 case 6:
7682 gen_helper_mtc0_taghi(cpu_env, arg);
7683 rn = "TagHi";
7684 break;
7685 case 1:
7686 case 3:
7687 case 5:
7688 case 7:
7689 gen_helper_mtc0_datahi(cpu_env, arg);
7690 rn = "DataHi";
7691 break;
7692 default:
7693 rn = "invalid sel";
7694 goto cp0_unimplemented;
7696 break;
7697 case 30:
7698 switch (sel) {
7699 case 0:
7700 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7701 rn = "ErrorEPC";
7702 break;
7703 default:
7704 goto cp0_unimplemented;
7706 break;
7707 case 31:
7708 switch (sel) {
7709 case 0:
7710 /* EJTAG support */
7711 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7712 rn = "DESAVE";
7713 break;
7714 case 2 ... 7:
7715 CP0_CHECK(ctx->kscrexist & (1 << sel));
7716 tcg_gen_st_tl(arg, cpu_env,
7717 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7718 rn = "KScratch";
7719 break;
7720 default:
7721 goto cp0_unimplemented;
7723 break;
7724 default:
7725 goto cp0_unimplemented;
7727 trace_mips_translate_c0("dmtc0", rn, reg, sel);
7729 /* For simplicity assume that all writes can cause interrupts. */
7730 if (ctx->tb->cflags & CF_USE_ICOUNT) {
7731 gen_io_end();
7732 /* BS_STOP isn't sufficient, we need to ensure we break out of
7733 * translated code to check for pending interrupts. */
7734 gen_save_pc(ctx->pc + 4);
7735 ctx->bstate = BS_EXCP;
7737 return;
7739 cp0_unimplemented:
7740 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7742 #endif /* TARGET_MIPS64 */
7744 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7745 int u, int sel, int h)
7747 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7748 TCGv t0 = tcg_temp_local_new();
7750 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7751 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7752 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7753 tcg_gen_movi_tl(t0, -1);
7754 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7755 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7756 tcg_gen_movi_tl(t0, -1);
7757 else if (u == 0) {
7758 switch (rt) {
7759 case 1:
7760 switch (sel) {
7761 case 1:
7762 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7763 break;
7764 case 2:
7765 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7766 break;
7767 default:
7768 goto die;
7769 break;
7771 break;
7772 case 2:
7773 switch (sel) {
7774 case 1:
7775 gen_helper_mftc0_tcstatus(t0, cpu_env);
7776 break;
7777 case 2:
7778 gen_helper_mftc0_tcbind(t0, cpu_env);
7779 break;
7780 case 3:
7781 gen_helper_mftc0_tcrestart(t0, cpu_env);
7782 break;
7783 case 4:
7784 gen_helper_mftc0_tchalt(t0, cpu_env);
7785 break;
7786 case 5:
7787 gen_helper_mftc0_tccontext(t0, cpu_env);
7788 break;
7789 case 6:
7790 gen_helper_mftc0_tcschedule(t0, cpu_env);
7791 break;
7792 case 7:
7793 gen_helper_mftc0_tcschefback(t0, cpu_env);
7794 break;
7795 default:
7796 gen_mfc0(ctx, t0, rt, sel);
7797 break;
7799 break;
7800 case 10:
7801 switch (sel) {
7802 case 0:
7803 gen_helper_mftc0_entryhi(t0, cpu_env);
7804 break;
7805 default:
7806 gen_mfc0(ctx, t0, rt, sel);
7807 break;
7809 case 12:
7810 switch (sel) {
7811 case 0:
7812 gen_helper_mftc0_status(t0, cpu_env);
7813 break;
7814 default:
7815 gen_mfc0(ctx, t0, rt, sel);
7816 break;
7818 case 13:
7819 switch (sel) {
7820 case 0:
7821 gen_helper_mftc0_cause(t0, cpu_env);
7822 break;
7823 default:
7824 goto die;
7825 break;
7827 break;
7828 case 14:
7829 switch (sel) {
7830 case 0:
7831 gen_helper_mftc0_epc(t0, cpu_env);
7832 break;
7833 default:
7834 goto die;
7835 break;
7837 break;
7838 case 15:
7839 switch (sel) {
7840 case 1:
7841 gen_helper_mftc0_ebase(t0, cpu_env);
7842 break;
7843 default:
7844 goto die;
7845 break;
7847 break;
7848 case 16:
7849 switch (sel) {
7850 case 0 ... 7:
7851 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7852 break;
7853 default:
7854 goto die;
7855 break;
7857 break;
7858 case 23:
7859 switch (sel) {
7860 case 0:
7861 gen_helper_mftc0_debug(t0, cpu_env);
7862 break;
7863 default:
7864 gen_mfc0(ctx, t0, rt, sel);
7865 break;
7867 break;
7868 default:
7869 gen_mfc0(ctx, t0, rt, sel);
7871 } else switch (sel) {
7872 /* GPR registers. */
7873 case 0:
7874 gen_helper_1e0i(mftgpr, t0, rt);
7875 break;
7876 /* Auxiliary CPU registers */
7877 case 1:
7878 switch (rt) {
7879 case 0:
7880 gen_helper_1e0i(mftlo, t0, 0);
7881 break;
7882 case 1:
7883 gen_helper_1e0i(mfthi, t0, 0);
7884 break;
7885 case 2:
7886 gen_helper_1e0i(mftacx, t0, 0);
7887 break;
7888 case 4:
7889 gen_helper_1e0i(mftlo, t0, 1);
7890 break;
7891 case 5:
7892 gen_helper_1e0i(mfthi, t0, 1);
7893 break;
7894 case 6:
7895 gen_helper_1e0i(mftacx, t0, 1);
7896 break;
7897 case 8:
7898 gen_helper_1e0i(mftlo, t0, 2);
7899 break;
7900 case 9:
7901 gen_helper_1e0i(mfthi, t0, 2);
7902 break;
7903 case 10:
7904 gen_helper_1e0i(mftacx, t0, 2);
7905 break;
7906 case 12:
7907 gen_helper_1e0i(mftlo, t0, 3);
7908 break;
7909 case 13:
7910 gen_helper_1e0i(mfthi, t0, 3);
7911 break;
7912 case 14:
7913 gen_helper_1e0i(mftacx, t0, 3);
7914 break;
7915 case 16:
7916 gen_helper_mftdsp(t0, cpu_env);
7917 break;
7918 default:
7919 goto die;
7921 break;
7922 /* Floating point (COP1). */
7923 case 2:
7924 /* XXX: For now we support only a single FPU context. */
7925 if (h == 0) {
7926 TCGv_i32 fp0 = tcg_temp_new_i32();
7928 gen_load_fpr32(ctx, fp0, rt);
7929 tcg_gen_ext_i32_tl(t0, fp0);
7930 tcg_temp_free_i32(fp0);
7931 } else {
7932 TCGv_i32 fp0 = tcg_temp_new_i32();
7934 gen_load_fpr32h(ctx, fp0, rt);
7935 tcg_gen_ext_i32_tl(t0, fp0);
7936 tcg_temp_free_i32(fp0);
7938 break;
7939 case 3:
7940 /* XXX: For now we support only a single FPU context. */
7941 gen_helper_1e0i(cfc1, t0, rt);
7942 break;
7943 /* COP2: Not implemented. */
7944 case 4:
7945 case 5:
7946 /* fall through */
7947 default:
7948 goto die;
7950 trace_mips_translate_tr("mftr", rt, u, sel, h);
7951 gen_store_gpr(t0, rd);
7952 tcg_temp_free(t0);
7953 return;
7955 die:
7956 tcg_temp_free(t0);
7957 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7958 generate_exception_end(ctx, EXCP_RI);
7961 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7962 int u, int sel, int h)
7964 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7965 TCGv t0 = tcg_temp_local_new();
7967 gen_load_gpr(t0, rt);
7968 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7969 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7970 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7971 /* NOP */ ;
7972 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7973 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7974 /* NOP */ ;
7975 else if (u == 0) {
7976 switch (rd) {
7977 case 1:
7978 switch (sel) {
7979 case 1:
7980 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7981 break;
7982 case 2:
7983 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7984 break;
7985 default:
7986 goto die;
7987 break;
7989 break;
7990 case 2:
7991 switch (sel) {
7992 case 1:
7993 gen_helper_mttc0_tcstatus(cpu_env, t0);
7994 break;
7995 case 2:
7996 gen_helper_mttc0_tcbind(cpu_env, t0);
7997 break;
7998 case 3:
7999 gen_helper_mttc0_tcrestart(cpu_env, t0);
8000 break;
8001 case 4:
8002 gen_helper_mttc0_tchalt(cpu_env, t0);
8003 break;
8004 case 5:
8005 gen_helper_mttc0_tccontext(cpu_env, t0);
8006 break;
8007 case 6:
8008 gen_helper_mttc0_tcschedule(cpu_env, t0);
8009 break;
8010 case 7:
8011 gen_helper_mttc0_tcschefback(cpu_env, t0);
8012 break;
8013 default:
8014 gen_mtc0(ctx, t0, rd, sel);
8015 break;
8017 break;
8018 case 10:
8019 switch (sel) {
8020 case 0:
8021 gen_helper_mttc0_entryhi(cpu_env, t0);
8022 break;
8023 default:
8024 gen_mtc0(ctx, t0, rd, sel);
8025 break;
8027 case 12:
8028 switch (sel) {
8029 case 0:
8030 gen_helper_mttc0_status(cpu_env, t0);
8031 break;
8032 default:
8033 gen_mtc0(ctx, t0, rd, sel);
8034 break;
8036 case 13:
8037 switch (sel) {
8038 case 0:
8039 gen_helper_mttc0_cause(cpu_env, t0);
8040 break;
8041 default:
8042 goto die;
8043 break;
8045 break;
8046 case 15:
8047 switch (sel) {
8048 case 1:
8049 gen_helper_mttc0_ebase(cpu_env, t0);
8050 break;
8051 default:
8052 goto die;
8053 break;
8055 break;
8056 case 23:
8057 switch (sel) {
8058 case 0:
8059 gen_helper_mttc0_debug(cpu_env, t0);
8060 break;
8061 default:
8062 gen_mtc0(ctx, t0, rd, sel);
8063 break;
8065 break;
8066 default:
8067 gen_mtc0(ctx, t0, rd, sel);
8069 } else switch (sel) {
8070 /* GPR registers. */
8071 case 0:
8072 gen_helper_0e1i(mttgpr, t0, rd);
8073 break;
8074 /* Auxiliary CPU registers */
8075 case 1:
8076 switch (rd) {
8077 case 0:
8078 gen_helper_0e1i(mttlo, t0, 0);
8079 break;
8080 case 1:
8081 gen_helper_0e1i(mtthi, t0, 0);
8082 break;
8083 case 2:
8084 gen_helper_0e1i(mttacx, t0, 0);
8085 break;
8086 case 4:
8087 gen_helper_0e1i(mttlo, t0, 1);
8088 break;
8089 case 5:
8090 gen_helper_0e1i(mtthi, t0, 1);
8091 break;
8092 case 6:
8093 gen_helper_0e1i(mttacx, t0, 1);
8094 break;
8095 case 8:
8096 gen_helper_0e1i(mttlo, t0, 2);
8097 break;
8098 case 9:
8099 gen_helper_0e1i(mtthi, t0, 2);
8100 break;
8101 case 10:
8102 gen_helper_0e1i(mttacx, t0, 2);
8103 break;
8104 case 12:
8105 gen_helper_0e1i(mttlo, t0, 3);
8106 break;
8107 case 13:
8108 gen_helper_0e1i(mtthi, t0, 3);
8109 break;
8110 case 14:
8111 gen_helper_0e1i(mttacx, t0, 3);
8112 break;
8113 case 16:
8114 gen_helper_mttdsp(cpu_env, t0);
8115 break;
8116 default:
8117 goto die;
8119 break;
8120 /* Floating point (COP1). */
8121 case 2:
8122 /* XXX: For now we support only a single FPU context. */
8123 if (h == 0) {
8124 TCGv_i32 fp0 = tcg_temp_new_i32();
8126 tcg_gen_trunc_tl_i32(fp0, t0);
8127 gen_store_fpr32(ctx, fp0, rd);
8128 tcg_temp_free_i32(fp0);
8129 } else {
8130 TCGv_i32 fp0 = tcg_temp_new_i32();
8132 tcg_gen_trunc_tl_i32(fp0, t0);
8133 gen_store_fpr32h(ctx, fp0, rd);
8134 tcg_temp_free_i32(fp0);
8136 break;
8137 case 3:
8138 /* XXX: For now we support only a single FPU context. */
8140 TCGv_i32 fs_tmp = tcg_const_i32(rd);
8142 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8143 tcg_temp_free_i32(fs_tmp);
8145 /* Stop translation as we may have changed hflags */
8146 ctx->bstate = BS_STOP;
8147 break;
8148 /* COP2: Not implemented. */
8149 case 4:
8150 case 5:
8151 /* fall through */
8152 default:
8153 goto die;
8155 trace_mips_translate_tr("mttr", rd, u, sel, h);
8156 tcg_temp_free(t0);
8157 return;
8159 die:
8160 tcg_temp_free(t0);
8161 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8162 generate_exception_end(ctx, EXCP_RI);
8165 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
8167 const char *opn = "ldst";
8169 check_cp0_enabled(ctx);
8170 switch (opc) {
8171 case OPC_MFC0:
8172 if (rt == 0) {
8173 /* Treat as NOP. */
8174 return;
8176 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8177 opn = "mfc0";
8178 break;
8179 case OPC_MTC0:
8181 TCGv t0 = tcg_temp_new();
8183 gen_load_gpr(t0, rt);
8184 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8185 tcg_temp_free(t0);
8187 opn = "mtc0";
8188 break;
8189 #if defined(TARGET_MIPS64)
8190 case OPC_DMFC0:
8191 check_insn(ctx, ISA_MIPS3);
8192 if (rt == 0) {
8193 /* Treat as NOP. */
8194 return;
8196 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8197 opn = "dmfc0";
8198 break;
8199 case OPC_DMTC0:
8200 check_insn(ctx, ISA_MIPS3);
8202 TCGv t0 = tcg_temp_new();
8204 gen_load_gpr(t0, rt);
8205 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8206 tcg_temp_free(t0);
8208 opn = "dmtc0";
8209 break;
8210 #endif
8211 case OPC_MFHC0:
8212 check_mvh(ctx);
8213 if (rt == 0) {
8214 /* Treat as NOP. */
8215 return;
8217 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8218 opn = "mfhc0";
8219 break;
8220 case OPC_MTHC0:
8221 check_mvh(ctx);
8223 TCGv t0 = tcg_temp_new();
8224 gen_load_gpr(t0, rt);
8225 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8226 tcg_temp_free(t0);
8228 opn = "mthc0";
8229 break;
8230 case OPC_MFTR:
8231 check_insn(ctx, ASE_MT);
8232 if (rd == 0) {
8233 /* Treat as NOP. */
8234 return;
8236 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8237 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8238 opn = "mftr";
8239 break;
8240 case OPC_MTTR:
8241 check_insn(ctx, ASE_MT);
8242 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8243 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8244 opn = "mttr";
8245 break;
8246 case OPC_TLBWI:
8247 opn = "tlbwi";
8248 if (!env->tlb->helper_tlbwi)
8249 goto die;
8250 gen_helper_tlbwi(cpu_env);
8251 break;
8252 case OPC_TLBINV:
8253 opn = "tlbinv";
8254 if (ctx->ie >= 2) {
8255 if (!env->tlb->helper_tlbinv) {
8256 goto die;
8258 gen_helper_tlbinv(cpu_env);
8259 } /* treat as nop if TLBINV not supported */
8260 break;
8261 case OPC_TLBINVF:
8262 opn = "tlbinvf";
8263 if (ctx->ie >= 2) {
8264 if (!env->tlb->helper_tlbinvf) {
8265 goto die;
8267 gen_helper_tlbinvf(cpu_env);
8268 } /* treat as nop if TLBINV not supported */
8269 break;
8270 case OPC_TLBWR:
8271 opn = "tlbwr";
8272 if (!env->tlb->helper_tlbwr)
8273 goto die;
8274 gen_helper_tlbwr(cpu_env);
8275 break;
8276 case OPC_TLBP:
8277 opn = "tlbp";
8278 if (!env->tlb->helper_tlbp)
8279 goto die;
8280 gen_helper_tlbp(cpu_env);
8281 break;
8282 case OPC_TLBR:
8283 opn = "tlbr";
8284 if (!env->tlb->helper_tlbr)
8285 goto die;
8286 gen_helper_tlbr(cpu_env);
8287 break;
8288 case OPC_ERET: /* OPC_ERETNC */
8289 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8290 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8291 goto die;
8292 } else {
8293 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8294 if (ctx->opcode & (1 << bit_shift)) {
8295 /* OPC_ERETNC */
8296 opn = "eretnc";
8297 check_insn(ctx, ISA_MIPS32R5);
8298 gen_helper_eretnc(cpu_env);
8299 } else {
8300 /* OPC_ERET */
8301 opn = "eret";
8302 check_insn(ctx, ISA_MIPS2);
8303 gen_helper_eret(cpu_env);
8305 ctx->bstate = BS_EXCP;
8307 break;
8308 case OPC_DERET:
8309 opn = "deret";
8310 check_insn(ctx, ISA_MIPS32);
8311 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8312 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8313 goto die;
8315 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8316 MIPS_INVAL(opn);
8317 generate_exception_end(ctx, EXCP_RI);
8318 } else {
8319 gen_helper_deret(cpu_env);
8320 ctx->bstate = BS_EXCP;
8322 break;
8323 case OPC_WAIT:
8324 opn = "wait";
8325 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
8326 if ((ctx->insn_flags & ISA_MIPS32R6) &&
8327 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8328 goto die;
8330 /* If we get an exception, we want to restart at next instruction */
8331 ctx->pc += 4;
8332 save_cpu_state(ctx, 1);
8333 ctx->pc -= 4;
8334 gen_helper_wait(cpu_env);
8335 ctx->bstate = BS_EXCP;
8336 break;
8337 default:
8338 die:
8339 MIPS_INVAL(opn);
8340 generate_exception_end(ctx, EXCP_RI);
8341 return;
8343 (void)opn; /* avoid a compiler warning */
8345 #endif /* !CONFIG_USER_ONLY */
8347 /* CP1 Branches (before delay slot) */
8348 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8349 int32_t cc, int32_t offset)
8351 target_ulong btarget;
8352 TCGv_i32 t0 = tcg_temp_new_i32();
8354 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8355 generate_exception_end(ctx, EXCP_RI);
8356 goto out;
8359 if (cc != 0)
8360 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
8362 btarget = ctx->pc + 4 + offset;
8364 switch (op) {
8365 case OPC_BC1F:
8366 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8367 tcg_gen_not_i32(t0, t0);
8368 tcg_gen_andi_i32(t0, t0, 1);
8369 tcg_gen_extu_i32_tl(bcond, t0);
8370 goto not_likely;
8371 case OPC_BC1FL:
8372 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8373 tcg_gen_not_i32(t0, t0);
8374 tcg_gen_andi_i32(t0, t0, 1);
8375 tcg_gen_extu_i32_tl(bcond, t0);
8376 goto likely;
8377 case OPC_BC1T:
8378 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8379 tcg_gen_andi_i32(t0, t0, 1);
8380 tcg_gen_extu_i32_tl(bcond, t0);
8381 goto not_likely;
8382 case OPC_BC1TL:
8383 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8384 tcg_gen_andi_i32(t0, t0, 1);
8385 tcg_gen_extu_i32_tl(bcond, t0);
8386 likely:
8387 ctx->hflags |= MIPS_HFLAG_BL;
8388 break;
8389 case OPC_BC1FANY2:
8391 TCGv_i32 t1 = tcg_temp_new_i32();
8392 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8393 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8394 tcg_gen_nand_i32(t0, t0, t1);
8395 tcg_temp_free_i32(t1);
8396 tcg_gen_andi_i32(t0, t0, 1);
8397 tcg_gen_extu_i32_tl(bcond, t0);
8399 goto not_likely;
8400 case OPC_BC1TANY2:
8402 TCGv_i32 t1 = tcg_temp_new_i32();
8403 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8404 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8405 tcg_gen_or_i32(t0, t0, t1);
8406 tcg_temp_free_i32(t1);
8407 tcg_gen_andi_i32(t0, t0, 1);
8408 tcg_gen_extu_i32_tl(bcond, t0);
8410 goto not_likely;
8411 case OPC_BC1FANY4:
8413 TCGv_i32 t1 = tcg_temp_new_i32();
8414 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8415 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8416 tcg_gen_and_i32(t0, t0, t1);
8417 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8418 tcg_gen_and_i32(t0, t0, t1);
8419 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8420 tcg_gen_nand_i32(t0, t0, t1);
8421 tcg_temp_free_i32(t1);
8422 tcg_gen_andi_i32(t0, t0, 1);
8423 tcg_gen_extu_i32_tl(bcond, t0);
8425 goto not_likely;
8426 case OPC_BC1TANY4:
8428 TCGv_i32 t1 = tcg_temp_new_i32();
8429 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8430 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
8431 tcg_gen_or_i32(t0, t0, t1);
8432 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
8433 tcg_gen_or_i32(t0, t0, t1);
8434 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
8435 tcg_gen_or_i32(t0, t0, t1);
8436 tcg_temp_free_i32(t1);
8437 tcg_gen_andi_i32(t0, t0, 1);
8438 tcg_gen_extu_i32_tl(bcond, t0);
8440 not_likely:
8441 ctx->hflags |= MIPS_HFLAG_BC;
8442 break;
8443 default:
8444 MIPS_INVAL("cp1 cond branch");
8445 generate_exception_end(ctx, EXCP_RI);
8446 goto out;
8448 ctx->btarget = btarget;
8449 ctx->hflags |= MIPS_HFLAG_BDS32;
8450 out:
8451 tcg_temp_free_i32(t0);
8454 /* R6 CP1 Branches */
8455 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8456 int32_t ft, int32_t offset,
8457 int delayslot_size)
8459 target_ulong btarget;
8460 TCGv_i64 t0 = tcg_temp_new_i64();
8462 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8463 #ifdef MIPS_DEBUG_DISAS
8464 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
8465 "\n", ctx->pc);
8466 #endif
8467 generate_exception_end(ctx, EXCP_RI);
8468 goto out;
8471 gen_load_fpr64(ctx, t0, ft);
8472 tcg_gen_andi_i64(t0, t0, 1);
8474 btarget = addr_add(ctx, ctx->pc + 4, offset);
8476 switch (op) {
8477 case OPC_BC1EQZ:
8478 tcg_gen_xori_i64(t0, t0, 1);
8479 ctx->hflags |= MIPS_HFLAG_BC;
8480 break;
8481 case OPC_BC1NEZ:
8482 /* t0 already set */
8483 ctx->hflags |= MIPS_HFLAG_BC;
8484 break;
8485 default:
8486 MIPS_INVAL("cp1 cond branch");
8487 generate_exception_end(ctx, EXCP_RI);
8488 goto out;
8491 tcg_gen_trunc_i64_tl(bcond, t0);
8493 ctx->btarget = btarget;
8495 switch (delayslot_size) {
8496 case 2:
8497 ctx->hflags |= MIPS_HFLAG_BDS16;
8498 break;
8499 case 4:
8500 ctx->hflags |= MIPS_HFLAG_BDS32;
8501 break;
8504 out:
8505 tcg_temp_free_i64(t0);
8508 /* Coprocessor 1 (FPU) */
8510 #define FOP(func, fmt) (((fmt) << 21) | (func))
8512 enum fopcode {
8513 OPC_ADD_S = FOP(0, FMT_S),
8514 OPC_SUB_S = FOP(1, FMT_S),
8515 OPC_MUL_S = FOP(2, FMT_S),
8516 OPC_DIV_S = FOP(3, FMT_S),
8517 OPC_SQRT_S = FOP(4, FMT_S),
8518 OPC_ABS_S = FOP(5, FMT_S),
8519 OPC_MOV_S = FOP(6, FMT_S),
8520 OPC_NEG_S = FOP(7, FMT_S),
8521 OPC_ROUND_L_S = FOP(8, FMT_S),
8522 OPC_TRUNC_L_S = FOP(9, FMT_S),
8523 OPC_CEIL_L_S = FOP(10, FMT_S),
8524 OPC_FLOOR_L_S = FOP(11, FMT_S),
8525 OPC_ROUND_W_S = FOP(12, FMT_S),
8526 OPC_TRUNC_W_S = FOP(13, FMT_S),
8527 OPC_CEIL_W_S = FOP(14, FMT_S),
8528 OPC_FLOOR_W_S = FOP(15, FMT_S),
8529 OPC_SEL_S = FOP(16, FMT_S),
8530 OPC_MOVCF_S = FOP(17, FMT_S),
8531 OPC_MOVZ_S = FOP(18, FMT_S),
8532 OPC_MOVN_S = FOP(19, FMT_S),
8533 OPC_SELEQZ_S = FOP(20, FMT_S),
8534 OPC_RECIP_S = FOP(21, FMT_S),
8535 OPC_RSQRT_S = FOP(22, FMT_S),
8536 OPC_SELNEZ_S = FOP(23, FMT_S),
8537 OPC_MADDF_S = FOP(24, FMT_S),
8538 OPC_MSUBF_S = FOP(25, FMT_S),
8539 OPC_RINT_S = FOP(26, FMT_S),
8540 OPC_CLASS_S = FOP(27, FMT_S),
8541 OPC_MIN_S = FOP(28, FMT_S),
8542 OPC_RECIP2_S = FOP(28, FMT_S),
8543 OPC_MINA_S = FOP(29, FMT_S),
8544 OPC_RECIP1_S = FOP(29, FMT_S),
8545 OPC_MAX_S = FOP(30, FMT_S),
8546 OPC_RSQRT1_S = FOP(30, FMT_S),
8547 OPC_MAXA_S = FOP(31, FMT_S),
8548 OPC_RSQRT2_S = FOP(31, FMT_S),
8549 OPC_CVT_D_S = FOP(33, FMT_S),
8550 OPC_CVT_W_S = FOP(36, FMT_S),
8551 OPC_CVT_L_S = FOP(37, FMT_S),
8552 OPC_CVT_PS_S = FOP(38, FMT_S),
8553 OPC_CMP_F_S = FOP (48, FMT_S),
8554 OPC_CMP_UN_S = FOP (49, FMT_S),
8555 OPC_CMP_EQ_S = FOP (50, FMT_S),
8556 OPC_CMP_UEQ_S = FOP (51, FMT_S),
8557 OPC_CMP_OLT_S = FOP (52, FMT_S),
8558 OPC_CMP_ULT_S = FOP (53, FMT_S),
8559 OPC_CMP_OLE_S = FOP (54, FMT_S),
8560 OPC_CMP_ULE_S = FOP (55, FMT_S),
8561 OPC_CMP_SF_S = FOP (56, FMT_S),
8562 OPC_CMP_NGLE_S = FOP (57, FMT_S),
8563 OPC_CMP_SEQ_S = FOP (58, FMT_S),
8564 OPC_CMP_NGL_S = FOP (59, FMT_S),
8565 OPC_CMP_LT_S = FOP (60, FMT_S),
8566 OPC_CMP_NGE_S = FOP (61, FMT_S),
8567 OPC_CMP_LE_S = FOP (62, FMT_S),
8568 OPC_CMP_NGT_S = FOP (63, FMT_S),
8570 OPC_ADD_D = FOP(0, FMT_D),
8571 OPC_SUB_D = FOP(1, FMT_D),
8572 OPC_MUL_D = FOP(2, FMT_D),
8573 OPC_DIV_D = FOP(3, FMT_D),
8574 OPC_SQRT_D = FOP(4, FMT_D),
8575 OPC_ABS_D = FOP(5, FMT_D),
8576 OPC_MOV_D = FOP(6, FMT_D),
8577 OPC_NEG_D = FOP(7, FMT_D),
8578 OPC_ROUND_L_D = FOP(8, FMT_D),
8579 OPC_TRUNC_L_D = FOP(9, FMT_D),
8580 OPC_CEIL_L_D = FOP(10, FMT_D),
8581 OPC_FLOOR_L_D = FOP(11, FMT_D),
8582 OPC_ROUND_W_D = FOP(12, FMT_D),
8583 OPC_TRUNC_W_D = FOP(13, FMT_D),
8584 OPC_CEIL_W_D = FOP(14, FMT_D),
8585 OPC_FLOOR_W_D = FOP(15, FMT_D),
8586 OPC_SEL_D = FOP(16, FMT_D),
8587 OPC_MOVCF_D = FOP(17, FMT_D),
8588 OPC_MOVZ_D = FOP(18, FMT_D),
8589 OPC_MOVN_D = FOP(19, FMT_D),
8590 OPC_SELEQZ_D = FOP(20, FMT_D),
8591 OPC_RECIP_D = FOP(21, FMT_D),
8592 OPC_RSQRT_D = FOP(22, FMT_D),
8593 OPC_SELNEZ_D = FOP(23, FMT_D),
8594 OPC_MADDF_D = FOP(24, FMT_D),
8595 OPC_MSUBF_D = FOP(25, FMT_D),
8596 OPC_RINT_D = FOP(26, FMT_D),
8597 OPC_CLASS_D = FOP(27, FMT_D),
8598 OPC_MIN_D = FOP(28, FMT_D),
8599 OPC_RECIP2_D = FOP(28, FMT_D),
8600 OPC_MINA_D = FOP(29, FMT_D),
8601 OPC_RECIP1_D = FOP(29, FMT_D),
8602 OPC_MAX_D = FOP(30, FMT_D),
8603 OPC_RSQRT1_D = FOP(30, FMT_D),
8604 OPC_MAXA_D = FOP(31, FMT_D),
8605 OPC_RSQRT2_D = FOP(31, FMT_D),
8606 OPC_CVT_S_D = FOP(32, FMT_D),
8607 OPC_CVT_W_D = FOP(36, FMT_D),
8608 OPC_CVT_L_D = FOP(37, FMT_D),
8609 OPC_CMP_F_D = FOP (48, FMT_D),
8610 OPC_CMP_UN_D = FOP (49, FMT_D),
8611 OPC_CMP_EQ_D = FOP (50, FMT_D),
8612 OPC_CMP_UEQ_D = FOP (51, FMT_D),
8613 OPC_CMP_OLT_D = FOP (52, FMT_D),
8614 OPC_CMP_ULT_D = FOP (53, FMT_D),
8615 OPC_CMP_OLE_D = FOP (54, FMT_D),
8616 OPC_CMP_ULE_D = FOP (55, FMT_D),
8617 OPC_CMP_SF_D = FOP (56, FMT_D),
8618 OPC_CMP_NGLE_D = FOP (57, FMT_D),
8619 OPC_CMP_SEQ_D = FOP (58, FMT_D),
8620 OPC_CMP_NGL_D = FOP (59, FMT_D),
8621 OPC_CMP_LT_D = FOP (60, FMT_D),
8622 OPC_CMP_NGE_D = FOP (61, FMT_D),
8623 OPC_CMP_LE_D = FOP (62, FMT_D),
8624 OPC_CMP_NGT_D = FOP (63, FMT_D),
8626 OPC_CVT_S_W = FOP(32, FMT_W),
8627 OPC_CVT_D_W = FOP(33, FMT_W),
8628 OPC_CVT_S_L = FOP(32, FMT_L),
8629 OPC_CVT_D_L = FOP(33, FMT_L),
8630 OPC_CVT_PS_PW = FOP(38, FMT_W),
8632 OPC_ADD_PS = FOP(0, FMT_PS),
8633 OPC_SUB_PS = FOP(1, FMT_PS),
8634 OPC_MUL_PS = FOP(2, FMT_PS),
8635 OPC_DIV_PS = FOP(3, FMT_PS),
8636 OPC_ABS_PS = FOP(5, FMT_PS),
8637 OPC_MOV_PS = FOP(6, FMT_PS),
8638 OPC_NEG_PS = FOP(7, FMT_PS),
8639 OPC_MOVCF_PS = FOP(17, FMT_PS),
8640 OPC_MOVZ_PS = FOP(18, FMT_PS),
8641 OPC_MOVN_PS = FOP(19, FMT_PS),
8642 OPC_ADDR_PS = FOP(24, FMT_PS),
8643 OPC_MULR_PS = FOP(26, FMT_PS),
8644 OPC_RECIP2_PS = FOP(28, FMT_PS),
8645 OPC_RECIP1_PS = FOP(29, FMT_PS),
8646 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8647 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8649 OPC_CVT_S_PU = FOP(32, FMT_PS),
8650 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8651 OPC_CVT_S_PL = FOP(40, FMT_PS),
8652 OPC_PLL_PS = FOP(44, FMT_PS),
8653 OPC_PLU_PS = FOP(45, FMT_PS),
8654 OPC_PUL_PS = FOP(46, FMT_PS),
8655 OPC_PUU_PS = FOP(47, FMT_PS),
8656 OPC_CMP_F_PS = FOP (48, FMT_PS),
8657 OPC_CMP_UN_PS = FOP (49, FMT_PS),
8658 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
8659 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
8660 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
8661 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
8662 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
8663 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
8664 OPC_CMP_SF_PS = FOP (56, FMT_PS),
8665 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
8666 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
8667 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
8668 OPC_CMP_LT_PS = FOP (60, FMT_PS),
8669 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
8670 OPC_CMP_LE_PS = FOP (62, FMT_PS),
8671 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
8674 enum r6_f_cmp_op {
8675 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8676 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8677 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8678 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8679 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8680 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8681 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8682 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
8683 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
8684 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
8685 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
8686 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
8687 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
8688 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
8689 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
8690 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
8691 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
8692 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
8693 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
8694 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
8695 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
8696 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
8698 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
8699 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
8700 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
8701 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
8702 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
8703 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
8704 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
8705 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
8706 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
8707 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
8708 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
8709 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
8710 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
8711 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
8712 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
8713 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
8714 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
8715 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
8716 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
8717 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
8718 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
8719 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
8721 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
8723 TCGv t0 = tcg_temp_new();
8725 switch (opc) {
8726 case OPC_MFC1:
8728 TCGv_i32 fp0 = tcg_temp_new_i32();
8730 gen_load_fpr32(ctx, fp0, fs);
8731 tcg_gen_ext_i32_tl(t0, fp0);
8732 tcg_temp_free_i32(fp0);
8734 gen_store_gpr(t0, rt);
8735 break;
8736 case OPC_MTC1:
8737 gen_load_gpr(t0, rt);
8739 TCGv_i32 fp0 = tcg_temp_new_i32();
8741 tcg_gen_trunc_tl_i32(fp0, t0);
8742 gen_store_fpr32(ctx, fp0, fs);
8743 tcg_temp_free_i32(fp0);
8745 break;
8746 case OPC_CFC1:
8747 gen_helper_1e0i(cfc1, t0, fs);
8748 gen_store_gpr(t0, rt);
8749 break;
8750 case OPC_CTC1:
8751 gen_load_gpr(t0, rt);
8752 save_cpu_state(ctx, 0);
8754 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8756 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8757 tcg_temp_free_i32(fs_tmp);
8759 /* Stop translation as we may have changed hflags */
8760 ctx->bstate = BS_STOP;
8761 break;
8762 #if defined(TARGET_MIPS64)
8763 case OPC_DMFC1:
8764 gen_load_fpr64(ctx, t0, fs);
8765 gen_store_gpr(t0, rt);
8766 break;
8767 case OPC_DMTC1:
8768 gen_load_gpr(t0, rt);
8769 gen_store_fpr64(ctx, t0, fs);
8770 break;
8771 #endif
8772 case OPC_MFHC1:
8774 TCGv_i32 fp0 = tcg_temp_new_i32();
8776 gen_load_fpr32h(ctx, fp0, fs);
8777 tcg_gen_ext_i32_tl(t0, fp0);
8778 tcg_temp_free_i32(fp0);
8780 gen_store_gpr(t0, rt);
8781 break;
8782 case OPC_MTHC1:
8783 gen_load_gpr(t0, rt);
8785 TCGv_i32 fp0 = tcg_temp_new_i32();
8787 tcg_gen_trunc_tl_i32(fp0, t0);
8788 gen_store_fpr32h(ctx, fp0, fs);
8789 tcg_temp_free_i32(fp0);
8791 break;
8792 default:
8793 MIPS_INVAL("cp1 move");
8794 generate_exception_end(ctx, EXCP_RI);
8795 goto out;
8798 out:
8799 tcg_temp_free(t0);
8802 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8804 TCGLabel *l1;
8805 TCGCond cond;
8806 TCGv_i32 t0;
8808 if (rd == 0) {
8809 /* Treat as NOP. */
8810 return;
8813 if (tf)
8814 cond = TCG_COND_EQ;
8815 else
8816 cond = TCG_COND_NE;
8818 l1 = gen_new_label();
8819 t0 = tcg_temp_new_i32();
8820 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8821 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8822 tcg_temp_free_i32(t0);
8823 if (rs == 0) {
8824 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8825 } else {
8826 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8828 gen_set_label(l1);
8831 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
8832 int tf)
8834 int cond;
8835 TCGv_i32 t0 = tcg_temp_new_i32();
8836 TCGLabel *l1 = gen_new_label();
8838 if (tf)
8839 cond = TCG_COND_EQ;
8840 else
8841 cond = TCG_COND_NE;
8843 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8844 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8845 gen_load_fpr32(ctx, t0, fs);
8846 gen_store_fpr32(ctx, t0, fd);
8847 gen_set_label(l1);
8848 tcg_temp_free_i32(t0);
8851 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8853 int cond;
8854 TCGv_i32 t0 = tcg_temp_new_i32();
8855 TCGv_i64 fp0;
8856 TCGLabel *l1 = gen_new_label();
8858 if (tf)
8859 cond = TCG_COND_EQ;
8860 else
8861 cond = TCG_COND_NE;
8863 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8864 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8865 tcg_temp_free_i32(t0);
8866 fp0 = tcg_temp_new_i64();
8867 gen_load_fpr64(ctx, fp0, fs);
8868 gen_store_fpr64(ctx, fp0, fd);
8869 tcg_temp_free_i64(fp0);
8870 gen_set_label(l1);
8873 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8874 int cc, int tf)
8876 int cond;
8877 TCGv_i32 t0 = tcg_temp_new_i32();
8878 TCGLabel *l1 = gen_new_label();
8879 TCGLabel *l2 = gen_new_label();
8881 if (tf)
8882 cond = TCG_COND_EQ;
8883 else
8884 cond = TCG_COND_NE;
8886 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8887 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8888 gen_load_fpr32(ctx, t0, fs);
8889 gen_store_fpr32(ctx, t0, fd);
8890 gen_set_label(l1);
8892 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8893 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8894 gen_load_fpr32h(ctx, t0, fs);
8895 gen_store_fpr32h(ctx, t0, fd);
8896 tcg_temp_free_i32(t0);
8897 gen_set_label(l2);
8900 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8901 int fs)
8903 TCGv_i32 t1 = tcg_const_i32(0);
8904 TCGv_i32 fp0 = tcg_temp_new_i32();
8905 TCGv_i32 fp1 = tcg_temp_new_i32();
8906 TCGv_i32 fp2 = tcg_temp_new_i32();
8907 gen_load_fpr32(ctx, fp0, fd);
8908 gen_load_fpr32(ctx, fp1, ft);
8909 gen_load_fpr32(ctx, fp2, fs);
8911 switch (op1) {
8912 case OPC_SEL_S:
8913 tcg_gen_andi_i32(fp0, fp0, 1);
8914 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8915 break;
8916 case OPC_SELEQZ_S:
8917 tcg_gen_andi_i32(fp1, fp1, 1);
8918 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8919 break;
8920 case OPC_SELNEZ_S:
8921 tcg_gen_andi_i32(fp1, fp1, 1);
8922 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8923 break;
8924 default:
8925 MIPS_INVAL("gen_sel_s");
8926 generate_exception_end(ctx, EXCP_RI);
8927 break;
8930 gen_store_fpr32(ctx, fp0, fd);
8931 tcg_temp_free_i32(fp2);
8932 tcg_temp_free_i32(fp1);
8933 tcg_temp_free_i32(fp0);
8934 tcg_temp_free_i32(t1);
8937 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8938 int fs)
8940 TCGv_i64 t1 = tcg_const_i64(0);
8941 TCGv_i64 fp0 = tcg_temp_new_i64();
8942 TCGv_i64 fp1 = tcg_temp_new_i64();
8943 TCGv_i64 fp2 = tcg_temp_new_i64();
8944 gen_load_fpr64(ctx, fp0, fd);
8945 gen_load_fpr64(ctx, fp1, ft);
8946 gen_load_fpr64(ctx, fp2, fs);
8948 switch (op1) {
8949 case OPC_SEL_D:
8950 tcg_gen_andi_i64(fp0, fp0, 1);
8951 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8952 break;
8953 case OPC_SELEQZ_D:
8954 tcg_gen_andi_i64(fp1, fp1, 1);
8955 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8956 break;
8957 case OPC_SELNEZ_D:
8958 tcg_gen_andi_i64(fp1, fp1, 1);
8959 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8960 break;
8961 default:
8962 MIPS_INVAL("gen_sel_d");
8963 generate_exception_end(ctx, EXCP_RI);
8964 break;
8967 gen_store_fpr64(ctx, fp0, fd);
8968 tcg_temp_free_i64(fp2);
8969 tcg_temp_free_i64(fp1);
8970 tcg_temp_free_i64(fp0);
8971 tcg_temp_free_i64(t1);
8974 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8975 int ft, int fs, int fd, int cc)
8977 uint32_t func = ctx->opcode & 0x3f;
8978 switch (op1) {
8979 case OPC_ADD_S:
8981 TCGv_i32 fp0 = tcg_temp_new_i32();
8982 TCGv_i32 fp1 = tcg_temp_new_i32();
8984 gen_load_fpr32(ctx, fp0, fs);
8985 gen_load_fpr32(ctx, fp1, ft);
8986 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8987 tcg_temp_free_i32(fp1);
8988 gen_store_fpr32(ctx, fp0, fd);
8989 tcg_temp_free_i32(fp0);
8991 break;
8992 case OPC_SUB_S:
8994 TCGv_i32 fp0 = tcg_temp_new_i32();
8995 TCGv_i32 fp1 = tcg_temp_new_i32();
8997 gen_load_fpr32(ctx, fp0, fs);
8998 gen_load_fpr32(ctx, fp1, ft);
8999 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
9000 tcg_temp_free_i32(fp1);
9001 gen_store_fpr32(ctx, fp0, fd);
9002 tcg_temp_free_i32(fp0);
9004 break;
9005 case OPC_MUL_S:
9007 TCGv_i32 fp0 = tcg_temp_new_i32();
9008 TCGv_i32 fp1 = tcg_temp_new_i32();
9010 gen_load_fpr32(ctx, fp0, fs);
9011 gen_load_fpr32(ctx, fp1, ft);
9012 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
9013 tcg_temp_free_i32(fp1);
9014 gen_store_fpr32(ctx, fp0, fd);
9015 tcg_temp_free_i32(fp0);
9017 break;
9018 case OPC_DIV_S:
9020 TCGv_i32 fp0 = tcg_temp_new_i32();
9021 TCGv_i32 fp1 = tcg_temp_new_i32();
9023 gen_load_fpr32(ctx, fp0, fs);
9024 gen_load_fpr32(ctx, fp1, ft);
9025 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
9026 tcg_temp_free_i32(fp1);
9027 gen_store_fpr32(ctx, fp0, fd);
9028 tcg_temp_free_i32(fp0);
9030 break;
9031 case OPC_SQRT_S:
9033 TCGv_i32 fp0 = tcg_temp_new_i32();
9035 gen_load_fpr32(ctx, fp0, fs);
9036 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
9037 gen_store_fpr32(ctx, fp0, fd);
9038 tcg_temp_free_i32(fp0);
9040 break;
9041 case OPC_ABS_S:
9043 TCGv_i32 fp0 = tcg_temp_new_i32();
9045 gen_load_fpr32(ctx, fp0, fs);
9046 if (ctx->abs2008) {
9047 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9048 } else {
9049 gen_helper_float_abs_s(fp0, fp0);
9051 gen_store_fpr32(ctx, fp0, fd);
9052 tcg_temp_free_i32(fp0);
9054 break;
9055 case OPC_MOV_S:
9057 TCGv_i32 fp0 = tcg_temp_new_i32();
9059 gen_load_fpr32(ctx, fp0, fs);
9060 gen_store_fpr32(ctx, fp0, fd);
9061 tcg_temp_free_i32(fp0);
9063 break;
9064 case OPC_NEG_S:
9066 TCGv_i32 fp0 = tcg_temp_new_i32();
9068 gen_load_fpr32(ctx, fp0, fs);
9069 if (ctx->abs2008) {
9070 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9071 } else {
9072 gen_helper_float_chs_s(fp0, fp0);
9074 gen_store_fpr32(ctx, fp0, fd);
9075 tcg_temp_free_i32(fp0);
9077 break;
9078 case OPC_ROUND_L_S:
9079 check_cp1_64bitmode(ctx);
9081 TCGv_i32 fp32 = tcg_temp_new_i32();
9082 TCGv_i64 fp64 = tcg_temp_new_i64();
9084 gen_load_fpr32(ctx, fp32, fs);
9085 if (ctx->nan2008) {
9086 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
9087 } else {
9088 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
9090 tcg_temp_free_i32(fp32);
9091 gen_store_fpr64(ctx, fp64, fd);
9092 tcg_temp_free_i64(fp64);
9094 break;
9095 case OPC_TRUNC_L_S:
9096 check_cp1_64bitmode(ctx);
9098 TCGv_i32 fp32 = tcg_temp_new_i32();
9099 TCGv_i64 fp64 = tcg_temp_new_i64();
9101 gen_load_fpr32(ctx, fp32, fs);
9102 if (ctx->nan2008) {
9103 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
9104 } else {
9105 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
9107 tcg_temp_free_i32(fp32);
9108 gen_store_fpr64(ctx, fp64, fd);
9109 tcg_temp_free_i64(fp64);
9111 break;
9112 case OPC_CEIL_L_S:
9113 check_cp1_64bitmode(ctx);
9115 TCGv_i32 fp32 = tcg_temp_new_i32();
9116 TCGv_i64 fp64 = tcg_temp_new_i64();
9118 gen_load_fpr32(ctx, fp32, fs);
9119 if (ctx->nan2008) {
9120 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
9121 } else {
9122 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
9124 tcg_temp_free_i32(fp32);
9125 gen_store_fpr64(ctx, fp64, fd);
9126 tcg_temp_free_i64(fp64);
9128 break;
9129 case OPC_FLOOR_L_S:
9130 check_cp1_64bitmode(ctx);
9132 TCGv_i32 fp32 = tcg_temp_new_i32();
9133 TCGv_i64 fp64 = tcg_temp_new_i64();
9135 gen_load_fpr32(ctx, fp32, fs);
9136 if (ctx->nan2008) {
9137 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
9138 } else {
9139 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
9141 tcg_temp_free_i32(fp32);
9142 gen_store_fpr64(ctx, fp64, fd);
9143 tcg_temp_free_i64(fp64);
9145 break;
9146 case OPC_ROUND_W_S:
9148 TCGv_i32 fp0 = tcg_temp_new_i32();
9150 gen_load_fpr32(ctx, fp0, fs);
9151 if (ctx->nan2008) {
9152 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
9153 } else {
9154 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
9156 gen_store_fpr32(ctx, fp0, fd);
9157 tcg_temp_free_i32(fp0);
9159 break;
9160 case OPC_TRUNC_W_S:
9162 TCGv_i32 fp0 = tcg_temp_new_i32();
9164 gen_load_fpr32(ctx, fp0, fs);
9165 if (ctx->nan2008) {
9166 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
9167 } else {
9168 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
9170 gen_store_fpr32(ctx, fp0, fd);
9171 tcg_temp_free_i32(fp0);
9173 break;
9174 case OPC_CEIL_W_S:
9176 TCGv_i32 fp0 = tcg_temp_new_i32();
9178 gen_load_fpr32(ctx, fp0, fs);
9179 if (ctx->nan2008) {
9180 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
9181 } else {
9182 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
9184 gen_store_fpr32(ctx, fp0, fd);
9185 tcg_temp_free_i32(fp0);
9187 break;
9188 case OPC_FLOOR_W_S:
9190 TCGv_i32 fp0 = tcg_temp_new_i32();
9192 gen_load_fpr32(ctx, fp0, fs);
9193 if (ctx->nan2008) {
9194 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
9195 } else {
9196 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
9198 gen_store_fpr32(ctx, fp0, fd);
9199 tcg_temp_free_i32(fp0);
9201 break;
9202 case OPC_SEL_S:
9203 check_insn(ctx, ISA_MIPS32R6);
9204 gen_sel_s(ctx, op1, fd, ft, fs);
9205 break;
9206 case OPC_SELEQZ_S:
9207 check_insn(ctx, ISA_MIPS32R6);
9208 gen_sel_s(ctx, op1, fd, ft, fs);
9209 break;
9210 case OPC_SELNEZ_S:
9211 check_insn(ctx, ISA_MIPS32R6);
9212 gen_sel_s(ctx, op1, fd, ft, fs);
9213 break;
9214 case OPC_MOVCF_S:
9215 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9216 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9217 break;
9218 case OPC_MOVZ_S:
9219 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9221 TCGLabel *l1 = gen_new_label();
9222 TCGv_i32 fp0;
9224 if (ft != 0) {
9225 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9227 fp0 = tcg_temp_new_i32();
9228 gen_load_fpr32(ctx, fp0, fs);
9229 gen_store_fpr32(ctx, fp0, fd);
9230 tcg_temp_free_i32(fp0);
9231 gen_set_label(l1);
9233 break;
9234 case OPC_MOVN_S:
9235 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9237 TCGLabel *l1 = gen_new_label();
9238 TCGv_i32 fp0;
9240 if (ft != 0) {
9241 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9242 fp0 = tcg_temp_new_i32();
9243 gen_load_fpr32(ctx, fp0, fs);
9244 gen_store_fpr32(ctx, fp0, fd);
9245 tcg_temp_free_i32(fp0);
9246 gen_set_label(l1);
9249 break;
9250 case OPC_RECIP_S:
9252 TCGv_i32 fp0 = tcg_temp_new_i32();
9254 gen_load_fpr32(ctx, fp0, fs);
9255 gen_helper_float_recip_s(fp0, cpu_env, fp0);
9256 gen_store_fpr32(ctx, fp0, fd);
9257 tcg_temp_free_i32(fp0);
9259 break;
9260 case OPC_RSQRT_S:
9262 TCGv_i32 fp0 = tcg_temp_new_i32();
9264 gen_load_fpr32(ctx, fp0, fs);
9265 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
9266 gen_store_fpr32(ctx, fp0, fd);
9267 tcg_temp_free_i32(fp0);
9269 break;
9270 case OPC_MADDF_S:
9271 check_insn(ctx, ISA_MIPS32R6);
9273 TCGv_i32 fp0 = tcg_temp_new_i32();
9274 TCGv_i32 fp1 = tcg_temp_new_i32();
9275 TCGv_i32 fp2 = tcg_temp_new_i32();
9276 gen_load_fpr32(ctx, fp0, fs);
9277 gen_load_fpr32(ctx, fp1, ft);
9278 gen_load_fpr32(ctx, fp2, fd);
9279 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
9280 gen_store_fpr32(ctx, fp2, fd);
9281 tcg_temp_free_i32(fp2);
9282 tcg_temp_free_i32(fp1);
9283 tcg_temp_free_i32(fp0);
9285 break;
9286 case OPC_MSUBF_S:
9287 check_insn(ctx, ISA_MIPS32R6);
9289 TCGv_i32 fp0 = tcg_temp_new_i32();
9290 TCGv_i32 fp1 = tcg_temp_new_i32();
9291 TCGv_i32 fp2 = tcg_temp_new_i32();
9292 gen_load_fpr32(ctx, fp0, fs);
9293 gen_load_fpr32(ctx, fp1, ft);
9294 gen_load_fpr32(ctx, fp2, fd);
9295 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
9296 gen_store_fpr32(ctx, fp2, fd);
9297 tcg_temp_free_i32(fp2);
9298 tcg_temp_free_i32(fp1);
9299 tcg_temp_free_i32(fp0);
9301 break;
9302 case OPC_RINT_S:
9303 check_insn(ctx, ISA_MIPS32R6);
9305 TCGv_i32 fp0 = tcg_temp_new_i32();
9306 gen_load_fpr32(ctx, fp0, fs);
9307 gen_helper_float_rint_s(fp0, cpu_env, fp0);
9308 gen_store_fpr32(ctx, fp0, fd);
9309 tcg_temp_free_i32(fp0);
9311 break;
9312 case OPC_CLASS_S:
9313 check_insn(ctx, ISA_MIPS32R6);
9315 TCGv_i32 fp0 = tcg_temp_new_i32();
9316 gen_load_fpr32(ctx, fp0, fs);
9317 gen_helper_float_class_s(fp0, cpu_env, fp0);
9318 gen_store_fpr32(ctx, fp0, fd);
9319 tcg_temp_free_i32(fp0);
9321 break;
9322 case OPC_MIN_S: /* OPC_RECIP2_S */
9323 if (ctx->insn_flags & ISA_MIPS32R6) {
9324 /* OPC_MIN_S */
9325 TCGv_i32 fp0 = tcg_temp_new_i32();
9326 TCGv_i32 fp1 = tcg_temp_new_i32();
9327 TCGv_i32 fp2 = tcg_temp_new_i32();
9328 gen_load_fpr32(ctx, fp0, fs);
9329 gen_load_fpr32(ctx, fp1, ft);
9330 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
9331 gen_store_fpr32(ctx, fp2, fd);
9332 tcg_temp_free_i32(fp2);
9333 tcg_temp_free_i32(fp1);
9334 tcg_temp_free_i32(fp0);
9335 } else {
9336 /* OPC_RECIP2_S */
9337 check_cp1_64bitmode(ctx);
9339 TCGv_i32 fp0 = tcg_temp_new_i32();
9340 TCGv_i32 fp1 = tcg_temp_new_i32();
9342 gen_load_fpr32(ctx, fp0, fs);
9343 gen_load_fpr32(ctx, fp1, ft);
9344 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
9345 tcg_temp_free_i32(fp1);
9346 gen_store_fpr32(ctx, fp0, fd);
9347 tcg_temp_free_i32(fp0);
9350 break;
9351 case OPC_MINA_S: /* OPC_RECIP1_S */
9352 if (ctx->insn_flags & ISA_MIPS32R6) {
9353 /* OPC_MINA_S */
9354 TCGv_i32 fp0 = tcg_temp_new_i32();
9355 TCGv_i32 fp1 = tcg_temp_new_i32();
9356 TCGv_i32 fp2 = tcg_temp_new_i32();
9357 gen_load_fpr32(ctx, fp0, fs);
9358 gen_load_fpr32(ctx, fp1, ft);
9359 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
9360 gen_store_fpr32(ctx, fp2, fd);
9361 tcg_temp_free_i32(fp2);
9362 tcg_temp_free_i32(fp1);
9363 tcg_temp_free_i32(fp0);
9364 } else {
9365 /* OPC_RECIP1_S */
9366 check_cp1_64bitmode(ctx);
9368 TCGv_i32 fp0 = tcg_temp_new_i32();
9370 gen_load_fpr32(ctx, fp0, fs);
9371 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
9372 gen_store_fpr32(ctx, fp0, fd);
9373 tcg_temp_free_i32(fp0);
9376 break;
9377 case OPC_MAX_S: /* OPC_RSQRT1_S */
9378 if (ctx->insn_flags & ISA_MIPS32R6) {
9379 /* OPC_MAX_S */
9380 TCGv_i32 fp0 = tcg_temp_new_i32();
9381 TCGv_i32 fp1 = tcg_temp_new_i32();
9382 gen_load_fpr32(ctx, fp0, fs);
9383 gen_load_fpr32(ctx, fp1, ft);
9384 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
9385 gen_store_fpr32(ctx, fp1, fd);
9386 tcg_temp_free_i32(fp1);
9387 tcg_temp_free_i32(fp0);
9388 } else {
9389 /* OPC_RSQRT1_S */
9390 check_cp1_64bitmode(ctx);
9392 TCGv_i32 fp0 = tcg_temp_new_i32();
9394 gen_load_fpr32(ctx, fp0, fs);
9395 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
9396 gen_store_fpr32(ctx, fp0, fd);
9397 tcg_temp_free_i32(fp0);
9400 break;
9401 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9402 if (ctx->insn_flags & ISA_MIPS32R6) {
9403 /* OPC_MAXA_S */
9404 TCGv_i32 fp0 = tcg_temp_new_i32();
9405 TCGv_i32 fp1 = tcg_temp_new_i32();
9406 gen_load_fpr32(ctx, fp0, fs);
9407 gen_load_fpr32(ctx, fp1, ft);
9408 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
9409 gen_store_fpr32(ctx, fp1, fd);
9410 tcg_temp_free_i32(fp1);
9411 tcg_temp_free_i32(fp0);
9412 } else {
9413 /* OPC_RSQRT2_S */
9414 check_cp1_64bitmode(ctx);
9416 TCGv_i32 fp0 = tcg_temp_new_i32();
9417 TCGv_i32 fp1 = tcg_temp_new_i32();
9419 gen_load_fpr32(ctx, fp0, fs);
9420 gen_load_fpr32(ctx, fp1, ft);
9421 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
9422 tcg_temp_free_i32(fp1);
9423 gen_store_fpr32(ctx, fp0, fd);
9424 tcg_temp_free_i32(fp0);
9427 break;
9428 case OPC_CVT_D_S:
9429 check_cp1_registers(ctx, fd);
9431 TCGv_i32 fp32 = tcg_temp_new_i32();
9432 TCGv_i64 fp64 = tcg_temp_new_i64();
9434 gen_load_fpr32(ctx, fp32, fs);
9435 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
9436 tcg_temp_free_i32(fp32);
9437 gen_store_fpr64(ctx, fp64, fd);
9438 tcg_temp_free_i64(fp64);
9440 break;
9441 case OPC_CVT_W_S:
9443 TCGv_i32 fp0 = tcg_temp_new_i32();
9445 gen_load_fpr32(ctx, fp0, fs);
9446 if (ctx->nan2008) {
9447 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
9448 } else {
9449 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
9451 gen_store_fpr32(ctx, fp0, fd);
9452 tcg_temp_free_i32(fp0);
9454 break;
9455 case OPC_CVT_L_S:
9456 check_cp1_64bitmode(ctx);
9458 TCGv_i32 fp32 = tcg_temp_new_i32();
9459 TCGv_i64 fp64 = tcg_temp_new_i64();
9461 gen_load_fpr32(ctx, fp32, fs);
9462 if (ctx->nan2008) {
9463 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
9464 } else {
9465 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
9467 tcg_temp_free_i32(fp32);
9468 gen_store_fpr64(ctx, fp64, fd);
9469 tcg_temp_free_i64(fp64);
9471 break;
9472 case OPC_CVT_PS_S:
9473 check_ps(ctx);
9475 TCGv_i64 fp64 = tcg_temp_new_i64();
9476 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9477 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9479 gen_load_fpr32(ctx, fp32_0, fs);
9480 gen_load_fpr32(ctx, fp32_1, ft);
9481 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9482 tcg_temp_free_i32(fp32_1);
9483 tcg_temp_free_i32(fp32_0);
9484 gen_store_fpr64(ctx, fp64, fd);
9485 tcg_temp_free_i64(fp64);
9487 break;
9488 case OPC_CMP_F_S:
9489 case OPC_CMP_UN_S:
9490 case OPC_CMP_EQ_S:
9491 case OPC_CMP_UEQ_S:
9492 case OPC_CMP_OLT_S:
9493 case OPC_CMP_ULT_S:
9494 case OPC_CMP_OLE_S:
9495 case OPC_CMP_ULE_S:
9496 case OPC_CMP_SF_S:
9497 case OPC_CMP_NGLE_S:
9498 case OPC_CMP_SEQ_S:
9499 case OPC_CMP_NGL_S:
9500 case OPC_CMP_LT_S:
9501 case OPC_CMP_NGE_S:
9502 case OPC_CMP_LE_S:
9503 case OPC_CMP_NGT_S:
9504 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9505 if (ctx->opcode & (1 << 6)) {
9506 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
9507 } else {
9508 gen_cmp_s(ctx, func-48, ft, fs, cc);
9510 break;
9511 case OPC_ADD_D:
9512 check_cp1_registers(ctx, fs | ft | fd);
9514 TCGv_i64 fp0 = tcg_temp_new_i64();
9515 TCGv_i64 fp1 = tcg_temp_new_i64();
9517 gen_load_fpr64(ctx, fp0, fs);
9518 gen_load_fpr64(ctx, fp1, ft);
9519 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
9520 tcg_temp_free_i64(fp1);
9521 gen_store_fpr64(ctx, fp0, fd);
9522 tcg_temp_free_i64(fp0);
9524 break;
9525 case OPC_SUB_D:
9526 check_cp1_registers(ctx, fs | ft | fd);
9528 TCGv_i64 fp0 = tcg_temp_new_i64();
9529 TCGv_i64 fp1 = tcg_temp_new_i64();
9531 gen_load_fpr64(ctx, fp0, fs);
9532 gen_load_fpr64(ctx, fp1, ft);
9533 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
9534 tcg_temp_free_i64(fp1);
9535 gen_store_fpr64(ctx, fp0, fd);
9536 tcg_temp_free_i64(fp0);
9538 break;
9539 case OPC_MUL_D:
9540 check_cp1_registers(ctx, fs | ft | fd);
9542 TCGv_i64 fp0 = tcg_temp_new_i64();
9543 TCGv_i64 fp1 = tcg_temp_new_i64();
9545 gen_load_fpr64(ctx, fp0, fs);
9546 gen_load_fpr64(ctx, fp1, ft);
9547 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
9548 tcg_temp_free_i64(fp1);
9549 gen_store_fpr64(ctx, fp0, fd);
9550 tcg_temp_free_i64(fp0);
9552 break;
9553 case OPC_DIV_D:
9554 check_cp1_registers(ctx, fs | ft | fd);
9556 TCGv_i64 fp0 = tcg_temp_new_i64();
9557 TCGv_i64 fp1 = tcg_temp_new_i64();
9559 gen_load_fpr64(ctx, fp0, fs);
9560 gen_load_fpr64(ctx, fp1, ft);
9561 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
9562 tcg_temp_free_i64(fp1);
9563 gen_store_fpr64(ctx, fp0, fd);
9564 tcg_temp_free_i64(fp0);
9566 break;
9567 case OPC_SQRT_D:
9568 check_cp1_registers(ctx, fs | fd);
9570 TCGv_i64 fp0 = tcg_temp_new_i64();
9572 gen_load_fpr64(ctx, fp0, fs);
9573 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
9574 gen_store_fpr64(ctx, fp0, fd);
9575 tcg_temp_free_i64(fp0);
9577 break;
9578 case OPC_ABS_D:
9579 check_cp1_registers(ctx, fs | fd);
9581 TCGv_i64 fp0 = tcg_temp_new_i64();
9583 gen_load_fpr64(ctx, fp0, fs);
9584 if (ctx->abs2008) {
9585 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9586 } else {
9587 gen_helper_float_abs_d(fp0, fp0);
9589 gen_store_fpr64(ctx, fp0, fd);
9590 tcg_temp_free_i64(fp0);
9592 break;
9593 case OPC_MOV_D:
9594 check_cp1_registers(ctx, fs | fd);
9596 TCGv_i64 fp0 = tcg_temp_new_i64();
9598 gen_load_fpr64(ctx, fp0, fs);
9599 gen_store_fpr64(ctx, fp0, fd);
9600 tcg_temp_free_i64(fp0);
9602 break;
9603 case OPC_NEG_D:
9604 check_cp1_registers(ctx, fs | fd);
9606 TCGv_i64 fp0 = tcg_temp_new_i64();
9608 gen_load_fpr64(ctx, fp0, fs);
9609 if (ctx->abs2008) {
9610 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
9611 } else {
9612 gen_helper_float_chs_d(fp0, fp0);
9614 gen_store_fpr64(ctx, fp0, fd);
9615 tcg_temp_free_i64(fp0);
9617 break;
9618 case OPC_ROUND_L_D:
9619 check_cp1_64bitmode(ctx);
9621 TCGv_i64 fp0 = tcg_temp_new_i64();
9623 gen_load_fpr64(ctx, fp0, fs);
9624 if (ctx->nan2008) {
9625 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
9626 } else {
9627 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
9629 gen_store_fpr64(ctx, fp0, fd);
9630 tcg_temp_free_i64(fp0);
9632 break;
9633 case OPC_TRUNC_L_D:
9634 check_cp1_64bitmode(ctx);
9636 TCGv_i64 fp0 = tcg_temp_new_i64();
9638 gen_load_fpr64(ctx, fp0, fs);
9639 if (ctx->nan2008) {
9640 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
9641 } else {
9642 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
9644 gen_store_fpr64(ctx, fp0, fd);
9645 tcg_temp_free_i64(fp0);
9647 break;
9648 case OPC_CEIL_L_D:
9649 check_cp1_64bitmode(ctx);
9651 TCGv_i64 fp0 = tcg_temp_new_i64();
9653 gen_load_fpr64(ctx, fp0, fs);
9654 if (ctx->nan2008) {
9655 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
9656 } else {
9657 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
9659 gen_store_fpr64(ctx, fp0, fd);
9660 tcg_temp_free_i64(fp0);
9662 break;
9663 case OPC_FLOOR_L_D:
9664 check_cp1_64bitmode(ctx);
9666 TCGv_i64 fp0 = tcg_temp_new_i64();
9668 gen_load_fpr64(ctx, fp0, fs);
9669 if (ctx->nan2008) {
9670 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
9671 } else {
9672 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
9674 gen_store_fpr64(ctx, fp0, fd);
9675 tcg_temp_free_i64(fp0);
9677 break;
9678 case OPC_ROUND_W_D:
9679 check_cp1_registers(ctx, fs);
9681 TCGv_i32 fp32 = tcg_temp_new_i32();
9682 TCGv_i64 fp64 = tcg_temp_new_i64();
9684 gen_load_fpr64(ctx, fp64, fs);
9685 if (ctx->nan2008) {
9686 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
9687 } else {
9688 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
9690 tcg_temp_free_i64(fp64);
9691 gen_store_fpr32(ctx, fp32, fd);
9692 tcg_temp_free_i32(fp32);
9694 break;
9695 case OPC_TRUNC_W_D:
9696 check_cp1_registers(ctx, fs);
9698 TCGv_i32 fp32 = tcg_temp_new_i32();
9699 TCGv_i64 fp64 = tcg_temp_new_i64();
9701 gen_load_fpr64(ctx, fp64, fs);
9702 if (ctx->nan2008) {
9703 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
9704 } else {
9705 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
9707 tcg_temp_free_i64(fp64);
9708 gen_store_fpr32(ctx, fp32, fd);
9709 tcg_temp_free_i32(fp32);
9711 break;
9712 case OPC_CEIL_W_D:
9713 check_cp1_registers(ctx, fs);
9715 TCGv_i32 fp32 = tcg_temp_new_i32();
9716 TCGv_i64 fp64 = tcg_temp_new_i64();
9718 gen_load_fpr64(ctx, fp64, fs);
9719 if (ctx->nan2008) {
9720 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
9721 } else {
9722 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
9724 tcg_temp_free_i64(fp64);
9725 gen_store_fpr32(ctx, fp32, fd);
9726 tcg_temp_free_i32(fp32);
9728 break;
9729 case OPC_FLOOR_W_D:
9730 check_cp1_registers(ctx, fs);
9732 TCGv_i32 fp32 = tcg_temp_new_i32();
9733 TCGv_i64 fp64 = tcg_temp_new_i64();
9735 gen_load_fpr64(ctx, fp64, fs);
9736 if (ctx->nan2008) {
9737 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
9738 } else {
9739 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
9741 tcg_temp_free_i64(fp64);
9742 gen_store_fpr32(ctx, fp32, fd);
9743 tcg_temp_free_i32(fp32);
9745 break;
9746 case OPC_SEL_D:
9747 check_insn(ctx, ISA_MIPS32R6);
9748 gen_sel_d(ctx, op1, fd, ft, fs);
9749 break;
9750 case OPC_SELEQZ_D:
9751 check_insn(ctx, ISA_MIPS32R6);
9752 gen_sel_d(ctx, op1, fd, ft, fs);
9753 break;
9754 case OPC_SELNEZ_D:
9755 check_insn(ctx, ISA_MIPS32R6);
9756 gen_sel_d(ctx, op1, fd, ft, fs);
9757 break;
9758 case OPC_MOVCF_D:
9759 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9760 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9761 break;
9762 case OPC_MOVZ_D:
9763 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9765 TCGLabel *l1 = gen_new_label();
9766 TCGv_i64 fp0;
9768 if (ft != 0) {
9769 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9771 fp0 = tcg_temp_new_i64();
9772 gen_load_fpr64(ctx, fp0, fs);
9773 gen_store_fpr64(ctx, fp0, fd);
9774 tcg_temp_free_i64(fp0);
9775 gen_set_label(l1);
9777 break;
9778 case OPC_MOVN_D:
9779 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9781 TCGLabel *l1 = gen_new_label();
9782 TCGv_i64 fp0;
9784 if (ft != 0) {
9785 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9786 fp0 = tcg_temp_new_i64();
9787 gen_load_fpr64(ctx, fp0, fs);
9788 gen_store_fpr64(ctx, fp0, fd);
9789 tcg_temp_free_i64(fp0);
9790 gen_set_label(l1);
9793 break;
9794 case OPC_RECIP_D:
9795 check_cp1_registers(ctx, fs | fd);
9797 TCGv_i64 fp0 = tcg_temp_new_i64();
9799 gen_load_fpr64(ctx, fp0, fs);
9800 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9801 gen_store_fpr64(ctx, fp0, fd);
9802 tcg_temp_free_i64(fp0);
9804 break;
9805 case OPC_RSQRT_D:
9806 check_cp1_registers(ctx, fs | fd);
9808 TCGv_i64 fp0 = tcg_temp_new_i64();
9810 gen_load_fpr64(ctx, fp0, fs);
9811 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9812 gen_store_fpr64(ctx, fp0, fd);
9813 tcg_temp_free_i64(fp0);
9815 break;
9816 case OPC_MADDF_D:
9817 check_insn(ctx, ISA_MIPS32R6);
9819 TCGv_i64 fp0 = tcg_temp_new_i64();
9820 TCGv_i64 fp1 = tcg_temp_new_i64();
9821 TCGv_i64 fp2 = tcg_temp_new_i64();
9822 gen_load_fpr64(ctx, fp0, fs);
9823 gen_load_fpr64(ctx, fp1, ft);
9824 gen_load_fpr64(ctx, fp2, fd);
9825 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9826 gen_store_fpr64(ctx, fp2, fd);
9827 tcg_temp_free_i64(fp2);
9828 tcg_temp_free_i64(fp1);
9829 tcg_temp_free_i64(fp0);
9831 break;
9832 case OPC_MSUBF_D:
9833 check_insn(ctx, ISA_MIPS32R6);
9835 TCGv_i64 fp0 = tcg_temp_new_i64();
9836 TCGv_i64 fp1 = tcg_temp_new_i64();
9837 TCGv_i64 fp2 = tcg_temp_new_i64();
9838 gen_load_fpr64(ctx, fp0, fs);
9839 gen_load_fpr64(ctx, fp1, ft);
9840 gen_load_fpr64(ctx, fp2, fd);
9841 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9842 gen_store_fpr64(ctx, fp2, fd);
9843 tcg_temp_free_i64(fp2);
9844 tcg_temp_free_i64(fp1);
9845 tcg_temp_free_i64(fp0);
9847 break;
9848 case OPC_RINT_D:
9849 check_insn(ctx, ISA_MIPS32R6);
9851 TCGv_i64 fp0 = tcg_temp_new_i64();
9852 gen_load_fpr64(ctx, fp0, fs);
9853 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9854 gen_store_fpr64(ctx, fp0, fd);
9855 tcg_temp_free_i64(fp0);
9857 break;
9858 case OPC_CLASS_D:
9859 check_insn(ctx, ISA_MIPS32R6);
9861 TCGv_i64 fp0 = tcg_temp_new_i64();
9862 gen_load_fpr64(ctx, fp0, fs);
9863 gen_helper_float_class_d(fp0, cpu_env, fp0);
9864 gen_store_fpr64(ctx, fp0, fd);
9865 tcg_temp_free_i64(fp0);
9867 break;
9868 case OPC_MIN_D: /* OPC_RECIP2_D */
9869 if (ctx->insn_flags & ISA_MIPS32R6) {
9870 /* OPC_MIN_D */
9871 TCGv_i64 fp0 = tcg_temp_new_i64();
9872 TCGv_i64 fp1 = tcg_temp_new_i64();
9873 gen_load_fpr64(ctx, fp0, fs);
9874 gen_load_fpr64(ctx, fp1, ft);
9875 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9876 gen_store_fpr64(ctx, fp1, fd);
9877 tcg_temp_free_i64(fp1);
9878 tcg_temp_free_i64(fp0);
9879 } else {
9880 /* OPC_RECIP2_D */
9881 check_cp1_64bitmode(ctx);
9883 TCGv_i64 fp0 = tcg_temp_new_i64();
9884 TCGv_i64 fp1 = tcg_temp_new_i64();
9886 gen_load_fpr64(ctx, fp0, fs);
9887 gen_load_fpr64(ctx, fp1, ft);
9888 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9889 tcg_temp_free_i64(fp1);
9890 gen_store_fpr64(ctx, fp0, fd);
9891 tcg_temp_free_i64(fp0);
9894 break;
9895 case OPC_MINA_D: /* OPC_RECIP1_D */
9896 if (ctx->insn_flags & ISA_MIPS32R6) {
9897 /* OPC_MINA_D */
9898 TCGv_i64 fp0 = tcg_temp_new_i64();
9899 TCGv_i64 fp1 = tcg_temp_new_i64();
9900 gen_load_fpr64(ctx, fp0, fs);
9901 gen_load_fpr64(ctx, fp1, ft);
9902 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9903 gen_store_fpr64(ctx, fp1, fd);
9904 tcg_temp_free_i64(fp1);
9905 tcg_temp_free_i64(fp0);
9906 } else {
9907 /* OPC_RECIP1_D */
9908 check_cp1_64bitmode(ctx);
9910 TCGv_i64 fp0 = tcg_temp_new_i64();
9912 gen_load_fpr64(ctx, fp0, fs);
9913 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9914 gen_store_fpr64(ctx, fp0, fd);
9915 tcg_temp_free_i64(fp0);
9918 break;
9919 case OPC_MAX_D: /* OPC_RSQRT1_D */
9920 if (ctx->insn_flags & ISA_MIPS32R6) {
9921 /* OPC_MAX_D */
9922 TCGv_i64 fp0 = tcg_temp_new_i64();
9923 TCGv_i64 fp1 = tcg_temp_new_i64();
9924 gen_load_fpr64(ctx, fp0, fs);
9925 gen_load_fpr64(ctx, fp1, ft);
9926 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9927 gen_store_fpr64(ctx, fp1, fd);
9928 tcg_temp_free_i64(fp1);
9929 tcg_temp_free_i64(fp0);
9930 } else {
9931 /* OPC_RSQRT1_D */
9932 check_cp1_64bitmode(ctx);
9934 TCGv_i64 fp0 = tcg_temp_new_i64();
9936 gen_load_fpr64(ctx, fp0, fs);
9937 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9938 gen_store_fpr64(ctx, fp0, fd);
9939 tcg_temp_free_i64(fp0);
9942 break;
9943 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9944 if (ctx->insn_flags & ISA_MIPS32R6) {
9945 /* OPC_MAXA_D */
9946 TCGv_i64 fp0 = tcg_temp_new_i64();
9947 TCGv_i64 fp1 = tcg_temp_new_i64();
9948 gen_load_fpr64(ctx, fp0, fs);
9949 gen_load_fpr64(ctx, fp1, ft);
9950 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9951 gen_store_fpr64(ctx, fp1, fd);
9952 tcg_temp_free_i64(fp1);
9953 tcg_temp_free_i64(fp0);
9954 } else {
9955 /* OPC_RSQRT2_D */
9956 check_cp1_64bitmode(ctx);
9958 TCGv_i64 fp0 = tcg_temp_new_i64();
9959 TCGv_i64 fp1 = tcg_temp_new_i64();
9961 gen_load_fpr64(ctx, fp0, fs);
9962 gen_load_fpr64(ctx, fp1, ft);
9963 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9964 tcg_temp_free_i64(fp1);
9965 gen_store_fpr64(ctx, fp0, fd);
9966 tcg_temp_free_i64(fp0);
9969 break;
9970 case OPC_CMP_F_D:
9971 case OPC_CMP_UN_D:
9972 case OPC_CMP_EQ_D:
9973 case OPC_CMP_UEQ_D:
9974 case OPC_CMP_OLT_D:
9975 case OPC_CMP_ULT_D:
9976 case OPC_CMP_OLE_D:
9977 case OPC_CMP_ULE_D:
9978 case OPC_CMP_SF_D:
9979 case OPC_CMP_NGLE_D:
9980 case OPC_CMP_SEQ_D:
9981 case OPC_CMP_NGL_D:
9982 case OPC_CMP_LT_D:
9983 case OPC_CMP_NGE_D:
9984 case OPC_CMP_LE_D:
9985 case OPC_CMP_NGT_D:
9986 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9987 if (ctx->opcode & (1 << 6)) {
9988 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9989 } else {
9990 gen_cmp_d(ctx, func-48, ft, fs, cc);
9992 break;
9993 case OPC_CVT_S_D:
9994 check_cp1_registers(ctx, fs);
9996 TCGv_i32 fp32 = tcg_temp_new_i32();
9997 TCGv_i64 fp64 = tcg_temp_new_i64();
9999 gen_load_fpr64(ctx, fp64, fs);
10000 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
10001 tcg_temp_free_i64(fp64);
10002 gen_store_fpr32(ctx, fp32, fd);
10003 tcg_temp_free_i32(fp32);
10005 break;
10006 case OPC_CVT_W_D:
10007 check_cp1_registers(ctx, fs);
10009 TCGv_i32 fp32 = tcg_temp_new_i32();
10010 TCGv_i64 fp64 = tcg_temp_new_i64();
10012 gen_load_fpr64(ctx, fp64, fs);
10013 if (ctx->nan2008) {
10014 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
10015 } else {
10016 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
10018 tcg_temp_free_i64(fp64);
10019 gen_store_fpr32(ctx, fp32, fd);
10020 tcg_temp_free_i32(fp32);
10022 break;
10023 case OPC_CVT_L_D:
10024 check_cp1_64bitmode(ctx);
10026 TCGv_i64 fp0 = tcg_temp_new_i64();
10028 gen_load_fpr64(ctx, fp0, fs);
10029 if (ctx->nan2008) {
10030 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
10031 } else {
10032 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
10034 gen_store_fpr64(ctx, fp0, fd);
10035 tcg_temp_free_i64(fp0);
10037 break;
10038 case OPC_CVT_S_W:
10040 TCGv_i32 fp0 = tcg_temp_new_i32();
10042 gen_load_fpr32(ctx, fp0, fs);
10043 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
10044 gen_store_fpr32(ctx, fp0, fd);
10045 tcg_temp_free_i32(fp0);
10047 break;
10048 case OPC_CVT_D_W:
10049 check_cp1_registers(ctx, fd);
10051 TCGv_i32 fp32 = tcg_temp_new_i32();
10052 TCGv_i64 fp64 = tcg_temp_new_i64();
10054 gen_load_fpr32(ctx, fp32, fs);
10055 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
10056 tcg_temp_free_i32(fp32);
10057 gen_store_fpr64(ctx, fp64, fd);
10058 tcg_temp_free_i64(fp64);
10060 break;
10061 case OPC_CVT_S_L:
10062 check_cp1_64bitmode(ctx);
10064 TCGv_i32 fp32 = tcg_temp_new_i32();
10065 TCGv_i64 fp64 = tcg_temp_new_i64();
10067 gen_load_fpr64(ctx, fp64, fs);
10068 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
10069 tcg_temp_free_i64(fp64);
10070 gen_store_fpr32(ctx, fp32, fd);
10071 tcg_temp_free_i32(fp32);
10073 break;
10074 case OPC_CVT_D_L:
10075 check_cp1_64bitmode(ctx);
10077 TCGv_i64 fp0 = tcg_temp_new_i64();
10079 gen_load_fpr64(ctx, fp0, fs);
10080 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
10081 gen_store_fpr64(ctx, fp0, fd);
10082 tcg_temp_free_i64(fp0);
10084 break;
10085 case OPC_CVT_PS_PW:
10086 check_ps(ctx);
10088 TCGv_i64 fp0 = tcg_temp_new_i64();
10090 gen_load_fpr64(ctx, fp0, fs);
10091 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
10092 gen_store_fpr64(ctx, fp0, fd);
10093 tcg_temp_free_i64(fp0);
10095 break;
10096 case OPC_ADD_PS:
10097 check_ps(ctx);
10099 TCGv_i64 fp0 = tcg_temp_new_i64();
10100 TCGv_i64 fp1 = tcg_temp_new_i64();
10102 gen_load_fpr64(ctx, fp0, fs);
10103 gen_load_fpr64(ctx, fp1, ft);
10104 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
10105 tcg_temp_free_i64(fp1);
10106 gen_store_fpr64(ctx, fp0, fd);
10107 tcg_temp_free_i64(fp0);
10109 break;
10110 case OPC_SUB_PS:
10111 check_ps(ctx);
10113 TCGv_i64 fp0 = tcg_temp_new_i64();
10114 TCGv_i64 fp1 = tcg_temp_new_i64();
10116 gen_load_fpr64(ctx, fp0, fs);
10117 gen_load_fpr64(ctx, fp1, ft);
10118 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
10119 tcg_temp_free_i64(fp1);
10120 gen_store_fpr64(ctx, fp0, fd);
10121 tcg_temp_free_i64(fp0);
10123 break;
10124 case OPC_MUL_PS:
10125 check_ps(ctx);
10127 TCGv_i64 fp0 = tcg_temp_new_i64();
10128 TCGv_i64 fp1 = tcg_temp_new_i64();
10130 gen_load_fpr64(ctx, fp0, fs);
10131 gen_load_fpr64(ctx, fp1, ft);
10132 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
10133 tcg_temp_free_i64(fp1);
10134 gen_store_fpr64(ctx, fp0, fd);
10135 tcg_temp_free_i64(fp0);
10137 break;
10138 case OPC_ABS_PS:
10139 check_ps(ctx);
10141 TCGv_i64 fp0 = tcg_temp_new_i64();
10143 gen_load_fpr64(ctx, fp0, fs);
10144 gen_helper_float_abs_ps(fp0, fp0);
10145 gen_store_fpr64(ctx, fp0, fd);
10146 tcg_temp_free_i64(fp0);
10148 break;
10149 case OPC_MOV_PS:
10150 check_ps(ctx);
10152 TCGv_i64 fp0 = tcg_temp_new_i64();
10154 gen_load_fpr64(ctx, fp0, fs);
10155 gen_store_fpr64(ctx, fp0, fd);
10156 tcg_temp_free_i64(fp0);
10158 break;
10159 case OPC_NEG_PS:
10160 check_ps(ctx);
10162 TCGv_i64 fp0 = tcg_temp_new_i64();
10164 gen_load_fpr64(ctx, fp0, fs);
10165 gen_helper_float_chs_ps(fp0, fp0);
10166 gen_store_fpr64(ctx, fp0, fd);
10167 tcg_temp_free_i64(fp0);
10169 break;
10170 case OPC_MOVCF_PS:
10171 check_ps(ctx);
10172 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10173 break;
10174 case OPC_MOVZ_PS:
10175 check_ps(ctx);
10177 TCGLabel *l1 = gen_new_label();
10178 TCGv_i64 fp0;
10180 if (ft != 0)
10181 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10182 fp0 = tcg_temp_new_i64();
10183 gen_load_fpr64(ctx, fp0, fs);
10184 gen_store_fpr64(ctx, fp0, fd);
10185 tcg_temp_free_i64(fp0);
10186 gen_set_label(l1);
10188 break;
10189 case OPC_MOVN_PS:
10190 check_ps(ctx);
10192 TCGLabel *l1 = gen_new_label();
10193 TCGv_i64 fp0;
10195 if (ft != 0) {
10196 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10197 fp0 = tcg_temp_new_i64();
10198 gen_load_fpr64(ctx, fp0, fs);
10199 gen_store_fpr64(ctx, fp0, fd);
10200 tcg_temp_free_i64(fp0);
10201 gen_set_label(l1);
10204 break;
10205 case OPC_ADDR_PS:
10206 check_ps(ctx);
10208 TCGv_i64 fp0 = tcg_temp_new_i64();
10209 TCGv_i64 fp1 = tcg_temp_new_i64();
10211 gen_load_fpr64(ctx, fp0, ft);
10212 gen_load_fpr64(ctx, fp1, fs);
10213 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
10214 tcg_temp_free_i64(fp1);
10215 gen_store_fpr64(ctx, fp0, fd);
10216 tcg_temp_free_i64(fp0);
10218 break;
10219 case OPC_MULR_PS:
10220 check_ps(ctx);
10222 TCGv_i64 fp0 = tcg_temp_new_i64();
10223 TCGv_i64 fp1 = tcg_temp_new_i64();
10225 gen_load_fpr64(ctx, fp0, ft);
10226 gen_load_fpr64(ctx, fp1, fs);
10227 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
10228 tcg_temp_free_i64(fp1);
10229 gen_store_fpr64(ctx, fp0, fd);
10230 tcg_temp_free_i64(fp0);
10232 break;
10233 case OPC_RECIP2_PS:
10234 check_ps(ctx);
10236 TCGv_i64 fp0 = tcg_temp_new_i64();
10237 TCGv_i64 fp1 = tcg_temp_new_i64();
10239 gen_load_fpr64(ctx, fp0, fs);
10240 gen_load_fpr64(ctx, fp1, ft);
10241 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
10242 tcg_temp_free_i64(fp1);
10243 gen_store_fpr64(ctx, fp0, fd);
10244 tcg_temp_free_i64(fp0);
10246 break;
10247 case OPC_RECIP1_PS:
10248 check_ps(ctx);
10250 TCGv_i64 fp0 = tcg_temp_new_i64();
10252 gen_load_fpr64(ctx, fp0, fs);
10253 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
10254 gen_store_fpr64(ctx, fp0, fd);
10255 tcg_temp_free_i64(fp0);
10257 break;
10258 case OPC_RSQRT1_PS:
10259 check_ps(ctx);
10261 TCGv_i64 fp0 = tcg_temp_new_i64();
10263 gen_load_fpr64(ctx, fp0, fs);
10264 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
10265 gen_store_fpr64(ctx, fp0, fd);
10266 tcg_temp_free_i64(fp0);
10268 break;
10269 case OPC_RSQRT2_PS:
10270 check_ps(ctx);
10272 TCGv_i64 fp0 = tcg_temp_new_i64();
10273 TCGv_i64 fp1 = tcg_temp_new_i64();
10275 gen_load_fpr64(ctx, fp0, fs);
10276 gen_load_fpr64(ctx, fp1, ft);
10277 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
10278 tcg_temp_free_i64(fp1);
10279 gen_store_fpr64(ctx, fp0, fd);
10280 tcg_temp_free_i64(fp0);
10282 break;
10283 case OPC_CVT_S_PU:
10284 check_cp1_64bitmode(ctx);
10286 TCGv_i32 fp0 = tcg_temp_new_i32();
10288 gen_load_fpr32h(ctx, fp0, fs);
10289 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
10290 gen_store_fpr32(ctx, fp0, fd);
10291 tcg_temp_free_i32(fp0);
10293 break;
10294 case OPC_CVT_PW_PS:
10295 check_ps(ctx);
10297 TCGv_i64 fp0 = tcg_temp_new_i64();
10299 gen_load_fpr64(ctx, fp0, fs);
10300 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
10301 gen_store_fpr64(ctx, fp0, fd);
10302 tcg_temp_free_i64(fp0);
10304 break;
10305 case OPC_CVT_S_PL:
10306 check_cp1_64bitmode(ctx);
10308 TCGv_i32 fp0 = tcg_temp_new_i32();
10310 gen_load_fpr32(ctx, fp0, fs);
10311 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
10312 gen_store_fpr32(ctx, fp0, fd);
10313 tcg_temp_free_i32(fp0);
10315 break;
10316 case OPC_PLL_PS:
10317 check_ps(ctx);
10319 TCGv_i32 fp0 = tcg_temp_new_i32();
10320 TCGv_i32 fp1 = tcg_temp_new_i32();
10322 gen_load_fpr32(ctx, fp0, fs);
10323 gen_load_fpr32(ctx, fp1, ft);
10324 gen_store_fpr32h(ctx, fp0, fd);
10325 gen_store_fpr32(ctx, fp1, fd);
10326 tcg_temp_free_i32(fp0);
10327 tcg_temp_free_i32(fp1);
10329 break;
10330 case OPC_PLU_PS:
10331 check_ps(ctx);
10333 TCGv_i32 fp0 = tcg_temp_new_i32();
10334 TCGv_i32 fp1 = tcg_temp_new_i32();
10336 gen_load_fpr32(ctx, fp0, fs);
10337 gen_load_fpr32h(ctx, fp1, ft);
10338 gen_store_fpr32(ctx, fp1, fd);
10339 gen_store_fpr32h(ctx, fp0, fd);
10340 tcg_temp_free_i32(fp0);
10341 tcg_temp_free_i32(fp1);
10343 break;
10344 case OPC_PUL_PS:
10345 check_ps(ctx);
10347 TCGv_i32 fp0 = tcg_temp_new_i32();
10348 TCGv_i32 fp1 = tcg_temp_new_i32();
10350 gen_load_fpr32h(ctx, fp0, fs);
10351 gen_load_fpr32(ctx, fp1, ft);
10352 gen_store_fpr32(ctx, fp1, fd);
10353 gen_store_fpr32h(ctx, fp0, fd);
10354 tcg_temp_free_i32(fp0);
10355 tcg_temp_free_i32(fp1);
10357 break;
10358 case OPC_PUU_PS:
10359 check_ps(ctx);
10361 TCGv_i32 fp0 = tcg_temp_new_i32();
10362 TCGv_i32 fp1 = tcg_temp_new_i32();
10364 gen_load_fpr32h(ctx, fp0, fs);
10365 gen_load_fpr32h(ctx, fp1, ft);
10366 gen_store_fpr32(ctx, fp1, fd);
10367 gen_store_fpr32h(ctx, fp0, fd);
10368 tcg_temp_free_i32(fp0);
10369 tcg_temp_free_i32(fp1);
10371 break;
10372 case OPC_CMP_F_PS:
10373 case OPC_CMP_UN_PS:
10374 case OPC_CMP_EQ_PS:
10375 case OPC_CMP_UEQ_PS:
10376 case OPC_CMP_OLT_PS:
10377 case OPC_CMP_ULT_PS:
10378 case OPC_CMP_OLE_PS:
10379 case OPC_CMP_ULE_PS:
10380 case OPC_CMP_SF_PS:
10381 case OPC_CMP_NGLE_PS:
10382 case OPC_CMP_SEQ_PS:
10383 case OPC_CMP_NGL_PS:
10384 case OPC_CMP_LT_PS:
10385 case OPC_CMP_NGE_PS:
10386 case OPC_CMP_LE_PS:
10387 case OPC_CMP_NGT_PS:
10388 if (ctx->opcode & (1 << 6)) {
10389 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
10390 } else {
10391 gen_cmp_ps(ctx, func-48, ft, fs, cc);
10393 break;
10394 default:
10395 MIPS_INVAL("farith");
10396 generate_exception_end(ctx, EXCP_RI);
10397 return;
10401 /* Coprocessor 3 (FPU) */
10402 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
10403 int fd, int fs, int base, int index)
10405 TCGv t0 = tcg_temp_new();
10407 if (base == 0) {
10408 gen_load_gpr(t0, index);
10409 } else if (index == 0) {
10410 gen_load_gpr(t0, base);
10411 } else {
10412 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10414 /* Don't do NOP if destination is zero: we must perform the actual
10415 memory access. */
10416 switch (opc) {
10417 case OPC_LWXC1:
10418 check_cop1x(ctx);
10420 TCGv_i32 fp0 = tcg_temp_new_i32();
10422 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
10423 tcg_gen_trunc_tl_i32(fp0, t0);
10424 gen_store_fpr32(ctx, fp0, fd);
10425 tcg_temp_free_i32(fp0);
10427 break;
10428 case OPC_LDXC1:
10429 check_cop1x(ctx);
10430 check_cp1_registers(ctx, fd);
10432 TCGv_i64 fp0 = tcg_temp_new_i64();
10433 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10434 gen_store_fpr64(ctx, fp0, fd);
10435 tcg_temp_free_i64(fp0);
10437 break;
10438 case OPC_LUXC1:
10439 check_cp1_64bitmode(ctx);
10440 tcg_gen_andi_tl(t0, t0, ~0x7);
10442 TCGv_i64 fp0 = tcg_temp_new_i64();
10444 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10445 gen_store_fpr64(ctx, fp0, fd);
10446 tcg_temp_free_i64(fp0);
10448 break;
10449 case OPC_SWXC1:
10450 check_cop1x(ctx);
10452 TCGv_i32 fp0 = tcg_temp_new_i32();
10453 gen_load_fpr32(ctx, fp0, fs);
10454 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
10455 tcg_temp_free_i32(fp0);
10457 break;
10458 case OPC_SDXC1:
10459 check_cop1x(ctx);
10460 check_cp1_registers(ctx, fs);
10462 TCGv_i64 fp0 = tcg_temp_new_i64();
10463 gen_load_fpr64(ctx, fp0, fs);
10464 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10465 tcg_temp_free_i64(fp0);
10467 break;
10468 case OPC_SUXC1:
10469 check_cp1_64bitmode(ctx);
10470 tcg_gen_andi_tl(t0, t0, ~0x7);
10472 TCGv_i64 fp0 = tcg_temp_new_i64();
10473 gen_load_fpr64(ctx, fp0, fs);
10474 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
10475 tcg_temp_free_i64(fp0);
10477 break;
10479 tcg_temp_free(t0);
10482 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
10483 int fd, int fr, int fs, int ft)
10485 switch (opc) {
10486 case OPC_ALNV_PS:
10487 check_ps(ctx);
10489 TCGv t0 = tcg_temp_local_new();
10490 TCGv_i32 fp = tcg_temp_new_i32();
10491 TCGv_i32 fph = tcg_temp_new_i32();
10492 TCGLabel *l1 = gen_new_label();
10493 TCGLabel *l2 = gen_new_label();
10495 gen_load_gpr(t0, fr);
10496 tcg_gen_andi_tl(t0, t0, 0x7);
10498 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10499 gen_load_fpr32(ctx, fp, fs);
10500 gen_load_fpr32h(ctx, fph, fs);
10501 gen_store_fpr32(ctx, fp, fd);
10502 gen_store_fpr32h(ctx, fph, fd);
10503 tcg_gen_br(l2);
10504 gen_set_label(l1);
10505 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10506 tcg_temp_free(t0);
10507 #ifdef TARGET_WORDS_BIGENDIAN
10508 gen_load_fpr32(ctx, fp, fs);
10509 gen_load_fpr32h(ctx, fph, ft);
10510 gen_store_fpr32h(ctx, fp, fd);
10511 gen_store_fpr32(ctx, fph, fd);
10512 #else
10513 gen_load_fpr32h(ctx, fph, fs);
10514 gen_load_fpr32(ctx, fp, ft);
10515 gen_store_fpr32(ctx, fph, fd);
10516 gen_store_fpr32h(ctx, fp, fd);
10517 #endif
10518 gen_set_label(l2);
10519 tcg_temp_free_i32(fp);
10520 tcg_temp_free_i32(fph);
10522 break;
10523 case OPC_MADD_S:
10524 check_cop1x(ctx);
10526 TCGv_i32 fp0 = tcg_temp_new_i32();
10527 TCGv_i32 fp1 = tcg_temp_new_i32();
10528 TCGv_i32 fp2 = tcg_temp_new_i32();
10530 gen_load_fpr32(ctx, fp0, fs);
10531 gen_load_fpr32(ctx, fp1, ft);
10532 gen_load_fpr32(ctx, fp2, fr);
10533 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
10534 tcg_temp_free_i32(fp0);
10535 tcg_temp_free_i32(fp1);
10536 gen_store_fpr32(ctx, fp2, fd);
10537 tcg_temp_free_i32(fp2);
10539 break;
10540 case OPC_MADD_D:
10541 check_cop1x(ctx);
10542 check_cp1_registers(ctx, fd | fs | ft | fr);
10544 TCGv_i64 fp0 = tcg_temp_new_i64();
10545 TCGv_i64 fp1 = tcg_temp_new_i64();
10546 TCGv_i64 fp2 = tcg_temp_new_i64();
10548 gen_load_fpr64(ctx, fp0, fs);
10549 gen_load_fpr64(ctx, fp1, ft);
10550 gen_load_fpr64(ctx, fp2, fr);
10551 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
10552 tcg_temp_free_i64(fp0);
10553 tcg_temp_free_i64(fp1);
10554 gen_store_fpr64(ctx, fp2, fd);
10555 tcg_temp_free_i64(fp2);
10557 break;
10558 case OPC_MADD_PS:
10559 check_ps(ctx);
10561 TCGv_i64 fp0 = tcg_temp_new_i64();
10562 TCGv_i64 fp1 = tcg_temp_new_i64();
10563 TCGv_i64 fp2 = tcg_temp_new_i64();
10565 gen_load_fpr64(ctx, fp0, fs);
10566 gen_load_fpr64(ctx, fp1, ft);
10567 gen_load_fpr64(ctx, fp2, fr);
10568 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
10569 tcg_temp_free_i64(fp0);
10570 tcg_temp_free_i64(fp1);
10571 gen_store_fpr64(ctx, fp2, fd);
10572 tcg_temp_free_i64(fp2);
10574 break;
10575 case OPC_MSUB_S:
10576 check_cop1x(ctx);
10578 TCGv_i32 fp0 = tcg_temp_new_i32();
10579 TCGv_i32 fp1 = tcg_temp_new_i32();
10580 TCGv_i32 fp2 = tcg_temp_new_i32();
10582 gen_load_fpr32(ctx, fp0, fs);
10583 gen_load_fpr32(ctx, fp1, ft);
10584 gen_load_fpr32(ctx, fp2, fr);
10585 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
10586 tcg_temp_free_i32(fp0);
10587 tcg_temp_free_i32(fp1);
10588 gen_store_fpr32(ctx, fp2, fd);
10589 tcg_temp_free_i32(fp2);
10591 break;
10592 case OPC_MSUB_D:
10593 check_cop1x(ctx);
10594 check_cp1_registers(ctx, fd | fs | ft | fr);
10596 TCGv_i64 fp0 = tcg_temp_new_i64();
10597 TCGv_i64 fp1 = tcg_temp_new_i64();
10598 TCGv_i64 fp2 = tcg_temp_new_i64();
10600 gen_load_fpr64(ctx, fp0, fs);
10601 gen_load_fpr64(ctx, fp1, ft);
10602 gen_load_fpr64(ctx, fp2, fr);
10603 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
10604 tcg_temp_free_i64(fp0);
10605 tcg_temp_free_i64(fp1);
10606 gen_store_fpr64(ctx, fp2, fd);
10607 tcg_temp_free_i64(fp2);
10609 break;
10610 case OPC_MSUB_PS:
10611 check_ps(ctx);
10613 TCGv_i64 fp0 = tcg_temp_new_i64();
10614 TCGv_i64 fp1 = tcg_temp_new_i64();
10615 TCGv_i64 fp2 = tcg_temp_new_i64();
10617 gen_load_fpr64(ctx, fp0, fs);
10618 gen_load_fpr64(ctx, fp1, ft);
10619 gen_load_fpr64(ctx, fp2, fr);
10620 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
10621 tcg_temp_free_i64(fp0);
10622 tcg_temp_free_i64(fp1);
10623 gen_store_fpr64(ctx, fp2, fd);
10624 tcg_temp_free_i64(fp2);
10626 break;
10627 case OPC_NMADD_S:
10628 check_cop1x(ctx);
10630 TCGv_i32 fp0 = tcg_temp_new_i32();
10631 TCGv_i32 fp1 = tcg_temp_new_i32();
10632 TCGv_i32 fp2 = tcg_temp_new_i32();
10634 gen_load_fpr32(ctx, fp0, fs);
10635 gen_load_fpr32(ctx, fp1, ft);
10636 gen_load_fpr32(ctx, fp2, fr);
10637 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
10638 tcg_temp_free_i32(fp0);
10639 tcg_temp_free_i32(fp1);
10640 gen_store_fpr32(ctx, fp2, fd);
10641 tcg_temp_free_i32(fp2);
10643 break;
10644 case OPC_NMADD_D:
10645 check_cop1x(ctx);
10646 check_cp1_registers(ctx, fd | fs | ft | fr);
10648 TCGv_i64 fp0 = tcg_temp_new_i64();
10649 TCGv_i64 fp1 = tcg_temp_new_i64();
10650 TCGv_i64 fp2 = tcg_temp_new_i64();
10652 gen_load_fpr64(ctx, fp0, fs);
10653 gen_load_fpr64(ctx, fp1, ft);
10654 gen_load_fpr64(ctx, fp2, fr);
10655 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10656 tcg_temp_free_i64(fp0);
10657 tcg_temp_free_i64(fp1);
10658 gen_store_fpr64(ctx, fp2, fd);
10659 tcg_temp_free_i64(fp2);
10661 break;
10662 case OPC_NMADD_PS:
10663 check_ps(ctx);
10665 TCGv_i64 fp0 = tcg_temp_new_i64();
10666 TCGv_i64 fp1 = tcg_temp_new_i64();
10667 TCGv_i64 fp2 = tcg_temp_new_i64();
10669 gen_load_fpr64(ctx, fp0, fs);
10670 gen_load_fpr64(ctx, fp1, ft);
10671 gen_load_fpr64(ctx, fp2, fr);
10672 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10673 tcg_temp_free_i64(fp0);
10674 tcg_temp_free_i64(fp1);
10675 gen_store_fpr64(ctx, fp2, fd);
10676 tcg_temp_free_i64(fp2);
10678 break;
10679 case OPC_NMSUB_S:
10680 check_cop1x(ctx);
10682 TCGv_i32 fp0 = tcg_temp_new_i32();
10683 TCGv_i32 fp1 = tcg_temp_new_i32();
10684 TCGv_i32 fp2 = tcg_temp_new_i32();
10686 gen_load_fpr32(ctx, fp0, fs);
10687 gen_load_fpr32(ctx, fp1, ft);
10688 gen_load_fpr32(ctx, fp2, fr);
10689 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10690 tcg_temp_free_i32(fp0);
10691 tcg_temp_free_i32(fp1);
10692 gen_store_fpr32(ctx, fp2, fd);
10693 tcg_temp_free_i32(fp2);
10695 break;
10696 case OPC_NMSUB_D:
10697 check_cop1x(ctx);
10698 check_cp1_registers(ctx, fd | fs | ft | fr);
10700 TCGv_i64 fp0 = tcg_temp_new_i64();
10701 TCGv_i64 fp1 = tcg_temp_new_i64();
10702 TCGv_i64 fp2 = tcg_temp_new_i64();
10704 gen_load_fpr64(ctx, fp0, fs);
10705 gen_load_fpr64(ctx, fp1, ft);
10706 gen_load_fpr64(ctx, fp2, fr);
10707 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10708 tcg_temp_free_i64(fp0);
10709 tcg_temp_free_i64(fp1);
10710 gen_store_fpr64(ctx, fp2, fd);
10711 tcg_temp_free_i64(fp2);
10713 break;
10714 case OPC_NMSUB_PS:
10715 check_ps(ctx);
10717 TCGv_i64 fp0 = tcg_temp_new_i64();
10718 TCGv_i64 fp1 = tcg_temp_new_i64();
10719 TCGv_i64 fp2 = tcg_temp_new_i64();
10721 gen_load_fpr64(ctx, fp0, fs);
10722 gen_load_fpr64(ctx, fp1, ft);
10723 gen_load_fpr64(ctx, fp2, fr);
10724 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10725 tcg_temp_free_i64(fp0);
10726 tcg_temp_free_i64(fp1);
10727 gen_store_fpr64(ctx, fp2, fd);
10728 tcg_temp_free_i64(fp2);
10730 break;
10731 default:
10732 MIPS_INVAL("flt3_arith");
10733 generate_exception_end(ctx, EXCP_RI);
10734 return;
10738 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10740 TCGv t0;
10742 #if !defined(CONFIG_USER_ONLY)
10743 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10744 Therefore only check the ISA in system mode. */
10745 check_insn(ctx, ISA_MIPS32R2);
10746 #endif
10747 t0 = tcg_temp_new();
10749 switch (rd) {
10750 case 0:
10751 gen_helper_rdhwr_cpunum(t0, cpu_env);
10752 gen_store_gpr(t0, rt);
10753 break;
10754 case 1:
10755 gen_helper_rdhwr_synci_step(t0, cpu_env);
10756 gen_store_gpr(t0, rt);
10757 break;
10758 case 2:
10759 if (ctx->tb->cflags & CF_USE_ICOUNT) {
10760 gen_io_start();
10762 gen_helper_rdhwr_cc(t0, cpu_env);
10763 if (ctx->tb->cflags & CF_USE_ICOUNT) {
10764 gen_io_end();
10766 gen_store_gpr(t0, rt);
10767 /* Break the TB to be able to take timer interrupts immediately
10768 after reading count. BS_STOP isn't sufficient, we need to ensure
10769 we break completely out of translated code. */
10770 gen_save_pc(ctx->pc + 4);
10771 ctx->bstate = BS_EXCP;
10772 break;
10773 case 3:
10774 gen_helper_rdhwr_ccres(t0, cpu_env);
10775 gen_store_gpr(t0, rt);
10776 break;
10777 case 4:
10778 check_insn(ctx, ISA_MIPS32R6);
10779 if (sel != 0) {
10780 /* Performance counter registers are not implemented other than
10781 * control register 0.
10783 generate_exception(ctx, EXCP_RI);
10785 gen_helper_rdhwr_performance(t0, cpu_env);
10786 gen_store_gpr(t0, rt);
10787 break;
10788 case 5:
10789 check_insn(ctx, ISA_MIPS32R6);
10790 gen_helper_rdhwr_xnp(t0, cpu_env);
10791 gen_store_gpr(t0, rt);
10792 break;
10793 case 29:
10794 #if defined(CONFIG_USER_ONLY)
10795 tcg_gen_ld_tl(t0, cpu_env,
10796 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10797 gen_store_gpr(t0, rt);
10798 break;
10799 #else
10800 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10801 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10802 tcg_gen_ld_tl(t0, cpu_env,
10803 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10804 gen_store_gpr(t0, rt);
10805 } else {
10806 generate_exception_end(ctx, EXCP_RI);
10808 break;
10809 #endif
10810 default: /* Invalid */
10811 MIPS_INVAL("rdhwr");
10812 generate_exception_end(ctx, EXCP_RI);
10813 break;
10815 tcg_temp_free(t0);
10818 static inline void clear_branch_hflags(DisasContext *ctx)
10820 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10821 if (ctx->bstate == BS_NONE) {
10822 save_cpu_state(ctx, 0);
10823 } else {
10824 /* it is not safe to save ctx->hflags as hflags may be changed
10825 in execution time by the instruction in delay / forbidden slot. */
10826 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10830 static void gen_branch(DisasContext *ctx, int insn_bytes)
10832 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10833 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10834 /* Branches completion */
10835 clear_branch_hflags(ctx);
10836 ctx->bstate = BS_BRANCH;
10837 /* FIXME: Need to clear can_do_io. */
10838 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10839 case MIPS_HFLAG_FBNSLOT:
10840 gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10841 break;
10842 case MIPS_HFLAG_B:
10843 /* unconditional branch */
10844 if (proc_hflags & MIPS_HFLAG_BX) {
10845 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10847 gen_goto_tb(ctx, 0, ctx->btarget);
10848 break;
10849 case MIPS_HFLAG_BL:
10850 /* blikely taken case */
10851 gen_goto_tb(ctx, 0, ctx->btarget);
10852 break;
10853 case MIPS_HFLAG_BC:
10854 /* Conditional branch */
10856 TCGLabel *l1 = gen_new_label();
10858 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10859 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10860 gen_set_label(l1);
10861 gen_goto_tb(ctx, 0, ctx->btarget);
10863 break;
10864 case MIPS_HFLAG_BR:
10865 /* unconditional branch to register */
10866 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10867 TCGv t0 = tcg_temp_new();
10868 TCGv_i32 t1 = tcg_temp_new_i32();
10870 tcg_gen_andi_tl(t0, btarget, 0x1);
10871 tcg_gen_trunc_tl_i32(t1, t0);
10872 tcg_temp_free(t0);
10873 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10874 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10875 tcg_gen_or_i32(hflags, hflags, t1);
10876 tcg_temp_free_i32(t1);
10878 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10879 } else {
10880 tcg_gen_mov_tl(cpu_PC, btarget);
10882 if (ctx->singlestep_enabled) {
10883 save_cpu_state(ctx, 0);
10884 gen_helper_raise_exception_debug(cpu_env);
10886 tcg_gen_lookup_and_goto_ptr(cpu_PC);
10887 break;
10888 default:
10889 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
10890 abort();
10895 /* Compact Branches */
10896 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10897 int rs, int rt, int32_t offset)
10899 int bcond_compute = 0;
10900 TCGv t0 = tcg_temp_new();
10901 TCGv t1 = tcg_temp_new();
10902 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10904 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10905 #ifdef MIPS_DEBUG_DISAS
10906 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
10907 "\n", ctx->pc);
10908 #endif
10909 generate_exception_end(ctx, EXCP_RI);
10910 goto out;
10913 /* Load needed operands and calculate btarget */
10914 switch (opc) {
10915 /* compact branch */
10916 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
10917 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
10918 gen_load_gpr(t0, rs);
10919 gen_load_gpr(t1, rt);
10920 bcond_compute = 1;
10921 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10922 if (rs <= rt && rs == 0) {
10923 /* OPC_BEQZALC, OPC_BNEZALC */
10924 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10926 break;
10927 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
10928 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
10929 gen_load_gpr(t0, rs);
10930 gen_load_gpr(t1, rt);
10931 bcond_compute = 1;
10932 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10933 break;
10934 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
10935 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
10936 if (rs == 0 || rs == rt) {
10937 /* OPC_BLEZALC, OPC_BGEZALC */
10938 /* OPC_BGTZALC, OPC_BLTZALC */
10939 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10941 gen_load_gpr(t0, rs);
10942 gen_load_gpr(t1, rt);
10943 bcond_compute = 1;
10944 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10945 break;
10946 case OPC_BC:
10947 case OPC_BALC:
10948 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10949 break;
10950 case OPC_BEQZC:
10951 case OPC_BNEZC:
10952 if (rs != 0) {
10953 /* OPC_BEQZC, OPC_BNEZC */
10954 gen_load_gpr(t0, rs);
10955 bcond_compute = 1;
10956 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
10957 } else {
10958 /* OPC_JIC, OPC_JIALC */
10959 TCGv tbase = tcg_temp_new();
10960 TCGv toffset = tcg_temp_new();
10962 gen_load_gpr(tbase, rt);
10963 tcg_gen_movi_tl(toffset, offset);
10964 gen_op_addr_add(ctx, btarget, tbase, toffset);
10965 tcg_temp_free(tbase);
10966 tcg_temp_free(toffset);
10968 break;
10969 default:
10970 MIPS_INVAL("Compact branch/jump");
10971 generate_exception_end(ctx, EXCP_RI);
10972 goto out;
10975 if (bcond_compute == 0) {
10976 /* Uncoditional compact branch */
10977 switch (opc) {
10978 case OPC_JIALC:
10979 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10980 /* Fallthrough */
10981 case OPC_JIC:
10982 ctx->hflags |= MIPS_HFLAG_BR;
10983 break;
10984 case OPC_BALC:
10985 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + m16_lowbit);
10986 /* Fallthrough */
10987 case OPC_BC:
10988 ctx->hflags |= MIPS_HFLAG_B;
10989 break;
10990 default:
10991 MIPS_INVAL("Compact branch/jump");
10992 generate_exception_end(ctx, EXCP_RI);
10993 goto out;
10996 /* Generating branch here as compact branches don't have delay slot */
10997 gen_branch(ctx, 4);
10998 } else {
10999 /* Conditional compact branch */
11000 TCGLabel *fs = gen_new_label();
11001 save_cpu_state(ctx, 0);
11003 switch (opc) {
11004 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11005 if (rs == 0 && rt != 0) {
11006 /* OPC_BLEZALC */
11007 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11008 } else if (rs != 0 && rt != 0 && rs == rt) {
11009 /* OPC_BGEZALC */
11010 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11011 } else {
11012 /* OPC_BGEUC */
11013 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11015 break;
11016 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11017 if (rs == 0 && rt != 0) {
11018 /* OPC_BGTZALC */
11019 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11020 } else if (rs != 0 && rt != 0 && rs == rt) {
11021 /* OPC_BLTZALC */
11022 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11023 } else {
11024 /* OPC_BLTUC */
11025 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11027 break;
11028 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11029 if (rs == 0 && rt != 0) {
11030 /* OPC_BLEZC */
11031 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11032 } else if (rs != 0 && rt != 0 && rs == rt) {
11033 /* OPC_BGEZC */
11034 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11035 } else {
11036 /* OPC_BGEC */
11037 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11039 break;
11040 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11041 if (rs == 0 && rt != 0) {
11042 /* OPC_BGTZC */
11043 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11044 } else if (rs != 0 && rt != 0 && rs == rt) {
11045 /* OPC_BLTZC */
11046 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11047 } else {
11048 /* OPC_BLTC */
11049 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11051 break;
11052 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11053 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11054 if (rs >= rt) {
11055 /* OPC_BOVC, OPC_BNVC */
11056 TCGv t2 = tcg_temp_new();
11057 TCGv t3 = tcg_temp_new();
11058 TCGv t4 = tcg_temp_new();
11059 TCGv input_overflow = tcg_temp_new();
11061 gen_load_gpr(t0, rs);
11062 gen_load_gpr(t1, rt);
11063 tcg_gen_ext32s_tl(t2, t0);
11064 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11065 tcg_gen_ext32s_tl(t3, t1);
11066 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11067 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11069 tcg_gen_add_tl(t4, t2, t3);
11070 tcg_gen_ext32s_tl(t4, t4);
11071 tcg_gen_xor_tl(t2, t2, t3);
11072 tcg_gen_xor_tl(t3, t4, t3);
11073 tcg_gen_andc_tl(t2, t3, t2);
11074 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11075 tcg_gen_or_tl(t4, t4, input_overflow);
11076 if (opc == OPC_BOVC) {
11077 /* OPC_BOVC */
11078 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11079 } else {
11080 /* OPC_BNVC */
11081 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11083 tcg_temp_free(input_overflow);
11084 tcg_temp_free(t4);
11085 tcg_temp_free(t3);
11086 tcg_temp_free(t2);
11087 } else if (rs < rt && rs == 0) {
11088 /* OPC_BEQZALC, OPC_BNEZALC */
11089 if (opc == OPC_BEQZALC) {
11090 /* OPC_BEQZALC */
11091 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11092 } else {
11093 /* OPC_BNEZALC */
11094 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11096 } else {
11097 /* OPC_BEQC, OPC_BNEC */
11098 if (opc == OPC_BEQC) {
11099 /* OPC_BEQC */
11100 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11101 } else {
11102 /* OPC_BNEC */
11103 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11106 break;
11107 case OPC_BEQZC:
11108 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11109 break;
11110 case OPC_BNEZC:
11111 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11112 break;
11113 default:
11114 MIPS_INVAL("Compact conditional branch/jump");
11115 generate_exception_end(ctx, EXCP_RI);
11116 goto out;
11119 /* Generating branch here as compact branches don't have delay slot */
11120 gen_goto_tb(ctx, 1, ctx->btarget);
11121 gen_set_label(fs);
11123 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11126 out:
11127 tcg_temp_free(t0);
11128 tcg_temp_free(t1);
11131 /* ISA extensions (ASEs) */
11132 /* MIPS16 extension to MIPS32 */
11134 /* MIPS16 major opcodes */
11135 enum {
11136 M16_OPC_ADDIUSP = 0x00,
11137 M16_OPC_ADDIUPC = 0x01,
11138 M16_OPC_B = 0x02,
11139 M16_OPC_JAL = 0x03,
11140 M16_OPC_BEQZ = 0x04,
11141 M16_OPC_BNEQZ = 0x05,
11142 M16_OPC_SHIFT = 0x06,
11143 M16_OPC_LD = 0x07,
11144 M16_OPC_RRIA = 0x08,
11145 M16_OPC_ADDIU8 = 0x09,
11146 M16_OPC_SLTI = 0x0a,
11147 M16_OPC_SLTIU = 0x0b,
11148 M16_OPC_I8 = 0x0c,
11149 M16_OPC_LI = 0x0d,
11150 M16_OPC_CMPI = 0x0e,
11151 M16_OPC_SD = 0x0f,
11152 M16_OPC_LB = 0x10,
11153 M16_OPC_LH = 0x11,
11154 M16_OPC_LWSP = 0x12,
11155 M16_OPC_LW = 0x13,
11156 M16_OPC_LBU = 0x14,
11157 M16_OPC_LHU = 0x15,
11158 M16_OPC_LWPC = 0x16,
11159 M16_OPC_LWU = 0x17,
11160 M16_OPC_SB = 0x18,
11161 M16_OPC_SH = 0x19,
11162 M16_OPC_SWSP = 0x1a,
11163 M16_OPC_SW = 0x1b,
11164 M16_OPC_RRR = 0x1c,
11165 M16_OPC_RR = 0x1d,
11166 M16_OPC_EXTEND = 0x1e,
11167 M16_OPC_I64 = 0x1f
11170 /* I8 funct field */
11171 enum {
11172 I8_BTEQZ = 0x0,
11173 I8_BTNEZ = 0x1,
11174 I8_SWRASP = 0x2,
11175 I8_ADJSP = 0x3,
11176 I8_SVRS = 0x4,
11177 I8_MOV32R = 0x5,
11178 I8_MOVR32 = 0x7
11181 /* RRR f field */
11182 enum {
11183 RRR_DADDU = 0x0,
11184 RRR_ADDU = 0x1,
11185 RRR_DSUBU = 0x2,
11186 RRR_SUBU = 0x3
11189 /* RR funct field */
11190 enum {
11191 RR_JR = 0x00,
11192 RR_SDBBP = 0x01,
11193 RR_SLT = 0x02,
11194 RR_SLTU = 0x03,
11195 RR_SLLV = 0x04,
11196 RR_BREAK = 0x05,
11197 RR_SRLV = 0x06,
11198 RR_SRAV = 0x07,
11199 RR_DSRL = 0x08,
11200 RR_CMP = 0x0a,
11201 RR_NEG = 0x0b,
11202 RR_AND = 0x0c,
11203 RR_OR = 0x0d,
11204 RR_XOR = 0x0e,
11205 RR_NOT = 0x0f,
11206 RR_MFHI = 0x10,
11207 RR_CNVT = 0x11,
11208 RR_MFLO = 0x12,
11209 RR_DSRA = 0x13,
11210 RR_DSLLV = 0x14,
11211 RR_DSRLV = 0x16,
11212 RR_DSRAV = 0x17,
11213 RR_MULT = 0x18,
11214 RR_MULTU = 0x19,
11215 RR_DIV = 0x1a,
11216 RR_DIVU = 0x1b,
11217 RR_DMULT = 0x1c,
11218 RR_DMULTU = 0x1d,
11219 RR_DDIV = 0x1e,
11220 RR_DDIVU = 0x1f
11223 /* I64 funct field */
11224 enum {
11225 I64_LDSP = 0x0,
11226 I64_SDSP = 0x1,
11227 I64_SDRASP = 0x2,
11228 I64_DADJSP = 0x3,
11229 I64_LDPC = 0x4,
11230 I64_DADDIU5 = 0x5,
11231 I64_DADDIUPC = 0x6,
11232 I64_DADDIUSP = 0x7
11235 /* RR ry field for CNVT */
11236 enum {
11237 RR_RY_CNVT_ZEB = 0x0,
11238 RR_RY_CNVT_ZEH = 0x1,
11239 RR_RY_CNVT_ZEW = 0x2,
11240 RR_RY_CNVT_SEB = 0x4,
11241 RR_RY_CNVT_SEH = 0x5,
11242 RR_RY_CNVT_SEW = 0x6,
11245 static int xlat (int r)
11247 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11249 return map[r];
11252 static void gen_mips16_save (DisasContext *ctx,
11253 int xsregs, int aregs,
11254 int do_ra, int do_s0, int do_s1,
11255 int framesize)
11257 TCGv t0 = tcg_temp_new();
11258 TCGv t1 = tcg_temp_new();
11259 TCGv t2 = tcg_temp_new();
11260 int args, astatic;
11262 switch (aregs) {
11263 case 0:
11264 case 1:
11265 case 2:
11266 case 3:
11267 case 11:
11268 args = 0;
11269 break;
11270 case 4:
11271 case 5:
11272 case 6:
11273 case 7:
11274 args = 1;
11275 break;
11276 case 8:
11277 case 9:
11278 case 10:
11279 args = 2;
11280 break;
11281 case 12:
11282 case 13:
11283 args = 3;
11284 break;
11285 case 14:
11286 args = 4;
11287 break;
11288 default:
11289 generate_exception_end(ctx, EXCP_RI);
11290 return;
11293 switch (args) {
11294 case 4:
11295 gen_base_offset_addr(ctx, t0, 29, 12);
11296 gen_load_gpr(t1, 7);
11297 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11298 /* Fall through */
11299 case 3:
11300 gen_base_offset_addr(ctx, t0, 29, 8);
11301 gen_load_gpr(t1, 6);
11302 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11303 /* Fall through */
11304 case 2:
11305 gen_base_offset_addr(ctx, t0, 29, 4);
11306 gen_load_gpr(t1, 5);
11307 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11308 /* Fall through */
11309 case 1:
11310 gen_base_offset_addr(ctx, t0, 29, 0);
11311 gen_load_gpr(t1, 4);
11312 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11315 gen_load_gpr(t0, 29);
11317 #define DECR_AND_STORE(reg) do { \
11318 tcg_gen_movi_tl(t2, -4); \
11319 gen_op_addr_add(ctx, t0, t0, t2); \
11320 gen_load_gpr(t1, reg); \
11321 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
11322 } while (0)
11324 if (do_ra) {
11325 DECR_AND_STORE(31);
11328 switch (xsregs) {
11329 case 7:
11330 DECR_AND_STORE(30);
11331 /* Fall through */
11332 case 6:
11333 DECR_AND_STORE(23);
11334 /* Fall through */
11335 case 5:
11336 DECR_AND_STORE(22);
11337 /* Fall through */
11338 case 4:
11339 DECR_AND_STORE(21);
11340 /* Fall through */
11341 case 3:
11342 DECR_AND_STORE(20);
11343 /* Fall through */
11344 case 2:
11345 DECR_AND_STORE(19);
11346 /* Fall through */
11347 case 1:
11348 DECR_AND_STORE(18);
11351 if (do_s1) {
11352 DECR_AND_STORE(17);
11354 if (do_s0) {
11355 DECR_AND_STORE(16);
11358 switch (aregs) {
11359 case 0:
11360 case 4:
11361 case 8:
11362 case 12:
11363 case 14:
11364 astatic = 0;
11365 break;
11366 case 1:
11367 case 5:
11368 case 9:
11369 case 13:
11370 astatic = 1;
11371 break;
11372 case 2:
11373 case 6:
11374 case 10:
11375 astatic = 2;
11376 break;
11377 case 3:
11378 case 7:
11379 astatic = 3;
11380 break;
11381 case 11:
11382 astatic = 4;
11383 break;
11384 default:
11385 generate_exception_end(ctx, EXCP_RI);
11386 return;
11389 if (astatic > 0) {
11390 DECR_AND_STORE(7);
11391 if (astatic > 1) {
11392 DECR_AND_STORE(6);
11393 if (astatic > 2) {
11394 DECR_AND_STORE(5);
11395 if (astatic > 3) {
11396 DECR_AND_STORE(4);
11401 #undef DECR_AND_STORE
11403 tcg_gen_movi_tl(t2, -framesize);
11404 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11405 tcg_temp_free(t0);
11406 tcg_temp_free(t1);
11407 tcg_temp_free(t2);
11410 static void gen_mips16_restore (DisasContext *ctx,
11411 int xsregs, int aregs,
11412 int do_ra, int do_s0, int do_s1,
11413 int framesize)
11415 int astatic;
11416 TCGv t0 = tcg_temp_new();
11417 TCGv t1 = tcg_temp_new();
11418 TCGv t2 = tcg_temp_new();
11420 tcg_gen_movi_tl(t2, framesize);
11421 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
11423 #define DECR_AND_LOAD(reg) do { \
11424 tcg_gen_movi_tl(t2, -4); \
11425 gen_op_addr_add(ctx, t0, t0, t2); \
11426 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
11427 gen_store_gpr(t1, reg); \
11428 } while (0)
11430 if (do_ra) {
11431 DECR_AND_LOAD(31);
11434 switch (xsregs) {
11435 case 7:
11436 DECR_AND_LOAD(30);
11437 /* Fall through */
11438 case 6:
11439 DECR_AND_LOAD(23);
11440 /* Fall through */
11441 case 5:
11442 DECR_AND_LOAD(22);
11443 /* Fall through */
11444 case 4:
11445 DECR_AND_LOAD(21);
11446 /* Fall through */
11447 case 3:
11448 DECR_AND_LOAD(20);
11449 /* Fall through */
11450 case 2:
11451 DECR_AND_LOAD(19);
11452 /* Fall through */
11453 case 1:
11454 DECR_AND_LOAD(18);
11457 if (do_s1) {
11458 DECR_AND_LOAD(17);
11460 if (do_s0) {
11461 DECR_AND_LOAD(16);
11464 switch (aregs) {
11465 case 0:
11466 case 4:
11467 case 8:
11468 case 12:
11469 case 14:
11470 astatic = 0;
11471 break;
11472 case 1:
11473 case 5:
11474 case 9:
11475 case 13:
11476 astatic = 1;
11477 break;
11478 case 2:
11479 case 6:
11480 case 10:
11481 astatic = 2;
11482 break;
11483 case 3:
11484 case 7:
11485 astatic = 3;
11486 break;
11487 case 11:
11488 astatic = 4;
11489 break;
11490 default:
11491 generate_exception_end(ctx, EXCP_RI);
11492 return;
11495 if (astatic > 0) {
11496 DECR_AND_LOAD(7);
11497 if (astatic > 1) {
11498 DECR_AND_LOAD(6);
11499 if (astatic > 2) {
11500 DECR_AND_LOAD(5);
11501 if (astatic > 3) {
11502 DECR_AND_LOAD(4);
11507 #undef DECR_AND_LOAD
11509 tcg_gen_movi_tl(t2, framesize);
11510 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
11511 tcg_temp_free(t0);
11512 tcg_temp_free(t1);
11513 tcg_temp_free(t2);
11516 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
11517 int is_64_bit, int extended)
11519 TCGv t0;
11521 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11522 generate_exception_end(ctx, EXCP_RI);
11523 return;
11526 t0 = tcg_temp_new();
11528 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
11529 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
11530 if (!is_64_bit) {
11531 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11534 tcg_temp_free(t0);
11537 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11538 int16_t offset)
11540 TCGv_i32 t0 = tcg_const_i32(op);
11541 TCGv t1 = tcg_temp_new();
11542 gen_base_offset_addr(ctx, t1, base, offset);
11543 gen_helper_cache(cpu_env, t1, t0);
11546 #if defined(TARGET_MIPS64)
11547 static void decode_i64_mips16 (DisasContext *ctx,
11548 int ry, int funct, int16_t offset,
11549 int extended)
11551 switch (funct) {
11552 case I64_LDSP:
11553 check_insn(ctx, ISA_MIPS3);
11554 check_mips_64(ctx);
11555 offset = extended ? offset : offset << 3;
11556 gen_ld(ctx, OPC_LD, ry, 29, offset);
11557 break;
11558 case I64_SDSP:
11559 check_insn(ctx, ISA_MIPS3);
11560 check_mips_64(ctx);
11561 offset = extended ? offset : offset << 3;
11562 gen_st(ctx, OPC_SD, ry, 29, offset);
11563 break;
11564 case I64_SDRASP:
11565 check_insn(ctx, ISA_MIPS3);
11566 check_mips_64(ctx);
11567 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
11568 gen_st(ctx, OPC_SD, 31, 29, offset);
11569 break;
11570 case I64_DADJSP:
11571 check_insn(ctx, ISA_MIPS3);
11572 check_mips_64(ctx);
11573 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
11574 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
11575 break;
11576 case I64_LDPC:
11577 check_insn(ctx, ISA_MIPS3);
11578 check_mips_64(ctx);
11579 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11580 generate_exception_end(ctx, EXCP_RI);
11581 } else {
11582 offset = extended ? offset : offset << 3;
11583 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
11585 break;
11586 case I64_DADDIU5:
11587 check_insn(ctx, ISA_MIPS3);
11588 check_mips_64(ctx);
11589 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
11590 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
11591 break;
11592 case I64_DADDIUPC:
11593 check_insn(ctx, ISA_MIPS3);
11594 check_mips_64(ctx);
11595 offset = extended ? offset : offset << 2;
11596 gen_addiupc(ctx, ry, offset, 1, extended);
11597 break;
11598 case I64_DADDIUSP:
11599 check_insn(ctx, ISA_MIPS3);
11600 check_mips_64(ctx);
11601 offset = extended ? offset : offset << 2;
11602 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
11603 break;
11606 #endif
11608 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11610 int extend = cpu_lduw_code(env, ctx->pc + 2);
11611 int op, rx, ry, funct, sa;
11612 int16_t imm, offset;
11614 ctx->opcode = (ctx->opcode << 16) | extend;
11615 op = (ctx->opcode >> 11) & 0x1f;
11616 sa = (ctx->opcode >> 22) & 0x1f;
11617 funct = (ctx->opcode >> 8) & 0x7;
11618 rx = xlat((ctx->opcode >> 8) & 0x7);
11619 ry = xlat((ctx->opcode >> 5) & 0x7);
11620 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
11621 | ((ctx->opcode >> 21) & 0x3f) << 5
11622 | (ctx->opcode & 0x1f));
11624 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
11625 counterparts. */
11626 switch (op) {
11627 case M16_OPC_ADDIUSP:
11628 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11629 break;
11630 case M16_OPC_ADDIUPC:
11631 gen_addiupc(ctx, rx, imm, 0, 1);
11632 break;
11633 case M16_OPC_B:
11634 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
11635 /* No delay slot, so just process as a normal instruction */
11636 break;
11637 case M16_OPC_BEQZ:
11638 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
11639 /* No delay slot, so just process as a normal instruction */
11640 break;
11641 case M16_OPC_BNEQZ:
11642 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
11643 /* No delay slot, so just process as a normal instruction */
11644 break;
11645 case M16_OPC_SHIFT:
11646 switch (ctx->opcode & 0x3) {
11647 case 0x0:
11648 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11649 break;
11650 case 0x1:
11651 #if defined(TARGET_MIPS64)
11652 check_mips_64(ctx);
11653 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11654 #else
11655 generate_exception_end(ctx, EXCP_RI);
11656 #endif
11657 break;
11658 case 0x2:
11659 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11660 break;
11661 case 0x3:
11662 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11663 break;
11665 break;
11666 #if defined(TARGET_MIPS64)
11667 case M16_OPC_LD:
11668 check_insn(ctx, ISA_MIPS3);
11669 check_mips_64(ctx);
11670 gen_ld(ctx, OPC_LD, ry, rx, offset);
11671 break;
11672 #endif
11673 case M16_OPC_RRIA:
11674 imm = ctx->opcode & 0xf;
11675 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
11676 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
11677 imm = (int16_t) (imm << 1) >> 1;
11678 if ((ctx->opcode >> 4) & 0x1) {
11679 #if defined(TARGET_MIPS64)
11680 check_mips_64(ctx);
11681 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11682 #else
11683 generate_exception_end(ctx, EXCP_RI);
11684 #endif
11685 } else {
11686 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11688 break;
11689 case M16_OPC_ADDIU8:
11690 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11691 break;
11692 case M16_OPC_SLTI:
11693 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11694 break;
11695 case M16_OPC_SLTIU:
11696 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11697 break;
11698 case M16_OPC_I8:
11699 switch (funct) {
11700 case I8_BTEQZ:
11701 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
11702 break;
11703 case I8_BTNEZ:
11704 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
11705 break;
11706 case I8_SWRASP:
11707 gen_st(ctx, OPC_SW, 31, 29, imm);
11708 break;
11709 case I8_ADJSP:
11710 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
11711 break;
11712 case I8_SVRS:
11713 check_insn(ctx, ISA_MIPS32);
11715 int xsregs = (ctx->opcode >> 24) & 0x7;
11716 int aregs = (ctx->opcode >> 16) & 0xf;
11717 int do_ra = (ctx->opcode >> 6) & 0x1;
11718 int do_s0 = (ctx->opcode >> 5) & 0x1;
11719 int do_s1 = (ctx->opcode >> 4) & 0x1;
11720 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
11721 | (ctx->opcode & 0xf)) << 3;
11723 if (ctx->opcode & (1 << 7)) {
11724 gen_mips16_save(ctx, xsregs, aregs,
11725 do_ra, do_s0, do_s1,
11726 framesize);
11727 } else {
11728 gen_mips16_restore(ctx, xsregs, aregs,
11729 do_ra, do_s0, do_s1,
11730 framesize);
11733 break;
11734 default:
11735 generate_exception_end(ctx, EXCP_RI);
11736 break;
11738 break;
11739 case M16_OPC_LI:
11740 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
11741 break;
11742 case M16_OPC_CMPI:
11743 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
11744 break;
11745 #if defined(TARGET_MIPS64)
11746 case M16_OPC_SD:
11747 check_insn(ctx, ISA_MIPS3);
11748 check_mips_64(ctx);
11749 gen_st(ctx, OPC_SD, ry, rx, offset);
11750 break;
11751 #endif
11752 case M16_OPC_LB:
11753 gen_ld(ctx, OPC_LB, ry, rx, offset);
11754 break;
11755 case M16_OPC_LH:
11756 gen_ld(ctx, OPC_LH, ry, rx, offset);
11757 break;
11758 case M16_OPC_LWSP:
11759 gen_ld(ctx, OPC_LW, rx, 29, offset);
11760 break;
11761 case M16_OPC_LW:
11762 gen_ld(ctx, OPC_LW, ry, rx, offset);
11763 break;
11764 case M16_OPC_LBU:
11765 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11766 break;
11767 case M16_OPC_LHU:
11768 gen_ld(ctx, OPC_LHU, ry, rx, offset);
11769 break;
11770 case M16_OPC_LWPC:
11771 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
11772 break;
11773 #if defined(TARGET_MIPS64)
11774 case M16_OPC_LWU:
11775 check_insn(ctx, ISA_MIPS3);
11776 check_mips_64(ctx);
11777 gen_ld(ctx, OPC_LWU, ry, rx, offset);
11778 break;
11779 #endif
11780 case M16_OPC_SB:
11781 gen_st(ctx, OPC_SB, ry, rx, offset);
11782 break;
11783 case M16_OPC_SH:
11784 gen_st(ctx, OPC_SH, ry, rx, offset);
11785 break;
11786 case M16_OPC_SWSP:
11787 gen_st(ctx, OPC_SW, rx, 29, offset);
11788 break;
11789 case M16_OPC_SW:
11790 gen_st(ctx, OPC_SW, ry, rx, offset);
11791 break;
11792 #if defined(TARGET_MIPS64)
11793 case M16_OPC_I64:
11794 decode_i64_mips16(ctx, ry, funct, offset, 1);
11795 break;
11796 #endif
11797 default:
11798 generate_exception_end(ctx, EXCP_RI);
11799 break;
11802 return 4;
11805 static inline bool is_uhi(int sdbbp_code)
11807 #ifdef CONFIG_USER_ONLY
11808 return false;
11809 #else
11810 return semihosting_enabled() && sdbbp_code == 1;
11811 #endif
11814 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
11816 int rx, ry;
11817 int sa;
11818 int op, cnvt_op, op1, offset;
11819 int funct;
11820 int n_bytes;
11822 op = (ctx->opcode >> 11) & 0x1f;
11823 sa = (ctx->opcode >> 2) & 0x7;
11824 sa = sa == 0 ? 8 : sa;
11825 rx = xlat((ctx->opcode >> 8) & 0x7);
11826 cnvt_op = (ctx->opcode >> 5) & 0x7;
11827 ry = xlat((ctx->opcode >> 5) & 0x7);
11828 op1 = offset = ctx->opcode & 0x1f;
11830 n_bytes = 2;
11832 switch (op) {
11833 case M16_OPC_ADDIUSP:
11835 int16_t imm = ((uint8_t) ctx->opcode) << 2;
11837 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
11839 break;
11840 case M16_OPC_ADDIUPC:
11841 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
11842 break;
11843 case M16_OPC_B:
11844 offset = (ctx->opcode & 0x7ff) << 1;
11845 offset = (int16_t)(offset << 4) >> 4;
11846 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
11847 /* No delay slot, so just process as a normal instruction */
11848 break;
11849 case M16_OPC_JAL:
11850 offset = cpu_lduw_code(env, ctx->pc + 2);
11851 offset = (((ctx->opcode & 0x1f) << 21)
11852 | ((ctx->opcode >> 5) & 0x1f) << 16
11853 | offset) << 2;
11854 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
11855 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
11856 n_bytes = 4;
11857 break;
11858 case M16_OPC_BEQZ:
11859 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
11860 ((int8_t)ctx->opcode) << 1, 0);
11861 /* No delay slot, so just process as a normal instruction */
11862 break;
11863 case M16_OPC_BNEQZ:
11864 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
11865 ((int8_t)ctx->opcode) << 1, 0);
11866 /* No delay slot, so just process as a normal instruction */
11867 break;
11868 case M16_OPC_SHIFT:
11869 switch (ctx->opcode & 0x3) {
11870 case 0x0:
11871 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
11872 break;
11873 case 0x1:
11874 #if defined(TARGET_MIPS64)
11875 check_insn(ctx, ISA_MIPS3);
11876 check_mips_64(ctx);
11877 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
11878 #else
11879 generate_exception_end(ctx, EXCP_RI);
11880 #endif
11881 break;
11882 case 0x2:
11883 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
11884 break;
11885 case 0x3:
11886 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
11887 break;
11889 break;
11890 #if defined(TARGET_MIPS64)
11891 case M16_OPC_LD:
11892 check_insn(ctx, ISA_MIPS3);
11893 check_mips_64(ctx);
11894 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
11895 break;
11896 #endif
11897 case M16_OPC_RRIA:
11899 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
11901 if ((ctx->opcode >> 4) & 1) {
11902 #if defined(TARGET_MIPS64)
11903 check_insn(ctx, ISA_MIPS3);
11904 check_mips_64(ctx);
11905 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
11906 #else
11907 generate_exception_end(ctx, EXCP_RI);
11908 #endif
11909 } else {
11910 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
11913 break;
11914 case M16_OPC_ADDIU8:
11916 int16_t imm = (int8_t) ctx->opcode;
11918 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
11920 break;
11921 case M16_OPC_SLTI:
11923 int16_t imm = (uint8_t) ctx->opcode;
11924 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
11926 break;
11927 case M16_OPC_SLTIU:
11929 int16_t imm = (uint8_t) ctx->opcode;
11930 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
11932 break;
11933 case M16_OPC_I8:
11935 int reg32;
11937 funct = (ctx->opcode >> 8) & 0x7;
11938 switch (funct) {
11939 case I8_BTEQZ:
11940 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
11941 ((int8_t)ctx->opcode) << 1, 0);
11942 break;
11943 case I8_BTNEZ:
11944 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11945 ((int8_t)ctx->opcode) << 1, 0);
11946 break;
11947 case I8_SWRASP:
11948 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11949 break;
11950 case I8_ADJSP:
11951 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11952 ((int8_t)ctx->opcode) << 3);
11953 break;
11954 case I8_SVRS:
11955 check_insn(ctx, ISA_MIPS32);
11957 int do_ra = ctx->opcode & (1 << 6);
11958 int do_s0 = ctx->opcode & (1 << 5);
11959 int do_s1 = ctx->opcode & (1 << 4);
11960 int framesize = ctx->opcode & 0xf;
11962 if (framesize == 0) {
11963 framesize = 128;
11964 } else {
11965 framesize = framesize << 3;
11968 if (ctx->opcode & (1 << 7)) {
11969 gen_mips16_save(ctx, 0, 0,
11970 do_ra, do_s0, do_s1, framesize);
11971 } else {
11972 gen_mips16_restore(ctx, 0, 0,
11973 do_ra, do_s0, do_s1, framesize);
11976 break;
11977 case I8_MOV32R:
11979 int rz = xlat(ctx->opcode & 0x7);
11981 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11982 ((ctx->opcode >> 5) & 0x7);
11983 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11985 break;
11986 case I8_MOVR32:
11987 reg32 = ctx->opcode & 0x1f;
11988 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11989 break;
11990 default:
11991 generate_exception_end(ctx, EXCP_RI);
11992 break;
11995 break;
11996 case M16_OPC_LI:
11998 int16_t imm = (uint8_t) ctx->opcode;
12000 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
12002 break;
12003 case M16_OPC_CMPI:
12005 int16_t imm = (uint8_t) ctx->opcode;
12006 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
12008 break;
12009 #if defined(TARGET_MIPS64)
12010 case M16_OPC_SD:
12011 check_insn(ctx, ISA_MIPS3);
12012 check_mips_64(ctx);
12013 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
12014 break;
12015 #endif
12016 case M16_OPC_LB:
12017 gen_ld(ctx, OPC_LB, ry, rx, offset);
12018 break;
12019 case M16_OPC_LH:
12020 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
12021 break;
12022 case M16_OPC_LWSP:
12023 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12024 break;
12025 case M16_OPC_LW:
12026 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
12027 break;
12028 case M16_OPC_LBU:
12029 gen_ld(ctx, OPC_LBU, ry, rx, offset);
12030 break;
12031 case M16_OPC_LHU:
12032 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
12033 break;
12034 case M16_OPC_LWPC:
12035 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
12036 break;
12037 #if defined (TARGET_MIPS64)
12038 case M16_OPC_LWU:
12039 check_insn(ctx, ISA_MIPS3);
12040 check_mips_64(ctx);
12041 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
12042 break;
12043 #endif
12044 case M16_OPC_SB:
12045 gen_st(ctx, OPC_SB, ry, rx, offset);
12046 break;
12047 case M16_OPC_SH:
12048 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
12049 break;
12050 case M16_OPC_SWSP:
12051 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
12052 break;
12053 case M16_OPC_SW:
12054 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
12055 break;
12056 case M16_OPC_RRR:
12058 int rz = xlat((ctx->opcode >> 2) & 0x7);
12059 int mips32_op;
12061 switch (ctx->opcode & 0x3) {
12062 case RRR_ADDU:
12063 mips32_op = OPC_ADDU;
12064 break;
12065 case RRR_SUBU:
12066 mips32_op = OPC_SUBU;
12067 break;
12068 #if defined(TARGET_MIPS64)
12069 case RRR_DADDU:
12070 mips32_op = OPC_DADDU;
12071 check_insn(ctx, ISA_MIPS3);
12072 check_mips_64(ctx);
12073 break;
12074 case RRR_DSUBU:
12075 mips32_op = OPC_DSUBU;
12076 check_insn(ctx, ISA_MIPS3);
12077 check_mips_64(ctx);
12078 break;
12079 #endif
12080 default:
12081 generate_exception_end(ctx, EXCP_RI);
12082 goto done;
12085 gen_arith(ctx, mips32_op, rz, rx, ry);
12086 done:
12089 break;
12090 case M16_OPC_RR:
12091 switch (op1) {
12092 case RR_JR:
12094 int nd = (ctx->opcode >> 7) & 0x1;
12095 int link = (ctx->opcode >> 6) & 0x1;
12096 int ra = (ctx->opcode >> 5) & 0x1;
12098 if (nd) {
12099 check_insn(ctx, ISA_MIPS32);
12102 if (link) {
12103 op = OPC_JALR;
12104 } else {
12105 op = OPC_JR;
12108 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
12109 (nd ? 0 : 2));
12111 break;
12112 case RR_SDBBP:
12113 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
12114 gen_helper_do_semihosting(cpu_env);
12115 } else {
12116 /* XXX: not clear which exception should be raised
12117 * when in debug mode...
12119 check_insn(ctx, ISA_MIPS32);
12120 generate_exception_end(ctx, EXCP_DBp);
12122 break;
12123 case RR_SLT:
12124 gen_slt(ctx, OPC_SLT, 24, rx, ry);
12125 break;
12126 case RR_SLTU:
12127 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
12128 break;
12129 case RR_BREAK:
12130 generate_exception_end(ctx, EXCP_BREAK);
12131 break;
12132 case RR_SLLV:
12133 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
12134 break;
12135 case RR_SRLV:
12136 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
12137 break;
12138 case RR_SRAV:
12139 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
12140 break;
12141 #if defined (TARGET_MIPS64)
12142 case RR_DSRL:
12143 check_insn(ctx, ISA_MIPS3);
12144 check_mips_64(ctx);
12145 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
12146 break;
12147 #endif
12148 case RR_CMP:
12149 gen_logic(ctx, OPC_XOR, 24, rx, ry);
12150 break;
12151 case RR_NEG:
12152 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
12153 break;
12154 case RR_AND:
12155 gen_logic(ctx, OPC_AND, rx, rx, ry);
12156 break;
12157 case RR_OR:
12158 gen_logic(ctx, OPC_OR, rx, rx, ry);
12159 break;
12160 case RR_XOR:
12161 gen_logic(ctx, OPC_XOR, rx, rx, ry);
12162 break;
12163 case RR_NOT:
12164 gen_logic(ctx, OPC_NOR, rx, ry, 0);
12165 break;
12166 case RR_MFHI:
12167 gen_HILO(ctx, OPC_MFHI, 0, rx);
12168 break;
12169 case RR_CNVT:
12170 check_insn(ctx, ISA_MIPS32);
12171 switch (cnvt_op) {
12172 case RR_RY_CNVT_ZEB:
12173 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12174 break;
12175 case RR_RY_CNVT_ZEH:
12176 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12177 break;
12178 case RR_RY_CNVT_SEB:
12179 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12180 break;
12181 case RR_RY_CNVT_SEH:
12182 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12183 break;
12184 #if defined (TARGET_MIPS64)
12185 case RR_RY_CNVT_ZEW:
12186 check_insn(ctx, ISA_MIPS64);
12187 check_mips_64(ctx);
12188 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
12189 break;
12190 case RR_RY_CNVT_SEW:
12191 check_insn(ctx, ISA_MIPS64);
12192 check_mips_64(ctx);
12193 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12194 break;
12195 #endif
12196 default:
12197 generate_exception_end(ctx, EXCP_RI);
12198 break;
12200 break;
12201 case RR_MFLO:
12202 gen_HILO(ctx, OPC_MFLO, 0, rx);
12203 break;
12204 #if defined (TARGET_MIPS64)
12205 case RR_DSRA:
12206 check_insn(ctx, ISA_MIPS3);
12207 check_mips_64(ctx);
12208 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
12209 break;
12210 case RR_DSLLV:
12211 check_insn(ctx, ISA_MIPS3);
12212 check_mips_64(ctx);
12213 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
12214 break;
12215 case RR_DSRLV:
12216 check_insn(ctx, ISA_MIPS3);
12217 check_mips_64(ctx);
12218 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
12219 break;
12220 case RR_DSRAV:
12221 check_insn(ctx, ISA_MIPS3);
12222 check_mips_64(ctx);
12223 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
12224 break;
12225 #endif
12226 case RR_MULT:
12227 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
12228 break;
12229 case RR_MULTU:
12230 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
12231 break;
12232 case RR_DIV:
12233 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
12234 break;
12235 case RR_DIVU:
12236 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
12237 break;
12238 #if defined (TARGET_MIPS64)
12239 case RR_DMULT:
12240 check_insn(ctx, ISA_MIPS3);
12241 check_mips_64(ctx);
12242 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
12243 break;
12244 case RR_DMULTU:
12245 check_insn(ctx, ISA_MIPS3);
12246 check_mips_64(ctx);
12247 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
12248 break;
12249 case RR_DDIV:
12250 check_insn(ctx, ISA_MIPS3);
12251 check_mips_64(ctx);
12252 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
12253 break;
12254 case RR_DDIVU:
12255 check_insn(ctx, ISA_MIPS3);
12256 check_mips_64(ctx);
12257 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
12258 break;
12259 #endif
12260 default:
12261 generate_exception_end(ctx, EXCP_RI);
12262 break;
12264 break;
12265 case M16_OPC_EXTEND:
12266 decode_extended_mips16_opc(env, ctx);
12267 n_bytes = 4;
12268 break;
12269 #if defined(TARGET_MIPS64)
12270 case M16_OPC_I64:
12271 funct = (ctx->opcode >> 8) & 0x7;
12272 decode_i64_mips16(ctx, ry, funct, offset, 0);
12273 break;
12274 #endif
12275 default:
12276 generate_exception_end(ctx, EXCP_RI);
12277 break;
12280 return n_bytes;
12283 /* microMIPS extension to MIPS32/MIPS64 */
12286 * microMIPS32/microMIPS64 major opcodes
12288 * 1. MIPS Architecture for Programmers Volume II-B:
12289 * The microMIPS32 Instruction Set (Revision 3.05)
12291 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
12293 * 2. MIPS Architecture For Programmers Volume II-A:
12294 * The MIPS64 Instruction Set (Revision 3.51)
12297 enum {
12298 POOL32A = 0x00,
12299 POOL16A = 0x01,
12300 LBU16 = 0x02,
12301 MOVE16 = 0x03,
12302 ADDI32 = 0x04,
12303 R6_LUI = 0x04,
12304 AUI = 0x04,
12305 LBU32 = 0x05,
12306 SB32 = 0x06,
12307 LB32 = 0x07,
12309 POOL32B = 0x08,
12310 POOL16B = 0x09,
12311 LHU16 = 0x0a,
12312 ANDI16 = 0x0b,
12313 ADDIU32 = 0x0c,
12314 LHU32 = 0x0d,
12315 SH32 = 0x0e,
12316 LH32 = 0x0f,
12318 POOL32I = 0x10,
12319 POOL16C = 0x11,
12320 LWSP16 = 0x12,
12321 POOL16D = 0x13,
12322 ORI32 = 0x14,
12323 POOL32F = 0x15,
12324 POOL32S = 0x16, /* MIPS64 */
12325 DADDIU32 = 0x17, /* MIPS64 */
12327 POOL32C = 0x18,
12328 LWGP16 = 0x19,
12329 LW16 = 0x1a,
12330 POOL16E = 0x1b,
12331 XORI32 = 0x1c,
12332 JALS32 = 0x1d,
12333 BOVC = 0x1d,
12334 BEQC = 0x1d,
12335 BEQZALC = 0x1d,
12336 ADDIUPC = 0x1e,
12337 PCREL = 0x1e,
12338 BNVC = 0x1f,
12339 BNEC = 0x1f,
12340 BNEZALC = 0x1f,
12342 R6_BEQZC = 0x20,
12343 JIC = 0x20,
12344 POOL16F = 0x21,
12345 SB16 = 0x22,
12346 BEQZ16 = 0x23,
12347 BEQZC16 = 0x23,
12348 SLTI32 = 0x24,
12349 BEQ32 = 0x25,
12350 BC = 0x25,
12351 SWC132 = 0x26,
12352 LWC132 = 0x27,
12354 /* 0x29 is reserved */
12355 RES_29 = 0x29,
12356 R6_BNEZC = 0x28,
12357 JIALC = 0x28,
12358 SH16 = 0x2a,
12359 BNEZ16 = 0x2b,
12360 BNEZC16 = 0x2b,
12361 SLTIU32 = 0x2c,
12362 BNE32 = 0x2d,
12363 BALC = 0x2d,
12364 SDC132 = 0x2e,
12365 LDC132 = 0x2f,
12367 /* 0x31 is reserved */
12368 RES_31 = 0x31,
12369 BLEZALC = 0x30,
12370 BGEZALC = 0x30,
12371 BGEUC = 0x30,
12372 SWSP16 = 0x32,
12373 B16 = 0x33,
12374 BC16 = 0x33,
12375 ANDI32 = 0x34,
12376 J32 = 0x35,
12377 BGTZC = 0x35,
12378 BLTZC = 0x35,
12379 BLTC = 0x35,
12380 SD32 = 0x36, /* MIPS64 */
12381 LD32 = 0x37, /* MIPS64 */
12383 /* 0x39 is reserved */
12384 RES_39 = 0x39,
12385 BGTZALC = 0x38,
12386 BLTZALC = 0x38,
12387 BLTUC = 0x38,
12388 SW16 = 0x3a,
12389 LI16 = 0x3b,
12390 JALX32 = 0x3c,
12391 JAL32 = 0x3d,
12392 BLEZC = 0x3d,
12393 BGEZC = 0x3d,
12394 BGEC = 0x3d,
12395 SW32 = 0x3e,
12396 LW32 = 0x3f
12399 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
12400 enum {
12401 ADDIUPC_00 = 0x00,
12402 ADDIUPC_07 = 0x07,
12403 AUIPC = 0x1e,
12404 ALUIPC = 0x1f,
12405 LWPC_08 = 0x08,
12406 LWPC_0F = 0x0F,
12409 /* POOL32A encoding of minor opcode field */
12411 enum {
12412 /* These opcodes are distinguished only by bits 9..6; those bits are
12413 * what are recorded below. */
12414 SLL32 = 0x0,
12415 SRL32 = 0x1,
12416 SRA = 0x2,
12417 ROTR = 0x3,
12418 SELEQZ = 0x5,
12419 SELNEZ = 0x6,
12420 R6_RDHWR = 0x7,
12422 SLLV = 0x0,
12423 SRLV = 0x1,
12424 SRAV = 0x2,
12425 ROTRV = 0x3,
12426 ADD = 0x4,
12427 ADDU32 = 0x5,
12428 SUB = 0x6,
12429 SUBU32 = 0x7,
12430 MUL = 0x8,
12431 AND = 0x9,
12432 OR32 = 0xa,
12433 NOR = 0xb,
12434 XOR32 = 0xc,
12435 SLT = 0xd,
12436 SLTU = 0xe,
12438 MOVN = 0x0,
12439 R6_MUL = 0x0,
12440 MOVZ = 0x1,
12441 MUH = 0x1,
12442 MULU = 0x2,
12443 MUHU = 0x3,
12444 LWXS = 0x4,
12445 R6_DIV = 0x4,
12446 MOD = 0x5,
12447 R6_DIVU = 0x6,
12448 MODU = 0x7,
12450 /* The following can be distinguished by their lower 6 bits. */
12451 BREAK32 = 0x07,
12452 INS = 0x0c,
12453 LSA = 0x0f,
12454 ALIGN = 0x1f,
12455 EXT = 0x2c,
12456 POOL32AXF = 0x3c,
12457 SIGRIE = 0x3f
12460 /* POOL32AXF encoding of minor opcode field extension */
12463 * 1. MIPS Architecture for Programmers Volume II-B:
12464 * The microMIPS32 Instruction Set (Revision 3.05)
12466 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
12468 * 2. MIPS Architecture for Programmers VolumeIV-e:
12469 * The MIPS DSP Application-Specific Extension
12470 * to the microMIPS32 Architecture (Revision 2.34)
12472 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
12475 enum {
12476 /* bits 11..6 */
12477 TEQ = 0x00,
12478 TGE = 0x08,
12479 TGEU = 0x10,
12480 TLT = 0x20,
12481 TLTU = 0x28,
12482 TNE = 0x30,
12484 MFC0 = 0x03,
12485 MTC0 = 0x0b,
12487 /* begin of microMIPS32 DSP */
12489 /* bits 13..12 for 0x01 */
12490 MFHI_ACC = 0x0,
12491 MFLO_ACC = 0x1,
12492 MTHI_ACC = 0x2,
12493 MTLO_ACC = 0x3,
12495 /* bits 13..12 for 0x2a */
12496 MADD_ACC = 0x0,
12497 MADDU_ACC = 0x1,
12498 MSUB_ACC = 0x2,
12499 MSUBU_ACC = 0x3,
12501 /* bits 13..12 for 0x32 */
12502 MULT_ACC = 0x0,
12503 MULTU_ACC = 0x1,
12505 /* end of microMIPS32 DSP */
12507 /* bits 15..12 for 0x2c */
12508 BITSWAP = 0x0,
12509 SEB = 0x2,
12510 SEH = 0x3,
12511 CLO = 0x4,
12512 CLZ = 0x5,
12513 RDHWR = 0x6,
12514 WSBH = 0x7,
12515 MULT = 0x8,
12516 MULTU = 0x9,
12517 DIV = 0xa,
12518 DIVU = 0xb,
12519 MADD = 0xc,
12520 MADDU = 0xd,
12521 MSUB = 0xe,
12522 MSUBU = 0xf,
12524 /* bits 15..12 for 0x34 */
12525 MFC2 = 0x4,
12526 MTC2 = 0x5,
12527 MFHC2 = 0x8,
12528 MTHC2 = 0x9,
12529 CFC2 = 0xc,
12530 CTC2 = 0xd,
12532 /* bits 15..12 for 0x3c */
12533 JALR = 0x0,
12534 JR = 0x0, /* alias */
12535 JALRC = 0x0,
12536 JRC = 0x0,
12537 JALR_HB = 0x1,
12538 JALRC_HB = 0x1,
12539 JALRS = 0x4,
12540 JALRS_HB = 0x5,
12542 /* bits 15..12 for 0x05 */
12543 RDPGPR = 0xe,
12544 WRPGPR = 0xf,
12546 /* bits 15..12 for 0x0d */
12547 TLBP = 0x0,
12548 TLBR = 0x1,
12549 TLBWI = 0x2,
12550 TLBWR = 0x3,
12551 TLBINV = 0x4,
12552 TLBINVF = 0x5,
12553 WAIT = 0x9,
12554 IRET = 0xd,
12555 DERET = 0xe,
12556 ERET = 0xf,
12558 /* bits 15..12 for 0x15 */
12559 DMT = 0x0,
12560 DVPE = 0x1,
12561 EMT = 0x2,
12562 EVPE = 0x3,
12564 /* bits 15..12 for 0x1d */
12565 DI = 0x4,
12566 EI = 0x5,
12568 /* bits 15..12 for 0x2d */
12569 SYNC = 0x6,
12570 SYSCALL = 0x8,
12571 SDBBP = 0xd,
12573 /* bits 15..12 for 0x35 */
12574 MFHI32 = 0x0,
12575 MFLO32 = 0x1,
12576 MTHI32 = 0x2,
12577 MTLO32 = 0x3,
12580 /* POOL32B encoding of minor opcode field (bits 15..12) */
12582 enum {
12583 LWC2 = 0x0,
12584 LWP = 0x1,
12585 LDP = 0x4,
12586 LWM32 = 0x5,
12587 CACHE = 0x6,
12588 LDM = 0x7,
12589 SWC2 = 0x8,
12590 SWP = 0x9,
12591 SDP = 0xc,
12592 SWM32 = 0xd,
12593 SDM = 0xf
12596 /* POOL32C encoding of minor opcode field (bits 15..12) */
12598 enum {
12599 LWL = 0x0,
12600 SWL = 0x8,
12601 LWR = 0x1,
12602 SWR = 0x9,
12603 PREF = 0x2,
12604 ST_EVA = 0xa,
12605 LL = 0x3,
12606 SC = 0xb,
12607 LDL = 0x4,
12608 SDL = 0xc,
12609 LDR = 0x5,
12610 SDR = 0xd,
12611 LD_EVA = 0x6,
12612 LWU = 0xe,
12613 LLD = 0x7,
12614 SCD = 0xf
12617 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
12619 enum {
12620 LBUE = 0x0,
12621 LHUE = 0x1,
12622 LWLE = 0x2,
12623 LWRE = 0x3,
12624 LBE = 0x4,
12625 LHE = 0x5,
12626 LLE = 0x6,
12627 LWE = 0x7,
12630 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
12632 enum {
12633 SWLE = 0x0,
12634 SWRE = 0x1,
12635 PREFE = 0x2,
12636 CACHEE = 0x3,
12637 SBE = 0x4,
12638 SHE = 0x5,
12639 SCE = 0x6,
12640 SWE = 0x7,
12643 /* POOL32F encoding of minor opcode field (bits 5..0) */
12645 enum {
12646 /* These are the bit 7..6 values */
12647 ADD_FMT = 0x0,
12649 SUB_FMT = 0x1,
12651 MUL_FMT = 0x2,
12653 DIV_FMT = 0x3,
12655 /* These are the bit 8..6 values */
12656 MOVN_FMT = 0x0,
12657 RSQRT2_FMT = 0x0,
12658 MOVF_FMT = 0x0,
12659 RINT_FMT = 0x0,
12660 SELNEZ_FMT = 0x0,
12662 MOVZ_FMT = 0x1,
12663 LWXC1 = 0x1,
12664 MOVT_FMT = 0x1,
12665 CLASS_FMT = 0x1,
12666 SELEQZ_FMT = 0x1,
12668 PLL_PS = 0x2,
12669 SWXC1 = 0x2,
12670 SEL_FMT = 0x2,
12672 PLU_PS = 0x3,
12673 LDXC1 = 0x3,
12675 MOVN_FMT_04 = 0x4,
12676 PUL_PS = 0x4,
12677 SDXC1 = 0x4,
12678 RECIP2_FMT = 0x4,
12680 MOVZ_FMT_05 = 0x05,
12681 PUU_PS = 0x5,
12682 LUXC1 = 0x5,
12684 CVT_PS_S = 0x6,
12685 SUXC1 = 0x6,
12686 ADDR_PS = 0x6,
12687 PREFX = 0x6,
12688 MADDF_FMT = 0x6,
12690 MULR_PS = 0x7,
12691 MSUBF_FMT = 0x7,
12693 MADD_S = 0x01,
12694 MADD_D = 0x09,
12695 MADD_PS = 0x11,
12696 ALNV_PS = 0x19,
12697 MSUB_S = 0x21,
12698 MSUB_D = 0x29,
12699 MSUB_PS = 0x31,
12701 NMADD_S = 0x02,
12702 NMADD_D = 0x0a,
12703 NMADD_PS = 0x12,
12704 NMSUB_S = 0x22,
12705 NMSUB_D = 0x2a,
12706 NMSUB_PS = 0x32,
12708 MIN_FMT = 0x3,
12709 MAX_FMT = 0xb,
12710 MINA_FMT = 0x23,
12711 MAXA_FMT = 0x2b,
12712 POOL32FXF = 0x3b,
12714 CABS_COND_FMT = 0x1c, /* MIPS3D */
12715 C_COND_FMT = 0x3c,
12717 CMP_CONDN_S = 0x5,
12718 CMP_CONDN_D = 0x15
12721 /* POOL32Fxf encoding of minor opcode extension field */
12723 enum {
12724 CVT_L = 0x04,
12725 RSQRT_FMT = 0x08,
12726 FLOOR_L = 0x0c,
12727 CVT_PW_PS = 0x1c,
12728 CVT_W = 0x24,
12729 SQRT_FMT = 0x28,
12730 FLOOR_W = 0x2c,
12731 CVT_PS_PW = 0x3c,
12732 CFC1 = 0x40,
12733 RECIP_FMT = 0x48,
12734 CEIL_L = 0x4c,
12735 CTC1 = 0x60,
12736 CEIL_W = 0x6c,
12737 MFC1 = 0x80,
12738 CVT_S_PL = 0x84,
12739 TRUNC_L = 0x8c,
12740 MTC1 = 0xa0,
12741 CVT_S_PU = 0xa4,
12742 TRUNC_W = 0xac,
12743 MFHC1 = 0xc0,
12744 ROUND_L = 0xcc,
12745 MTHC1 = 0xe0,
12746 ROUND_W = 0xec,
12748 MOV_FMT = 0x01,
12749 MOVF = 0x05,
12750 ABS_FMT = 0x0d,
12751 RSQRT1_FMT = 0x1d,
12752 MOVT = 0x25,
12753 NEG_FMT = 0x2d,
12754 CVT_D = 0x4d,
12755 RECIP1_FMT = 0x5d,
12756 CVT_S = 0x6d
12759 /* POOL32I encoding of minor opcode field (bits 25..21) */
12761 enum {
12762 BLTZ = 0x00,
12763 BLTZAL = 0x01,
12764 BGEZ = 0x02,
12765 BGEZAL = 0x03,
12766 BLEZ = 0x04,
12767 BNEZC = 0x05,
12768 BGTZ = 0x06,
12769 BEQZC = 0x07,
12770 TLTI = 0x08,
12771 BC1EQZC = 0x08,
12772 TGEI = 0x09,
12773 BC1NEZC = 0x09,
12774 TLTIU = 0x0a,
12775 BC2EQZC = 0x0a,
12776 TGEIU = 0x0b,
12777 BC2NEZC = 0x0a,
12778 TNEI = 0x0c,
12779 R6_SYNCI = 0x0c,
12780 LUI = 0x0d,
12781 TEQI = 0x0e,
12782 SYNCI = 0x10,
12783 BLTZALS = 0x11,
12784 BGEZALS = 0x13,
12785 BC2F = 0x14,
12786 BC2T = 0x15,
12787 BPOSGE64 = 0x1a,
12788 BPOSGE32 = 0x1b,
12789 /* These overlap and are distinguished by bit16 of the instruction */
12790 BC1F = 0x1c,
12791 BC1T = 0x1d,
12792 BC1ANY2F = 0x1c,
12793 BC1ANY2T = 0x1d,
12794 BC1ANY4F = 0x1e,
12795 BC1ANY4T = 0x1f
12798 /* POOL16A encoding of minor opcode field */
12800 enum {
12801 ADDU16 = 0x0,
12802 SUBU16 = 0x1
12805 /* POOL16B encoding of minor opcode field */
12807 enum {
12808 SLL16 = 0x0,
12809 SRL16 = 0x1
12812 /* POOL16C encoding of minor opcode field */
12814 enum {
12815 NOT16 = 0x00,
12816 XOR16 = 0x04,
12817 AND16 = 0x08,
12818 OR16 = 0x0c,
12819 LWM16 = 0x10,
12820 SWM16 = 0x14,
12821 JR16 = 0x18,
12822 JRC16 = 0x1a,
12823 JALR16 = 0x1c,
12824 JALR16S = 0x1e,
12825 MFHI16 = 0x20,
12826 MFLO16 = 0x24,
12827 BREAK16 = 0x28,
12828 SDBBP16 = 0x2c,
12829 JRADDIUSP = 0x30
12832 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
12834 enum {
12835 R6_NOT16 = 0x00,
12836 R6_AND16 = 0x01,
12837 R6_LWM16 = 0x02,
12838 R6_JRC16 = 0x03,
12839 MOVEP = 0x04,
12840 MOVEP_07 = 0x07,
12841 R6_XOR16 = 0x08,
12842 R6_OR16 = 0x09,
12843 R6_SWM16 = 0x0a,
12844 JALRC16 = 0x0b,
12845 MOVEP_0C = 0x0c,
12846 MOVEP_0F = 0x0f,
12847 JRCADDIUSP = 0x13,
12848 R6_BREAK16 = 0x1b,
12849 R6_SDBBP16 = 0x3b
12852 /* POOL16D encoding of minor opcode field */
12854 enum {
12855 ADDIUS5 = 0x0,
12856 ADDIUSP = 0x1
12859 /* POOL16E encoding of minor opcode field */
12861 enum {
12862 ADDIUR2 = 0x0,
12863 ADDIUR1SP = 0x1
12866 static int mmreg (int r)
12868 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12870 return map[r];
12873 /* Used for 16-bit store instructions. */
12874 static int mmreg2 (int r)
12876 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
12878 return map[r];
12881 #define uMIPS_RD(op) ((op >> 7) & 0x7)
12882 #define uMIPS_RS(op) ((op >> 4) & 0x7)
12883 #define uMIPS_RS2(op) uMIPS_RS(op)
12884 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
12885 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
12886 #define uMIPS_RS5(op) (op & 0x1f)
12888 /* Signed immediate */
12889 #define SIMM(op, start, width) \
12890 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
12891 << (32-width)) \
12892 >> (32-width))
12893 /* Zero-extended immediate */
12894 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
12896 static void gen_addiur1sp(DisasContext *ctx)
12898 int rd = mmreg(uMIPS_RD(ctx->opcode));
12900 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
12903 static void gen_addiur2(DisasContext *ctx)
12905 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
12906 int rd = mmreg(uMIPS_RD(ctx->opcode));
12907 int rs = mmreg(uMIPS_RS(ctx->opcode));
12909 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
12912 static void gen_addiusp(DisasContext *ctx)
12914 int encoded = ZIMM(ctx->opcode, 1, 9);
12915 int decoded;
12917 if (encoded <= 1) {
12918 decoded = 256 + encoded;
12919 } else if (encoded <= 255) {
12920 decoded = encoded;
12921 } else if (encoded <= 509) {
12922 decoded = encoded - 512;
12923 } else {
12924 decoded = encoded - 768;
12927 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
12930 static void gen_addius5(DisasContext *ctx)
12932 int imm = SIMM(ctx->opcode, 1, 4);
12933 int rd = (ctx->opcode >> 5) & 0x1f;
12935 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
12938 static void gen_andi16(DisasContext *ctx)
12940 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
12941 31, 32, 63, 64, 255, 32768, 65535 };
12942 int rd = mmreg(uMIPS_RD(ctx->opcode));
12943 int rs = mmreg(uMIPS_RS(ctx->opcode));
12944 int encoded = ZIMM(ctx->opcode, 0, 4);
12946 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
12949 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
12950 int base, int16_t offset)
12952 TCGv t0, t1;
12953 TCGv_i32 t2;
12955 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12956 generate_exception_end(ctx, EXCP_RI);
12957 return;
12960 t0 = tcg_temp_new();
12962 gen_base_offset_addr(ctx, t0, base, offset);
12964 t1 = tcg_const_tl(reglist);
12965 t2 = tcg_const_i32(ctx->mem_idx);
12967 save_cpu_state(ctx, 1);
12968 switch (opc) {
12969 case LWM32:
12970 gen_helper_lwm(cpu_env, t0, t1, t2);
12971 break;
12972 case SWM32:
12973 gen_helper_swm(cpu_env, t0, t1, t2);
12974 break;
12975 #ifdef TARGET_MIPS64
12976 case LDM:
12977 gen_helper_ldm(cpu_env, t0, t1, t2);
12978 break;
12979 case SDM:
12980 gen_helper_sdm(cpu_env, t0, t1, t2);
12981 break;
12982 #endif
12984 tcg_temp_free(t0);
12985 tcg_temp_free(t1);
12986 tcg_temp_free_i32(t2);
12990 static void gen_pool16c_insn(DisasContext *ctx)
12992 int rd = mmreg((ctx->opcode >> 3) & 0x7);
12993 int rs = mmreg(ctx->opcode & 0x7);
12995 switch (((ctx->opcode) >> 4) & 0x3f) {
12996 case NOT16 + 0:
12997 case NOT16 + 1:
12998 case NOT16 + 2:
12999 case NOT16 + 3:
13000 gen_logic(ctx, OPC_NOR, rd, rs, 0);
13001 break;
13002 case XOR16 + 0:
13003 case XOR16 + 1:
13004 case XOR16 + 2:
13005 case XOR16 + 3:
13006 gen_logic(ctx, OPC_XOR, rd, rd, rs);
13007 break;
13008 case AND16 + 0:
13009 case AND16 + 1:
13010 case AND16 + 2:
13011 case AND16 + 3:
13012 gen_logic(ctx, OPC_AND, rd, rd, rs);
13013 break;
13014 case OR16 + 0:
13015 case OR16 + 1:
13016 case OR16 + 2:
13017 case OR16 + 3:
13018 gen_logic(ctx, OPC_OR, rd, rd, rs);
13019 break;
13020 case LWM16 + 0:
13021 case LWM16 + 1:
13022 case LWM16 + 2:
13023 case LWM16 + 3:
13025 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13026 int offset = ZIMM(ctx->opcode, 0, 4);
13028 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
13029 29, offset << 2);
13031 break;
13032 case SWM16 + 0:
13033 case SWM16 + 1:
13034 case SWM16 + 2:
13035 case SWM16 + 3:
13037 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
13038 int offset = ZIMM(ctx->opcode, 0, 4);
13040 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
13041 29, offset << 2);
13043 break;
13044 case JR16 + 0:
13045 case JR16 + 1:
13047 int reg = ctx->opcode & 0x1f;
13049 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
13051 break;
13052 case JRC16 + 0:
13053 case JRC16 + 1:
13055 int reg = ctx->opcode & 0x1f;
13056 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
13057 /* Let normal delay slot handling in our caller take us
13058 to the branch target. */
13060 break;
13061 case JALR16 + 0:
13062 case JALR16 + 1:
13063 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
13064 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13065 break;
13066 case JALR16S + 0:
13067 case JALR16S + 1:
13068 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
13069 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13070 break;
13071 case MFHI16 + 0:
13072 case MFHI16 + 1:
13073 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
13074 break;
13075 case MFLO16 + 0:
13076 case MFLO16 + 1:
13077 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
13078 break;
13079 case BREAK16:
13080 generate_exception_end(ctx, EXCP_BREAK);
13081 break;
13082 case SDBBP16:
13083 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
13084 gen_helper_do_semihosting(cpu_env);
13085 } else {
13086 /* XXX: not clear which exception should be raised
13087 * when in debug mode...
13089 check_insn(ctx, ISA_MIPS32);
13090 generate_exception_end(ctx, EXCP_DBp);
13092 break;
13093 case JRADDIUSP + 0:
13094 case JRADDIUSP + 1:
13096 int imm = ZIMM(ctx->opcode, 0, 5);
13097 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13098 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13099 /* Let normal delay slot handling in our caller take us
13100 to the branch target. */
13102 break;
13103 default:
13104 generate_exception_end(ctx, EXCP_RI);
13105 break;
13109 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
13110 int enc_rs)
13112 int rd, rs, re, rt;
13113 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13114 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13115 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13116 rd = rd_enc[enc_dest];
13117 re = re_enc[enc_dest];
13118 rs = rs_rt_enc[enc_rs];
13119 rt = rs_rt_enc[enc_rt];
13120 if (rs) {
13121 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
13122 } else {
13123 tcg_gen_movi_tl(cpu_gpr[rd], 0);
13125 if (rt) {
13126 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
13127 } else {
13128 tcg_gen_movi_tl(cpu_gpr[re], 0);
13132 static void gen_pool16c_r6_insn(DisasContext *ctx)
13134 int rt = mmreg((ctx->opcode >> 7) & 0x7);
13135 int rs = mmreg((ctx->opcode >> 4) & 0x7);
13137 switch (ctx->opcode & 0xf) {
13138 case R6_NOT16:
13139 gen_logic(ctx, OPC_NOR, rt, rs, 0);
13140 break;
13141 case R6_AND16:
13142 gen_logic(ctx, OPC_AND, rt, rt, rs);
13143 break;
13144 case R6_LWM16:
13146 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13147 int offset = extract32(ctx->opcode, 4, 4);
13148 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
13150 break;
13151 case R6_JRC16: /* JRCADDIUSP */
13152 if ((ctx->opcode >> 4) & 1) {
13153 /* JRCADDIUSP */
13154 int imm = extract32(ctx->opcode, 5, 5);
13155 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
13156 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
13157 } else {
13158 /* JRC16 */
13159 int rs = extract32(ctx->opcode, 5, 5);
13160 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
13162 break;
13163 case MOVEP ... MOVEP_07:
13164 case MOVEP_0C ... MOVEP_0F:
13166 int enc_dest = uMIPS_RD(ctx->opcode);
13167 int enc_rt = uMIPS_RS2(ctx->opcode);
13168 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
13169 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
13171 break;
13172 case R6_XOR16:
13173 gen_logic(ctx, OPC_XOR, rt, rt, rs);
13174 break;
13175 case R6_OR16:
13176 gen_logic(ctx, OPC_OR, rt, rt, rs);
13177 break;
13178 case R6_SWM16:
13180 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
13181 int offset = extract32(ctx->opcode, 4, 4);
13182 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
13184 break;
13185 case JALRC16: /* BREAK16, SDBBP16 */
13186 switch (ctx->opcode & 0x3f) {
13187 case JALRC16:
13188 case JALRC16 + 0x20:
13189 /* JALRC16 */
13190 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
13191 31, 0, 0);
13192 break;
13193 case R6_BREAK16:
13194 /* BREAK16 */
13195 generate_exception(ctx, EXCP_BREAK);
13196 break;
13197 case R6_SDBBP16:
13198 /* SDBBP16 */
13199 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
13200 gen_helper_do_semihosting(cpu_env);
13201 } else {
13202 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13203 generate_exception(ctx, EXCP_RI);
13204 } else {
13205 generate_exception(ctx, EXCP_DBp);
13208 break;
13210 break;
13211 default:
13212 generate_exception(ctx, EXCP_RI);
13213 break;
13217 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
13219 TCGv t0 = tcg_temp_new();
13220 TCGv t1 = tcg_temp_new();
13222 gen_load_gpr(t0, base);
13224 if (index != 0) {
13225 gen_load_gpr(t1, index);
13226 tcg_gen_shli_tl(t1, t1, 2);
13227 gen_op_addr_add(ctx, t0, t1, t0);
13230 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13231 gen_store_gpr(t1, rd);
13233 tcg_temp_free(t0);
13234 tcg_temp_free(t1);
13237 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
13238 int base, int16_t offset)
13240 TCGv t0, t1;
13242 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
13243 generate_exception_end(ctx, EXCP_RI);
13244 return;
13247 t0 = tcg_temp_new();
13248 t1 = tcg_temp_new();
13250 gen_base_offset_addr(ctx, t0, base, offset);
13252 switch (opc) {
13253 case LWP:
13254 if (rd == base) {
13255 generate_exception_end(ctx, EXCP_RI);
13256 return;
13258 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13259 gen_store_gpr(t1, rd);
13260 tcg_gen_movi_tl(t1, 4);
13261 gen_op_addr_add(ctx, t0, t0, t1);
13262 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
13263 gen_store_gpr(t1, rd+1);
13264 break;
13265 case SWP:
13266 gen_load_gpr(t1, rd);
13267 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13268 tcg_gen_movi_tl(t1, 4);
13269 gen_op_addr_add(ctx, t0, t0, t1);
13270 gen_load_gpr(t1, rd+1);
13271 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13272 break;
13273 #ifdef TARGET_MIPS64
13274 case LDP:
13275 if (rd == base) {
13276 generate_exception_end(ctx, EXCP_RI);
13277 return;
13279 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13280 gen_store_gpr(t1, rd);
13281 tcg_gen_movi_tl(t1, 8);
13282 gen_op_addr_add(ctx, t0, t0, t1);
13283 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13284 gen_store_gpr(t1, rd+1);
13285 break;
13286 case SDP:
13287 gen_load_gpr(t1, rd);
13288 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13289 tcg_gen_movi_tl(t1, 8);
13290 gen_op_addr_add(ctx, t0, t0, t1);
13291 gen_load_gpr(t1, rd+1);
13292 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
13293 break;
13294 #endif
13296 tcg_temp_free(t0);
13297 tcg_temp_free(t1);
13300 static void gen_sync(int stype)
13302 TCGBar tcg_mo = TCG_BAR_SC;
13304 switch (stype) {
13305 case 0x4: /* SYNC_WMB */
13306 tcg_mo |= TCG_MO_ST_ST;
13307 break;
13308 case 0x10: /* SYNC_MB */
13309 tcg_mo |= TCG_MO_ALL;
13310 break;
13311 case 0x11: /* SYNC_ACQUIRE */
13312 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
13313 break;
13314 case 0x12: /* SYNC_RELEASE */
13315 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
13316 break;
13317 case 0x13: /* SYNC_RMB */
13318 tcg_mo |= TCG_MO_LD_LD;
13319 break;
13320 default:
13321 tcg_mo |= TCG_MO_ALL;
13322 break;
13325 tcg_gen_mb(tcg_mo);
13328 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
13330 int extension = (ctx->opcode >> 6) & 0x3f;
13331 int minor = (ctx->opcode >> 12) & 0xf;
13332 uint32_t mips32_op;
13334 switch (extension) {
13335 case TEQ:
13336 mips32_op = OPC_TEQ;
13337 goto do_trap;
13338 case TGE:
13339 mips32_op = OPC_TGE;
13340 goto do_trap;
13341 case TGEU:
13342 mips32_op = OPC_TGEU;
13343 goto do_trap;
13344 case TLT:
13345 mips32_op = OPC_TLT;
13346 goto do_trap;
13347 case TLTU:
13348 mips32_op = OPC_TLTU;
13349 goto do_trap;
13350 case TNE:
13351 mips32_op = OPC_TNE;
13352 do_trap:
13353 gen_trap(ctx, mips32_op, rs, rt, -1);
13354 break;
13355 #ifndef CONFIG_USER_ONLY
13356 case MFC0:
13357 case MFC0 + 32:
13358 check_cp0_enabled(ctx);
13359 if (rt == 0) {
13360 /* Treat as NOP. */
13361 break;
13363 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
13364 break;
13365 case MTC0:
13366 case MTC0 + 32:
13367 check_cp0_enabled(ctx);
13369 TCGv t0 = tcg_temp_new();
13371 gen_load_gpr(t0, rt);
13372 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
13373 tcg_temp_free(t0);
13375 break;
13376 #endif
13377 case 0x2a:
13378 switch (minor & 3) {
13379 case MADD_ACC:
13380 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
13381 break;
13382 case MADDU_ACC:
13383 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
13384 break;
13385 case MSUB_ACC:
13386 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
13387 break;
13388 case MSUBU_ACC:
13389 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
13390 break;
13391 default:
13392 goto pool32axf_invalid;
13394 break;
13395 case 0x32:
13396 switch (minor & 3) {
13397 case MULT_ACC:
13398 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
13399 break;
13400 case MULTU_ACC:
13401 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
13402 break;
13403 default:
13404 goto pool32axf_invalid;
13406 break;
13407 case 0x2c:
13408 switch (minor) {
13409 case BITSWAP:
13410 check_insn(ctx, ISA_MIPS32R6);
13411 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
13412 break;
13413 case SEB:
13414 gen_bshfl(ctx, OPC_SEB, rs, rt);
13415 break;
13416 case SEH:
13417 gen_bshfl(ctx, OPC_SEH, rs, rt);
13418 break;
13419 case CLO:
13420 mips32_op = OPC_CLO;
13421 goto do_cl;
13422 case CLZ:
13423 mips32_op = OPC_CLZ;
13424 do_cl:
13425 check_insn(ctx, ISA_MIPS32);
13426 gen_cl(ctx, mips32_op, rt, rs);
13427 break;
13428 case RDHWR:
13429 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13430 gen_rdhwr(ctx, rt, rs, 0);
13431 break;
13432 case WSBH:
13433 gen_bshfl(ctx, OPC_WSBH, rs, rt);
13434 break;
13435 case MULT:
13436 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13437 mips32_op = OPC_MULT;
13438 goto do_mul;
13439 case MULTU:
13440 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13441 mips32_op = OPC_MULTU;
13442 goto do_mul;
13443 case DIV:
13444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13445 mips32_op = OPC_DIV;
13446 goto do_div;
13447 case DIVU:
13448 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13449 mips32_op = OPC_DIVU;
13450 goto do_div;
13451 do_div:
13452 check_insn(ctx, ISA_MIPS32);
13453 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13454 break;
13455 case MADD:
13456 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13457 mips32_op = OPC_MADD;
13458 goto do_mul;
13459 case MADDU:
13460 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13461 mips32_op = OPC_MADDU;
13462 goto do_mul;
13463 case MSUB:
13464 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13465 mips32_op = OPC_MSUB;
13466 goto do_mul;
13467 case MSUBU:
13468 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13469 mips32_op = OPC_MSUBU;
13470 do_mul:
13471 check_insn(ctx, ISA_MIPS32);
13472 gen_muldiv(ctx, mips32_op, 0, rs, rt);
13473 break;
13474 default:
13475 goto pool32axf_invalid;
13477 break;
13478 case 0x34:
13479 switch (minor) {
13480 case MFC2:
13481 case MTC2:
13482 case MFHC2:
13483 case MTHC2:
13484 case CFC2:
13485 case CTC2:
13486 generate_exception_err(ctx, EXCP_CpU, 2);
13487 break;
13488 default:
13489 goto pool32axf_invalid;
13491 break;
13492 case 0x3c:
13493 switch (minor) {
13494 case JALR: /* JALRC */
13495 case JALR_HB: /* JALRC_HB */
13496 if (ctx->insn_flags & ISA_MIPS32R6) {
13497 /* JALRC, JALRC_HB */
13498 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
13499 } else {
13500 /* JALR, JALR_HB */
13501 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
13502 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13504 break;
13505 case JALRS:
13506 case JALRS_HB:
13507 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13508 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
13509 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13510 break;
13511 default:
13512 goto pool32axf_invalid;
13514 break;
13515 case 0x05:
13516 switch (minor) {
13517 case RDPGPR:
13518 check_cp0_enabled(ctx);
13519 check_insn(ctx, ISA_MIPS32R2);
13520 gen_load_srsgpr(rs, rt);
13521 break;
13522 case WRPGPR:
13523 check_cp0_enabled(ctx);
13524 check_insn(ctx, ISA_MIPS32R2);
13525 gen_store_srsgpr(rs, rt);
13526 break;
13527 default:
13528 goto pool32axf_invalid;
13530 break;
13531 #ifndef CONFIG_USER_ONLY
13532 case 0x0d:
13533 switch (minor) {
13534 case TLBP:
13535 mips32_op = OPC_TLBP;
13536 goto do_cp0;
13537 case TLBR:
13538 mips32_op = OPC_TLBR;
13539 goto do_cp0;
13540 case TLBWI:
13541 mips32_op = OPC_TLBWI;
13542 goto do_cp0;
13543 case TLBWR:
13544 mips32_op = OPC_TLBWR;
13545 goto do_cp0;
13546 case TLBINV:
13547 mips32_op = OPC_TLBINV;
13548 goto do_cp0;
13549 case TLBINVF:
13550 mips32_op = OPC_TLBINVF;
13551 goto do_cp0;
13552 case WAIT:
13553 mips32_op = OPC_WAIT;
13554 goto do_cp0;
13555 case DERET:
13556 mips32_op = OPC_DERET;
13557 goto do_cp0;
13558 case ERET:
13559 mips32_op = OPC_ERET;
13560 do_cp0:
13561 gen_cp0(env, ctx, mips32_op, rt, rs);
13562 break;
13563 default:
13564 goto pool32axf_invalid;
13566 break;
13567 case 0x1d:
13568 switch (minor) {
13569 case DI:
13570 check_cp0_enabled(ctx);
13572 TCGv t0 = tcg_temp_new();
13574 save_cpu_state(ctx, 1);
13575 gen_helper_di(t0, cpu_env);
13576 gen_store_gpr(t0, rs);
13577 /* Stop translation as we may have switched the execution mode */
13578 ctx->bstate = BS_STOP;
13579 tcg_temp_free(t0);
13581 break;
13582 case EI:
13583 check_cp0_enabled(ctx);
13585 TCGv t0 = tcg_temp_new();
13587 save_cpu_state(ctx, 1);
13588 gen_helper_ei(t0, cpu_env);
13589 gen_store_gpr(t0, rs);
13590 /* BS_STOP isn't sufficient, we need to ensure we break out
13591 of translated code to check for pending interrupts. */
13592 gen_save_pc(ctx->pc + 4);
13593 ctx->bstate = BS_EXCP;
13594 tcg_temp_free(t0);
13596 break;
13597 default:
13598 goto pool32axf_invalid;
13600 break;
13601 #endif
13602 case 0x2d:
13603 switch (minor) {
13604 case SYNC:
13605 gen_sync(extract32(ctx->opcode, 16, 5));
13606 break;
13607 case SYSCALL:
13608 generate_exception_end(ctx, EXCP_SYSCALL);
13609 break;
13610 case SDBBP:
13611 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
13612 gen_helper_do_semihosting(cpu_env);
13613 } else {
13614 check_insn(ctx, ISA_MIPS32);
13615 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13616 generate_exception_end(ctx, EXCP_RI);
13617 } else {
13618 generate_exception_end(ctx, EXCP_DBp);
13621 break;
13622 default:
13623 goto pool32axf_invalid;
13625 break;
13626 case 0x01:
13627 switch (minor & 3) {
13628 case MFHI_ACC:
13629 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
13630 break;
13631 case MFLO_ACC:
13632 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
13633 break;
13634 case MTHI_ACC:
13635 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
13636 break;
13637 case MTLO_ACC:
13638 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
13639 break;
13640 default:
13641 goto pool32axf_invalid;
13643 break;
13644 case 0x35:
13645 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13646 switch (minor) {
13647 case MFHI32:
13648 gen_HILO(ctx, OPC_MFHI, 0, rs);
13649 break;
13650 case MFLO32:
13651 gen_HILO(ctx, OPC_MFLO, 0, rs);
13652 break;
13653 case MTHI32:
13654 gen_HILO(ctx, OPC_MTHI, 0, rs);
13655 break;
13656 case MTLO32:
13657 gen_HILO(ctx, OPC_MTLO, 0, rs);
13658 break;
13659 default:
13660 goto pool32axf_invalid;
13662 break;
13663 default:
13664 pool32axf_invalid:
13665 MIPS_INVAL("pool32axf");
13666 generate_exception_end(ctx, EXCP_RI);
13667 break;
13671 /* Values for microMIPS fmt field. Variable-width, depending on which
13672 formats the instruction supports. */
13674 enum {
13675 FMT_SD_S = 0,
13676 FMT_SD_D = 1,
13678 FMT_SDPS_S = 0,
13679 FMT_SDPS_D = 1,
13680 FMT_SDPS_PS = 2,
13682 FMT_SWL_S = 0,
13683 FMT_SWL_W = 1,
13684 FMT_SWL_L = 2,
13686 FMT_DWL_D = 0,
13687 FMT_DWL_W = 1,
13688 FMT_DWL_L = 2
13691 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
13693 int extension = (ctx->opcode >> 6) & 0x3ff;
13694 uint32_t mips32_op;
13696 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
13697 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
13698 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
13700 switch (extension) {
13701 case FLOAT_1BIT_FMT(CFC1, 0):
13702 mips32_op = OPC_CFC1;
13703 goto do_cp1;
13704 case FLOAT_1BIT_FMT(CTC1, 0):
13705 mips32_op = OPC_CTC1;
13706 goto do_cp1;
13707 case FLOAT_1BIT_FMT(MFC1, 0):
13708 mips32_op = OPC_MFC1;
13709 goto do_cp1;
13710 case FLOAT_1BIT_FMT(MTC1, 0):
13711 mips32_op = OPC_MTC1;
13712 goto do_cp1;
13713 case FLOAT_1BIT_FMT(MFHC1, 0):
13714 mips32_op = OPC_MFHC1;
13715 goto do_cp1;
13716 case FLOAT_1BIT_FMT(MTHC1, 0):
13717 mips32_op = OPC_MTHC1;
13718 do_cp1:
13719 gen_cp1(ctx, mips32_op, rt, rs);
13720 break;
13722 /* Reciprocal square root */
13723 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
13724 mips32_op = OPC_RSQRT_S;
13725 goto do_unaryfp;
13726 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
13727 mips32_op = OPC_RSQRT_D;
13728 goto do_unaryfp;
13730 /* Square root */
13731 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
13732 mips32_op = OPC_SQRT_S;
13733 goto do_unaryfp;
13734 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
13735 mips32_op = OPC_SQRT_D;
13736 goto do_unaryfp;
13738 /* Reciprocal */
13739 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
13740 mips32_op = OPC_RECIP_S;
13741 goto do_unaryfp;
13742 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
13743 mips32_op = OPC_RECIP_D;
13744 goto do_unaryfp;
13746 /* Floor */
13747 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
13748 mips32_op = OPC_FLOOR_L_S;
13749 goto do_unaryfp;
13750 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
13751 mips32_op = OPC_FLOOR_L_D;
13752 goto do_unaryfp;
13753 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
13754 mips32_op = OPC_FLOOR_W_S;
13755 goto do_unaryfp;
13756 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
13757 mips32_op = OPC_FLOOR_W_D;
13758 goto do_unaryfp;
13760 /* Ceiling */
13761 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
13762 mips32_op = OPC_CEIL_L_S;
13763 goto do_unaryfp;
13764 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
13765 mips32_op = OPC_CEIL_L_D;
13766 goto do_unaryfp;
13767 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
13768 mips32_op = OPC_CEIL_W_S;
13769 goto do_unaryfp;
13770 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
13771 mips32_op = OPC_CEIL_W_D;
13772 goto do_unaryfp;
13774 /* Truncation */
13775 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
13776 mips32_op = OPC_TRUNC_L_S;
13777 goto do_unaryfp;
13778 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
13779 mips32_op = OPC_TRUNC_L_D;
13780 goto do_unaryfp;
13781 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
13782 mips32_op = OPC_TRUNC_W_S;
13783 goto do_unaryfp;
13784 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
13785 mips32_op = OPC_TRUNC_W_D;
13786 goto do_unaryfp;
13788 /* Round */
13789 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
13790 mips32_op = OPC_ROUND_L_S;
13791 goto do_unaryfp;
13792 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
13793 mips32_op = OPC_ROUND_L_D;
13794 goto do_unaryfp;
13795 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
13796 mips32_op = OPC_ROUND_W_S;
13797 goto do_unaryfp;
13798 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
13799 mips32_op = OPC_ROUND_W_D;
13800 goto do_unaryfp;
13802 /* Integer to floating-point conversion */
13803 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
13804 mips32_op = OPC_CVT_L_S;
13805 goto do_unaryfp;
13806 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
13807 mips32_op = OPC_CVT_L_D;
13808 goto do_unaryfp;
13809 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
13810 mips32_op = OPC_CVT_W_S;
13811 goto do_unaryfp;
13812 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
13813 mips32_op = OPC_CVT_W_D;
13814 goto do_unaryfp;
13816 /* Paired-foo conversions */
13817 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
13818 mips32_op = OPC_CVT_S_PL;
13819 goto do_unaryfp;
13820 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
13821 mips32_op = OPC_CVT_S_PU;
13822 goto do_unaryfp;
13823 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
13824 mips32_op = OPC_CVT_PW_PS;
13825 goto do_unaryfp;
13826 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
13827 mips32_op = OPC_CVT_PS_PW;
13828 goto do_unaryfp;
13830 /* Floating-point moves */
13831 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
13832 mips32_op = OPC_MOV_S;
13833 goto do_unaryfp;
13834 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
13835 mips32_op = OPC_MOV_D;
13836 goto do_unaryfp;
13837 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
13838 mips32_op = OPC_MOV_PS;
13839 goto do_unaryfp;
13841 /* Absolute value */
13842 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
13843 mips32_op = OPC_ABS_S;
13844 goto do_unaryfp;
13845 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
13846 mips32_op = OPC_ABS_D;
13847 goto do_unaryfp;
13848 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
13849 mips32_op = OPC_ABS_PS;
13850 goto do_unaryfp;
13852 /* Negation */
13853 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
13854 mips32_op = OPC_NEG_S;
13855 goto do_unaryfp;
13856 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
13857 mips32_op = OPC_NEG_D;
13858 goto do_unaryfp;
13859 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
13860 mips32_op = OPC_NEG_PS;
13861 goto do_unaryfp;
13863 /* Reciprocal square root step */
13864 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
13865 mips32_op = OPC_RSQRT1_S;
13866 goto do_unaryfp;
13867 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
13868 mips32_op = OPC_RSQRT1_D;
13869 goto do_unaryfp;
13870 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
13871 mips32_op = OPC_RSQRT1_PS;
13872 goto do_unaryfp;
13874 /* Reciprocal step */
13875 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
13876 mips32_op = OPC_RECIP1_S;
13877 goto do_unaryfp;
13878 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
13879 mips32_op = OPC_RECIP1_S;
13880 goto do_unaryfp;
13881 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
13882 mips32_op = OPC_RECIP1_PS;
13883 goto do_unaryfp;
13885 /* Conversions from double */
13886 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
13887 mips32_op = OPC_CVT_D_S;
13888 goto do_unaryfp;
13889 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
13890 mips32_op = OPC_CVT_D_W;
13891 goto do_unaryfp;
13892 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
13893 mips32_op = OPC_CVT_D_L;
13894 goto do_unaryfp;
13896 /* Conversions from single */
13897 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
13898 mips32_op = OPC_CVT_S_D;
13899 goto do_unaryfp;
13900 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
13901 mips32_op = OPC_CVT_S_W;
13902 goto do_unaryfp;
13903 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
13904 mips32_op = OPC_CVT_S_L;
13905 do_unaryfp:
13906 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
13907 break;
13909 /* Conditional moves on floating-point codes */
13910 case COND_FLOAT_MOV(MOVT, 0):
13911 case COND_FLOAT_MOV(MOVT, 1):
13912 case COND_FLOAT_MOV(MOVT, 2):
13913 case COND_FLOAT_MOV(MOVT, 3):
13914 case COND_FLOAT_MOV(MOVT, 4):
13915 case COND_FLOAT_MOV(MOVT, 5):
13916 case COND_FLOAT_MOV(MOVT, 6):
13917 case COND_FLOAT_MOV(MOVT, 7):
13918 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13919 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
13920 break;
13921 case COND_FLOAT_MOV(MOVF, 0):
13922 case COND_FLOAT_MOV(MOVF, 1):
13923 case COND_FLOAT_MOV(MOVF, 2):
13924 case COND_FLOAT_MOV(MOVF, 3):
13925 case COND_FLOAT_MOV(MOVF, 4):
13926 case COND_FLOAT_MOV(MOVF, 5):
13927 case COND_FLOAT_MOV(MOVF, 6):
13928 case COND_FLOAT_MOV(MOVF, 7):
13929 check_insn_opc_removed(ctx, ISA_MIPS32R6);
13930 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
13931 break;
13932 default:
13933 MIPS_INVAL("pool32fxf");
13934 generate_exception_end(ctx, EXCP_RI);
13935 break;
13939 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
13941 int32_t offset;
13942 uint16_t insn;
13943 int rt, rs, rd, rr;
13944 int16_t imm;
13945 uint32_t op, minor, minor2, mips32_op;
13946 uint32_t cond, fmt, cc;
13948 insn = cpu_lduw_code(env, ctx->pc + 2);
13949 ctx->opcode = (ctx->opcode << 16) | insn;
13951 rt = (ctx->opcode >> 21) & 0x1f;
13952 rs = (ctx->opcode >> 16) & 0x1f;
13953 rd = (ctx->opcode >> 11) & 0x1f;
13954 rr = (ctx->opcode >> 6) & 0x1f;
13955 imm = (int16_t) ctx->opcode;
13957 op = (ctx->opcode >> 26) & 0x3f;
13958 switch (op) {
13959 case POOL32A:
13960 minor = ctx->opcode & 0x3f;
13961 switch (minor) {
13962 case 0x00:
13963 minor = (ctx->opcode >> 6) & 0xf;
13964 switch (minor) {
13965 case SLL32:
13966 mips32_op = OPC_SLL;
13967 goto do_shifti;
13968 case SRA:
13969 mips32_op = OPC_SRA;
13970 goto do_shifti;
13971 case SRL32:
13972 mips32_op = OPC_SRL;
13973 goto do_shifti;
13974 case ROTR:
13975 mips32_op = OPC_ROTR;
13976 do_shifti:
13977 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
13978 break;
13979 case SELEQZ:
13980 check_insn(ctx, ISA_MIPS32R6);
13981 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
13982 break;
13983 case SELNEZ:
13984 check_insn(ctx, ISA_MIPS32R6);
13985 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
13986 break;
13987 case R6_RDHWR:
13988 check_insn(ctx, ISA_MIPS32R6);
13989 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
13990 break;
13991 default:
13992 goto pool32a_invalid;
13994 break;
13995 case 0x10:
13996 minor = (ctx->opcode >> 6) & 0xf;
13997 switch (minor) {
13998 /* Arithmetic */
13999 case ADD:
14000 mips32_op = OPC_ADD;
14001 goto do_arith;
14002 case ADDU32:
14003 mips32_op = OPC_ADDU;
14004 goto do_arith;
14005 case SUB:
14006 mips32_op = OPC_SUB;
14007 goto do_arith;
14008 case SUBU32:
14009 mips32_op = OPC_SUBU;
14010 goto do_arith;
14011 case MUL:
14012 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14013 mips32_op = OPC_MUL;
14014 do_arith:
14015 gen_arith(ctx, mips32_op, rd, rs, rt);
14016 break;
14017 /* Shifts */
14018 case SLLV:
14019 mips32_op = OPC_SLLV;
14020 goto do_shift;
14021 case SRLV:
14022 mips32_op = OPC_SRLV;
14023 goto do_shift;
14024 case SRAV:
14025 mips32_op = OPC_SRAV;
14026 goto do_shift;
14027 case ROTRV:
14028 mips32_op = OPC_ROTRV;
14029 do_shift:
14030 gen_shift(ctx, mips32_op, rd, rs, rt);
14031 break;
14032 /* Logical operations */
14033 case AND:
14034 mips32_op = OPC_AND;
14035 goto do_logic;
14036 case OR32:
14037 mips32_op = OPC_OR;
14038 goto do_logic;
14039 case NOR:
14040 mips32_op = OPC_NOR;
14041 goto do_logic;
14042 case XOR32:
14043 mips32_op = OPC_XOR;
14044 do_logic:
14045 gen_logic(ctx, mips32_op, rd, rs, rt);
14046 break;
14047 /* Set less than */
14048 case SLT:
14049 mips32_op = OPC_SLT;
14050 goto do_slt;
14051 case SLTU:
14052 mips32_op = OPC_SLTU;
14053 do_slt:
14054 gen_slt(ctx, mips32_op, rd, rs, rt);
14055 break;
14056 default:
14057 goto pool32a_invalid;
14059 break;
14060 case 0x18:
14061 minor = (ctx->opcode >> 6) & 0xf;
14062 switch (minor) {
14063 /* Conditional moves */
14064 case MOVN: /* MUL */
14065 if (ctx->insn_flags & ISA_MIPS32R6) {
14066 /* MUL */
14067 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
14068 } else {
14069 /* MOVN */
14070 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
14072 break;
14073 case MOVZ: /* MUH */
14074 if (ctx->insn_flags & ISA_MIPS32R6) {
14075 /* MUH */
14076 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
14077 } else {
14078 /* MOVZ */
14079 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
14081 break;
14082 case MULU:
14083 check_insn(ctx, ISA_MIPS32R6);
14084 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
14085 break;
14086 case MUHU:
14087 check_insn(ctx, ISA_MIPS32R6);
14088 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
14089 break;
14090 case LWXS: /* DIV */
14091 if (ctx->insn_flags & ISA_MIPS32R6) {
14092 /* DIV */
14093 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
14094 } else {
14095 /* LWXS */
14096 gen_ldxs(ctx, rs, rt, rd);
14098 break;
14099 case MOD:
14100 check_insn(ctx, ISA_MIPS32R6);
14101 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
14102 break;
14103 case R6_DIVU:
14104 check_insn(ctx, ISA_MIPS32R6);
14105 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
14106 break;
14107 case MODU:
14108 check_insn(ctx, ISA_MIPS32R6);
14109 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
14110 break;
14111 default:
14112 goto pool32a_invalid;
14114 break;
14115 case INS:
14116 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
14117 return;
14118 case LSA:
14119 check_insn(ctx, ISA_MIPS32R6);
14120 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
14121 extract32(ctx->opcode, 9, 2));
14122 break;
14123 case ALIGN:
14124 check_insn(ctx, ISA_MIPS32R6);
14125 gen_align(ctx, OPC_ALIGN, rd, rs, rt,
14126 extract32(ctx->opcode, 9, 2));
14127 break;
14128 case EXT:
14129 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
14130 return;
14131 case POOL32AXF:
14132 gen_pool32axf(env, ctx, rt, rs);
14133 break;
14134 case BREAK32:
14135 generate_exception_end(ctx, EXCP_BREAK);
14136 break;
14137 case SIGRIE:
14138 check_insn(ctx, ISA_MIPS32R6);
14139 generate_exception_end(ctx, EXCP_RI);
14140 break;
14141 default:
14142 pool32a_invalid:
14143 MIPS_INVAL("pool32a");
14144 generate_exception_end(ctx, EXCP_RI);
14145 break;
14147 break;
14148 case POOL32B:
14149 minor = (ctx->opcode >> 12) & 0xf;
14150 switch (minor) {
14151 case CACHE:
14152 check_cp0_enabled(ctx);
14153 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14154 gen_cache_operation(ctx, rt, rs, imm);
14156 break;
14157 case LWC2:
14158 case SWC2:
14159 /* COP2: Not implemented. */
14160 generate_exception_err(ctx, EXCP_CpU, 2);
14161 break;
14162 #ifdef TARGET_MIPS64
14163 case LDP:
14164 case SDP:
14165 check_insn(ctx, ISA_MIPS3);
14166 check_mips_64(ctx);
14167 /* Fallthrough */
14168 #endif
14169 case LWP:
14170 case SWP:
14171 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14172 break;
14173 #ifdef TARGET_MIPS64
14174 case LDM:
14175 case SDM:
14176 check_insn(ctx, ISA_MIPS3);
14177 check_mips_64(ctx);
14178 /* Fallthrough */
14179 #endif
14180 case LWM32:
14181 case SWM32:
14182 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
14183 break;
14184 default:
14185 MIPS_INVAL("pool32b");
14186 generate_exception_end(ctx, EXCP_RI);
14187 break;
14189 break;
14190 case POOL32F:
14191 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14192 minor = ctx->opcode & 0x3f;
14193 check_cp1_enabled(ctx);
14194 switch (minor) {
14195 case ALNV_PS:
14196 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14197 mips32_op = OPC_ALNV_PS;
14198 goto do_madd;
14199 case MADD_S:
14200 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14201 mips32_op = OPC_MADD_S;
14202 goto do_madd;
14203 case MADD_D:
14204 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14205 mips32_op = OPC_MADD_D;
14206 goto do_madd;
14207 case MADD_PS:
14208 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14209 mips32_op = OPC_MADD_PS;
14210 goto do_madd;
14211 case MSUB_S:
14212 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14213 mips32_op = OPC_MSUB_S;
14214 goto do_madd;
14215 case MSUB_D:
14216 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14217 mips32_op = OPC_MSUB_D;
14218 goto do_madd;
14219 case MSUB_PS:
14220 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14221 mips32_op = OPC_MSUB_PS;
14222 goto do_madd;
14223 case NMADD_S:
14224 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14225 mips32_op = OPC_NMADD_S;
14226 goto do_madd;
14227 case NMADD_D:
14228 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14229 mips32_op = OPC_NMADD_D;
14230 goto do_madd;
14231 case NMADD_PS:
14232 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14233 mips32_op = OPC_NMADD_PS;
14234 goto do_madd;
14235 case NMSUB_S:
14236 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14237 mips32_op = OPC_NMSUB_S;
14238 goto do_madd;
14239 case NMSUB_D:
14240 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14241 mips32_op = OPC_NMSUB_D;
14242 goto do_madd;
14243 case NMSUB_PS:
14244 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14245 mips32_op = OPC_NMSUB_PS;
14246 do_madd:
14247 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
14248 break;
14249 case CABS_COND_FMT:
14250 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14251 cond = (ctx->opcode >> 6) & 0xf;
14252 cc = (ctx->opcode >> 13) & 0x7;
14253 fmt = (ctx->opcode >> 10) & 0x3;
14254 switch (fmt) {
14255 case 0x0:
14256 gen_cmpabs_s(ctx, cond, rt, rs, cc);
14257 break;
14258 case 0x1:
14259 gen_cmpabs_d(ctx, cond, rt, rs, cc);
14260 break;
14261 case 0x2:
14262 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
14263 break;
14264 default:
14265 goto pool32f_invalid;
14267 break;
14268 case C_COND_FMT:
14269 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14270 cond = (ctx->opcode >> 6) & 0xf;
14271 cc = (ctx->opcode >> 13) & 0x7;
14272 fmt = (ctx->opcode >> 10) & 0x3;
14273 switch (fmt) {
14274 case 0x0:
14275 gen_cmp_s(ctx, cond, rt, rs, cc);
14276 break;
14277 case 0x1:
14278 gen_cmp_d(ctx, cond, rt, rs, cc);
14279 break;
14280 case 0x2:
14281 gen_cmp_ps(ctx, cond, rt, rs, cc);
14282 break;
14283 default:
14284 goto pool32f_invalid;
14286 break;
14287 case CMP_CONDN_S:
14288 check_insn(ctx, ISA_MIPS32R6);
14289 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14290 break;
14291 case CMP_CONDN_D:
14292 check_insn(ctx, ISA_MIPS32R6);
14293 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
14294 break;
14295 case POOL32FXF:
14296 gen_pool32fxf(ctx, rt, rs);
14297 break;
14298 case 0x00:
14299 /* PLL foo */
14300 switch ((ctx->opcode >> 6) & 0x7) {
14301 case PLL_PS:
14302 mips32_op = OPC_PLL_PS;
14303 goto do_ps;
14304 case PLU_PS:
14305 mips32_op = OPC_PLU_PS;
14306 goto do_ps;
14307 case PUL_PS:
14308 mips32_op = OPC_PUL_PS;
14309 goto do_ps;
14310 case PUU_PS:
14311 mips32_op = OPC_PUU_PS;
14312 goto do_ps;
14313 case CVT_PS_S:
14314 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14315 mips32_op = OPC_CVT_PS_S;
14316 do_ps:
14317 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14318 break;
14319 default:
14320 goto pool32f_invalid;
14322 break;
14323 case MIN_FMT:
14324 check_insn(ctx, ISA_MIPS32R6);
14325 switch ((ctx->opcode >> 9) & 0x3) {
14326 case FMT_SDPS_S:
14327 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
14328 break;
14329 case FMT_SDPS_D:
14330 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
14331 break;
14332 default:
14333 goto pool32f_invalid;
14335 break;
14336 case 0x08:
14337 /* [LS][WDU]XC1 */
14338 switch ((ctx->opcode >> 6) & 0x7) {
14339 case LWXC1:
14340 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14341 mips32_op = OPC_LWXC1;
14342 goto do_ldst_cp1;
14343 case SWXC1:
14344 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14345 mips32_op = OPC_SWXC1;
14346 goto do_ldst_cp1;
14347 case LDXC1:
14348 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14349 mips32_op = OPC_LDXC1;
14350 goto do_ldst_cp1;
14351 case SDXC1:
14352 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14353 mips32_op = OPC_SDXC1;
14354 goto do_ldst_cp1;
14355 case LUXC1:
14356 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14357 mips32_op = OPC_LUXC1;
14358 goto do_ldst_cp1;
14359 case SUXC1:
14360 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14361 mips32_op = OPC_SUXC1;
14362 do_ldst_cp1:
14363 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
14364 break;
14365 default:
14366 goto pool32f_invalid;
14368 break;
14369 case MAX_FMT:
14370 check_insn(ctx, ISA_MIPS32R6);
14371 switch ((ctx->opcode >> 9) & 0x3) {
14372 case FMT_SDPS_S:
14373 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
14374 break;
14375 case FMT_SDPS_D:
14376 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
14377 break;
14378 default:
14379 goto pool32f_invalid;
14381 break;
14382 case 0x18:
14383 /* 3D insns */
14384 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14385 fmt = (ctx->opcode >> 9) & 0x3;
14386 switch ((ctx->opcode >> 6) & 0x7) {
14387 case RSQRT2_FMT:
14388 switch (fmt) {
14389 case FMT_SDPS_S:
14390 mips32_op = OPC_RSQRT2_S;
14391 goto do_3d;
14392 case FMT_SDPS_D:
14393 mips32_op = OPC_RSQRT2_D;
14394 goto do_3d;
14395 case FMT_SDPS_PS:
14396 mips32_op = OPC_RSQRT2_PS;
14397 goto do_3d;
14398 default:
14399 goto pool32f_invalid;
14401 break;
14402 case RECIP2_FMT:
14403 switch (fmt) {
14404 case FMT_SDPS_S:
14405 mips32_op = OPC_RECIP2_S;
14406 goto do_3d;
14407 case FMT_SDPS_D:
14408 mips32_op = OPC_RECIP2_D;
14409 goto do_3d;
14410 case FMT_SDPS_PS:
14411 mips32_op = OPC_RECIP2_PS;
14412 goto do_3d;
14413 default:
14414 goto pool32f_invalid;
14416 break;
14417 case ADDR_PS:
14418 mips32_op = OPC_ADDR_PS;
14419 goto do_3d;
14420 case MULR_PS:
14421 mips32_op = OPC_MULR_PS;
14422 do_3d:
14423 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14424 break;
14425 default:
14426 goto pool32f_invalid;
14428 break;
14429 case 0x20:
14430 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
14431 cc = (ctx->opcode >> 13) & 0x7;
14432 fmt = (ctx->opcode >> 9) & 0x3;
14433 switch ((ctx->opcode >> 6) & 0x7) {
14434 case MOVF_FMT: /* RINT_FMT */
14435 if (ctx->insn_flags & ISA_MIPS32R6) {
14436 /* RINT_FMT */
14437 switch (fmt) {
14438 case FMT_SDPS_S:
14439 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
14440 break;
14441 case FMT_SDPS_D:
14442 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
14443 break;
14444 default:
14445 goto pool32f_invalid;
14447 } else {
14448 /* MOVF_FMT */
14449 switch (fmt) {
14450 case FMT_SDPS_S:
14451 gen_movcf_s(ctx, rs, rt, cc, 0);
14452 break;
14453 case FMT_SDPS_D:
14454 gen_movcf_d(ctx, rs, rt, cc, 0);
14455 break;
14456 case FMT_SDPS_PS:
14457 check_ps(ctx);
14458 gen_movcf_ps(ctx, rs, rt, cc, 0);
14459 break;
14460 default:
14461 goto pool32f_invalid;
14464 break;
14465 case MOVT_FMT: /* CLASS_FMT */
14466 if (ctx->insn_flags & ISA_MIPS32R6) {
14467 /* CLASS_FMT */
14468 switch (fmt) {
14469 case FMT_SDPS_S:
14470 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
14471 break;
14472 case FMT_SDPS_D:
14473 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
14474 break;
14475 default:
14476 goto pool32f_invalid;
14478 } else {
14479 /* MOVT_FMT */
14480 switch (fmt) {
14481 case FMT_SDPS_S:
14482 gen_movcf_s(ctx, rs, rt, cc, 1);
14483 break;
14484 case FMT_SDPS_D:
14485 gen_movcf_d(ctx, rs, rt, cc, 1);
14486 break;
14487 case FMT_SDPS_PS:
14488 check_ps(ctx);
14489 gen_movcf_ps(ctx, rs, rt, cc, 1);
14490 break;
14491 default:
14492 goto pool32f_invalid;
14495 break;
14496 case PREFX:
14497 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14498 break;
14499 default:
14500 goto pool32f_invalid;
14502 break;
14503 #define FINSN_3ARG_SDPS(prfx) \
14504 switch ((ctx->opcode >> 8) & 0x3) { \
14505 case FMT_SDPS_S: \
14506 mips32_op = OPC_##prfx##_S; \
14507 goto do_fpop; \
14508 case FMT_SDPS_D: \
14509 mips32_op = OPC_##prfx##_D; \
14510 goto do_fpop; \
14511 case FMT_SDPS_PS: \
14512 check_ps(ctx); \
14513 mips32_op = OPC_##prfx##_PS; \
14514 goto do_fpop; \
14515 default: \
14516 goto pool32f_invalid; \
14518 case MINA_FMT:
14519 check_insn(ctx, ISA_MIPS32R6);
14520 switch ((ctx->opcode >> 9) & 0x3) {
14521 case FMT_SDPS_S:
14522 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
14523 break;
14524 case FMT_SDPS_D:
14525 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
14526 break;
14527 default:
14528 goto pool32f_invalid;
14530 break;
14531 case MAXA_FMT:
14532 check_insn(ctx, ISA_MIPS32R6);
14533 switch ((ctx->opcode >> 9) & 0x3) {
14534 case FMT_SDPS_S:
14535 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
14536 break;
14537 case FMT_SDPS_D:
14538 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
14539 break;
14540 default:
14541 goto pool32f_invalid;
14543 break;
14544 case 0x30:
14545 /* regular FP ops */
14546 switch ((ctx->opcode >> 6) & 0x3) {
14547 case ADD_FMT:
14548 FINSN_3ARG_SDPS(ADD);
14549 break;
14550 case SUB_FMT:
14551 FINSN_3ARG_SDPS(SUB);
14552 break;
14553 case MUL_FMT:
14554 FINSN_3ARG_SDPS(MUL);
14555 break;
14556 case DIV_FMT:
14557 fmt = (ctx->opcode >> 8) & 0x3;
14558 if (fmt == 1) {
14559 mips32_op = OPC_DIV_D;
14560 } else if (fmt == 0) {
14561 mips32_op = OPC_DIV_S;
14562 } else {
14563 goto pool32f_invalid;
14565 goto do_fpop;
14566 default:
14567 goto pool32f_invalid;
14569 break;
14570 case 0x38:
14571 /* cmovs */
14572 switch ((ctx->opcode >> 6) & 0x7) {
14573 case MOVN_FMT: /* SELNEZ_FMT */
14574 if (ctx->insn_flags & ISA_MIPS32R6) {
14575 /* SELNEZ_FMT */
14576 switch ((ctx->opcode >> 9) & 0x3) {
14577 case FMT_SDPS_S:
14578 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
14579 break;
14580 case FMT_SDPS_D:
14581 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
14582 break;
14583 default:
14584 goto pool32f_invalid;
14586 } else {
14587 /* MOVN_FMT */
14588 FINSN_3ARG_SDPS(MOVN);
14590 break;
14591 case MOVN_FMT_04:
14592 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14593 FINSN_3ARG_SDPS(MOVN);
14594 break;
14595 case MOVZ_FMT: /* SELEQZ_FMT */
14596 if (ctx->insn_flags & ISA_MIPS32R6) {
14597 /* SELEQZ_FMT */
14598 switch ((ctx->opcode >> 9) & 0x3) {
14599 case FMT_SDPS_S:
14600 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
14601 break;
14602 case FMT_SDPS_D:
14603 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
14604 break;
14605 default:
14606 goto pool32f_invalid;
14608 } else {
14609 /* MOVZ_FMT */
14610 FINSN_3ARG_SDPS(MOVZ);
14612 break;
14613 case MOVZ_FMT_05:
14614 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14615 FINSN_3ARG_SDPS(MOVZ);
14616 break;
14617 case SEL_FMT:
14618 check_insn(ctx, ISA_MIPS32R6);
14619 switch ((ctx->opcode >> 9) & 0x3) {
14620 case FMT_SDPS_S:
14621 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
14622 break;
14623 case FMT_SDPS_D:
14624 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
14625 break;
14626 default:
14627 goto pool32f_invalid;
14629 break;
14630 case MADDF_FMT:
14631 check_insn(ctx, ISA_MIPS32R6);
14632 switch ((ctx->opcode >> 9) & 0x3) {
14633 case FMT_SDPS_S:
14634 mips32_op = OPC_MADDF_S;
14635 goto do_fpop;
14636 case FMT_SDPS_D:
14637 mips32_op = OPC_MADDF_D;
14638 goto do_fpop;
14639 default:
14640 goto pool32f_invalid;
14642 break;
14643 case MSUBF_FMT:
14644 check_insn(ctx, ISA_MIPS32R6);
14645 switch ((ctx->opcode >> 9) & 0x3) {
14646 case FMT_SDPS_S:
14647 mips32_op = OPC_MSUBF_S;
14648 goto do_fpop;
14649 case FMT_SDPS_D:
14650 mips32_op = OPC_MSUBF_D;
14651 goto do_fpop;
14652 default:
14653 goto pool32f_invalid;
14655 break;
14656 default:
14657 goto pool32f_invalid;
14659 break;
14660 do_fpop:
14661 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
14662 break;
14663 default:
14664 pool32f_invalid:
14665 MIPS_INVAL("pool32f");
14666 generate_exception_end(ctx, EXCP_RI);
14667 break;
14669 } else {
14670 generate_exception_err(ctx, EXCP_CpU, 1);
14672 break;
14673 case POOL32I:
14674 minor = (ctx->opcode >> 21) & 0x1f;
14675 switch (minor) {
14676 case BLTZ:
14677 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14678 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
14679 break;
14680 case BLTZAL:
14681 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14682 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
14683 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14684 break;
14685 case BLTZALS:
14686 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14687 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
14688 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14689 break;
14690 case BGEZ:
14691 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14692 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
14693 break;
14694 case BGEZAL:
14695 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14696 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
14697 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14698 break;
14699 case BGEZALS:
14700 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14701 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
14702 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14703 break;
14704 case BLEZ:
14705 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14706 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
14707 break;
14708 case BGTZ:
14709 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14710 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
14711 break;
14713 /* Traps */
14714 case TLTI: /* BC1EQZC */
14715 if (ctx->insn_flags & ISA_MIPS32R6) {
14716 /* BC1EQZC */
14717 check_cp1_enabled(ctx);
14718 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
14719 } else {
14720 /* TLTI */
14721 mips32_op = OPC_TLTI;
14722 goto do_trapi;
14724 break;
14725 case TGEI: /* BC1NEZC */
14726 if (ctx->insn_flags & ISA_MIPS32R6) {
14727 /* BC1NEZC */
14728 check_cp1_enabled(ctx);
14729 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
14730 } else {
14731 /* TGEI */
14732 mips32_op = OPC_TGEI;
14733 goto do_trapi;
14735 break;
14736 case TLTIU:
14737 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14738 mips32_op = OPC_TLTIU;
14739 goto do_trapi;
14740 case TGEIU:
14741 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14742 mips32_op = OPC_TGEIU;
14743 goto do_trapi;
14744 case TNEI: /* SYNCI */
14745 if (ctx->insn_flags & ISA_MIPS32R6) {
14746 /* SYNCI */
14747 /* Break the TB to be able to sync copied instructions
14748 immediately */
14749 ctx->bstate = BS_STOP;
14750 } else {
14751 /* TNEI */
14752 mips32_op = OPC_TNEI;
14753 goto do_trapi;
14755 break;
14756 case TEQI:
14757 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14758 mips32_op = OPC_TEQI;
14759 do_trapi:
14760 gen_trap(ctx, mips32_op, rs, -1, imm);
14761 break;
14763 case BNEZC:
14764 case BEQZC:
14765 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14766 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
14767 4, rs, 0, imm << 1, 0);
14768 /* Compact branches don't have a delay slot, so just let
14769 the normal delay slot handling take us to the branch
14770 target. */
14771 break;
14772 case LUI:
14773 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14774 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
14775 break;
14776 case SYNCI:
14777 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14778 /* Break the TB to be able to sync copied instructions
14779 immediately */
14780 ctx->bstate = BS_STOP;
14781 break;
14782 case BC2F:
14783 case BC2T:
14784 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14785 /* COP2: Not implemented. */
14786 generate_exception_err(ctx, EXCP_CpU, 2);
14787 break;
14788 case BC1F:
14789 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14790 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
14791 goto do_cp1branch;
14792 case BC1T:
14793 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14794 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
14795 goto do_cp1branch;
14796 case BC1ANY4F:
14797 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14798 mips32_op = OPC_BC1FANY4;
14799 goto do_cp1mips3d;
14800 case BC1ANY4T:
14801 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14802 mips32_op = OPC_BC1TANY4;
14803 do_cp1mips3d:
14804 check_cop1x(ctx);
14805 check_insn(ctx, ASE_MIPS3D);
14806 /* Fall through */
14807 do_cp1branch:
14808 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
14809 check_cp1_enabled(ctx);
14810 gen_compute_branch1(ctx, mips32_op,
14811 (ctx->opcode >> 18) & 0x7, imm << 1);
14812 } else {
14813 generate_exception_err(ctx, EXCP_CpU, 1);
14815 break;
14816 case BPOSGE64:
14817 case BPOSGE32:
14818 /* MIPS DSP: not implemented */
14819 /* Fall through */
14820 default:
14821 MIPS_INVAL("pool32i");
14822 generate_exception_end(ctx, EXCP_RI);
14823 break;
14825 break;
14826 case POOL32C:
14827 minor = (ctx->opcode >> 12) & 0xf;
14828 offset = sextract32(ctx->opcode, 0,
14829 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
14830 switch (minor) {
14831 case LWL:
14832 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14833 mips32_op = OPC_LWL;
14834 goto do_ld_lr;
14835 case SWL:
14836 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14837 mips32_op = OPC_SWL;
14838 goto do_st_lr;
14839 case LWR:
14840 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14841 mips32_op = OPC_LWR;
14842 goto do_ld_lr;
14843 case SWR:
14844 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14845 mips32_op = OPC_SWR;
14846 goto do_st_lr;
14847 #if defined(TARGET_MIPS64)
14848 case LDL:
14849 check_insn(ctx, ISA_MIPS3);
14850 check_mips_64(ctx);
14851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14852 mips32_op = OPC_LDL;
14853 goto do_ld_lr;
14854 case SDL:
14855 check_insn(ctx, ISA_MIPS3);
14856 check_mips_64(ctx);
14857 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14858 mips32_op = OPC_SDL;
14859 goto do_st_lr;
14860 case LDR:
14861 check_insn(ctx, ISA_MIPS3);
14862 check_mips_64(ctx);
14863 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14864 mips32_op = OPC_LDR;
14865 goto do_ld_lr;
14866 case SDR:
14867 check_insn(ctx, ISA_MIPS3);
14868 check_mips_64(ctx);
14869 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14870 mips32_op = OPC_SDR;
14871 goto do_st_lr;
14872 case LWU:
14873 check_insn(ctx, ISA_MIPS3);
14874 check_mips_64(ctx);
14875 mips32_op = OPC_LWU;
14876 goto do_ld_lr;
14877 case LLD:
14878 check_insn(ctx, ISA_MIPS3);
14879 check_mips_64(ctx);
14880 mips32_op = OPC_LLD;
14881 goto do_ld_lr;
14882 #endif
14883 case LL:
14884 mips32_op = OPC_LL;
14885 goto do_ld_lr;
14886 do_ld_lr:
14887 gen_ld(ctx, mips32_op, rt, rs, offset);
14888 break;
14889 do_st_lr:
14890 gen_st(ctx, mips32_op, rt, rs, offset);
14891 break;
14892 case SC:
14893 gen_st_cond(ctx, OPC_SC, rt, rs, offset);
14894 break;
14895 #if defined(TARGET_MIPS64)
14896 case SCD:
14897 check_insn(ctx, ISA_MIPS3);
14898 check_mips_64(ctx);
14899 gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
14900 break;
14901 #endif
14902 case LD_EVA:
14903 if (!ctx->eva) {
14904 MIPS_INVAL("pool32c ld-eva");
14905 generate_exception_end(ctx, EXCP_RI);
14906 break;
14908 check_cp0_enabled(ctx);
14910 minor2 = (ctx->opcode >> 9) & 0x7;
14911 offset = sextract32(ctx->opcode, 0, 9);
14912 switch (minor2) {
14913 case LBUE:
14914 mips32_op = OPC_LBUE;
14915 goto do_ld_lr;
14916 case LHUE:
14917 mips32_op = OPC_LHUE;
14918 goto do_ld_lr;
14919 case LWLE:
14920 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14921 mips32_op = OPC_LWLE;
14922 goto do_ld_lr;
14923 case LWRE:
14924 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14925 mips32_op = OPC_LWRE;
14926 goto do_ld_lr;
14927 case LBE:
14928 mips32_op = OPC_LBE;
14929 goto do_ld_lr;
14930 case LHE:
14931 mips32_op = OPC_LHE;
14932 goto do_ld_lr;
14933 case LLE:
14934 mips32_op = OPC_LLE;
14935 goto do_ld_lr;
14936 case LWE:
14937 mips32_op = OPC_LWE;
14938 goto do_ld_lr;
14940 break;
14941 case ST_EVA:
14942 if (!ctx->eva) {
14943 MIPS_INVAL("pool32c st-eva");
14944 generate_exception_end(ctx, EXCP_RI);
14945 break;
14947 check_cp0_enabled(ctx);
14949 minor2 = (ctx->opcode >> 9) & 0x7;
14950 offset = sextract32(ctx->opcode, 0, 9);
14951 switch (minor2) {
14952 case SWLE:
14953 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14954 mips32_op = OPC_SWLE;
14955 goto do_st_lr;
14956 case SWRE:
14957 check_insn_opc_removed(ctx, ISA_MIPS32R6);
14958 mips32_op = OPC_SWRE;
14959 goto do_st_lr;
14960 case PREFE:
14961 /* Treat as no-op */
14962 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14963 /* hint codes 24-31 are reserved and signal RI */
14964 generate_exception(ctx, EXCP_RI);
14966 break;
14967 case CACHEE:
14968 /* Treat as no-op */
14969 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14970 gen_cache_operation(ctx, rt, rs, offset);
14972 break;
14973 case SBE:
14974 mips32_op = OPC_SBE;
14975 goto do_st_lr;
14976 case SHE:
14977 mips32_op = OPC_SHE;
14978 goto do_st_lr;
14979 case SCE:
14980 gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
14981 break;
14982 case SWE:
14983 mips32_op = OPC_SWE;
14984 goto do_st_lr;
14986 break;
14987 case PREF:
14988 /* Treat as no-op */
14989 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
14990 /* hint codes 24-31 are reserved and signal RI */
14991 generate_exception(ctx, EXCP_RI);
14993 break;
14994 default:
14995 MIPS_INVAL("pool32c");
14996 generate_exception_end(ctx, EXCP_RI);
14997 break;
14999 break;
15000 case ADDI32: /* AUI, LUI */
15001 if (ctx->insn_flags & ISA_MIPS32R6) {
15002 /* AUI, LUI */
15003 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
15004 } else {
15005 /* ADDI32 */
15006 mips32_op = OPC_ADDI;
15007 goto do_addi;
15009 break;
15010 case ADDIU32:
15011 mips32_op = OPC_ADDIU;
15012 do_addi:
15013 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
15014 break;
15016 /* Logical operations */
15017 case ORI32:
15018 mips32_op = OPC_ORI;
15019 goto do_logici;
15020 case XORI32:
15021 mips32_op = OPC_XORI;
15022 goto do_logici;
15023 case ANDI32:
15024 mips32_op = OPC_ANDI;
15025 do_logici:
15026 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
15027 break;
15029 /* Set less than immediate */
15030 case SLTI32:
15031 mips32_op = OPC_SLTI;
15032 goto do_slti;
15033 case SLTIU32:
15034 mips32_op = OPC_SLTIU;
15035 do_slti:
15036 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
15037 break;
15038 case JALX32:
15039 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15040 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15041 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
15042 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15043 break;
15044 case JALS32: /* BOVC, BEQC, BEQZALC */
15045 if (ctx->insn_flags & ISA_MIPS32R6) {
15046 if (rs >= rt) {
15047 /* BOVC */
15048 mips32_op = OPC_BOVC;
15049 } else if (rs < rt && rs == 0) {
15050 /* BEQZALC */
15051 mips32_op = OPC_BEQZALC;
15052 } else {
15053 /* BEQC */
15054 mips32_op = OPC_BEQC;
15056 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15057 } else {
15058 /* JALS32 */
15059 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
15060 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
15061 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15063 break;
15064 case BEQ32: /* BC */
15065 if (ctx->insn_flags & ISA_MIPS32R6) {
15066 /* BC */
15067 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
15068 sextract32(ctx->opcode << 1, 0, 27));
15069 } else {
15070 /* BEQ32 */
15071 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
15073 break;
15074 case BNE32: /* BALC */
15075 if (ctx->insn_flags & ISA_MIPS32R6) {
15076 /* BALC */
15077 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
15078 sextract32(ctx->opcode << 1, 0, 27));
15079 } else {
15080 /* BNE32 */
15081 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
15083 break;
15084 case J32: /* BGTZC, BLTZC, BLTC */
15085 if (ctx->insn_flags & ISA_MIPS32R6) {
15086 if (rs == 0 && rt != 0) {
15087 /* BGTZC */
15088 mips32_op = OPC_BGTZC;
15089 } else if (rs != 0 && rt != 0 && rs == rt) {
15090 /* BLTZC */
15091 mips32_op = OPC_BLTZC;
15092 } else {
15093 /* BLTC */
15094 mips32_op = OPC_BLTC;
15096 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15097 } else {
15098 /* J32 */
15099 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
15100 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15102 break;
15103 case JAL32: /* BLEZC, BGEZC, BGEC */
15104 if (ctx->insn_flags & ISA_MIPS32R6) {
15105 if (rs == 0 && rt != 0) {
15106 /* BLEZC */
15107 mips32_op = OPC_BLEZC;
15108 } else if (rs != 0 && rt != 0 && rs == rt) {
15109 /* BGEZC */
15110 mips32_op = OPC_BGEZC;
15111 } else {
15112 /* BGEC */
15113 mips32_op = OPC_BGEC;
15115 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15116 } else {
15117 /* JAL32 */
15118 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
15119 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
15120 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15122 break;
15123 /* Floating point (COP1) */
15124 case LWC132:
15125 mips32_op = OPC_LWC1;
15126 goto do_cop1;
15127 case LDC132:
15128 mips32_op = OPC_LDC1;
15129 goto do_cop1;
15130 case SWC132:
15131 mips32_op = OPC_SWC1;
15132 goto do_cop1;
15133 case SDC132:
15134 mips32_op = OPC_SDC1;
15135 do_cop1:
15136 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
15137 break;
15138 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15139 if (ctx->insn_flags & ISA_MIPS32R6) {
15140 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
15141 switch ((ctx->opcode >> 16) & 0x1f) {
15142 case ADDIUPC_00 ... ADDIUPC_07:
15143 gen_pcrel(ctx, OPC_ADDIUPC, ctx->pc & ~0x3, rt);
15144 break;
15145 case AUIPC:
15146 gen_pcrel(ctx, OPC_AUIPC, ctx->pc, rt);
15147 break;
15148 case ALUIPC:
15149 gen_pcrel(ctx, OPC_ALUIPC, ctx->pc, rt);
15150 break;
15151 case LWPC_08 ... LWPC_0F:
15152 gen_pcrel(ctx, R6_OPC_LWPC, ctx->pc & ~0x3, rt);
15153 break;
15154 default:
15155 generate_exception(ctx, EXCP_RI);
15156 break;
15158 } else {
15159 /* ADDIUPC */
15160 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
15161 int offset = SIMM(ctx->opcode, 0, 23) << 2;
15163 gen_addiupc(ctx, reg, offset, 0, 0);
15165 break;
15166 case BNVC: /* BNEC, BNEZALC */
15167 check_insn(ctx, ISA_MIPS32R6);
15168 if (rs >= rt) {
15169 /* BNVC */
15170 mips32_op = OPC_BNVC;
15171 } else if (rs < rt && rs == 0) {
15172 /* BNEZALC */
15173 mips32_op = OPC_BNEZALC;
15174 } else {
15175 /* BNEC */
15176 mips32_op = OPC_BNEC;
15178 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15179 break;
15180 case R6_BNEZC: /* JIALC */
15181 check_insn(ctx, ISA_MIPS32R6);
15182 if (rt != 0) {
15183 /* BNEZC */
15184 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
15185 sextract32(ctx->opcode << 1, 0, 22));
15186 } else {
15187 /* JIALC */
15188 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
15190 break;
15191 case R6_BEQZC: /* JIC */
15192 check_insn(ctx, ISA_MIPS32R6);
15193 if (rt != 0) {
15194 /* BEQZC */
15195 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
15196 sextract32(ctx->opcode << 1, 0, 22));
15197 } else {
15198 /* JIC */
15199 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
15201 break;
15202 case BLEZALC: /* BGEZALC, BGEUC */
15203 check_insn(ctx, ISA_MIPS32R6);
15204 if (rs == 0 && rt != 0) {
15205 /* BLEZALC */
15206 mips32_op = OPC_BLEZALC;
15207 } else if (rs != 0 && rt != 0 && rs == rt) {
15208 /* BGEZALC */
15209 mips32_op = OPC_BGEZALC;
15210 } else {
15211 /* BGEUC */
15212 mips32_op = OPC_BGEUC;
15214 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15215 break;
15216 case BGTZALC: /* BLTZALC, BLTUC */
15217 check_insn(ctx, ISA_MIPS32R6);
15218 if (rs == 0 && rt != 0) {
15219 /* BGTZALC */
15220 mips32_op = OPC_BGTZALC;
15221 } else if (rs != 0 && rt != 0 && rs == rt) {
15222 /* BLTZALC */
15223 mips32_op = OPC_BLTZALC;
15224 } else {
15225 /* BLTUC */
15226 mips32_op = OPC_BLTUC;
15228 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
15229 break;
15230 /* Loads and stores */
15231 case LB32:
15232 mips32_op = OPC_LB;
15233 goto do_ld;
15234 case LBU32:
15235 mips32_op = OPC_LBU;
15236 goto do_ld;
15237 case LH32:
15238 mips32_op = OPC_LH;
15239 goto do_ld;
15240 case LHU32:
15241 mips32_op = OPC_LHU;
15242 goto do_ld;
15243 case LW32:
15244 mips32_op = OPC_LW;
15245 goto do_ld;
15246 #ifdef TARGET_MIPS64
15247 case LD32:
15248 check_insn(ctx, ISA_MIPS3);
15249 check_mips_64(ctx);
15250 mips32_op = OPC_LD;
15251 goto do_ld;
15252 case SD32:
15253 check_insn(ctx, ISA_MIPS3);
15254 check_mips_64(ctx);
15255 mips32_op = OPC_SD;
15256 goto do_st;
15257 #endif
15258 case SB32:
15259 mips32_op = OPC_SB;
15260 goto do_st;
15261 case SH32:
15262 mips32_op = OPC_SH;
15263 goto do_st;
15264 case SW32:
15265 mips32_op = OPC_SW;
15266 goto do_st;
15267 do_ld:
15268 gen_ld(ctx, mips32_op, rt, rs, imm);
15269 break;
15270 do_st:
15271 gen_st(ctx, mips32_op, rt, rs, imm);
15272 break;
15273 default:
15274 generate_exception_end(ctx, EXCP_RI);
15275 break;
15279 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
15281 uint32_t op;
15283 /* make sure instructions are on a halfword boundary */
15284 if (ctx->pc & 0x1) {
15285 env->CP0_BadVAddr = ctx->pc;
15286 generate_exception_end(ctx, EXCP_AdEL);
15287 return 2;
15290 op = (ctx->opcode >> 10) & 0x3f;
15291 /* Enforce properly-sized instructions in a delay slot */
15292 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
15293 switch (op & 0x7) { /* MSB-3..MSB-5 */
15294 case 0:
15295 /* POOL32A, POOL32B, POOL32I, POOL32C */
15296 case 4:
15297 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
15298 case 5:
15299 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
15300 case 6:
15301 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
15302 case 7:
15303 /* LB32, LH32, LWC132, LDC132, LW32 */
15304 if (ctx->hflags & MIPS_HFLAG_BDS16) {
15305 generate_exception_end(ctx, EXCP_RI);
15306 return 2;
15308 break;
15309 case 1:
15310 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
15311 case 2:
15312 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
15313 case 3:
15314 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
15315 if (ctx->hflags & MIPS_HFLAG_BDS32) {
15316 generate_exception_end(ctx, EXCP_RI);
15317 return 2;
15319 break;
15323 switch (op) {
15324 case POOL16A:
15326 int rd = mmreg(uMIPS_RD(ctx->opcode));
15327 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
15328 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
15329 uint32_t opc = 0;
15331 switch (ctx->opcode & 0x1) {
15332 case ADDU16:
15333 opc = OPC_ADDU;
15334 break;
15335 case SUBU16:
15336 opc = OPC_SUBU;
15337 break;
15339 if (ctx->insn_flags & ISA_MIPS32R6) {
15340 /* In the Release 6 the register number location in
15341 * the instruction encoding has changed.
15343 gen_arith(ctx, opc, rs1, rd, rs2);
15344 } else {
15345 gen_arith(ctx, opc, rd, rs1, rs2);
15348 break;
15349 case POOL16B:
15351 int rd = mmreg(uMIPS_RD(ctx->opcode));
15352 int rs = mmreg(uMIPS_RS(ctx->opcode));
15353 int amount = (ctx->opcode >> 1) & 0x7;
15354 uint32_t opc = 0;
15355 amount = amount == 0 ? 8 : amount;
15357 switch (ctx->opcode & 0x1) {
15358 case SLL16:
15359 opc = OPC_SLL;
15360 break;
15361 case SRL16:
15362 opc = OPC_SRL;
15363 break;
15366 gen_shift_imm(ctx, opc, rd, rs, amount);
15368 break;
15369 case POOL16C:
15370 if (ctx->insn_flags & ISA_MIPS32R6) {
15371 gen_pool16c_r6_insn(ctx);
15372 } else {
15373 gen_pool16c_insn(ctx);
15375 break;
15376 case LWGP16:
15378 int rd = mmreg(uMIPS_RD(ctx->opcode));
15379 int rb = 28; /* GP */
15380 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
15382 gen_ld(ctx, OPC_LW, rd, rb, offset);
15384 break;
15385 case POOL16F:
15386 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15387 if (ctx->opcode & 1) {
15388 generate_exception_end(ctx, EXCP_RI);
15389 } else {
15390 /* MOVEP */
15391 int enc_dest = uMIPS_RD(ctx->opcode);
15392 int enc_rt = uMIPS_RS2(ctx->opcode);
15393 int enc_rs = uMIPS_RS1(ctx->opcode);
15394 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15396 break;
15397 case LBU16:
15399 int rd = mmreg(uMIPS_RD(ctx->opcode));
15400 int rb = mmreg(uMIPS_RS(ctx->opcode));
15401 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15402 offset = (offset == 0xf ? -1 : offset);
15404 gen_ld(ctx, OPC_LBU, rd, rb, offset);
15406 break;
15407 case LHU16:
15409 int rd = mmreg(uMIPS_RD(ctx->opcode));
15410 int rb = mmreg(uMIPS_RS(ctx->opcode));
15411 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15413 gen_ld(ctx, OPC_LHU, rd, rb, offset);
15415 break;
15416 case LWSP16:
15418 int rd = (ctx->opcode >> 5) & 0x1f;
15419 int rb = 29; /* SP */
15420 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15422 gen_ld(ctx, OPC_LW, rd, rb, offset);
15424 break;
15425 case LW16:
15427 int rd = mmreg(uMIPS_RD(ctx->opcode));
15428 int rb = mmreg(uMIPS_RS(ctx->opcode));
15429 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15431 gen_ld(ctx, OPC_LW, rd, rb, offset);
15433 break;
15434 case SB16:
15436 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15437 int rb = mmreg(uMIPS_RS(ctx->opcode));
15438 int16_t offset = ZIMM(ctx->opcode, 0, 4);
15440 gen_st(ctx, OPC_SB, rd, rb, offset);
15442 break;
15443 case SH16:
15445 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15446 int rb = mmreg(uMIPS_RS(ctx->opcode));
15447 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
15449 gen_st(ctx, OPC_SH, rd, rb, offset);
15451 break;
15452 case SWSP16:
15454 int rd = (ctx->opcode >> 5) & 0x1f;
15455 int rb = 29; /* SP */
15456 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
15458 gen_st(ctx, OPC_SW, rd, rb, offset);
15460 break;
15461 case SW16:
15463 int rd = mmreg2(uMIPS_RD(ctx->opcode));
15464 int rb = mmreg(uMIPS_RS(ctx->opcode));
15465 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
15467 gen_st(ctx, OPC_SW, rd, rb, offset);
15469 break;
15470 case MOVE16:
15472 int rd = uMIPS_RD5(ctx->opcode);
15473 int rs = uMIPS_RS5(ctx->opcode);
15475 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
15477 break;
15478 case ANDI16:
15479 gen_andi16(ctx);
15480 break;
15481 case POOL16D:
15482 switch (ctx->opcode & 0x1) {
15483 case ADDIUS5:
15484 gen_addius5(ctx);
15485 break;
15486 case ADDIUSP:
15487 gen_addiusp(ctx);
15488 break;
15490 break;
15491 case POOL16E:
15492 switch (ctx->opcode & 0x1) {
15493 case ADDIUR2:
15494 gen_addiur2(ctx);
15495 break;
15496 case ADDIUR1SP:
15497 gen_addiur1sp(ctx);
15498 break;
15500 break;
15501 case B16: /* BC16 */
15502 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
15503 sextract32(ctx->opcode, 0, 10) << 1,
15504 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15505 break;
15506 case BNEZ16: /* BNEZC16 */
15507 case BEQZ16: /* BEQZC16 */
15508 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
15509 mmreg(uMIPS_RD(ctx->opcode)),
15510 0, sextract32(ctx->opcode, 0, 7) << 1,
15511 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
15513 break;
15514 case LI16:
15516 int reg = mmreg(uMIPS_RD(ctx->opcode));
15517 int imm = ZIMM(ctx->opcode, 0, 7);
15519 imm = (imm == 0x7f ? -1 : imm);
15520 tcg_gen_movi_tl(cpu_gpr[reg], imm);
15522 break;
15523 case RES_29:
15524 case RES_31:
15525 case RES_39:
15526 generate_exception_end(ctx, EXCP_RI);
15527 break;
15528 default:
15529 decode_micromips32_opc(env, ctx);
15530 return 4;
15533 return 2;
15536 /* SmartMIPS extension to MIPS32 */
15538 #if defined(TARGET_MIPS64)
15540 /* MDMX extension to MIPS64 */
15542 #endif
15544 /* MIPSDSP functions. */
15545 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
15546 int rd, int base, int offset)
15548 TCGv t0;
15550 check_dsp(ctx);
15551 t0 = tcg_temp_new();
15553 if (base == 0) {
15554 gen_load_gpr(t0, offset);
15555 } else if (offset == 0) {
15556 gen_load_gpr(t0, base);
15557 } else {
15558 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
15561 switch (opc) {
15562 case OPC_LBUX:
15563 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
15564 gen_store_gpr(t0, rd);
15565 break;
15566 case OPC_LHX:
15567 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
15568 gen_store_gpr(t0, rd);
15569 break;
15570 case OPC_LWX:
15571 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
15572 gen_store_gpr(t0, rd);
15573 break;
15574 #if defined(TARGET_MIPS64)
15575 case OPC_LDX:
15576 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
15577 gen_store_gpr(t0, rd);
15578 break;
15579 #endif
15581 tcg_temp_free(t0);
15584 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
15585 int ret, int v1, int v2)
15587 TCGv v1_t;
15588 TCGv v2_t;
15590 if (ret == 0) {
15591 /* Treat as NOP. */
15592 return;
15595 v1_t = tcg_temp_new();
15596 v2_t = tcg_temp_new();
15598 gen_load_gpr(v1_t, v1);
15599 gen_load_gpr(v2_t, v2);
15601 switch (op1) {
15602 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
15603 case OPC_MULT_G_2E:
15604 check_dspr2(ctx);
15605 switch (op2) {
15606 case OPC_ADDUH_QB:
15607 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
15608 break;
15609 case OPC_ADDUH_R_QB:
15610 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15611 break;
15612 case OPC_ADDQH_PH:
15613 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
15614 break;
15615 case OPC_ADDQH_R_PH:
15616 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15617 break;
15618 case OPC_ADDQH_W:
15619 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
15620 break;
15621 case OPC_ADDQH_R_W:
15622 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15623 break;
15624 case OPC_SUBUH_QB:
15625 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
15626 break;
15627 case OPC_SUBUH_R_QB:
15628 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
15629 break;
15630 case OPC_SUBQH_PH:
15631 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
15632 break;
15633 case OPC_SUBQH_R_PH:
15634 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
15635 break;
15636 case OPC_SUBQH_W:
15637 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
15638 break;
15639 case OPC_SUBQH_R_W:
15640 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
15641 break;
15643 break;
15644 case OPC_ABSQ_S_PH_DSP:
15645 switch (op2) {
15646 case OPC_ABSQ_S_QB:
15647 check_dspr2(ctx);
15648 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
15649 break;
15650 case OPC_ABSQ_S_PH:
15651 check_dsp(ctx);
15652 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
15653 break;
15654 case OPC_ABSQ_S_W:
15655 check_dsp(ctx);
15656 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
15657 break;
15658 case OPC_PRECEQ_W_PHL:
15659 check_dsp(ctx);
15660 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
15661 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15662 break;
15663 case OPC_PRECEQ_W_PHR:
15664 check_dsp(ctx);
15665 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
15666 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
15667 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
15668 break;
15669 case OPC_PRECEQU_PH_QBL:
15670 check_dsp(ctx);
15671 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
15672 break;
15673 case OPC_PRECEQU_PH_QBR:
15674 check_dsp(ctx);
15675 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
15676 break;
15677 case OPC_PRECEQU_PH_QBLA:
15678 check_dsp(ctx);
15679 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
15680 break;
15681 case OPC_PRECEQU_PH_QBRA:
15682 check_dsp(ctx);
15683 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
15684 break;
15685 case OPC_PRECEU_PH_QBL:
15686 check_dsp(ctx);
15687 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
15688 break;
15689 case OPC_PRECEU_PH_QBR:
15690 check_dsp(ctx);
15691 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
15692 break;
15693 case OPC_PRECEU_PH_QBLA:
15694 check_dsp(ctx);
15695 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
15696 break;
15697 case OPC_PRECEU_PH_QBRA:
15698 check_dsp(ctx);
15699 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
15700 break;
15702 break;
15703 case OPC_ADDU_QB_DSP:
15704 switch (op2) {
15705 case OPC_ADDQ_PH:
15706 check_dsp(ctx);
15707 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15708 break;
15709 case OPC_ADDQ_S_PH:
15710 check_dsp(ctx);
15711 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15712 break;
15713 case OPC_ADDQ_S_W:
15714 check_dsp(ctx);
15715 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15716 break;
15717 case OPC_ADDU_QB:
15718 check_dsp(ctx);
15719 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15720 break;
15721 case OPC_ADDU_S_QB:
15722 check_dsp(ctx);
15723 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15724 break;
15725 case OPC_ADDU_PH:
15726 check_dspr2(ctx);
15727 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15728 break;
15729 case OPC_ADDU_S_PH:
15730 check_dspr2(ctx);
15731 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15732 break;
15733 case OPC_SUBQ_PH:
15734 check_dsp(ctx);
15735 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15736 break;
15737 case OPC_SUBQ_S_PH:
15738 check_dsp(ctx);
15739 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15740 break;
15741 case OPC_SUBQ_S_W:
15742 check_dsp(ctx);
15743 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15744 break;
15745 case OPC_SUBU_QB:
15746 check_dsp(ctx);
15747 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15748 break;
15749 case OPC_SUBU_S_QB:
15750 check_dsp(ctx);
15751 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15752 break;
15753 case OPC_SUBU_PH:
15754 check_dspr2(ctx);
15755 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15756 break;
15757 case OPC_SUBU_S_PH:
15758 check_dspr2(ctx);
15759 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15760 break;
15761 case OPC_ADDSC:
15762 check_dsp(ctx);
15763 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15764 break;
15765 case OPC_ADDWC:
15766 check_dsp(ctx);
15767 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15768 break;
15769 case OPC_MODSUB:
15770 check_dsp(ctx);
15771 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
15772 break;
15773 case OPC_RADDU_W_QB:
15774 check_dsp(ctx);
15775 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
15776 break;
15778 break;
15779 case OPC_CMPU_EQ_QB_DSP:
15780 switch (op2) {
15781 case OPC_PRECR_QB_PH:
15782 check_dspr2(ctx);
15783 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15784 break;
15785 case OPC_PRECRQ_QB_PH:
15786 check_dsp(ctx);
15787 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
15788 break;
15789 case OPC_PRECR_SRA_PH_W:
15790 check_dspr2(ctx);
15792 TCGv_i32 sa_t = tcg_const_i32(v2);
15793 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
15794 cpu_gpr[ret]);
15795 tcg_temp_free_i32(sa_t);
15796 break;
15798 case OPC_PRECR_SRA_R_PH_W:
15799 check_dspr2(ctx);
15801 TCGv_i32 sa_t = tcg_const_i32(v2);
15802 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
15803 cpu_gpr[ret]);
15804 tcg_temp_free_i32(sa_t);
15805 break;
15807 case OPC_PRECRQ_PH_W:
15808 check_dsp(ctx);
15809 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
15810 break;
15811 case OPC_PRECRQ_RS_PH_W:
15812 check_dsp(ctx);
15813 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15814 break;
15815 case OPC_PRECRQU_S_QB_PH:
15816 check_dsp(ctx);
15817 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15818 break;
15820 break;
15821 #ifdef TARGET_MIPS64
15822 case OPC_ABSQ_S_QH_DSP:
15823 switch (op2) {
15824 case OPC_PRECEQ_L_PWL:
15825 check_dsp(ctx);
15826 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
15827 break;
15828 case OPC_PRECEQ_L_PWR:
15829 check_dsp(ctx);
15830 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
15831 break;
15832 case OPC_PRECEQ_PW_QHL:
15833 check_dsp(ctx);
15834 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
15835 break;
15836 case OPC_PRECEQ_PW_QHR:
15837 check_dsp(ctx);
15838 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
15839 break;
15840 case OPC_PRECEQ_PW_QHLA:
15841 check_dsp(ctx);
15842 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
15843 break;
15844 case OPC_PRECEQ_PW_QHRA:
15845 check_dsp(ctx);
15846 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
15847 break;
15848 case OPC_PRECEQU_QH_OBL:
15849 check_dsp(ctx);
15850 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
15851 break;
15852 case OPC_PRECEQU_QH_OBR:
15853 check_dsp(ctx);
15854 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
15855 break;
15856 case OPC_PRECEQU_QH_OBLA:
15857 check_dsp(ctx);
15858 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
15859 break;
15860 case OPC_PRECEQU_QH_OBRA:
15861 check_dsp(ctx);
15862 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
15863 break;
15864 case OPC_PRECEU_QH_OBL:
15865 check_dsp(ctx);
15866 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
15867 break;
15868 case OPC_PRECEU_QH_OBR:
15869 check_dsp(ctx);
15870 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
15871 break;
15872 case OPC_PRECEU_QH_OBLA:
15873 check_dsp(ctx);
15874 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
15875 break;
15876 case OPC_PRECEU_QH_OBRA:
15877 check_dsp(ctx);
15878 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
15879 break;
15880 case OPC_ABSQ_S_OB:
15881 check_dspr2(ctx);
15882 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
15883 break;
15884 case OPC_ABSQ_S_PW:
15885 check_dsp(ctx);
15886 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
15887 break;
15888 case OPC_ABSQ_S_QH:
15889 check_dsp(ctx);
15890 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
15891 break;
15893 break;
15894 case OPC_ADDU_OB_DSP:
15895 switch (op2) {
15896 case OPC_RADDU_L_OB:
15897 check_dsp(ctx);
15898 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
15899 break;
15900 case OPC_SUBQ_PW:
15901 check_dsp(ctx);
15902 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15903 break;
15904 case OPC_SUBQ_S_PW:
15905 check_dsp(ctx);
15906 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15907 break;
15908 case OPC_SUBQ_QH:
15909 check_dsp(ctx);
15910 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15911 break;
15912 case OPC_SUBQ_S_QH:
15913 check_dsp(ctx);
15914 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15915 break;
15916 case OPC_SUBU_OB:
15917 check_dsp(ctx);
15918 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15919 break;
15920 case OPC_SUBU_S_OB:
15921 check_dsp(ctx);
15922 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15923 break;
15924 case OPC_SUBU_QH:
15925 check_dspr2(ctx);
15926 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15927 break;
15928 case OPC_SUBU_S_QH:
15929 check_dspr2(ctx);
15930 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15931 break;
15932 case OPC_SUBUH_OB:
15933 check_dspr2(ctx);
15934 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
15935 break;
15936 case OPC_SUBUH_R_OB:
15937 check_dspr2(ctx);
15938 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15939 break;
15940 case OPC_ADDQ_PW:
15941 check_dsp(ctx);
15942 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15943 break;
15944 case OPC_ADDQ_S_PW:
15945 check_dsp(ctx);
15946 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15947 break;
15948 case OPC_ADDQ_QH:
15949 check_dsp(ctx);
15950 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15951 break;
15952 case OPC_ADDQ_S_QH:
15953 check_dsp(ctx);
15954 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15955 break;
15956 case OPC_ADDU_OB:
15957 check_dsp(ctx);
15958 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15959 break;
15960 case OPC_ADDU_S_OB:
15961 check_dsp(ctx);
15962 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15963 break;
15964 case OPC_ADDU_QH:
15965 check_dspr2(ctx);
15966 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15967 break;
15968 case OPC_ADDU_S_QH:
15969 check_dspr2(ctx);
15970 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15971 break;
15972 case OPC_ADDUH_OB:
15973 check_dspr2(ctx);
15974 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
15975 break;
15976 case OPC_ADDUH_R_OB:
15977 check_dspr2(ctx);
15978 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
15979 break;
15981 break;
15982 case OPC_CMPU_EQ_OB_DSP:
15983 switch (op2) {
15984 case OPC_PRECR_OB_QH:
15985 check_dspr2(ctx);
15986 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
15987 break;
15988 case OPC_PRECR_SRA_QH_PW:
15989 check_dspr2(ctx);
15991 TCGv_i32 ret_t = tcg_const_i32(ret);
15992 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
15993 tcg_temp_free_i32(ret_t);
15994 break;
15996 case OPC_PRECR_SRA_R_QH_PW:
15997 check_dspr2(ctx);
15999 TCGv_i32 sa_v = tcg_const_i32(ret);
16000 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
16001 tcg_temp_free_i32(sa_v);
16002 break;
16004 case OPC_PRECRQ_OB_QH:
16005 check_dsp(ctx);
16006 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
16007 break;
16008 case OPC_PRECRQ_PW_L:
16009 check_dsp(ctx);
16010 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
16011 break;
16012 case OPC_PRECRQ_QH_PW:
16013 check_dsp(ctx);
16014 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
16015 break;
16016 case OPC_PRECRQ_RS_QH_PW:
16017 check_dsp(ctx);
16018 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16019 break;
16020 case OPC_PRECRQU_S_OB_QH:
16021 check_dsp(ctx);
16022 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16023 break;
16025 break;
16026 #endif
16029 tcg_temp_free(v1_t);
16030 tcg_temp_free(v2_t);
16033 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
16034 int ret, int v1, int v2)
16036 uint32_t op2;
16037 TCGv t0;
16038 TCGv v1_t;
16039 TCGv v2_t;
16041 if (ret == 0) {
16042 /* Treat as NOP. */
16043 return;
16046 t0 = tcg_temp_new();
16047 v1_t = tcg_temp_new();
16048 v2_t = tcg_temp_new();
16050 tcg_gen_movi_tl(t0, v1);
16051 gen_load_gpr(v1_t, v1);
16052 gen_load_gpr(v2_t, v2);
16054 switch (opc) {
16055 case OPC_SHLL_QB_DSP:
16057 op2 = MASK_SHLL_QB(ctx->opcode);
16058 switch (op2) {
16059 case OPC_SHLL_QB:
16060 check_dsp(ctx);
16061 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
16062 break;
16063 case OPC_SHLLV_QB:
16064 check_dsp(ctx);
16065 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16066 break;
16067 case OPC_SHLL_PH:
16068 check_dsp(ctx);
16069 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16070 break;
16071 case OPC_SHLLV_PH:
16072 check_dsp(ctx);
16073 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16074 break;
16075 case OPC_SHLL_S_PH:
16076 check_dsp(ctx);
16077 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
16078 break;
16079 case OPC_SHLLV_S_PH:
16080 check_dsp(ctx);
16081 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16082 break;
16083 case OPC_SHLL_S_W:
16084 check_dsp(ctx);
16085 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
16086 break;
16087 case OPC_SHLLV_S_W:
16088 check_dsp(ctx);
16089 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16090 break;
16091 case OPC_SHRL_QB:
16092 check_dsp(ctx);
16093 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
16094 break;
16095 case OPC_SHRLV_QB:
16096 check_dsp(ctx);
16097 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
16098 break;
16099 case OPC_SHRL_PH:
16100 check_dspr2(ctx);
16101 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
16102 break;
16103 case OPC_SHRLV_PH:
16104 check_dspr2(ctx);
16105 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
16106 break;
16107 case OPC_SHRA_QB:
16108 check_dspr2(ctx);
16109 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
16110 break;
16111 case OPC_SHRA_R_QB:
16112 check_dspr2(ctx);
16113 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
16114 break;
16115 case OPC_SHRAV_QB:
16116 check_dspr2(ctx);
16117 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
16118 break;
16119 case OPC_SHRAV_R_QB:
16120 check_dspr2(ctx);
16121 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
16122 break;
16123 case OPC_SHRA_PH:
16124 check_dsp(ctx);
16125 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
16126 break;
16127 case OPC_SHRA_R_PH:
16128 check_dsp(ctx);
16129 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
16130 break;
16131 case OPC_SHRAV_PH:
16132 check_dsp(ctx);
16133 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
16134 break;
16135 case OPC_SHRAV_R_PH:
16136 check_dsp(ctx);
16137 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
16138 break;
16139 case OPC_SHRA_R_W:
16140 check_dsp(ctx);
16141 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
16142 break;
16143 case OPC_SHRAV_R_W:
16144 check_dsp(ctx);
16145 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
16146 break;
16147 default: /* Invalid */
16148 MIPS_INVAL("MASK SHLL.QB");
16149 generate_exception_end(ctx, EXCP_RI);
16150 break;
16152 break;
16154 #ifdef TARGET_MIPS64
16155 case OPC_SHLL_OB_DSP:
16156 op2 = MASK_SHLL_OB(ctx->opcode);
16157 switch (op2) {
16158 case OPC_SHLL_PW:
16159 check_dsp(ctx);
16160 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16161 break;
16162 case OPC_SHLLV_PW:
16163 check_dsp(ctx);
16164 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16165 break;
16166 case OPC_SHLL_S_PW:
16167 check_dsp(ctx);
16168 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
16169 break;
16170 case OPC_SHLLV_S_PW:
16171 check_dsp(ctx);
16172 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16173 break;
16174 case OPC_SHLL_OB:
16175 check_dsp(ctx);
16176 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
16177 break;
16178 case OPC_SHLLV_OB:
16179 check_dsp(ctx);
16180 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16181 break;
16182 case OPC_SHLL_QH:
16183 check_dsp(ctx);
16184 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16185 break;
16186 case OPC_SHLLV_QH:
16187 check_dsp(ctx);
16188 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16189 break;
16190 case OPC_SHLL_S_QH:
16191 check_dsp(ctx);
16192 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
16193 break;
16194 case OPC_SHLLV_S_QH:
16195 check_dsp(ctx);
16196 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
16197 break;
16198 case OPC_SHRA_OB:
16199 check_dspr2(ctx);
16200 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
16201 break;
16202 case OPC_SHRAV_OB:
16203 check_dspr2(ctx);
16204 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
16205 break;
16206 case OPC_SHRA_R_OB:
16207 check_dspr2(ctx);
16208 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
16209 break;
16210 case OPC_SHRAV_R_OB:
16211 check_dspr2(ctx);
16212 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
16213 break;
16214 case OPC_SHRA_PW:
16215 check_dsp(ctx);
16216 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
16217 break;
16218 case OPC_SHRAV_PW:
16219 check_dsp(ctx);
16220 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
16221 break;
16222 case OPC_SHRA_R_PW:
16223 check_dsp(ctx);
16224 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
16225 break;
16226 case OPC_SHRAV_R_PW:
16227 check_dsp(ctx);
16228 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
16229 break;
16230 case OPC_SHRA_QH:
16231 check_dsp(ctx);
16232 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
16233 break;
16234 case OPC_SHRAV_QH:
16235 check_dsp(ctx);
16236 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
16237 break;
16238 case OPC_SHRA_R_QH:
16239 check_dsp(ctx);
16240 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
16241 break;
16242 case OPC_SHRAV_R_QH:
16243 check_dsp(ctx);
16244 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
16245 break;
16246 case OPC_SHRL_OB:
16247 check_dsp(ctx);
16248 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
16249 break;
16250 case OPC_SHRLV_OB:
16251 check_dsp(ctx);
16252 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
16253 break;
16254 case OPC_SHRL_QH:
16255 check_dspr2(ctx);
16256 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
16257 break;
16258 case OPC_SHRLV_QH:
16259 check_dspr2(ctx);
16260 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
16261 break;
16262 default: /* Invalid */
16263 MIPS_INVAL("MASK SHLL.OB");
16264 generate_exception_end(ctx, EXCP_RI);
16265 break;
16267 break;
16268 #endif
16271 tcg_temp_free(t0);
16272 tcg_temp_free(v1_t);
16273 tcg_temp_free(v2_t);
16276 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
16277 int ret, int v1, int v2, int check_ret)
16279 TCGv_i32 t0;
16280 TCGv v1_t;
16281 TCGv v2_t;
16283 if ((ret == 0) && (check_ret == 1)) {
16284 /* Treat as NOP. */
16285 return;
16288 t0 = tcg_temp_new_i32();
16289 v1_t = tcg_temp_new();
16290 v2_t = tcg_temp_new();
16292 tcg_gen_movi_i32(t0, ret);
16293 gen_load_gpr(v1_t, v1);
16294 gen_load_gpr(v2_t, v2);
16296 switch (op1) {
16297 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16298 * the same mask and op1. */
16299 case OPC_MULT_G_2E:
16300 check_dspr2(ctx);
16301 switch (op2) {
16302 case OPC_MUL_PH:
16303 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16304 break;
16305 case OPC_MUL_S_PH:
16306 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16307 break;
16308 case OPC_MULQ_S_W:
16309 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16310 break;
16311 case OPC_MULQ_RS_W:
16312 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16313 break;
16315 break;
16316 case OPC_DPA_W_PH_DSP:
16317 switch (op2) {
16318 case OPC_DPAU_H_QBL:
16319 check_dsp(ctx);
16320 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
16321 break;
16322 case OPC_DPAU_H_QBR:
16323 check_dsp(ctx);
16324 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
16325 break;
16326 case OPC_DPSU_H_QBL:
16327 check_dsp(ctx);
16328 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
16329 break;
16330 case OPC_DPSU_H_QBR:
16331 check_dsp(ctx);
16332 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
16333 break;
16334 case OPC_DPA_W_PH:
16335 check_dspr2(ctx);
16336 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
16337 break;
16338 case OPC_DPAX_W_PH:
16339 check_dspr2(ctx);
16340 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
16341 break;
16342 case OPC_DPAQ_S_W_PH:
16343 check_dsp(ctx);
16344 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16345 break;
16346 case OPC_DPAQX_S_W_PH:
16347 check_dspr2(ctx);
16348 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16349 break;
16350 case OPC_DPAQX_SA_W_PH:
16351 check_dspr2(ctx);
16352 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16353 break;
16354 case OPC_DPS_W_PH:
16355 check_dspr2(ctx);
16356 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
16357 break;
16358 case OPC_DPSX_W_PH:
16359 check_dspr2(ctx);
16360 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
16361 break;
16362 case OPC_DPSQ_S_W_PH:
16363 check_dsp(ctx);
16364 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16365 break;
16366 case OPC_DPSQX_S_W_PH:
16367 check_dspr2(ctx);
16368 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
16369 break;
16370 case OPC_DPSQX_SA_W_PH:
16371 check_dspr2(ctx);
16372 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
16373 break;
16374 case OPC_MULSAQ_S_W_PH:
16375 check_dsp(ctx);
16376 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
16377 break;
16378 case OPC_DPAQ_SA_L_W:
16379 check_dsp(ctx);
16380 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16381 break;
16382 case OPC_DPSQ_SA_L_W:
16383 check_dsp(ctx);
16384 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
16385 break;
16386 case OPC_MAQ_S_W_PHL:
16387 check_dsp(ctx);
16388 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
16389 break;
16390 case OPC_MAQ_S_W_PHR:
16391 check_dsp(ctx);
16392 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
16393 break;
16394 case OPC_MAQ_SA_W_PHL:
16395 check_dsp(ctx);
16396 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
16397 break;
16398 case OPC_MAQ_SA_W_PHR:
16399 check_dsp(ctx);
16400 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
16401 break;
16402 case OPC_MULSA_W_PH:
16403 check_dspr2(ctx);
16404 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
16405 break;
16407 break;
16408 #ifdef TARGET_MIPS64
16409 case OPC_DPAQ_W_QH_DSP:
16411 int ac = ret & 0x03;
16412 tcg_gen_movi_i32(t0, ac);
16414 switch (op2) {
16415 case OPC_DMADD:
16416 check_dsp(ctx);
16417 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
16418 break;
16419 case OPC_DMADDU:
16420 check_dsp(ctx);
16421 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
16422 break;
16423 case OPC_DMSUB:
16424 check_dsp(ctx);
16425 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
16426 break;
16427 case OPC_DMSUBU:
16428 check_dsp(ctx);
16429 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
16430 break;
16431 case OPC_DPA_W_QH:
16432 check_dspr2(ctx);
16433 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
16434 break;
16435 case OPC_DPAQ_S_W_QH:
16436 check_dsp(ctx);
16437 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16438 break;
16439 case OPC_DPAQ_SA_L_PW:
16440 check_dsp(ctx);
16441 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16442 break;
16443 case OPC_DPAU_H_OBL:
16444 check_dsp(ctx);
16445 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
16446 break;
16447 case OPC_DPAU_H_OBR:
16448 check_dsp(ctx);
16449 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
16450 break;
16451 case OPC_DPS_W_QH:
16452 check_dspr2(ctx);
16453 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
16454 break;
16455 case OPC_DPSQ_S_W_QH:
16456 check_dsp(ctx);
16457 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16458 break;
16459 case OPC_DPSQ_SA_L_PW:
16460 check_dsp(ctx);
16461 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
16462 break;
16463 case OPC_DPSU_H_OBL:
16464 check_dsp(ctx);
16465 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
16466 break;
16467 case OPC_DPSU_H_OBR:
16468 check_dsp(ctx);
16469 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
16470 break;
16471 case OPC_MAQ_S_L_PWL:
16472 check_dsp(ctx);
16473 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
16474 break;
16475 case OPC_MAQ_S_L_PWR:
16476 check_dsp(ctx);
16477 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
16478 break;
16479 case OPC_MAQ_S_W_QHLL:
16480 check_dsp(ctx);
16481 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
16482 break;
16483 case OPC_MAQ_SA_W_QHLL:
16484 check_dsp(ctx);
16485 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
16486 break;
16487 case OPC_MAQ_S_W_QHLR:
16488 check_dsp(ctx);
16489 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
16490 break;
16491 case OPC_MAQ_SA_W_QHLR:
16492 check_dsp(ctx);
16493 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
16494 break;
16495 case OPC_MAQ_S_W_QHRL:
16496 check_dsp(ctx);
16497 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
16498 break;
16499 case OPC_MAQ_SA_W_QHRL:
16500 check_dsp(ctx);
16501 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
16502 break;
16503 case OPC_MAQ_S_W_QHRR:
16504 check_dsp(ctx);
16505 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
16506 break;
16507 case OPC_MAQ_SA_W_QHRR:
16508 check_dsp(ctx);
16509 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
16510 break;
16511 case OPC_MULSAQ_S_L_PW:
16512 check_dsp(ctx);
16513 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
16514 break;
16515 case OPC_MULSAQ_S_W_QH:
16516 check_dsp(ctx);
16517 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
16518 break;
16521 break;
16522 #endif
16523 case OPC_ADDU_QB_DSP:
16524 switch (op2) {
16525 case OPC_MULEU_S_PH_QBL:
16526 check_dsp(ctx);
16527 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16528 break;
16529 case OPC_MULEU_S_PH_QBR:
16530 check_dsp(ctx);
16531 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16532 break;
16533 case OPC_MULQ_RS_PH:
16534 check_dsp(ctx);
16535 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16536 break;
16537 case OPC_MULEQ_S_W_PHL:
16538 check_dsp(ctx);
16539 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16540 break;
16541 case OPC_MULEQ_S_W_PHR:
16542 check_dsp(ctx);
16543 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16544 break;
16545 case OPC_MULQ_S_PH:
16546 check_dspr2(ctx);
16547 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16548 break;
16550 break;
16551 #ifdef TARGET_MIPS64
16552 case OPC_ADDU_OB_DSP:
16553 switch (op2) {
16554 case OPC_MULEQ_S_PW_QHL:
16555 check_dsp(ctx);
16556 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16557 break;
16558 case OPC_MULEQ_S_PW_QHR:
16559 check_dsp(ctx);
16560 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16561 break;
16562 case OPC_MULEU_S_QH_OBL:
16563 check_dsp(ctx);
16564 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16565 break;
16566 case OPC_MULEU_S_QH_OBR:
16567 check_dsp(ctx);
16568 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16569 break;
16570 case OPC_MULQ_RS_QH:
16571 check_dsp(ctx);
16572 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16573 break;
16575 break;
16576 #endif
16579 tcg_temp_free_i32(t0);
16580 tcg_temp_free(v1_t);
16581 tcg_temp_free(v2_t);
16584 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16585 int ret, int val)
16587 int16_t imm;
16588 TCGv t0;
16589 TCGv val_t;
16591 if (ret == 0) {
16592 /* Treat as NOP. */
16593 return;
16596 t0 = tcg_temp_new();
16597 val_t = tcg_temp_new();
16598 gen_load_gpr(val_t, val);
16600 switch (op1) {
16601 case OPC_ABSQ_S_PH_DSP:
16602 switch (op2) {
16603 case OPC_BITREV:
16604 check_dsp(ctx);
16605 gen_helper_bitrev(cpu_gpr[ret], val_t);
16606 break;
16607 case OPC_REPL_QB:
16608 check_dsp(ctx);
16610 target_long result;
16611 imm = (ctx->opcode >> 16) & 0xFF;
16612 result = (uint32_t)imm << 24 |
16613 (uint32_t)imm << 16 |
16614 (uint32_t)imm << 8 |
16615 (uint32_t)imm;
16616 result = (int32_t)result;
16617 tcg_gen_movi_tl(cpu_gpr[ret], result);
16619 break;
16620 case OPC_REPLV_QB:
16621 check_dsp(ctx);
16622 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16623 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16624 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16625 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16626 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16627 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16628 break;
16629 case OPC_REPL_PH:
16630 check_dsp(ctx);
16632 imm = (ctx->opcode >> 16) & 0x03FF;
16633 imm = (int16_t)(imm << 6) >> 6;
16634 tcg_gen_movi_tl(cpu_gpr[ret], \
16635 (target_long)((int32_t)imm << 16 | \
16636 (uint16_t)imm));
16638 break;
16639 case OPC_REPLV_PH:
16640 check_dsp(ctx);
16641 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16642 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16643 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16644 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
16645 break;
16647 break;
16648 #ifdef TARGET_MIPS64
16649 case OPC_ABSQ_S_QH_DSP:
16650 switch (op2) {
16651 case OPC_REPL_OB:
16652 check_dsp(ctx);
16654 target_long temp;
16656 imm = (ctx->opcode >> 16) & 0xFF;
16657 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
16658 temp = (temp << 16) | temp;
16659 temp = (temp << 32) | temp;
16660 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16661 break;
16663 case OPC_REPL_PW:
16664 check_dsp(ctx);
16666 target_long temp;
16668 imm = (ctx->opcode >> 16) & 0x03FF;
16669 imm = (int16_t)(imm << 6) >> 6;
16670 temp = ((target_long)imm << 32) \
16671 | ((target_long)imm & 0xFFFFFFFF);
16672 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16673 break;
16675 case OPC_REPL_QH:
16676 check_dsp(ctx);
16678 target_long temp;
16680 imm = (ctx->opcode >> 16) & 0x03FF;
16681 imm = (int16_t)(imm << 6) >> 6;
16683 temp = ((uint64_t)(uint16_t)imm << 48) |
16684 ((uint64_t)(uint16_t)imm << 32) |
16685 ((uint64_t)(uint16_t)imm << 16) |
16686 (uint64_t)(uint16_t)imm;
16687 tcg_gen_movi_tl(cpu_gpr[ret], temp);
16688 break;
16690 case OPC_REPLV_OB:
16691 check_dsp(ctx);
16692 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
16693 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
16694 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16695 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16696 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16697 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16698 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16699 break;
16700 case OPC_REPLV_PW:
16701 check_dsp(ctx);
16702 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
16703 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16704 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16705 break;
16706 case OPC_REPLV_QH:
16707 check_dsp(ctx);
16708 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
16709 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
16710 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16711 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
16712 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
16713 break;
16715 break;
16716 #endif
16718 tcg_temp_free(t0);
16719 tcg_temp_free(val_t);
16722 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
16723 uint32_t op1, uint32_t op2,
16724 int ret, int v1, int v2, int check_ret)
16726 TCGv t1;
16727 TCGv v1_t;
16728 TCGv v2_t;
16730 if ((ret == 0) && (check_ret == 1)) {
16731 /* Treat as NOP. */
16732 return;
16735 t1 = tcg_temp_new();
16736 v1_t = tcg_temp_new();
16737 v2_t = tcg_temp_new();
16739 gen_load_gpr(v1_t, v1);
16740 gen_load_gpr(v2_t, v2);
16742 switch (op1) {
16743 case OPC_CMPU_EQ_QB_DSP:
16744 switch (op2) {
16745 case OPC_CMPU_EQ_QB:
16746 check_dsp(ctx);
16747 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
16748 break;
16749 case OPC_CMPU_LT_QB:
16750 check_dsp(ctx);
16751 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
16752 break;
16753 case OPC_CMPU_LE_QB:
16754 check_dsp(ctx);
16755 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
16756 break;
16757 case OPC_CMPGU_EQ_QB:
16758 check_dsp(ctx);
16759 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
16760 break;
16761 case OPC_CMPGU_LT_QB:
16762 check_dsp(ctx);
16763 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
16764 break;
16765 case OPC_CMPGU_LE_QB:
16766 check_dsp(ctx);
16767 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
16768 break;
16769 case OPC_CMPGDU_EQ_QB:
16770 check_dspr2(ctx);
16771 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
16772 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16773 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16774 tcg_gen_shli_tl(t1, t1, 24);
16775 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16776 break;
16777 case OPC_CMPGDU_LT_QB:
16778 check_dspr2(ctx);
16779 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
16780 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16781 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16782 tcg_gen_shli_tl(t1, t1, 24);
16783 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16784 break;
16785 case OPC_CMPGDU_LE_QB:
16786 check_dspr2(ctx);
16787 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
16788 tcg_gen_mov_tl(cpu_gpr[ret], t1);
16789 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
16790 tcg_gen_shli_tl(t1, t1, 24);
16791 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
16792 break;
16793 case OPC_CMP_EQ_PH:
16794 check_dsp(ctx);
16795 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
16796 break;
16797 case OPC_CMP_LT_PH:
16798 check_dsp(ctx);
16799 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
16800 break;
16801 case OPC_CMP_LE_PH:
16802 check_dsp(ctx);
16803 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
16804 break;
16805 case OPC_PICK_QB:
16806 check_dsp(ctx);
16807 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16808 break;
16809 case OPC_PICK_PH:
16810 check_dsp(ctx);
16811 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16812 break;
16813 case OPC_PACKRL_PH:
16814 check_dsp(ctx);
16815 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
16816 break;
16818 break;
16819 #ifdef TARGET_MIPS64
16820 case OPC_CMPU_EQ_OB_DSP:
16821 switch (op2) {
16822 case OPC_CMP_EQ_PW:
16823 check_dsp(ctx);
16824 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
16825 break;
16826 case OPC_CMP_LT_PW:
16827 check_dsp(ctx);
16828 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
16829 break;
16830 case OPC_CMP_LE_PW:
16831 check_dsp(ctx);
16832 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
16833 break;
16834 case OPC_CMP_EQ_QH:
16835 check_dsp(ctx);
16836 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
16837 break;
16838 case OPC_CMP_LT_QH:
16839 check_dsp(ctx);
16840 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
16841 break;
16842 case OPC_CMP_LE_QH:
16843 check_dsp(ctx);
16844 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
16845 break;
16846 case OPC_CMPGDU_EQ_OB:
16847 check_dspr2(ctx);
16848 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16849 break;
16850 case OPC_CMPGDU_LT_OB:
16851 check_dspr2(ctx);
16852 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16853 break;
16854 case OPC_CMPGDU_LE_OB:
16855 check_dspr2(ctx);
16856 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16857 break;
16858 case OPC_CMPGU_EQ_OB:
16859 check_dsp(ctx);
16860 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
16861 break;
16862 case OPC_CMPGU_LT_OB:
16863 check_dsp(ctx);
16864 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
16865 break;
16866 case OPC_CMPGU_LE_OB:
16867 check_dsp(ctx);
16868 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
16869 break;
16870 case OPC_CMPU_EQ_OB:
16871 check_dsp(ctx);
16872 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
16873 break;
16874 case OPC_CMPU_LT_OB:
16875 check_dsp(ctx);
16876 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
16877 break;
16878 case OPC_CMPU_LE_OB:
16879 check_dsp(ctx);
16880 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
16881 break;
16882 case OPC_PACKRL_PW:
16883 check_dsp(ctx);
16884 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
16885 break;
16886 case OPC_PICK_OB:
16887 check_dsp(ctx);
16888 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16889 break;
16890 case OPC_PICK_PW:
16891 check_dsp(ctx);
16892 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16893 break;
16894 case OPC_PICK_QH:
16895 check_dsp(ctx);
16896 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
16897 break;
16899 break;
16900 #endif
16903 tcg_temp_free(t1);
16904 tcg_temp_free(v1_t);
16905 tcg_temp_free(v2_t);
16908 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
16909 uint32_t op1, int rt, int rs, int sa)
16911 TCGv t0;
16913 check_dspr2(ctx);
16915 if (rt == 0) {
16916 /* Treat as NOP. */
16917 return;
16920 t0 = tcg_temp_new();
16921 gen_load_gpr(t0, rs);
16923 switch (op1) {
16924 case OPC_APPEND_DSP:
16925 switch (MASK_APPEND(ctx->opcode)) {
16926 case OPC_APPEND:
16927 if (sa != 0) {
16928 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
16930 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16931 break;
16932 case OPC_PREPEND:
16933 if (sa != 0) {
16934 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
16935 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16936 tcg_gen_shli_tl(t0, t0, 32 - sa);
16937 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16939 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16940 break;
16941 case OPC_BALIGN:
16942 sa &= 3;
16943 if (sa != 0 && sa != 2) {
16944 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16945 tcg_gen_ext32u_tl(t0, t0);
16946 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
16947 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16949 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
16950 break;
16951 default: /* Invalid */
16952 MIPS_INVAL("MASK APPEND");
16953 generate_exception_end(ctx, EXCP_RI);
16954 break;
16956 break;
16957 #ifdef TARGET_MIPS64
16958 case OPC_DAPPEND_DSP:
16959 switch (MASK_DAPPEND(ctx->opcode)) {
16960 case OPC_DAPPEND:
16961 if (sa != 0) {
16962 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
16964 break;
16965 case OPC_PREPENDD:
16966 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
16967 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
16968 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
16969 break;
16970 case OPC_PREPENDW:
16971 if (sa != 0) {
16972 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
16973 tcg_gen_shli_tl(t0, t0, 64 - sa);
16974 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16976 break;
16977 case OPC_DBALIGN:
16978 sa &= 7;
16979 if (sa != 0 && sa != 2 && sa != 4) {
16980 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
16981 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
16982 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
16984 break;
16985 default: /* Invalid */
16986 MIPS_INVAL("MASK DAPPEND");
16987 generate_exception_end(ctx, EXCP_RI);
16988 break;
16990 break;
16991 #endif
16993 tcg_temp_free(t0);
16996 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
16997 int ret, int v1, int v2, int check_ret)
17000 TCGv t0;
17001 TCGv t1;
17002 TCGv v1_t;
17003 TCGv v2_t;
17004 int16_t imm;
17006 if ((ret == 0) && (check_ret == 1)) {
17007 /* Treat as NOP. */
17008 return;
17011 t0 = tcg_temp_new();
17012 t1 = tcg_temp_new();
17013 v1_t = tcg_temp_new();
17014 v2_t = tcg_temp_new();
17016 gen_load_gpr(v1_t, v1);
17017 gen_load_gpr(v2_t, v2);
17019 switch (op1) {
17020 case OPC_EXTR_W_DSP:
17021 check_dsp(ctx);
17022 switch (op2) {
17023 case OPC_EXTR_W:
17024 tcg_gen_movi_tl(t0, v2);
17025 tcg_gen_movi_tl(t1, v1);
17026 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
17027 break;
17028 case OPC_EXTR_R_W:
17029 tcg_gen_movi_tl(t0, v2);
17030 tcg_gen_movi_tl(t1, v1);
17031 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17032 break;
17033 case OPC_EXTR_RS_W:
17034 tcg_gen_movi_tl(t0, v2);
17035 tcg_gen_movi_tl(t1, v1);
17036 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17037 break;
17038 case OPC_EXTR_S_H:
17039 tcg_gen_movi_tl(t0, v2);
17040 tcg_gen_movi_tl(t1, v1);
17041 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17042 break;
17043 case OPC_EXTRV_S_H:
17044 tcg_gen_movi_tl(t0, v2);
17045 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
17046 break;
17047 case OPC_EXTRV_W:
17048 tcg_gen_movi_tl(t0, v2);
17049 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17050 break;
17051 case OPC_EXTRV_R_W:
17052 tcg_gen_movi_tl(t0, v2);
17053 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17054 break;
17055 case OPC_EXTRV_RS_W:
17056 tcg_gen_movi_tl(t0, v2);
17057 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17058 break;
17059 case OPC_EXTP:
17060 tcg_gen_movi_tl(t0, v2);
17061 tcg_gen_movi_tl(t1, v1);
17062 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
17063 break;
17064 case OPC_EXTPV:
17065 tcg_gen_movi_tl(t0, v2);
17066 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
17067 break;
17068 case OPC_EXTPDP:
17069 tcg_gen_movi_tl(t0, v2);
17070 tcg_gen_movi_tl(t1, v1);
17071 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
17072 break;
17073 case OPC_EXTPDPV:
17074 tcg_gen_movi_tl(t0, v2);
17075 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17076 break;
17077 case OPC_SHILO:
17078 imm = (ctx->opcode >> 20) & 0x3F;
17079 tcg_gen_movi_tl(t0, ret);
17080 tcg_gen_movi_tl(t1, imm);
17081 gen_helper_shilo(t0, t1, cpu_env);
17082 break;
17083 case OPC_SHILOV:
17084 tcg_gen_movi_tl(t0, ret);
17085 gen_helper_shilo(t0, v1_t, cpu_env);
17086 break;
17087 case OPC_MTHLIP:
17088 tcg_gen_movi_tl(t0, ret);
17089 gen_helper_mthlip(t0, v1_t, cpu_env);
17090 break;
17091 case OPC_WRDSP:
17092 imm = (ctx->opcode >> 11) & 0x3FF;
17093 tcg_gen_movi_tl(t0, imm);
17094 gen_helper_wrdsp(v1_t, t0, cpu_env);
17095 break;
17096 case OPC_RDDSP:
17097 imm = (ctx->opcode >> 16) & 0x03FF;
17098 tcg_gen_movi_tl(t0, imm);
17099 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
17100 break;
17102 break;
17103 #ifdef TARGET_MIPS64
17104 case OPC_DEXTR_W_DSP:
17105 check_dsp(ctx);
17106 switch (op2) {
17107 case OPC_DMTHLIP:
17108 tcg_gen_movi_tl(t0, ret);
17109 gen_helper_dmthlip(v1_t, t0, cpu_env);
17110 break;
17111 case OPC_DSHILO:
17113 int shift = (ctx->opcode >> 19) & 0x7F;
17114 int ac = (ctx->opcode >> 11) & 0x03;
17115 tcg_gen_movi_tl(t0, shift);
17116 tcg_gen_movi_tl(t1, ac);
17117 gen_helper_dshilo(t0, t1, cpu_env);
17118 break;
17120 case OPC_DSHILOV:
17122 int ac = (ctx->opcode >> 11) & 0x03;
17123 tcg_gen_movi_tl(t0, ac);
17124 gen_helper_dshilo(v1_t, t0, cpu_env);
17125 break;
17127 case OPC_DEXTP:
17128 tcg_gen_movi_tl(t0, v2);
17129 tcg_gen_movi_tl(t1, v1);
17131 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
17132 break;
17133 case OPC_DEXTPV:
17134 tcg_gen_movi_tl(t0, v2);
17135 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
17136 break;
17137 case OPC_DEXTPDP:
17138 tcg_gen_movi_tl(t0, v2);
17139 tcg_gen_movi_tl(t1, v1);
17140 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
17141 break;
17142 case OPC_DEXTPDPV:
17143 tcg_gen_movi_tl(t0, v2);
17144 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
17145 break;
17146 case OPC_DEXTR_L:
17147 tcg_gen_movi_tl(t0, v2);
17148 tcg_gen_movi_tl(t1, v1);
17149 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
17150 break;
17151 case OPC_DEXTR_R_L:
17152 tcg_gen_movi_tl(t0, v2);
17153 tcg_gen_movi_tl(t1, v1);
17154 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
17155 break;
17156 case OPC_DEXTR_RS_L:
17157 tcg_gen_movi_tl(t0, v2);
17158 tcg_gen_movi_tl(t1, v1);
17159 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
17160 break;
17161 case OPC_DEXTR_W:
17162 tcg_gen_movi_tl(t0, v2);
17163 tcg_gen_movi_tl(t1, v1);
17164 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
17165 break;
17166 case OPC_DEXTR_R_W:
17167 tcg_gen_movi_tl(t0, v2);
17168 tcg_gen_movi_tl(t1, v1);
17169 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
17170 break;
17171 case OPC_DEXTR_RS_W:
17172 tcg_gen_movi_tl(t0, v2);
17173 tcg_gen_movi_tl(t1, v1);
17174 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
17175 break;
17176 case OPC_DEXTR_S_H:
17177 tcg_gen_movi_tl(t0, v2);
17178 tcg_gen_movi_tl(t1, v1);
17179 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17180 break;
17181 case OPC_DEXTRV_S_H:
17182 tcg_gen_movi_tl(t0, v2);
17183 tcg_gen_movi_tl(t1, v1);
17184 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
17185 break;
17186 case OPC_DEXTRV_L:
17187 tcg_gen_movi_tl(t0, v2);
17188 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17189 break;
17190 case OPC_DEXTRV_R_L:
17191 tcg_gen_movi_tl(t0, v2);
17192 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17193 break;
17194 case OPC_DEXTRV_RS_L:
17195 tcg_gen_movi_tl(t0, v2);
17196 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
17197 break;
17198 case OPC_DEXTRV_W:
17199 tcg_gen_movi_tl(t0, v2);
17200 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17201 break;
17202 case OPC_DEXTRV_R_W:
17203 tcg_gen_movi_tl(t0, v2);
17204 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17205 break;
17206 case OPC_DEXTRV_RS_W:
17207 tcg_gen_movi_tl(t0, v2);
17208 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
17209 break;
17211 break;
17212 #endif
17215 tcg_temp_free(t0);
17216 tcg_temp_free(t1);
17217 tcg_temp_free(v1_t);
17218 tcg_temp_free(v2_t);
17221 /* End MIPSDSP functions. */
17223 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
17225 int rs, rt, rd, sa;
17226 uint32_t op1, op2;
17228 rs = (ctx->opcode >> 21) & 0x1f;
17229 rt = (ctx->opcode >> 16) & 0x1f;
17230 rd = (ctx->opcode >> 11) & 0x1f;
17231 sa = (ctx->opcode >> 6) & 0x1f;
17233 op1 = MASK_SPECIAL(ctx->opcode);
17234 switch (op1) {
17235 case OPC_LSA:
17236 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17237 break;
17238 case OPC_MULT ... OPC_DIVU:
17239 op2 = MASK_R6_MULDIV(ctx->opcode);
17240 switch (op2) {
17241 case R6_OPC_MUL:
17242 case R6_OPC_MUH:
17243 case R6_OPC_MULU:
17244 case R6_OPC_MUHU:
17245 case R6_OPC_DIV:
17246 case R6_OPC_MOD:
17247 case R6_OPC_DIVU:
17248 case R6_OPC_MODU:
17249 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17250 break;
17251 default:
17252 MIPS_INVAL("special_r6 muldiv");
17253 generate_exception_end(ctx, EXCP_RI);
17254 break;
17256 break;
17257 case OPC_SELEQZ:
17258 case OPC_SELNEZ:
17259 gen_cond_move(ctx, op1, rd, rs, rt);
17260 break;
17261 case R6_OPC_CLO:
17262 case R6_OPC_CLZ:
17263 if (rt == 0 && sa == 1) {
17264 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17265 We need additionally to check other fields */
17266 gen_cl(ctx, op1, rd, rs);
17267 } else {
17268 generate_exception_end(ctx, EXCP_RI);
17270 break;
17271 case R6_OPC_SDBBP:
17272 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17273 gen_helper_do_semihosting(cpu_env);
17274 } else {
17275 if (ctx->hflags & MIPS_HFLAG_SBRI) {
17276 generate_exception_end(ctx, EXCP_RI);
17277 } else {
17278 generate_exception_end(ctx, EXCP_DBp);
17281 break;
17282 #if defined(TARGET_MIPS64)
17283 case OPC_DLSA:
17284 check_mips_64(ctx);
17285 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
17286 break;
17287 case R6_OPC_DCLO:
17288 case R6_OPC_DCLZ:
17289 if (rt == 0 && sa == 1) {
17290 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
17291 We need additionally to check other fields */
17292 check_mips_64(ctx);
17293 gen_cl(ctx, op1, rd, rs);
17294 } else {
17295 generate_exception_end(ctx, EXCP_RI);
17297 break;
17298 case OPC_DMULT ... OPC_DDIVU:
17299 op2 = MASK_R6_MULDIV(ctx->opcode);
17300 switch (op2) {
17301 case R6_OPC_DMUL:
17302 case R6_OPC_DMUH:
17303 case R6_OPC_DMULU:
17304 case R6_OPC_DMUHU:
17305 case R6_OPC_DDIV:
17306 case R6_OPC_DMOD:
17307 case R6_OPC_DDIVU:
17308 case R6_OPC_DMODU:
17309 check_mips_64(ctx);
17310 gen_r6_muldiv(ctx, op2, rd, rs, rt);
17311 break;
17312 default:
17313 MIPS_INVAL("special_r6 muldiv");
17314 generate_exception_end(ctx, EXCP_RI);
17315 break;
17317 break;
17318 #endif
17319 default: /* Invalid */
17320 MIPS_INVAL("special_r6");
17321 generate_exception_end(ctx, EXCP_RI);
17322 break;
17326 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
17328 int rs, rt, rd, sa;
17329 uint32_t op1;
17331 rs = (ctx->opcode >> 21) & 0x1f;
17332 rt = (ctx->opcode >> 16) & 0x1f;
17333 rd = (ctx->opcode >> 11) & 0x1f;
17334 sa = (ctx->opcode >> 6) & 0x1f;
17336 op1 = MASK_SPECIAL(ctx->opcode);
17337 switch (op1) {
17338 case OPC_MOVN: /* Conditional move */
17339 case OPC_MOVZ:
17340 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
17341 INSN_LOONGSON2E | INSN_LOONGSON2F);
17342 gen_cond_move(ctx, op1, rd, rs, rt);
17343 break;
17344 case OPC_MFHI: /* Move from HI/LO */
17345 case OPC_MFLO:
17346 gen_HILO(ctx, op1, rs & 3, rd);
17347 break;
17348 case OPC_MTHI:
17349 case OPC_MTLO: /* Move to HI/LO */
17350 gen_HILO(ctx, op1, rd & 3, rs);
17351 break;
17352 case OPC_MOVCI:
17353 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17354 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17355 check_cp1_enabled(ctx);
17356 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
17357 (ctx->opcode >> 16) & 1);
17358 } else {
17359 generate_exception_err(ctx, EXCP_CpU, 1);
17361 break;
17362 case OPC_MULT:
17363 case OPC_MULTU:
17364 if (sa) {
17365 check_insn(ctx, INSN_VR54XX);
17366 op1 = MASK_MUL_VR54XX(ctx->opcode);
17367 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
17368 } else {
17369 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17371 break;
17372 case OPC_DIV:
17373 case OPC_DIVU:
17374 gen_muldiv(ctx, op1, 0, rs, rt);
17375 break;
17376 #if defined(TARGET_MIPS64)
17377 case OPC_DMULT ... OPC_DDIVU:
17378 check_insn(ctx, ISA_MIPS3);
17379 check_mips_64(ctx);
17380 gen_muldiv(ctx, op1, 0, rs, rt);
17381 break;
17382 #endif
17383 case OPC_JR:
17384 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17385 break;
17386 case OPC_SPIM:
17387 #ifdef MIPS_STRICT_STANDARD
17388 MIPS_INVAL("SPIM");
17389 generate_exception_end(ctx, EXCP_RI);
17390 #else
17391 /* Implemented as RI exception for now. */
17392 MIPS_INVAL("spim (unofficial)");
17393 generate_exception_end(ctx, EXCP_RI);
17394 #endif
17395 break;
17396 default: /* Invalid */
17397 MIPS_INVAL("special_legacy");
17398 generate_exception_end(ctx, EXCP_RI);
17399 break;
17403 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
17405 int rs, rt, rd, sa;
17406 uint32_t op1;
17408 rs = (ctx->opcode >> 21) & 0x1f;
17409 rt = (ctx->opcode >> 16) & 0x1f;
17410 rd = (ctx->opcode >> 11) & 0x1f;
17411 sa = (ctx->opcode >> 6) & 0x1f;
17413 op1 = MASK_SPECIAL(ctx->opcode);
17414 switch (op1) {
17415 case OPC_SLL: /* Shift with immediate */
17416 if (sa == 5 && rd == 0 &&
17417 rs == 0 && rt == 0) { /* PAUSE */
17418 if ((ctx->insn_flags & ISA_MIPS32R6) &&
17419 (ctx->hflags & MIPS_HFLAG_BMASK)) {
17420 generate_exception_end(ctx, EXCP_RI);
17421 break;
17424 /* Fallthrough */
17425 case OPC_SRA:
17426 gen_shift_imm(ctx, op1, rd, rt, sa);
17427 break;
17428 case OPC_SRL:
17429 switch ((ctx->opcode >> 21) & 0x1f) {
17430 case 1:
17431 /* rotr is decoded as srl on non-R2 CPUs */
17432 if (ctx->insn_flags & ISA_MIPS32R2) {
17433 op1 = OPC_ROTR;
17435 /* Fallthrough */
17436 case 0:
17437 gen_shift_imm(ctx, op1, rd, rt, sa);
17438 break;
17439 default:
17440 generate_exception_end(ctx, EXCP_RI);
17441 break;
17443 break;
17444 case OPC_ADD ... OPC_SUBU:
17445 gen_arith(ctx, op1, rd, rs, rt);
17446 break;
17447 case OPC_SLLV: /* Shifts */
17448 case OPC_SRAV:
17449 gen_shift(ctx, op1, rd, rs, rt);
17450 break;
17451 case OPC_SRLV:
17452 switch ((ctx->opcode >> 6) & 0x1f) {
17453 case 1:
17454 /* rotrv is decoded as srlv on non-R2 CPUs */
17455 if (ctx->insn_flags & ISA_MIPS32R2) {
17456 op1 = OPC_ROTRV;
17458 /* Fallthrough */
17459 case 0:
17460 gen_shift(ctx, op1, rd, rs, rt);
17461 break;
17462 default:
17463 generate_exception_end(ctx, EXCP_RI);
17464 break;
17466 break;
17467 case OPC_SLT: /* Set on less than */
17468 case OPC_SLTU:
17469 gen_slt(ctx, op1, rd, rs, rt);
17470 break;
17471 case OPC_AND: /* Logic*/
17472 case OPC_OR:
17473 case OPC_NOR:
17474 case OPC_XOR:
17475 gen_logic(ctx, op1, rd, rs, rt);
17476 break;
17477 case OPC_JALR:
17478 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
17479 break;
17480 case OPC_TGE ... OPC_TEQ: /* Traps */
17481 case OPC_TNE:
17482 check_insn(ctx, ISA_MIPS2);
17483 gen_trap(ctx, op1, rs, rt, -1);
17484 break;
17485 case OPC_LSA: /* OPC_PMON */
17486 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17487 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17488 decode_opc_special_r6(env, ctx);
17489 } else {
17490 /* Pmon entry point, also R4010 selsl */
17491 #ifdef MIPS_STRICT_STANDARD
17492 MIPS_INVAL("PMON / selsl");
17493 generate_exception_end(ctx, EXCP_RI);
17494 #else
17495 gen_helper_0e0i(pmon, sa);
17496 #endif
17498 break;
17499 case OPC_SYSCALL:
17500 generate_exception_end(ctx, EXCP_SYSCALL);
17501 break;
17502 case OPC_BREAK:
17503 generate_exception_end(ctx, EXCP_BREAK);
17504 break;
17505 case OPC_SYNC:
17506 check_insn(ctx, ISA_MIPS2);
17507 gen_sync(extract32(ctx->opcode, 6, 5));
17508 break;
17510 #if defined(TARGET_MIPS64)
17511 /* MIPS64 specific opcodes */
17512 case OPC_DSLL:
17513 case OPC_DSRA:
17514 case OPC_DSLL32:
17515 case OPC_DSRA32:
17516 check_insn(ctx, ISA_MIPS3);
17517 check_mips_64(ctx);
17518 gen_shift_imm(ctx, op1, rd, rt, sa);
17519 break;
17520 case OPC_DSRL:
17521 switch ((ctx->opcode >> 21) & 0x1f) {
17522 case 1:
17523 /* drotr is decoded as dsrl on non-R2 CPUs */
17524 if (ctx->insn_flags & ISA_MIPS32R2) {
17525 op1 = OPC_DROTR;
17527 /* Fallthrough */
17528 case 0:
17529 check_insn(ctx, ISA_MIPS3);
17530 check_mips_64(ctx);
17531 gen_shift_imm(ctx, op1, rd, rt, sa);
17532 break;
17533 default:
17534 generate_exception_end(ctx, EXCP_RI);
17535 break;
17537 break;
17538 case OPC_DSRL32:
17539 switch ((ctx->opcode >> 21) & 0x1f) {
17540 case 1:
17541 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
17542 if (ctx->insn_flags & ISA_MIPS32R2) {
17543 op1 = OPC_DROTR32;
17545 /* Fallthrough */
17546 case 0:
17547 check_insn(ctx, ISA_MIPS3);
17548 check_mips_64(ctx);
17549 gen_shift_imm(ctx, op1, rd, rt, sa);
17550 break;
17551 default:
17552 generate_exception_end(ctx, EXCP_RI);
17553 break;
17555 break;
17556 case OPC_DADD ... OPC_DSUBU:
17557 check_insn(ctx, ISA_MIPS3);
17558 check_mips_64(ctx);
17559 gen_arith(ctx, op1, rd, rs, rt);
17560 break;
17561 case OPC_DSLLV:
17562 case OPC_DSRAV:
17563 check_insn(ctx, ISA_MIPS3);
17564 check_mips_64(ctx);
17565 gen_shift(ctx, op1, rd, rs, rt);
17566 break;
17567 case OPC_DSRLV:
17568 switch ((ctx->opcode >> 6) & 0x1f) {
17569 case 1:
17570 /* drotrv is decoded as dsrlv on non-R2 CPUs */
17571 if (ctx->insn_flags & ISA_MIPS32R2) {
17572 op1 = OPC_DROTRV;
17574 /* Fallthrough */
17575 case 0:
17576 check_insn(ctx, ISA_MIPS3);
17577 check_mips_64(ctx);
17578 gen_shift(ctx, op1, rd, rs, rt);
17579 break;
17580 default:
17581 generate_exception_end(ctx, EXCP_RI);
17582 break;
17584 break;
17585 case OPC_DLSA:
17586 if ((ctx->insn_flags & ISA_MIPS32R6) ||
17587 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
17588 decode_opc_special_r6(env, ctx);
17590 break;
17591 #endif
17592 default:
17593 if (ctx->insn_flags & ISA_MIPS32R6) {
17594 decode_opc_special_r6(env, ctx);
17595 } else {
17596 decode_opc_special_legacy(env, ctx);
17601 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
17603 int rs, rt, rd;
17604 uint32_t op1;
17606 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17608 rs = (ctx->opcode >> 21) & 0x1f;
17609 rt = (ctx->opcode >> 16) & 0x1f;
17610 rd = (ctx->opcode >> 11) & 0x1f;
17612 op1 = MASK_SPECIAL2(ctx->opcode);
17613 switch (op1) {
17614 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
17615 case OPC_MSUB ... OPC_MSUBU:
17616 check_insn(ctx, ISA_MIPS32);
17617 gen_muldiv(ctx, op1, rd & 3, rs, rt);
17618 break;
17619 case OPC_MUL:
17620 gen_arith(ctx, op1, rd, rs, rt);
17621 break;
17622 case OPC_DIV_G_2F:
17623 case OPC_DIVU_G_2F:
17624 case OPC_MULT_G_2F:
17625 case OPC_MULTU_G_2F:
17626 case OPC_MOD_G_2F:
17627 case OPC_MODU_G_2F:
17628 check_insn(ctx, INSN_LOONGSON2F);
17629 gen_loongson_integer(ctx, op1, rd, rs, rt);
17630 break;
17631 case OPC_CLO:
17632 case OPC_CLZ:
17633 check_insn(ctx, ISA_MIPS32);
17634 gen_cl(ctx, op1, rd, rs);
17635 break;
17636 case OPC_SDBBP:
17637 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
17638 gen_helper_do_semihosting(cpu_env);
17639 } else {
17640 /* XXX: not clear which exception should be raised
17641 * when in debug mode...
17643 check_insn(ctx, ISA_MIPS32);
17644 generate_exception_end(ctx, EXCP_DBp);
17646 break;
17647 #if defined(TARGET_MIPS64)
17648 case OPC_DCLO:
17649 case OPC_DCLZ:
17650 check_insn(ctx, ISA_MIPS64);
17651 check_mips_64(ctx);
17652 gen_cl(ctx, op1, rd, rs);
17653 break;
17654 case OPC_DMULT_G_2F:
17655 case OPC_DMULTU_G_2F:
17656 case OPC_DDIV_G_2F:
17657 case OPC_DDIVU_G_2F:
17658 case OPC_DMOD_G_2F:
17659 case OPC_DMODU_G_2F:
17660 check_insn(ctx, INSN_LOONGSON2F);
17661 gen_loongson_integer(ctx, op1, rd, rs, rt);
17662 break;
17663 #endif
17664 default: /* Invalid */
17665 MIPS_INVAL("special2_legacy");
17666 generate_exception_end(ctx, EXCP_RI);
17667 break;
17671 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
17673 int rs, rt, rd, sa;
17674 uint32_t op1, op2;
17675 int16_t imm;
17677 rs = (ctx->opcode >> 21) & 0x1f;
17678 rt = (ctx->opcode >> 16) & 0x1f;
17679 rd = (ctx->opcode >> 11) & 0x1f;
17680 sa = (ctx->opcode >> 6) & 0x1f;
17681 imm = (int16_t)ctx->opcode >> 7;
17683 op1 = MASK_SPECIAL3(ctx->opcode);
17684 switch (op1) {
17685 case R6_OPC_PREF:
17686 if (rt >= 24) {
17687 /* hint codes 24-31 are reserved and signal RI */
17688 generate_exception_end(ctx, EXCP_RI);
17690 /* Treat as NOP. */
17691 break;
17692 case R6_OPC_CACHE:
17693 check_cp0_enabled(ctx);
17694 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17695 gen_cache_operation(ctx, rt, rs, imm);
17697 break;
17698 case R6_OPC_SC:
17699 gen_st_cond(ctx, op1, rt, rs, imm);
17700 break;
17701 case R6_OPC_LL:
17702 gen_ld(ctx, op1, rt, rs, imm);
17703 break;
17704 case OPC_BSHFL:
17706 if (rd == 0) {
17707 /* Treat as NOP. */
17708 break;
17710 op2 = MASK_BSHFL(ctx->opcode);
17711 switch (op2) {
17712 case OPC_ALIGN ... OPC_ALIGN_END:
17713 gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
17714 break;
17715 case OPC_BITSWAP:
17716 gen_bitswap(ctx, op2, rd, rt);
17717 break;
17720 break;
17721 #if defined(TARGET_MIPS64)
17722 case R6_OPC_SCD:
17723 gen_st_cond(ctx, op1, rt, rs, imm);
17724 break;
17725 case R6_OPC_LLD:
17726 gen_ld(ctx, op1, rt, rs, imm);
17727 break;
17728 case OPC_DBSHFL:
17729 check_mips_64(ctx);
17731 if (rd == 0) {
17732 /* Treat as NOP. */
17733 break;
17735 op2 = MASK_DBSHFL(ctx->opcode);
17736 switch (op2) {
17737 case OPC_DALIGN ... OPC_DALIGN_END:
17738 gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
17739 break;
17740 case OPC_DBITSWAP:
17741 gen_bitswap(ctx, op2, rd, rt);
17742 break;
17746 break;
17747 #endif
17748 default: /* Invalid */
17749 MIPS_INVAL("special3_r6");
17750 generate_exception_end(ctx, EXCP_RI);
17751 break;
17755 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
17757 int rs, rt, rd;
17758 uint32_t op1, op2;
17760 rs = (ctx->opcode >> 21) & 0x1f;
17761 rt = (ctx->opcode >> 16) & 0x1f;
17762 rd = (ctx->opcode >> 11) & 0x1f;
17764 op1 = MASK_SPECIAL3(ctx->opcode);
17765 switch (op1) {
17766 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
17767 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
17768 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
17769 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
17770 * the same mask and op1. */
17771 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
17772 op2 = MASK_ADDUH_QB(ctx->opcode);
17773 switch (op2) {
17774 case OPC_ADDUH_QB:
17775 case OPC_ADDUH_R_QB:
17776 case OPC_ADDQH_PH:
17777 case OPC_ADDQH_R_PH:
17778 case OPC_ADDQH_W:
17779 case OPC_ADDQH_R_W:
17780 case OPC_SUBUH_QB:
17781 case OPC_SUBUH_R_QB:
17782 case OPC_SUBQH_PH:
17783 case OPC_SUBQH_R_PH:
17784 case OPC_SUBQH_W:
17785 case OPC_SUBQH_R_W:
17786 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17787 break;
17788 case OPC_MUL_PH:
17789 case OPC_MUL_S_PH:
17790 case OPC_MULQ_S_W:
17791 case OPC_MULQ_RS_W:
17792 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17793 break;
17794 default:
17795 MIPS_INVAL("MASK ADDUH.QB");
17796 generate_exception_end(ctx, EXCP_RI);
17797 break;
17799 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
17800 gen_loongson_integer(ctx, op1, rd, rs, rt);
17801 } else {
17802 generate_exception_end(ctx, EXCP_RI);
17804 break;
17805 case OPC_LX_DSP:
17806 op2 = MASK_LX(ctx->opcode);
17807 switch (op2) {
17808 #if defined(TARGET_MIPS64)
17809 case OPC_LDX:
17810 #endif
17811 case OPC_LBUX:
17812 case OPC_LHX:
17813 case OPC_LWX:
17814 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
17815 break;
17816 default: /* Invalid */
17817 MIPS_INVAL("MASK LX");
17818 generate_exception_end(ctx, EXCP_RI);
17819 break;
17821 break;
17822 case OPC_ABSQ_S_PH_DSP:
17823 op2 = MASK_ABSQ_S_PH(ctx->opcode);
17824 switch (op2) {
17825 case OPC_ABSQ_S_QB:
17826 case OPC_ABSQ_S_PH:
17827 case OPC_ABSQ_S_W:
17828 case OPC_PRECEQ_W_PHL:
17829 case OPC_PRECEQ_W_PHR:
17830 case OPC_PRECEQU_PH_QBL:
17831 case OPC_PRECEQU_PH_QBR:
17832 case OPC_PRECEQU_PH_QBLA:
17833 case OPC_PRECEQU_PH_QBRA:
17834 case OPC_PRECEU_PH_QBL:
17835 case OPC_PRECEU_PH_QBR:
17836 case OPC_PRECEU_PH_QBLA:
17837 case OPC_PRECEU_PH_QBRA:
17838 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17839 break;
17840 case OPC_BITREV:
17841 case OPC_REPL_QB:
17842 case OPC_REPLV_QB:
17843 case OPC_REPL_PH:
17844 case OPC_REPLV_PH:
17845 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
17846 break;
17847 default:
17848 MIPS_INVAL("MASK ABSQ_S.PH");
17849 generate_exception_end(ctx, EXCP_RI);
17850 break;
17852 break;
17853 case OPC_ADDU_QB_DSP:
17854 op2 = MASK_ADDU_QB(ctx->opcode);
17855 switch (op2) {
17856 case OPC_ADDQ_PH:
17857 case OPC_ADDQ_S_PH:
17858 case OPC_ADDQ_S_W:
17859 case OPC_ADDU_QB:
17860 case OPC_ADDU_S_QB:
17861 case OPC_ADDU_PH:
17862 case OPC_ADDU_S_PH:
17863 case OPC_SUBQ_PH:
17864 case OPC_SUBQ_S_PH:
17865 case OPC_SUBQ_S_W:
17866 case OPC_SUBU_QB:
17867 case OPC_SUBU_S_QB:
17868 case OPC_SUBU_PH:
17869 case OPC_SUBU_S_PH:
17870 case OPC_ADDSC:
17871 case OPC_ADDWC:
17872 case OPC_MODSUB:
17873 case OPC_RADDU_W_QB:
17874 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17875 break;
17876 case OPC_MULEU_S_PH_QBL:
17877 case OPC_MULEU_S_PH_QBR:
17878 case OPC_MULQ_RS_PH:
17879 case OPC_MULEQ_S_W_PHL:
17880 case OPC_MULEQ_S_W_PHR:
17881 case OPC_MULQ_S_PH:
17882 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
17883 break;
17884 default: /* Invalid */
17885 MIPS_INVAL("MASK ADDU.QB");
17886 generate_exception_end(ctx, EXCP_RI);
17887 break;
17890 break;
17891 case OPC_CMPU_EQ_QB_DSP:
17892 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
17893 switch (op2) {
17894 case OPC_PRECR_SRA_PH_W:
17895 case OPC_PRECR_SRA_R_PH_W:
17896 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
17897 break;
17898 case OPC_PRECR_QB_PH:
17899 case OPC_PRECRQ_QB_PH:
17900 case OPC_PRECRQ_PH_W:
17901 case OPC_PRECRQ_RS_PH_W:
17902 case OPC_PRECRQU_S_QB_PH:
17903 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
17904 break;
17905 case OPC_CMPU_EQ_QB:
17906 case OPC_CMPU_LT_QB:
17907 case OPC_CMPU_LE_QB:
17908 case OPC_CMP_EQ_PH:
17909 case OPC_CMP_LT_PH:
17910 case OPC_CMP_LE_PH:
17911 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
17912 break;
17913 case OPC_CMPGU_EQ_QB:
17914 case OPC_CMPGU_LT_QB:
17915 case OPC_CMPGU_LE_QB:
17916 case OPC_CMPGDU_EQ_QB:
17917 case OPC_CMPGDU_LT_QB:
17918 case OPC_CMPGDU_LE_QB:
17919 case OPC_PICK_QB:
17920 case OPC_PICK_PH:
17921 case OPC_PACKRL_PH:
17922 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
17923 break;
17924 default: /* Invalid */
17925 MIPS_INVAL("MASK CMPU.EQ.QB");
17926 generate_exception_end(ctx, EXCP_RI);
17927 break;
17929 break;
17930 case OPC_SHLL_QB_DSP:
17931 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
17932 break;
17933 case OPC_DPA_W_PH_DSP:
17934 op2 = MASK_DPA_W_PH(ctx->opcode);
17935 switch (op2) {
17936 case OPC_DPAU_H_QBL:
17937 case OPC_DPAU_H_QBR:
17938 case OPC_DPSU_H_QBL:
17939 case OPC_DPSU_H_QBR:
17940 case OPC_DPA_W_PH:
17941 case OPC_DPAX_W_PH:
17942 case OPC_DPAQ_S_W_PH:
17943 case OPC_DPAQX_S_W_PH:
17944 case OPC_DPAQX_SA_W_PH:
17945 case OPC_DPS_W_PH:
17946 case OPC_DPSX_W_PH:
17947 case OPC_DPSQ_S_W_PH:
17948 case OPC_DPSQX_S_W_PH:
17949 case OPC_DPSQX_SA_W_PH:
17950 case OPC_MULSAQ_S_W_PH:
17951 case OPC_DPAQ_SA_L_W:
17952 case OPC_DPSQ_SA_L_W:
17953 case OPC_MAQ_S_W_PHL:
17954 case OPC_MAQ_S_W_PHR:
17955 case OPC_MAQ_SA_W_PHL:
17956 case OPC_MAQ_SA_W_PHR:
17957 case OPC_MULSA_W_PH:
17958 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
17959 break;
17960 default: /* Invalid */
17961 MIPS_INVAL("MASK DPAW.PH");
17962 generate_exception_end(ctx, EXCP_RI);
17963 break;
17965 break;
17966 case OPC_INSV_DSP:
17967 op2 = MASK_INSV(ctx->opcode);
17968 switch (op2) {
17969 case OPC_INSV:
17970 check_dsp(ctx);
17972 TCGv t0, t1;
17974 if (rt == 0) {
17975 break;
17978 t0 = tcg_temp_new();
17979 t1 = tcg_temp_new();
17981 gen_load_gpr(t0, rt);
17982 gen_load_gpr(t1, rs);
17984 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
17986 tcg_temp_free(t0);
17987 tcg_temp_free(t1);
17988 break;
17990 default: /* Invalid */
17991 MIPS_INVAL("MASK INSV");
17992 generate_exception_end(ctx, EXCP_RI);
17993 break;
17995 break;
17996 case OPC_APPEND_DSP:
17997 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
17998 break;
17999 case OPC_EXTR_W_DSP:
18000 op2 = MASK_EXTR_W(ctx->opcode);
18001 switch (op2) {
18002 case OPC_EXTR_W:
18003 case OPC_EXTR_R_W:
18004 case OPC_EXTR_RS_W:
18005 case OPC_EXTR_S_H:
18006 case OPC_EXTRV_S_H:
18007 case OPC_EXTRV_W:
18008 case OPC_EXTRV_R_W:
18009 case OPC_EXTRV_RS_W:
18010 case OPC_EXTP:
18011 case OPC_EXTPV:
18012 case OPC_EXTPDP:
18013 case OPC_EXTPDPV:
18014 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18015 break;
18016 case OPC_RDDSP:
18017 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
18018 break;
18019 case OPC_SHILO:
18020 case OPC_SHILOV:
18021 case OPC_MTHLIP:
18022 case OPC_WRDSP:
18023 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18024 break;
18025 default: /* Invalid */
18026 MIPS_INVAL("MASK EXTR.W");
18027 generate_exception_end(ctx, EXCP_RI);
18028 break;
18030 break;
18031 #if defined(TARGET_MIPS64)
18032 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
18033 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
18034 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
18035 check_insn(ctx, INSN_LOONGSON2E);
18036 gen_loongson_integer(ctx, op1, rd, rs, rt);
18037 break;
18038 case OPC_ABSQ_S_QH_DSP:
18039 op2 = MASK_ABSQ_S_QH(ctx->opcode);
18040 switch (op2) {
18041 case OPC_PRECEQ_L_PWL:
18042 case OPC_PRECEQ_L_PWR:
18043 case OPC_PRECEQ_PW_QHL:
18044 case OPC_PRECEQ_PW_QHR:
18045 case OPC_PRECEQ_PW_QHLA:
18046 case OPC_PRECEQ_PW_QHRA:
18047 case OPC_PRECEQU_QH_OBL:
18048 case OPC_PRECEQU_QH_OBR:
18049 case OPC_PRECEQU_QH_OBLA:
18050 case OPC_PRECEQU_QH_OBRA:
18051 case OPC_PRECEU_QH_OBL:
18052 case OPC_PRECEU_QH_OBR:
18053 case OPC_PRECEU_QH_OBLA:
18054 case OPC_PRECEU_QH_OBRA:
18055 case OPC_ABSQ_S_OB:
18056 case OPC_ABSQ_S_PW:
18057 case OPC_ABSQ_S_QH:
18058 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18059 break;
18060 case OPC_REPL_OB:
18061 case OPC_REPL_PW:
18062 case OPC_REPL_QH:
18063 case OPC_REPLV_OB:
18064 case OPC_REPLV_PW:
18065 case OPC_REPLV_QH:
18066 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
18067 break;
18068 default: /* Invalid */
18069 MIPS_INVAL("MASK ABSQ_S.QH");
18070 generate_exception_end(ctx, EXCP_RI);
18071 break;
18073 break;
18074 case OPC_ADDU_OB_DSP:
18075 op2 = MASK_ADDU_OB(ctx->opcode);
18076 switch (op2) {
18077 case OPC_RADDU_L_OB:
18078 case OPC_SUBQ_PW:
18079 case OPC_SUBQ_S_PW:
18080 case OPC_SUBQ_QH:
18081 case OPC_SUBQ_S_QH:
18082 case OPC_SUBU_OB:
18083 case OPC_SUBU_S_OB:
18084 case OPC_SUBU_QH:
18085 case OPC_SUBU_S_QH:
18086 case OPC_SUBUH_OB:
18087 case OPC_SUBUH_R_OB:
18088 case OPC_ADDQ_PW:
18089 case OPC_ADDQ_S_PW:
18090 case OPC_ADDQ_QH:
18091 case OPC_ADDQ_S_QH:
18092 case OPC_ADDU_OB:
18093 case OPC_ADDU_S_OB:
18094 case OPC_ADDU_QH:
18095 case OPC_ADDU_S_QH:
18096 case OPC_ADDUH_OB:
18097 case OPC_ADDUH_R_OB:
18098 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18099 break;
18100 case OPC_MULEQ_S_PW_QHL:
18101 case OPC_MULEQ_S_PW_QHR:
18102 case OPC_MULEU_S_QH_OBL:
18103 case OPC_MULEU_S_QH_OBR:
18104 case OPC_MULQ_RS_QH:
18105 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
18106 break;
18107 default: /* Invalid */
18108 MIPS_INVAL("MASK ADDU.OB");
18109 generate_exception_end(ctx, EXCP_RI);
18110 break;
18112 break;
18113 case OPC_CMPU_EQ_OB_DSP:
18114 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
18115 switch (op2) {
18116 case OPC_PRECR_SRA_QH_PW:
18117 case OPC_PRECR_SRA_R_QH_PW:
18118 /* Return value is rt. */
18119 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
18120 break;
18121 case OPC_PRECR_OB_QH:
18122 case OPC_PRECRQ_OB_QH:
18123 case OPC_PRECRQ_PW_L:
18124 case OPC_PRECRQ_QH_PW:
18125 case OPC_PRECRQ_RS_QH_PW:
18126 case OPC_PRECRQU_S_OB_QH:
18127 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
18128 break;
18129 case OPC_CMPU_EQ_OB:
18130 case OPC_CMPU_LT_OB:
18131 case OPC_CMPU_LE_OB:
18132 case OPC_CMP_EQ_QH:
18133 case OPC_CMP_LT_QH:
18134 case OPC_CMP_LE_QH:
18135 case OPC_CMP_EQ_PW:
18136 case OPC_CMP_LT_PW:
18137 case OPC_CMP_LE_PW:
18138 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
18139 break;
18140 case OPC_CMPGDU_EQ_OB:
18141 case OPC_CMPGDU_LT_OB:
18142 case OPC_CMPGDU_LE_OB:
18143 case OPC_CMPGU_EQ_OB:
18144 case OPC_CMPGU_LT_OB:
18145 case OPC_CMPGU_LE_OB:
18146 case OPC_PACKRL_PW:
18147 case OPC_PICK_OB:
18148 case OPC_PICK_PW:
18149 case OPC_PICK_QH:
18150 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
18151 break;
18152 default: /* Invalid */
18153 MIPS_INVAL("MASK CMPU_EQ.OB");
18154 generate_exception_end(ctx, EXCP_RI);
18155 break;
18157 break;
18158 case OPC_DAPPEND_DSP:
18159 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
18160 break;
18161 case OPC_DEXTR_W_DSP:
18162 op2 = MASK_DEXTR_W(ctx->opcode);
18163 switch (op2) {
18164 case OPC_DEXTP:
18165 case OPC_DEXTPDP:
18166 case OPC_DEXTPDPV:
18167 case OPC_DEXTPV:
18168 case OPC_DEXTR_L:
18169 case OPC_DEXTR_R_L:
18170 case OPC_DEXTR_RS_L:
18171 case OPC_DEXTR_W:
18172 case OPC_DEXTR_R_W:
18173 case OPC_DEXTR_RS_W:
18174 case OPC_DEXTR_S_H:
18175 case OPC_DEXTRV_L:
18176 case OPC_DEXTRV_R_L:
18177 case OPC_DEXTRV_RS_L:
18178 case OPC_DEXTRV_S_H:
18179 case OPC_DEXTRV_W:
18180 case OPC_DEXTRV_R_W:
18181 case OPC_DEXTRV_RS_W:
18182 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
18183 break;
18184 case OPC_DMTHLIP:
18185 case OPC_DSHILO:
18186 case OPC_DSHILOV:
18187 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
18188 break;
18189 default: /* Invalid */
18190 MIPS_INVAL("MASK EXTR.W");
18191 generate_exception_end(ctx, EXCP_RI);
18192 break;
18194 break;
18195 case OPC_DPAQ_W_QH_DSP:
18196 op2 = MASK_DPAQ_W_QH(ctx->opcode);
18197 switch (op2) {
18198 case OPC_DPAU_H_OBL:
18199 case OPC_DPAU_H_OBR:
18200 case OPC_DPSU_H_OBL:
18201 case OPC_DPSU_H_OBR:
18202 case OPC_DPA_W_QH:
18203 case OPC_DPAQ_S_W_QH:
18204 case OPC_DPS_W_QH:
18205 case OPC_DPSQ_S_W_QH:
18206 case OPC_MULSAQ_S_W_QH:
18207 case OPC_DPAQ_SA_L_PW:
18208 case OPC_DPSQ_SA_L_PW:
18209 case OPC_MULSAQ_S_L_PW:
18210 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18211 break;
18212 case OPC_MAQ_S_W_QHLL:
18213 case OPC_MAQ_S_W_QHLR:
18214 case OPC_MAQ_S_W_QHRL:
18215 case OPC_MAQ_S_W_QHRR:
18216 case OPC_MAQ_SA_W_QHLL:
18217 case OPC_MAQ_SA_W_QHLR:
18218 case OPC_MAQ_SA_W_QHRL:
18219 case OPC_MAQ_SA_W_QHRR:
18220 case OPC_MAQ_S_L_PWL:
18221 case OPC_MAQ_S_L_PWR:
18222 case OPC_DMADD:
18223 case OPC_DMADDU:
18224 case OPC_DMSUB:
18225 case OPC_DMSUBU:
18226 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
18227 break;
18228 default: /* Invalid */
18229 MIPS_INVAL("MASK DPAQ.W.QH");
18230 generate_exception_end(ctx, EXCP_RI);
18231 break;
18233 break;
18234 case OPC_DINSV_DSP:
18235 op2 = MASK_INSV(ctx->opcode);
18236 switch (op2) {
18237 case OPC_DINSV:
18239 TCGv t0, t1;
18241 if (rt == 0) {
18242 break;
18244 check_dsp(ctx);
18246 t0 = tcg_temp_new();
18247 t1 = tcg_temp_new();
18249 gen_load_gpr(t0, rt);
18250 gen_load_gpr(t1, rs);
18252 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
18254 tcg_temp_free(t0);
18255 tcg_temp_free(t1);
18256 break;
18258 default: /* Invalid */
18259 MIPS_INVAL("MASK DINSV");
18260 generate_exception_end(ctx, EXCP_RI);
18261 break;
18263 break;
18264 case OPC_SHLL_OB_DSP:
18265 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
18266 break;
18267 #endif
18268 default: /* Invalid */
18269 MIPS_INVAL("special3_legacy");
18270 generate_exception_end(ctx, EXCP_RI);
18271 break;
18275 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
18277 int rs, rt, rd, sa;
18278 uint32_t op1, op2;
18279 int16_t imm;
18281 rs = (ctx->opcode >> 21) & 0x1f;
18282 rt = (ctx->opcode >> 16) & 0x1f;
18283 rd = (ctx->opcode >> 11) & 0x1f;
18284 sa = (ctx->opcode >> 6) & 0x1f;
18285 imm = sextract32(ctx->opcode, 7, 9);
18287 op1 = MASK_SPECIAL3(ctx->opcode);
18290 * EVA loads and stores overlap Loongson 2E instructions decoded by
18291 * decode_opc_special3_legacy(), so be careful to allow their decoding when
18292 * EVA is absent.
18294 if (ctx->eva) {
18295 switch (op1) {
18296 case OPC_LWLE ... OPC_LWRE:
18297 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18298 /* fall through */
18299 case OPC_LBUE ... OPC_LHUE:
18300 case OPC_LBE ... OPC_LWE:
18301 check_cp0_enabled(ctx);
18302 gen_ld(ctx, op1, rt, rs, imm);
18303 return;
18304 case OPC_SWLE ... OPC_SWRE:
18305 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18306 /* fall through */
18307 case OPC_SBE ... OPC_SHE:
18308 case OPC_SWE:
18309 check_cp0_enabled(ctx);
18310 gen_st(ctx, op1, rt, rs, imm);
18311 return;
18312 case OPC_SCE:
18313 check_cp0_enabled(ctx);
18314 gen_st_cond(ctx, op1, rt, rs, imm);
18315 return;
18316 case OPC_CACHEE:
18317 check_cp0_enabled(ctx);
18318 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
18319 gen_cache_operation(ctx, rt, rs, imm);
18321 /* Treat as NOP. */
18322 return;
18323 case OPC_PREFE:
18324 check_cp0_enabled(ctx);
18325 /* Treat as NOP. */
18326 return;
18330 switch (op1) {
18331 case OPC_EXT:
18332 case OPC_INS:
18333 check_insn(ctx, ISA_MIPS32R2);
18334 gen_bitops(ctx, op1, rt, rs, sa, rd);
18335 break;
18336 case OPC_BSHFL:
18337 op2 = MASK_BSHFL(ctx->opcode);
18338 switch (op2) {
18339 case OPC_ALIGN ... OPC_ALIGN_END:
18340 case OPC_BITSWAP:
18341 check_insn(ctx, ISA_MIPS32R6);
18342 decode_opc_special3_r6(env, ctx);
18343 break;
18344 default:
18345 check_insn(ctx, ISA_MIPS32R2);
18346 gen_bshfl(ctx, op2, rt, rd);
18347 break;
18349 break;
18350 #if defined(TARGET_MIPS64)
18351 case OPC_DEXTM ... OPC_DEXT:
18352 case OPC_DINSM ... OPC_DINS:
18353 check_insn(ctx, ISA_MIPS64R2);
18354 check_mips_64(ctx);
18355 gen_bitops(ctx, op1, rt, rs, sa, rd);
18356 break;
18357 case OPC_DBSHFL:
18358 op2 = MASK_DBSHFL(ctx->opcode);
18359 switch (op2) {
18360 case OPC_DALIGN ... OPC_DALIGN_END:
18361 case OPC_DBITSWAP:
18362 check_insn(ctx, ISA_MIPS32R6);
18363 decode_opc_special3_r6(env, ctx);
18364 break;
18365 default:
18366 check_insn(ctx, ISA_MIPS64R2);
18367 check_mips_64(ctx);
18368 op2 = MASK_DBSHFL(ctx->opcode);
18369 gen_bshfl(ctx, op2, rt, rd);
18370 break;
18372 break;
18373 #endif
18374 case OPC_RDHWR:
18375 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
18376 break;
18377 case OPC_FORK:
18378 check_insn(ctx, ASE_MT);
18380 TCGv t0 = tcg_temp_new();
18381 TCGv t1 = tcg_temp_new();
18383 gen_load_gpr(t0, rt);
18384 gen_load_gpr(t1, rs);
18385 gen_helper_fork(t0, t1);
18386 tcg_temp_free(t0);
18387 tcg_temp_free(t1);
18389 break;
18390 case OPC_YIELD:
18391 check_insn(ctx, ASE_MT);
18393 TCGv t0 = tcg_temp_new();
18395 gen_load_gpr(t0, rs);
18396 gen_helper_yield(t0, cpu_env, t0);
18397 gen_store_gpr(t0, rd);
18398 tcg_temp_free(t0);
18400 break;
18401 default:
18402 if (ctx->insn_flags & ISA_MIPS32R6) {
18403 decode_opc_special3_r6(env, ctx);
18404 } else {
18405 decode_opc_special3_legacy(env, ctx);
18410 /* MIPS SIMD Architecture (MSA) */
18411 static inline int check_msa_access(DisasContext *ctx)
18413 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
18414 !(ctx->hflags & MIPS_HFLAG_F64))) {
18415 generate_exception_end(ctx, EXCP_RI);
18416 return 0;
18419 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
18420 if (ctx->insn_flags & ASE_MSA) {
18421 generate_exception_end(ctx, EXCP_MSADIS);
18422 return 0;
18423 } else {
18424 generate_exception_end(ctx, EXCP_RI);
18425 return 0;
18428 return 1;
18431 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
18433 /* generates tcg ops to check if any element is 0 */
18434 /* Note this function only works with MSA_WRLEN = 128 */
18435 uint64_t eval_zero_or_big = 0;
18436 uint64_t eval_big = 0;
18437 TCGv_i64 t0 = tcg_temp_new_i64();
18438 TCGv_i64 t1 = tcg_temp_new_i64();
18439 switch (df) {
18440 case DF_BYTE:
18441 eval_zero_or_big = 0x0101010101010101ULL;
18442 eval_big = 0x8080808080808080ULL;
18443 break;
18444 case DF_HALF:
18445 eval_zero_or_big = 0x0001000100010001ULL;
18446 eval_big = 0x8000800080008000ULL;
18447 break;
18448 case DF_WORD:
18449 eval_zero_or_big = 0x0000000100000001ULL;
18450 eval_big = 0x8000000080000000ULL;
18451 break;
18452 case DF_DOUBLE:
18453 eval_zero_or_big = 0x0000000000000001ULL;
18454 eval_big = 0x8000000000000000ULL;
18455 break;
18457 tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
18458 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
18459 tcg_gen_andi_i64(t0, t0, eval_big);
18460 tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
18461 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
18462 tcg_gen_andi_i64(t1, t1, eval_big);
18463 tcg_gen_or_i64(t0, t0, t1);
18464 /* if all bits are zero then all elements are not zero */
18465 /* if some bit is non-zero then some element is zero */
18466 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
18467 tcg_gen_trunc_i64_tl(tresult, t0);
18468 tcg_temp_free_i64(t0);
18469 tcg_temp_free_i64(t1);
18472 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
18474 uint8_t df = (ctx->opcode >> 21) & 0x3;
18475 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18476 int64_t s16 = (int16_t)ctx->opcode;
18478 check_msa_access(ctx);
18480 if (ctx->hflags & MIPS_HFLAG_BMASK) {
18481 generate_exception_end(ctx, EXCP_RI);
18482 return;
18484 switch (op1) {
18485 case OPC_BZ_V:
18486 case OPC_BNZ_V:
18488 TCGv_i64 t0 = tcg_temp_new_i64();
18489 tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
18490 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
18491 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
18492 tcg_gen_trunc_i64_tl(bcond, t0);
18493 tcg_temp_free_i64(t0);
18495 break;
18496 case OPC_BZ_B:
18497 case OPC_BZ_H:
18498 case OPC_BZ_W:
18499 case OPC_BZ_D:
18500 gen_check_zero_element(bcond, df, wt);
18501 break;
18502 case OPC_BNZ_B:
18503 case OPC_BNZ_H:
18504 case OPC_BNZ_W:
18505 case OPC_BNZ_D:
18506 gen_check_zero_element(bcond, df, wt);
18507 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
18508 break;
18511 ctx->btarget = ctx->pc + (s16 << 2) + 4;
18513 ctx->hflags |= MIPS_HFLAG_BC;
18514 ctx->hflags |= MIPS_HFLAG_BDS32;
18517 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
18519 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
18520 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
18521 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18522 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18524 TCGv_i32 twd = tcg_const_i32(wd);
18525 TCGv_i32 tws = tcg_const_i32(ws);
18526 TCGv_i32 ti8 = tcg_const_i32(i8);
18528 switch (MASK_MSA_I8(ctx->opcode)) {
18529 case OPC_ANDI_B:
18530 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
18531 break;
18532 case OPC_ORI_B:
18533 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
18534 break;
18535 case OPC_NORI_B:
18536 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
18537 break;
18538 case OPC_XORI_B:
18539 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
18540 break;
18541 case OPC_BMNZI_B:
18542 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
18543 break;
18544 case OPC_BMZI_B:
18545 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
18546 break;
18547 case OPC_BSELI_B:
18548 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
18549 break;
18550 case OPC_SHF_B:
18551 case OPC_SHF_H:
18552 case OPC_SHF_W:
18554 uint8_t df = (ctx->opcode >> 24) & 0x3;
18555 if (df == DF_DOUBLE) {
18556 generate_exception_end(ctx, EXCP_RI);
18557 } else {
18558 TCGv_i32 tdf = tcg_const_i32(df);
18559 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
18560 tcg_temp_free_i32(tdf);
18563 break;
18564 default:
18565 MIPS_INVAL("MSA instruction");
18566 generate_exception_end(ctx, EXCP_RI);
18567 break;
18570 tcg_temp_free_i32(twd);
18571 tcg_temp_free_i32(tws);
18572 tcg_temp_free_i32(ti8);
18575 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
18577 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18578 uint8_t df = (ctx->opcode >> 21) & 0x3;
18579 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
18580 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
18581 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18582 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18584 TCGv_i32 tdf = tcg_const_i32(df);
18585 TCGv_i32 twd = tcg_const_i32(wd);
18586 TCGv_i32 tws = tcg_const_i32(ws);
18587 TCGv_i32 timm = tcg_temp_new_i32();
18588 tcg_gen_movi_i32(timm, u5);
18590 switch (MASK_MSA_I5(ctx->opcode)) {
18591 case OPC_ADDVI_df:
18592 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
18593 break;
18594 case OPC_SUBVI_df:
18595 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
18596 break;
18597 case OPC_MAXI_S_df:
18598 tcg_gen_movi_i32(timm, s5);
18599 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
18600 break;
18601 case OPC_MAXI_U_df:
18602 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
18603 break;
18604 case OPC_MINI_S_df:
18605 tcg_gen_movi_i32(timm, s5);
18606 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
18607 break;
18608 case OPC_MINI_U_df:
18609 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
18610 break;
18611 case OPC_CEQI_df:
18612 tcg_gen_movi_i32(timm, s5);
18613 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
18614 break;
18615 case OPC_CLTI_S_df:
18616 tcg_gen_movi_i32(timm, s5);
18617 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
18618 break;
18619 case OPC_CLTI_U_df:
18620 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
18621 break;
18622 case OPC_CLEI_S_df:
18623 tcg_gen_movi_i32(timm, s5);
18624 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
18625 break;
18626 case OPC_CLEI_U_df:
18627 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
18628 break;
18629 case OPC_LDI_df:
18631 int32_t s10 = sextract32(ctx->opcode, 11, 10);
18632 tcg_gen_movi_i32(timm, s10);
18633 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
18635 break;
18636 default:
18637 MIPS_INVAL("MSA instruction");
18638 generate_exception_end(ctx, EXCP_RI);
18639 break;
18642 tcg_temp_free_i32(tdf);
18643 tcg_temp_free_i32(twd);
18644 tcg_temp_free_i32(tws);
18645 tcg_temp_free_i32(timm);
18648 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
18650 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18651 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
18652 uint32_t df = 0, m = 0;
18653 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18654 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18656 TCGv_i32 tdf;
18657 TCGv_i32 tm;
18658 TCGv_i32 twd;
18659 TCGv_i32 tws;
18661 if ((dfm & 0x40) == 0x00) {
18662 m = dfm & 0x3f;
18663 df = DF_DOUBLE;
18664 } else if ((dfm & 0x60) == 0x40) {
18665 m = dfm & 0x1f;
18666 df = DF_WORD;
18667 } else if ((dfm & 0x70) == 0x60) {
18668 m = dfm & 0x0f;
18669 df = DF_HALF;
18670 } else if ((dfm & 0x78) == 0x70) {
18671 m = dfm & 0x7;
18672 df = DF_BYTE;
18673 } else {
18674 generate_exception_end(ctx, EXCP_RI);
18675 return;
18678 tdf = tcg_const_i32(df);
18679 tm = tcg_const_i32(m);
18680 twd = tcg_const_i32(wd);
18681 tws = tcg_const_i32(ws);
18683 switch (MASK_MSA_BIT(ctx->opcode)) {
18684 case OPC_SLLI_df:
18685 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
18686 break;
18687 case OPC_SRAI_df:
18688 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
18689 break;
18690 case OPC_SRLI_df:
18691 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
18692 break;
18693 case OPC_BCLRI_df:
18694 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
18695 break;
18696 case OPC_BSETI_df:
18697 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
18698 break;
18699 case OPC_BNEGI_df:
18700 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
18701 break;
18702 case OPC_BINSLI_df:
18703 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
18704 break;
18705 case OPC_BINSRI_df:
18706 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
18707 break;
18708 case OPC_SAT_S_df:
18709 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
18710 break;
18711 case OPC_SAT_U_df:
18712 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
18713 break;
18714 case OPC_SRARI_df:
18715 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
18716 break;
18717 case OPC_SRLRI_df:
18718 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
18719 break;
18720 default:
18721 MIPS_INVAL("MSA instruction");
18722 generate_exception_end(ctx, EXCP_RI);
18723 break;
18726 tcg_temp_free_i32(tdf);
18727 tcg_temp_free_i32(tm);
18728 tcg_temp_free_i32(twd);
18729 tcg_temp_free_i32(tws);
18732 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
18734 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
18735 uint8_t df = (ctx->opcode >> 21) & 0x3;
18736 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
18737 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
18738 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
18740 TCGv_i32 tdf = tcg_const_i32(df);
18741 TCGv_i32 twd = tcg_const_i32(wd);
18742 TCGv_i32 tws = tcg_const_i32(ws);
18743 TCGv_i32 twt = tcg_const_i32(wt);
18745 switch (MASK_MSA_3R(ctx->opcode)) {
18746 case OPC_SLL_df:
18747 gen_helper_msa_sll_df(cpu_env, tdf, twd, tws, twt);
18748 break;
18749 case OPC_ADDV_df:
18750 gen_helper_msa_addv_df(cpu_env, tdf, twd, tws, twt);
18751 break;
18752 case OPC_CEQ_df:
18753 gen_helper_msa_ceq_df(cpu_env, tdf, twd, tws, twt);
18754 break;
18755 case OPC_ADD_A_df:
18756 gen_helper_msa_add_a_df(cpu_env, tdf, twd, tws, twt);
18757 break;
18758 case OPC_SUBS_S_df:
18759 gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
18760 break;
18761 case OPC_MULV_df:
18762 gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
18763 break;
18764 case OPC_SLD_df:
18765 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
18766 break;
18767 case OPC_VSHF_df:
18768 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
18769 break;
18770 case OPC_SRA_df:
18771 gen_helper_msa_sra_df(cpu_env, tdf, twd, tws, twt);
18772 break;
18773 case OPC_SUBV_df:
18774 gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
18775 break;
18776 case OPC_ADDS_A_df:
18777 gen_helper_msa_adds_a_df(cpu_env, tdf, twd, tws, twt);
18778 break;
18779 case OPC_SUBS_U_df:
18780 gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
18781 break;
18782 case OPC_MADDV_df:
18783 gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
18784 break;
18785 case OPC_SPLAT_df:
18786 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
18787 break;
18788 case OPC_SRAR_df:
18789 gen_helper_msa_srar_df(cpu_env, tdf, twd, tws, twt);
18790 break;
18791 case OPC_SRL_df:
18792 gen_helper_msa_srl_df(cpu_env, tdf, twd, tws, twt);
18793 break;
18794 case OPC_MAX_S_df:
18795 gen_helper_msa_max_s_df(cpu_env, tdf, twd, tws, twt);
18796 break;
18797 case OPC_CLT_S_df:
18798 gen_helper_msa_clt_s_df(cpu_env, tdf, twd, tws, twt);
18799 break;
18800 case OPC_ADDS_S_df:
18801 gen_helper_msa_adds_s_df(cpu_env, tdf, twd, tws, twt);
18802 break;
18803 case OPC_SUBSUS_U_df:
18804 gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
18805 break;
18806 case OPC_MSUBV_df:
18807 gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
18808 break;
18809 case OPC_PCKEV_df:
18810 gen_helper_msa_pckev_df(cpu_env, tdf, twd, tws, twt);
18811 break;
18812 case OPC_SRLR_df:
18813 gen_helper_msa_srlr_df(cpu_env, tdf, twd, tws, twt);
18814 break;
18815 case OPC_BCLR_df:
18816 gen_helper_msa_bclr_df(cpu_env, tdf, twd, tws, twt);
18817 break;
18818 case OPC_MAX_U_df:
18819 gen_helper_msa_max_u_df(cpu_env, tdf, twd, tws, twt);
18820 break;
18821 case OPC_CLT_U_df:
18822 gen_helper_msa_clt_u_df(cpu_env, tdf, twd, tws, twt);
18823 break;
18824 case OPC_ADDS_U_df:
18825 gen_helper_msa_adds_u_df(cpu_env, tdf, twd, tws, twt);
18826 break;
18827 case OPC_SUBSUU_S_df:
18828 gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
18829 break;
18830 case OPC_PCKOD_df:
18831 gen_helper_msa_pckod_df(cpu_env, tdf, twd, tws, twt);
18832 break;
18833 case OPC_BSET_df:
18834 gen_helper_msa_bset_df(cpu_env, tdf, twd, tws, twt);
18835 break;
18836 case OPC_MIN_S_df:
18837 gen_helper_msa_min_s_df(cpu_env, tdf, twd, tws, twt);
18838 break;
18839 case OPC_CLE_S_df:
18840 gen_helper_msa_cle_s_df(cpu_env, tdf, twd, tws, twt);
18841 break;
18842 case OPC_AVE_S_df:
18843 gen_helper_msa_ave_s_df(cpu_env, tdf, twd, tws, twt);
18844 break;
18845 case OPC_ASUB_S_df:
18846 gen_helper_msa_asub_s_df(cpu_env, tdf, twd, tws, twt);
18847 break;
18848 case OPC_DIV_S_df:
18849 gen_helper_msa_div_s_df(cpu_env, tdf, twd, tws, twt);
18850 break;
18851 case OPC_ILVL_df:
18852 gen_helper_msa_ilvl_df(cpu_env, tdf, twd, tws, twt);
18853 break;
18854 case OPC_BNEG_df:
18855 gen_helper_msa_bneg_df(cpu_env, tdf, twd, tws, twt);
18856 break;
18857 case OPC_MIN_U_df:
18858 gen_helper_msa_min_u_df(cpu_env, tdf, twd, tws, twt);
18859 break;
18860 case OPC_CLE_U_df:
18861 gen_helper_msa_cle_u_df(cpu_env, tdf, twd, tws, twt);
18862 break;
18863 case OPC_AVE_U_df:
18864 gen_helper_msa_ave_u_df(cpu_env, tdf, twd, tws, twt);
18865 break;
18866 case OPC_ASUB_U_df:
18867 gen_helper_msa_asub_u_df(cpu_env, tdf, twd, tws, twt);
18868 break;
18869 case OPC_DIV_U_df:
18870 gen_helper_msa_div_u_df(cpu_env, tdf, twd, tws, twt);
18871 break;
18872 case OPC_ILVR_df:
18873 gen_helper_msa_ilvr_df(cpu_env, tdf, twd, tws, twt);
18874 break;
18875 case OPC_BINSL_df:
18876 gen_helper_msa_binsl_df(cpu_env, tdf, twd, tws, twt);
18877 break;
18878 case OPC_MAX_A_df:
18879 gen_helper_msa_max_a_df(cpu_env, tdf, twd, tws, twt);
18880 break;
18881 case OPC_AVER_S_df:
18882 gen_helper_msa_aver_s_df(cpu_env, tdf, twd, tws, twt);
18883 break;
18884 case OPC_MOD_S_df:
18885 gen_helper_msa_mod_s_df(cpu_env, tdf, twd, tws, twt);
18886 break;
18887 case OPC_ILVEV_df:
18888 gen_helper_msa_ilvev_df(cpu_env, tdf, twd, tws, twt);
18889 break;
18890 case OPC_BINSR_df:
18891 gen_helper_msa_binsr_df(cpu_env, tdf, twd, tws, twt);
18892 break;
18893 case OPC_MIN_A_df:
18894 gen_helper_msa_min_a_df(cpu_env, tdf, twd, tws, twt);
18895 break;
18896 case OPC_AVER_U_df:
18897 gen_helper_msa_aver_u_df(cpu_env, tdf, twd, tws, twt);
18898 break;
18899 case OPC_MOD_U_df:
18900 gen_helper_msa_mod_u_df(cpu_env, tdf, twd, tws, twt);
18901 break;
18902 case OPC_ILVOD_df:
18903 gen_helper_msa_ilvod_df(cpu_env, tdf, twd, tws, twt);
18904 break;
18906 case OPC_DOTP_S_df:
18907 case OPC_DOTP_U_df:
18908 case OPC_DPADD_S_df:
18909 case OPC_DPADD_U_df:
18910 case OPC_DPSUB_S_df:
18911 case OPC_HADD_S_df:
18912 case OPC_DPSUB_U_df:
18913 case OPC_HADD_U_df:
18914 case OPC_HSUB_S_df:
18915 case OPC_HSUB_U_df:
18916 if (df == DF_BYTE) {
18917 generate_exception_end(ctx, EXCP_RI);
18918 break;
18920 switch (MASK_MSA_3R(ctx->opcode)) {
18921 case OPC_DOTP_S_df:
18922 gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
18923 break;
18924 case OPC_DOTP_U_df:
18925 gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
18926 break;
18927 case OPC_DPADD_S_df:
18928 gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
18929 break;
18930 case OPC_DPADD_U_df:
18931 gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
18932 break;
18933 case OPC_DPSUB_S_df:
18934 gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
18935 break;
18936 case OPC_HADD_S_df:
18937 gen_helper_msa_hadd_s_df(cpu_env, tdf, twd, tws, twt);
18938 break;
18939 case OPC_DPSUB_U_df:
18940 gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
18941 break;
18942 case OPC_HADD_U_df:
18943 gen_helper_msa_hadd_u_df(cpu_env, tdf, twd, tws, twt);
18944 break;
18945 case OPC_HSUB_S_df:
18946 gen_helper_msa_hsub_s_df(cpu_env, tdf, twd, tws, twt);
18947 break;
18948 case OPC_HSUB_U_df:
18949 gen_helper_msa_hsub_u_df(cpu_env, tdf, twd, tws, twt);
18950 break;
18952 break;
18953 default:
18954 MIPS_INVAL("MSA instruction");
18955 generate_exception_end(ctx, EXCP_RI);
18956 break;
18958 tcg_temp_free_i32(twd);
18959 tcg_temp_free_i32(tws);
18960 tcg_temp_free_i32(twt);
18961 tcg_temp_free_i32(tdf);
18964 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
18966 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
18967 uint8_t source = (ctx->opcode >> 11) & 0x1f;
18968 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
18969 TCGv telm = tcg_temp_new();
18970 TCGv_i32 tsr = tcg_const_i32(source);
18971 TCGv_i32 tdt = tcg_const_i32(dest);
18973 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
18974 case OPC_CTCMSA:
18975 gen_load_gpr(telm, source);
18976 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
18977 break;
18978 case OPC_CFCMSA:
18979 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
18980 gen_store_gpr(telm, dest);
18981 break;
18982 case OPC_MOVE_V:
18983 gen_helper_msa_move_v(cpu_env, tdt, tsr);
18984 break;
18985 default:
18986 MIPS_INVAL("MSA instruction");
18987 generate_exception_end(ctx, EXCP_RI);
18988 break;
18991 tcg_temp_free(telm);
18992 tcg_temp_free_i32(tdt);
18993 tcg_temp_free_i32(tsr);
18996 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
18997 uint32_t n)
18999 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
19000 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19001 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19003 TCGv_i32 tws = tcg_const_i32(ws);
19004 TCGv_i32 twd = tcg_const_i32(wd);
19005 TCGv_i32 tn = tcg_const_i32(n);
19006 TCGv_i32 tdf = tcg_const_i32(df);
19008 switch (MASK_MSA_ELM(ctx->opcode)) {
19009 case OPC_SLDI_df:
19010 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
19011 break;
19012 case OPC_SPLATI_df:
19013 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
19014 break;
19015 case OPC_INSVE_df:
19016 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
19017 break;
19018 case OPC_COPY_S_df:
19019 case OPC_COPY_U_df:
19020 case OPC_INSERT_df:
19021 #if !defined(TARGET_MIPS64)
19022 /* Double format valid only for MIPS64 */
19023 if (df == DF_DOUBLE) {
19024 generate_exception_end(ctx, EXCP_RI);
19025 break;
19027 #endif
19028 switch (MASK_MSA_ELM(ctx->opcode)) {
19029 case OPC_COPY_S_df:
19030 if (likely(wd != 0)) {
19031 gen_helper_msa_copy_s_df(cpu_env, tdf, twd, tws, tn);
19033 break;
19034 case OPC_COPY_U_df:
19035 if (likely(wd != 0)) {
19036 gen_helper_msa_copy_u_df(cpu_env, tdf, twd, tws, tn);
19038 break;
19039 case OPC_INSERT_df:
19040 gen_helper_msa_insert_df(cpu_env, tdf, twd, tws, tn);
19041 break;
19043 break;
19044 default:
19045 MIPS_INVAL("MSA instruction");
19046 generate_exception_end(ctx, EXCP_RI);
19048 tcg_temp_free_i32(twd);
19049 tcg_temp_free_i32(tws);
19050 tcg_temp_free_i32(tn);
19051 tcg_temp_free_i32(tdf);
19054 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
19056 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
19057 uint32_t df = 0, n = 0;
19059 if ((dfn & 0x30) == 0x00) {
19060 n = dfn & 0x0f;
19061 df = DF_BYTE;
19062 } else if ((dfn & 0x38) == 0x20) {
19063 n = dfn & 0x07;
19064 df = DF_HALF;
19065 } else if ((dfn & 0x3c) == 0x30) {
19066 n = dfn & 0x03;
19067 df = DF_WORD;
19068 } else if ((dfn & 0x3e) == 0x38) {
19069 n = dfn & 0x01;
19070 df = DF_DOUBLE;
19071 } else if (dfn == 0x3E) {
19072 /* CTCMSA, CFCMSA, MOVE.V */
19073 gen_msa_elm_3e(env, ctx);
19074 return;
19075 } else {
19076 generate_exception_end(ctx, EXCP_RI);
19077 return;
19080 gen_msa_elm_df(env, ctx, df, n);
19083 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
19085 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
19086 uint8_t df = (ctx->opcode >> 21) & 0x1;
19087 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19088 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19089 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19091 TCGv_i32 twd = tcg_const_i32(wd);
19092 TCGv_i32 tws = tcg_const_i32(ws);
19093 TCGv_i32 twt = tcg_const_i32(wt);
19094 TCGv_i32 tdf = tcg_temp_new_i32();
19096 /* adjust df value for floating-point instruction */
19097 tcg_gen_movi_i32(tdf, df + 2);
19099 switch (MASK_MSA_3RF(ctx->opcode)) {
19100 case OPC_FCAF_df:
19101 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
19102 break;
19103 case OPC_FADD_df:
19104 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
19105 break;
19106 case OPC_FCUN_df:
19107 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
19108 break;
19109 case OPC_FSUB_df:
19110 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
19111 break;
19112 case OPC_FCOR_df:
19113 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
19114 break;
19115 case OPC_FCEQ_df:
19116 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
19117 break;
19118 case OPC_FMUL_df:
19119 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
19120 break;
19121 case OPC_FCUNE_df:
19122 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
19123 break;
19124 case OPC_FCUEQ_df:
19125 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
19126 break;
19127 case OPC_FDIV_df:
19128 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
19129 break;
19130 case OPC_FCNE_df:
19131 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
19132 break;
19133 case OPC_FCLT_df:
19134 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
19135 break;
19136 case OPC_FMADD_df:
19137 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
19138 break;
19139 case OPC_MUL_Q_df:
19140 tcg_gen_movi_i32(tdf, df + 1);
19141 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
19142 break;
19143 case OPC_FCULT_df:
19144 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
19145 break;
19146 case OPC_FMSUB_df:
19147 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
19148 break;
19149 case OPC_MADD_Q_df:
19150 tcg_gen_movi_i32(tdf, df + 1);
19151 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
19152 break;
19153 case OPC_FCLE_df:
19154 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
19155 break;
19156 case OPC_MSUB_Q_df:
19157 tcg_gen_movi_i32(tdf, df + 1);
19158 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
19159 break;
19160 case OPC_FCULE_df:
19161 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
19162 break;
19163 case OPC_FEXP2_df:
19164 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
19165 break;
19166 case OPC_FSAF_df:
19167 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
19168 break;
19169 case OPC_FEXDO_df:
19170 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
19171 break;
19172 case OPC_FSUN_df:
19173 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
19174 break;
19175 case OPC_FSOR_df:
19176 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
19177 break;
19178 case OPC_FSEQ_df:
19179 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
19180 break;
19181 case OPC_FTQ_df:
19182 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
19183 break;
19184 case OPC_FSUNE_df:
19185 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
19186 break;
19187 case OPC_FSUEQ_df:
19188 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
19189 break;
19190 case OPC_FSNE_df:
19191 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
19192 break;
19193 case OPC_FSLT_df:
19194 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
19195 break;
19196 case OPC_FMIN_df:
19197 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
19198 break;
19199 case OPC_MULR_Q_df:
19200 tcg_gen_movi_i32(tdf, df + 1);
19201 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
19202 break;
19203 case OPC_FSULT_df:
19204 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
19205 break;
19206 case OPC_FMIN_A_df:
19207 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
19208 break;
19209 case OPC_MADDR_Q_df:
19210 tcg_gen_movi_i32(tdf, df + 1);
19211 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
19212 break;
19213 case OPC_FSLE_df:
19214 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
19215 break;
19216 case OPC_FMAX_df:
19217 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
19218 break;
19219 case OPC_MSUBR_Q_df:
19220 tcg_gen_movi_i32(tdf, df + 1);
19221 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
19222 break;
19223 case OPC_FSULE_df:
19224 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
19225 break;
19226 case OPC_FMAX_A_df:
19227 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
19228 break;
19229 default:
19230 MIPS_INVAL("MSA instruction");
19231 generate_exception_end(ctx, EXCP_RI);
19232 break;
19235 tcg_temp_free_i32(twd);
19236 tcg_temp_free_i32(tws);
19237 tcg_temp_free_i32(twt);
19238 tcg_temp_free_i32(tdf);
19241 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
19243 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19244 (op & (0x7 << 18)))
19245 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19246 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19247 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19248 uint8_t df = (ctx->opcode >> 16) & 0x3;
19249 TCGv_i32 twd = tcg_const_i32(wd);
19250 TCGv_i32 tws = tcg_const_i32(ws);
19251 TCGv_i32 twt = tcg_const_i32(wt);
19252 TCGv_i32 tdf = tcg_const_i32(df);
19254 switch (MASK_MSA_2R(ctx->opcode)) {
19255 case OPC_FILL_df:
19256 #if !defined(TARGET_MIPS64)
19257 /* Double format valid only for MIPS64 */
19258 if (df == DF_DOUBLE) {
19259 generate_exception_end(ctx, EXCP_RI);
19260 break;
19262 #endif
19263 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
19264 break;
19265 case OPC_PCNT_df:
19266 gen_helper_msa_pcnt_df(cpu_env, tdf, twd, tws);
19267 break;
19268 case OPC_NLOC_df:
19269 gen_helper_msa_nloc_df(cpu_env, tdf, twd, tws);
19270 break;
19271 case OPC_NLZC_df:
19272 gen_helper_msa_nlzc_df(cpu_env, tdf, twd, tws);
19273 break;
19274 default:
19275 MIPS_INVAL("MSA instruction");
19276 generate_exception_end(ctx, EXCP_RI);
19277 break;
19280 tcg_temp_free_i32(twd);
19281 tcg_temp_free_i32(tws);
19282 tcg_temp_free_i32(twt);
19283 tcg_temp_free_i32(tdf);
19286 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
19288 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
19289 (op & (0xf << 17)))
19290 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19291 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19292 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19293 uint8_t df = (ctx->opcode >> 16) & 0x1;
19294 TCGv_i32 twd = tcg_const_i32(wd);
19295 TCGv_i32 tws = tcg_const_i32(ws);
19296 TCGv_i32 twt = tcg_const_i32(wt);
19297 /* adjust df value for floating-point instruction */
19298 TCGv_i32 tdf = tcg_const_i32(df + 2);
19300 switch (MASK_MSA_2RF(ctx->opcode)) {
19301 case OPC_FCLASS_df:
19302 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
19303 break;
19304 case OPC_FTRUNC_S_df:
19305 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
19306 break;
19307 case OPC_FTRUNC_U_df:
19308 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
19309 break;
19310 case OPC_FSQRT_df:
19311 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
19312 break;
19313 case OPC_FRSQRT_df:
19314 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
19315 break;
19316 case OPC_FRCP_df:
19317 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
19318 break;
19319 case OPC_FRINT_df:
19320 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
19321 break;
19322 case OPC_FLOG2_df:
19323 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
19324 break;
19325 case OPC_FEXUPL_df:
19326 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
19327 break;
19328 case OPC_FEXUPR_df:
19329 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
19330 break;
19331 case OPC_FFQL_df:
19332 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
19333 break;
19334 case OPC_FFQR_df:
19335 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
19336 break;
19337 case OPC_FTINT_S_df:
19338 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
19339 break;
19340 case OPC_FTINT_U_df:
19341 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
19342 break;
19343 case OPC_FFINT_S_df:
19344 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
19345 break;
19346 case OPC_FFINT_U_df:
19347 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
19348 break;
19351 tcg_temp_free_i32(twd);
19352 tcg_temp_free_i32(tws);
19353 tcg_temp_free_i32(twt);
19354 tcg_temp_free_i32(tdf);
19357 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
19359 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
19360 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
19361 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
19362 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19363 TCGv_i32 twd = tcg_const_i32(wd);
19364 TCGv_i32 tws = tcg_const_i32(ws);
19365 TCGv_i32 twt = tcg_const_i32(wt);
19367 switch (MASK_MSA_VEC(ctx->opcode)) {
19368 case OPC_AND_V:
19369 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
19370 break;
19371 case OPC_OR_V:
19372 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
19373 break;
19374 case OPC_NOR_V:
19375 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
19376 break;
19377 case OPC_XOR_V:
19378 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
19379 break;
19380 case OPC_BMNZ_V:
19381 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
19382 break;
19383 case OPC_BMZ_V:
19384 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
19385 break;
19386 case OPC_BSEL_V:
19387 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
19388 break;
19389 default:
19390 MIPS_INVAL("MSA instruction");
19391 generate_exception_end(ctx, EXCP_RI);
19392 break;
19395 tcg_temp_free_i32(twd);
19396 tcg_temp_free_i32(tws);
19397 tcg_temp_free_i32(twt);
19400 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
19402 switch (MASK_MSA_VEC(ctx->opcode)) {
19403 case OPC_AND_V:
19404 case OPC_OR_V:
19405 case OPC_NOR_V:
19406 case OPC_XOR_V:
19407 case OPC_BMNZ_V:
19408 case OPC_BMZ_V:
19409 case OPC_BSEL_V:
19410 gen_msa_vec_v(env, ctx);
19411 break;
19412 case OPC_MSA_2R:
19413 gen_msa_2r(env, ctx);
19414 break;
19415 case OPC_MSA_2RF:
19416 gen_msa_2rf(env, ctx);
19417 break;
19418 default:
19419 MIPS_INVAL("MSA instruction");
19420 generate_exception_end(ctx, EXCP_RI);
19421 break;
19425 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
19427 uint32_t opcode = ctx->opcode;
19428 check_insn(ctx, ASE_MSA);
19429 check_msa_access(ctx);
19431 switch (MASK_MSA_MINOR(opcode)) {
19432 case OPC_MSA_I8_00:
19433 case OPC_MSA_I8_01:
19434 case OPC_MSA_I8_02:
19435 gen_msa_i8(env, ctx);
19436 break;
19437 case OPC_MSA_I5_06:
19438 case OPC_MSA_I5_07:
19439 gen_msa_i5(env, ctx);
19440 break;
19441 case OPC_MSA_BIT_09:
19442 case OPC_MSA_BIT_0A:
19443 gen_msa_bit(env, ctx);
19444 break;
19445 case OPC_MSA_3R_0D:
19446 case OPC_MSA_3R_0E:
19447 case OPC_MSA_3R_0F:
19448 case OPC_MSA_3R_10:
19449 case OPC_MSA_3R_11:
19450 case OPC_MSA_3R_12:
19451 case OPC_MSA_3R_13:
19452 case OPC_MSA_3R_14:
19453 case OPC_MSA_3R_15:
19454 gen_msa_3r(env, ctx);
19455 break;
19456 case OPC_MSA_ELM:
19457 gen_msa_elm(env, ctx);
19458 break;
19459 case OPC_MSA_3RF_1A:
19460 case OPC_MSA_3RF_1B:
19461 case OPC_MSA_3RF_1C:
19462 gen_msa_3rf(env, ctx);
19463 break;
19464 case OPC_MSA_VEC:
19465 gen_msa_vec(env, ctx);
19466 break;
19467 case OPC_LD_B:
19468 case OPC_LD_H:
19469 case OPC_LD_W:
19470 case OPC_LD_D:
19471 case OPC_ST_B:
19472 case OPC_ST_H:
19473 case OPC_ST_W:
19474 case OPC_ST_D:
19476 int32_t s10 = sextract32(ctx->opcode, 16, 10);
19477 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
19478 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
19479 uint8_t df = (ctx->opcode >> 0) & 0x3;
19481 TCGv_i32 twd = tcg_const_i32(wd);
19482 TCGv taddr = tcg_temp_new();
19483 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
19485 switch (MASK_MSA_MINOR(opcode)) {
19486 case OPC_LD_B:
19487 gen_helper_msa_ld_b(cpu_env, twd, taddr);
19488 break;
19489 case OPC_LD_H:
19490 gen_helper_msa_ld_h(cpu_env, twd, taddr);
19491 break;
19492 case OPC_LD_W:
19493 gen_helper_msa_ld_w(cpu_env, twd, taddr);
19494 break;
19495 case OPC_LD_D:
19496 gen_helper_msa_ld_d(cpu_env, twd, taddr);
19497 break;
19498 case OPC_ST_B:
19499 gen_helper_msa_st_b(cpu_env, twd, taddr);
19500 break;
19501 case OPC_ST_H:
19502 gen_helper_msa_st_h(cpu_env, twd, taddr);
19503 break;
19504 case OPC_ST_W:
19505 gen_helper_msa_st_w(cpu_env, twd, taddr);
19506 break;
19507 case OPC_ST_D:
19508 gen_helper_msa_st_d(cpu_env, twd, taddr);
19509 break;
19512 tcg_temp_free_i32(twd);
19513 tcg_temp_free(taddr);
19515 break;
19516 default:
19517 MIPS_INVAL("MSA instruction");
19518 generate_exception_end(ctx, EXCP_RI);
19519 break;
19524 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
19526 int32_t offset;
19527 int rs, rt, rd, sa;
19528 uint32_t op, op1;
19529 int16_t imm;
19531 /* make sure instructions are on a word boundary */
19532 if (ctx->pc & 0x3) {
19533 env->CP0_BadVAddr = ctx->pc;
19534 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
19535 return;
19538 /* Handle blikely not taken case */
19539 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
19540 TCGLabel *l1 = gen_new_label();
19542 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
19543 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
19544 gen_goto_tb(ctx, 1, ctx->pc + 4);
19545 gen_set_label(l1);
19548 op = MASK_OP_MAJOR(ctx->opcode);
19549 rs = (ctx->opcode >> 21) & 0x1f;
19550 rt = (ctx->opcode >> 16) & 0x1f;
19551 rd = (ctx->opcode >> 11) & 0x1f;
19552 sa = (ctx->opcode >> 6) & 0x1f;
19553 imm = (int16_t)ctx->opcode;
19554 switch (op) {
19555 case OPC_SPECIAL:
19556 decode_opc_special(env, ctx);
19557 break;
19558 case OPC_SPECIAL2:
19559 decode_opc_special2_legacy(env, ctx);
19560 break;
19561 case OPC_SPECIAL3:
19562 decode_opc_special3(env, ctx);
19563 break;
19564 case OPC_REGIMM:
19565 op1 = MASK_REGIMM(ctx->opcode);
19566 switch (op1) {
19567 case OPC_BLTZL: /* REGIMM branches */
19568 case OPC_BGEZL:
19569 case OPC_BLTZALL:
19570 case OPC_BGEZALL:
19571 check_insn(ctx, ISA_MIPS2);
19572 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19573 /* Fallthrough */
19574 case OPC_BLTZ:
19575 case OPC_BGEZ:
19576 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19577 break;
19578 case OPC_BLTZAL:
19579 case OPC_BGEZAL:
19580 if (ctx->insn_flags & ISA_MIPS32R6) {
19581 if (rs == 0) {
19582 /* OPC_NAL, OPC_BAL */
19583 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
19584 } else {
19585 generate_exception_end(ctx, EXCP_RI);
19587 } else {
19588 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
19590 break;
19591 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
19592 case OPC_TNEI:
19593 check_insn(ctx, ISA_MIPS2);
19594 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19595 gen_trap(ctx, op1, rs, -1, imm);
19596 break;
19597 case OPC_SIGRIE:
19598 check_insn(ctx, ISA_MIPS32R6);
19599 generate_exception_end(ctx, EXCP_RI);
19600 break;
19601 case OPC_SYNCI:
19602 check_insn(ctx, ISA_MIPS32R2);
19603 /* Break the TB to be able to sync copied instructions
19604 immediately */
19605 ctx->bstate = BS_STOP;
19606 break;
19607 case OPC_BPOSGE32: /* MIPS DSP branch */
19608 #if defined(TARGET_MIPS64)
19609 case OPC_BPOSGE64:
19610 #endif
19611 check_dsp(ctx);
19612 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
19613 break;
19614 #if defined(TARGET_MIPS64)
19615 case OPC_DAHI:
19616 check_insn(ctx, ISA_MIPS32R6);
19617 check_mips_64(ctx);
19618 if (rs != 0) {
19619 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
19621 break;
19622 case OPC_DATI:
19623 check_insn(ctx, ISA_MIPS32R6);
19624 check_mips_64(ctx);
19625 if (rs != 0) {
19626 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
19628 break;
19629 #endif
19630 default: /* Invalid */
19631 MIPS_INVAL("regimm");
19632 generate_exception_end(ctx, EXCP_RI);
19633 break;
19635 break;
19636 case OPC_CP0:
19637 check_cp0_enabled(ctx);
19638 op1 = MASK_CP0(ctx->opcode);
19639 switch (op1) {
19640 case OPC_MFC0:
19641 case OPC_MTC0:
19642 case OPC_MFTR:
19643 case OPC_MTTR:
19644 case OPC_MFHC0:
19645 case OPC_MTHC0:
19646 #if defined(TARGET_MIPS64)
19647 case OPC_DMFC0:
19648 case OPC_DMTC0:
19649 #endif
19650 #ifndef CONFIG_USER_ONLY
19651 gen_cp0(env, ctx, op1, rt, rd);
19652 #endif /* !CONFIG_USER_ONLY */
19653 break;
19654 case OPC_C0_FIRST ... OPC_C0_LAST:
19655 #ifndef CONFIG_USER_ONLY
19656 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
19657 #endif /* !CONFIG_USER_ONLY */
19658 break;
19659 case OPC_MFMC0:
19660 #ifndef CONFIG_USER_ONLY
19662 uint32_t op2;
19663 TCGv t0 = tcg_temp_new();
19665 op2 = MASK_MFMC0(ctx->opcode);
19666 switch (op2) {
19667 case OPC_DMT:
19668 check_insn(ctx, ASE_MT);
19669 gen_helper_dmt(t0);
19670 gen_store_gpr(t0, rt);
19671 break;
19672 case OPC_EMT:
19673 check_insn(ctx, ASE_MT);
19674 gen_helper_emt(t0);
19675 gen_store_gpr(t0, rt);
19676 break;
19677 case OPC_DVPE:
19678 check_insn(ctx, ASE_MT);
19679 gen_helper_dvpe(t0, cpu_env);
19680 gen_store_gpr(t0, rt);
19681 break;
19682 case OPC_EVPE:
19683 check_insn(ctx, ASE_MT);
19684 gen_helper_evpe(t0, cpu_env);
19685 gen_store_gpr(t0, rt);
19686 break;
19687 case OPC_DVP:
19688 check_insn(ctx, ISA_MIPS32R6);
19689 if (ctx->vp) {
19690 gen_helper_dvp(t0, cpu_env);
19691 gen_store_gpr(t0, rt);
19693 break;
19694 case OPC_EVP:
19695 check_insn(ctx, ISA_MIPS32R6);
19696 if (ctx->vp) {
19697 gen_helper_evp(t0, cpu_env);
19698 gen_store_gpr(t0, rt);
19700 break;
19701 case OPC_DI:
19702 check_insn(ctx, ISA_MIPS32R2);
19703 save_cpu_state(ctx, 1);
19704 gen_helper_di(t0, cpu_env);
19705 gen_store_gpr(t0, rt);
19706 /* Stop translation as we may have switched
19707 the execution mode. */
19708 ctx->bstate = BS_STOP;
19709 break;
19710 case OPC_EI:
19711 check_insn(ctx, ISA_MIPS32R2);
19712 save_cpu_state(ctx, 1);
19713 gen_helper_ei(t0, cpu_env);
19714 gen_store_gpr(t0, rt);
19715 /* BS_STOP isn't sufficient, we need to ensure we break out
19716 of translated code to check for pending interrupts. */
19717 gen_save_pc(ctx->pc + 4);
19718 ctx->bstate = BS_EXCP;
19719 break;
19720 default: /* Invalid */
19721 MIPS_INVAL("mfmc0");
19722 generate_exception_end(ctx, EXCP_RI);
19723 break;
19725 tcg_temp_free(t0);
19727 #endif /* !CONFIG_USER_ONLY */
19728 break;
19729 case OPC_RDPGPR:
19730 check_insn(ctx, ISA_MIPS32R2);
19731 gen_load_srsgpr(rt, rd);
19732 break;
19733 case OPC_WRPGPR:
19734 check_insn(ctx, ISA_MIPS32R2);
19735 gen_store_srsgpr(rt, rd);
19736 break;
19737 default:
19738 MIPS_INVAL("cp0");
19739 generate_exception_end(ctx, EXCP_RI);
19740 break;
19742 break;
19743 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
19744 if (ctx->insn_flags & ISA_MIPS32R6) {
19745 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
19746 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19747 } else {
19748 /* OPC_ADDI */
19749 /* Arithmetic with immediate opcode */
19750 gen_arith_imm(ctx, op, rt, rs, imm);
19752 break;
19753 case OPC_ADDIU:
19754 gen_arith_imm(ctx, op, rt, rs, imm);
19755 break;
19756 case OPC_SLTI: /* Set on less than with immediate opcode */
19757 case OPC_SLTIU:
19758 gen_slt_imm(ctx, op, rt, rs, imm);
19759 break;
19760 case OPC_ANDI: /* Arithmetic with immediate opcode */
19761 case OPC_LUI: /* OPC_AUI */
19762 case OPC_ORI:
19763 case OPC_XORI:
19764 gen_logic_imm(ctx, op, rt, rs, imm);
19765 break;
19766 case OPC_J ... OPC_JAL: /* Jump */
19767 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
19768 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
19769 break;
19770 /* Branch */
19771 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
19772 if (ctx->insn_flags & ISA_MIPS32R6) {
19773 if (rt == 0) {
19774 generate_exception_end(ctx, EXCP_RI);
19775 break;
19777 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
19778 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19779 } else {
19780 /* OPC_BLEZL */
19781 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19783 break;
19784 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
19785 if (ctx->insn_flags & ISA_MIPS32R6) {
19786 if (rt == 0) {
19787 generate_exception_end(ctx, EXCP_RI);
19788 break;
19790 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
19791 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19792 } else {
19793 /* OPC_BGTZL */
19794 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19796 break;
19797 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
19798 if (rt == 0) {
19799 /* OPC_BLEZ */
19800 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19801 } else {
19802 check_insn(ctx, ISA_MIPS32R6);
19803 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
19804 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19806 break;
19807 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
19808 if (rt == 0) {
19809 /* OPC_BGTZ */
19810 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19811 } else {
19812 check_insn(ctx, ISA_MIPS32R6);
19813 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
19814 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
19816 break;
19817 case OPC_BEQL:
19818 case OPC_BNEL:
19819 check_insn(ctx, ISA_MIPS2);
19820 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19821 /* Fallthrough */
19822 case OPC_BEQ:
19823 case OPC_BNE:
19824 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
19825 break;
19826 case OPC_LL: /* Load and stores */
19827 check_insn(ctx, ISA_MIPS2);
19828 /* Fallthrough */
19829 case OPC_LWL:
19830 case OPC_LWR:
19831 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19832 /* Fallthrough */
19833 case OPC_LB ... OPC_LH:
19834 case OPC_LW ... OPC_LHU:
19835 gen_ld(ctx, op, rt, rs, imm);
19836 break;
19837 case OPC_SWL:
19838 case OPC_SWR:
19839 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19840 /* fall through */
19841 case OPC_SB ... OPC_SH:
19842 case OPC_SW:
19843 gen_st(ctx, op, rt, rs, imm);
19844 break;
19845 case OPC_SC:
19846 check_insn(ctx, ISA_MIPS2);
19847 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19848 gen_st_cond(ctx, op, rt, rs, imm);
19849 break;
19850 case OPC_CACHE:
19851 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19852 check_cp0_enabled(ctx);
19853 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
19854 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
19855 gen_cache_operation(ctx, rt, rs, imm);
19857 /* Treat as NOP. */
19858 break;
19859 case OPC_PREF:
19860 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19861 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
19862 /* Treat as NOP. */
19863 break;
19865 /* Floating point (COP1). */
19866 case OPC_LWC1:
19867 case OPC_LDC1:
19868 case OPC_SWC1:
19869 case OPC_SDC1:
19870 gen_cop1_ldst(ctx, op, rt, rs, imm);
19871 break;
19873 case OPC_CP1:
19874 op1 = MASK_CP1(ctx->opcode);
19876 switch (op1) {
19877 case OPC_MFHC1:
19878 case OPC_MTHC1:
19879 check_cp1_enabled(ctx);
19880 check_insn(ctx, ISA_MIPS32R2);
19881 case OPC_MFC1:
19882 case OPC_CFC1:
19883 case OPC_MTC1:
19884 case OPC_CTC1:
19885 check_cp1_enabled(ctx);
19886 gen_cp1(ctx, op1, rt, rd);
19887 break;
19888 #if defined(TARGET_MIPS64)
19889 case OPC_DMFC1:
19890 case OPC_DMTC1:
19891 check_cp1_enabled(ctx);
19892 check_insn(ctx, ISA_MIPS3);
19893 check_mips_64(ctx);
19894 gen_cp1(ctx, op1, rt, rd);
19895 break;
19896 #endif
19897 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
19898 check_cp1_enabled(ctx);
19899 if (ctx->insn_flags & ISA_MIPS32R6) {
19900 /* OPC_BC1EQZ */
19901 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19902 rt, imm << 2, 4);
19903 } else {
19904 /* OPC_BC1ANY2 */
19905 check_cop1x(ctx);
19906 check_insn(ctx, ASE_MIPS3D);
19907 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19908 (rt >> 2) & 0x7, imm << 2);
19910 break;
19911 case OPC_BC1NEZ:
19912 check_cp1_enabled(ctx);
19913 check_insn(ctx, ISA_MIPS32R6);
19914 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
19915 rt, imm << 2, 4);
19916 break;
19917 case OPC_BC1ANY4:
19918 check_cp1_enabled(ctx);
19919 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19920 check_cop1x(ctx);
19921 check_insn(ctx, ASE_MIPS3D);
19922 /* fall through */
19923 case OPC_BC1:
19924 check_cp1_enabled(ctx);
19925 check_insn_opc_removed(ctx, ISA_MIPS32R6);
19926 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
19927 (rt >> 2) & 0x7, imm << 2);
19928 break;
19929 case OPC_PS_FMT:
19930 check_ps(ctx);
19931 /* fall through */
19932 case OPC_S_FMT:
19933 case OPC_D_FMT:
19934 check_cp1_enabled(ctx);
19935 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
19936 (imm >> 8) & 0x7);
19937 break;
19938 case OPC_W_FMT:
19939 case OPC_L_FMT:
19941 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
19942 check_cp1_enabled(ctx);
19943 if (ctx->insn_flags & ISA_MIPS32R6) {
19944 switch (r6_op) {
19945 case R6_OPC_CMP_AF_S:
19946 case R6_OPC_CMP_UN_S:
19947 case R6_OPC_CMP_EQ_S:
19948 case R6_OPC_CMP_UEQ_S:
19949 case R6_OPC_CMP_LT_S:
19950 case R6_OPC_CMP_ULT_S:
19951 case R6_OPC_CMP_LE_S:
19952 case R6_OPC_CMP_ULE_S:
19953 case R6_OPC_CMP_SAF_S:
19954 case R6_OPC_CMP_SUN_S:
19955 case R6_OPC_CMP_SEQ_S:
19956 case R6_OPC_CMP_SEUQ_S:
19957 case R6_OPC_CMP_SLT_S:
19958 case R6_OPC_CMP_SULT_S:
19959 case R6_OPC_CMP_SLE_S:
19960 case R6_OPC_CMP_SULE_S:
19961 case R6_OPC_CMP_OR_S:
19962 case R6_OPC_CMP_UNE_S:
19963 case R6_OPC_CMP_NE_S:
19964 case R6_OPC_CMP_SOR_S:
19965 case R6_OPC_CMP_SUNE_S:
19966 case R6_OPC_CMP_SNE_S:
19967 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19968 break;
19969 case R6_OPC_CMP_AF_D:
19970 case R6_OPC_CMP_UN_D:
19971 case R6_OPC_CMP_EQ_D:
19972 case R6_OPC_CMP_UEQ_D:
19973 case R6_OPC_CMP_LT_D:
19974 case R6_OPC_CMP_ULT_D:
19975 case R6_OPC_CMP_LE_D:
19976 case R6_OPC_CMP_ULE_D:
19977 case R6_OPC_CMP_SAF_D:
19978 case R6_OPC_CMP_SUN_D:
19979 case R6_OPC_CMP_SEQ_D:
19980 case R6_OPC_CMP_SEUQ_D:
19981 case R6_OPC_CMP_SLT_D:
19982 case R6_OPC_CMP_SULT_D:
19983 case R6_OPC_CMP_SLE_D:
19984 case R6_OPC_CMP_SULE_D:
19985 case R6_OPC_CMP_OR_D:
19986 case R6_OPC_CMP_UNE_D:
19987 case R6_OPC_CMP_NE_D:
19988 case R6_OPC_CMP_SOR_D:
19989 case R6_OPC_CMP_SUNE_D:
19990 case R6_OPC_CMP_SNE_D:
19991 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
19992 break;
19993 default:
19994 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
19995 rt, rd, sa, (imm >> 8) & 0x7);
19997 break;
19999 } else {
20000 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
20001 (imm >> 8) & 0x7);
20003 break;
20005 case OPC_BZ_V:
20006 case OPC_BNZ_V:
20007 case OPC_BZ_B:
20008 case OPC_BZ_H:
20009 case OPC_BZ_W:
20010 case OPC_BZ_D:
20011 case OPC_BNZ_B:
20012 case OPC_BNZ_H:
20013 case OPC_BNZ_W:
20014 case OPC_BNZ_D:
20015 check_insn(ctx, ASE_MSA);
20016 gen_msa_branch(env, ctx, op1);
20017 break;
20018 default:
20019 MIPS_INVAL("cp1");
20020 generate_exception_end(ctx, EXCP_RI);
20021 break;
20023 break;
20025 /* Compact branches [R6] and COP2 [non-R6] */
20026 case OPC_BC: /* OPC_LWC2 */
20027 case OPC_BALC: /* OPC_SWC2 */
20028 if (ctx->insn_flags & ISA_MIPS32R6) {
20029 /* OPC_BC, OPC_BALC */
20030 gen_compute_compact_branch(ctx, op, 0, 0,
20031 sextract32(ctx->opcode << 2, 0, 28));
20032 } else {
20033 /* OPC_LWC2, OPC_SWC2 */
20034 /* COP2: Not implemented. */
20035 generate_exception_err(ctx, EXCP_CpU, 2);
20037 break;
20038 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
20039 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
20040 if (ctx->insn_flags & ISA_MIPS32R6) {
20041 if (rs != 0) {
20042 /* OPC_BEQZC, OPC_BNEZC */
20043 gen_compute_compact_branch(ctx, op, rs, 0,
20044 sextract32(ctx->opcode << 2, 0, 23));
20045 } else {
20046 /* OPC_JIC, OPC_JIALC */
20047 gen_compute_compact_branch(ctx, op, 0, rt, imm);
20049 } else {
20050 /* OPC_LWC2, OPC_SWC2 */
20051 /* COP2: Not implemented. */
20052 generate_exception_err(ctx, EXCP_CpU, 2);
20054 break;
20055 case OPC_CP2:
20056 check_insn(ctx, INSN_LOONGSON2F);
20057 /* Note that these instructions use different fields. */
20058 gen_loongson_multimedia(ctx, sa, rd, rt);
20059 break;
20061 case OPC_CP3:
20062 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20063 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20064 check_cp1_enabled(ctx);
20065 op1 = MASK_CP3(ctx->opcode);
20066 switch (op1) {
20067 case OPC_LUXC1:
20068 case OPC_SUXC1:
20069 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20070 /* Fallthrough */
20071 case OPC_LWXC1:
20072 case OPC_LDXC1:
20073 case OPC_SWXC1:
20074 case OPC_SDXC1:
20075 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20076 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
20077 break;
20078 case OPC_PREFX:
20079 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20080 /* Treat as NOP. */
20081 break;
20082 case OPC_ALNV_PS:
20083 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
20084 /* Fallthrough */
20085 case OPC_MADD_S:
20086 case OPC_MADD_D:
20087 case OPC_MADD_PS:
20088 case OPC_MSUB_S:
20089 case OPC_MSUB_D:
20090 case OPC_MSUB_PS:
20091 case OPC_NMADD_S:
20092 case OPC_NMADD_D:
20093 case OPC_NMADD_PS:
20094 case OPC_NMSUB_S:
20095 case OPC_NMSUB_D:
20096 case OPC_NMSUB_PS:
20097 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
20098 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
20099 break;
20100 default:
20101 MIPS_INVAL("cp3");
20102 generate_exception_end(ctx, EXCP_RI);
20103 break;
20105 } else {
20106 generate_exception_err(ctx, EXCP_CpU, 1);
20108 break;
20110 #if defined(TARGET_MIPS64)
20111 /* MIPS64 opcodes */
20112 case OPC_LDL ... OPC_LDR:
20113 case OPC_LLD:
20114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20115 /* fall through */
20116 case OPC_LWU:
20117 case OPC_LD:
20118 check_insn(ctx, ISA_MIPS3);
20119 check_mips_64(ctx);
20120 gen_ld(ctx, op, rt, rs, imm);
20121 break;
20122 case OPC_SDL ... OPC_SDR:
20123 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20124 /* fall through */
20125 case OPC_SD:
20126 check_insn(ctx, ISA_MIPS3);
20127 check_mips_64(ctx);
20128 gen_st(ctx, op, rt, rs, imm);
20129 break;
20130 case OPC_SCD:
20131 check_insn_opc_removed(ctx, ISA_MIPS32R6);
20132 check_insn(ctx, ISA_MIPS3);
20133 check_mips_64(ctx);
20134 gen_st_cond(ctx, op, rt, rs, imm);
20135 break;
20136 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
20137 if (ctx->insn_flags & ISA_MIPS32R6) {
20138 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
20139 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20140 } else {
20141 /* OPC_DADDI */
20142 check_insn(ctx, ISA_MIPS3);
20143 check_mips_64(ctx);
20144 gen_arith_imm(ctx, op, rt, rs, imm);
20146 break;
20147 case OPC_DADDIU:
20148 check_insn(ctx, ISA_MIPS3);
20149 check_mips_64(ctx);
20150 gen_arith_imm(ctx, op, rt, rs, imm);
20151 break;
20152 #else
20153 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
20154 if (ctx->insn_flags & ISA_MIPS32R6) {
20155 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
20156 } else {
20157 MIPS_INVAL("major opcode");
20158 generate_exception_end(ctx, EXCP_RI);
20160 break;
20161 #endif
20162 case OPC_DAUI: /* OPC_JALX */
20163 if (ctx->insn_flags & ISA_MIPS32R6) {
20164 #if defined(TARGET_MIPS64)
20165 /* OPC_DAUI */
20166 check_mips_64(ctx);
20167 if (rs == 0) {
20168 generate_exception(ctx, EXCP_RI);
20169 } else if (rt != 0) {
20170 TCGv t0 = tcg_temp_new();
20171 gen_load_gpr(t0, rs);
20172 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
20173 tcg_temp_free(t0);
20175 #else
20176 generate_exception_end(ctx, EXCP_RI);
20177 MIPS_INVAL("major opcode");
20178 #endif
20179 } else {
20180 /* OPC_JALX */
20181 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
20182 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
20183 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
20185 break;
20186 case OPC_MSA: /* OPC_MDMX */
20187 /* MDMX: Not implemented. */
20188 gen_msa(env, ctx);
20189 break;
20190 case OPC_PCREL:
20191 check_insn(ctx, ISA_MIPS32R6);
20192 gen_pcrel(ctx, ctx->opcode, ctx->pc, rs);
20193 break;
20194 default: /* Invalid */
20195 MIPS_INVAL("major opcode");
20196 generate_exception_end(ctx, EXCP_RI);
20197 break;
20201 void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
20203 CPUMIPSState *env = cs->env_ptr;
20204 DisasContext ctx;
20205 target_ulong pc_start;
20206 target_ulong next_page_start;
20207 int num_insns;
20208 int max_insns;
20209 int insn_bytes;
20210 int is_slot;
20212 pc_start = tb->pc;
20213 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
20214 ctx.pc = pc_start;
20215 ctx.saved_pc = -1;
20216 ctx.singlestep_enabled = cs->singlestep_enabled;
20217 ctx.insn_flags = env->insn_flags;
20218 ctx.CP0_Config1 = env->CP0_Config1;
20219 ctx.tb = tb;
20220 ctx.bstate = BS_NONE;
20221 ctx.btarget = 0;
20222 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
20223 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
20224 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
20225 ctx.bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
20226 ctx.bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
20227 ctx.PAMask = env->PAMask;
20228 ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
20229 ctx.eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
20230 ctx.sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
20231 ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
20232 ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
20233 /* Restore delay slot state from the tb context. */
20234 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
20235 ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
20236 ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
20237 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
20238 ctx.vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
20239 ctx.mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
20240 ctx.nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
20241 ctx.abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
20242 restore_cpu_state(env, &ctx);
20243 #ifdef CONFIG_USER_ONLY
20244 ctx.mem_idx = MIPS_HFLAG_UM;
20245 #else
20246 ctx.mem_idx = hflags_mmu_index(ctx.hflags);
20247 #endif
20248 ctx.default_tcg_memop_mask = (ctx.insn_flags & ISA_MIPS32R6) ?
20249 MO_UNALN : MO_ALIGN;
20250 num_insns = 0;
20251 max_insns = tb->cflags & CF_COUNT_MASK;
20252 if (max_insns == 0) {
20253 max_insns = CF_COUNT_MASK;
20255 if (max_insns > TCG_MAX_INSNS) {
20256 max_insns = TCG_MAX_INSNS;
20259 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
20260 gen_tb_start(tb);
20261 while (ctx.bstate == BS_NONE) {
20262 tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
20263 num_insns++;
20265 if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
20266 save_cpu_state(&ctx, 1);
20267 ctx.bstate = BS_BRANCH;
20268 gen_helper_raise_exception_debug(cpu_env);
20269 /* The address covered by the breakpoint must be included in
20270 [tb->pc, tb->pc + tb->size) in order to for it to be
20271 properly cleared -- thus we increment the PC here so that
20272 the logic setting tb->size below does the right thing. */
20273 ctx.pc += 4;
20274 goto done_generating;
20277 if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
20278 gen_io_start();
20281 is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
20282 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
20283 ctx.opcode = cpu_ldl_code(env, ctx.pc);
20284 insn_bytes = 4;
20285 decode_opc(env, &ctx);
20286 } else if (ctx.insn_flags & ASE_MICROMIPS) {
20287 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20288 insn_bytes = decode_micromips_opc(env, &ctx);
20289 } else if (ctx.insn_flags & ASE_MIPS16) {
20290 ctx.opcode = cpu_lduw_code(env, ctx.pc);
20291 insn_bytes = decode_mips16_opc(env, &ctx);
20292 } else {
20293 generate_exception_end(&ctx, EXCP_RI);
20294 break;
20297 if (ctx.hflags & MIPS_HFLAG_BMASK) {
20298 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
20299 MIPS_HFLAG_FBNSLOT))) {
20300 /* force to generate branch as there is neither delay nor
20301 forbidden slot */
20302 is_slot = 1;
20304 if ((ctx.hflags & MIPS_HFLAG_M16) &&
20305 (ctx.hflags & MIPS_HFLAG_FBNSLOT)) {
20306 /* Force to generate branch as microMIPS R6 doesn't restrict
20307 branches in the forbidden slot. */
20308 is_slot = 1;
20311 if (is_slot) {
20312 gen_branch(&ctx, insn_bytes);
20314 ctx.pc += insn_bytes;
20316 /* Execute a branch and its delay slot as a single instruction.
20317 This is what GDB expects and is consistent with what the
20318 hardware does (e.g. if a delay slot instruction faults, the
20319 reported PC is the PC of the branch). */
20320 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
20321 break;
20324 if (ctx.pc >= next_page_start) {
20325 break;
20328 if (tcg_op_buf_full()) {
20329 break;
20332 if (num_insns >= max_insns)
20333 break;
20335 if (singlestep)
20336 break;
20338 if (tb->cflags & CF_LAST_IO) {
20339 gen_io_end();
20341 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
20342 save_cpu_state(&ctx, ctx.bstate != BS_EXCP);
20343 gen_helper_raise_exception_debug(cpu_env);
20344 } else {
20345 switch (ctx.bstate) {
20346 case BS_STOP:
20347 gen_goto_tb(&ctx, 0, ctx.pc);
20348 break;
20349 case BS_NONE:
20350 save_cpu_state(&ctx, 0);
20351 gen_goto_tb(&ctx, 0, ctx.pc);
20352 break;
20353 case BS_EXCP:
20354 tcg_gen_exit_tb(0);
20355 break;
20356 case BS_BRANCH:
20357 default:
20358 break;
20361 done_generating:
20362 gen_tb_end(tb, num_insns);
20364 tb->size = ctx.pc - pc_start;
20365 tb->icount = num_insns;
20367 #ifdef DEBUG_DISAS
20368 LOG_DISAS("\n");
20369 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
20370 && qemu_log_in_addr_range(pc_start)) {
20371 qemu_log_lock();
20372 qemu_log("IN: %s\n", lookup_symbol(pc_start));
20373 log_target_disas(cs, pc_start, ctx.pc - pc_start, 0);
20374 qemu_log("\n");
20375 qemu_log_unlock();
20377 #endif
20380 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
20381 int flags)
20383 int i;
20384 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
20386 #define printfpr(fp) \
20387 do { \
20388 if (is_fpu64) \
20389 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20390 " fd:%13g fs:%13g psu: %13g\n", \
20391 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
20392 (double)(fp)->fd, \
20393 (double)(fp)->fs[FP_ENDIAN_IDX], \
20394 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
20395 else { \
20396 fpr_t tmp; \
20397 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
20398 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
20399 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
20400 " fd:%13g fs:%13g psu:%13g\n", \
20401 tmp.w[FP_ENDIAN_IDX], tmp.d, \
20402 (double)tmp.fd, \
20403 (double)tmp.fs[FP_ENDIAN_IDX], \
20404 (double)tmp.fs[!FP_ENDIAN_IDX]); \
20406 } while(0)
20409 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
20410 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
20411 get_float_exception_flags(&env->active_fpu.fp_status));
20412 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
20413 fpu_fprintf(f, "%3s: ", fregnames[i]);
20414 printfpr(&env->active_fpu.fpr[i]);
20417 #undef printfpr
20420 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
20421 int flags)
20423 MIPSCPU *cpu = MIPS_CPU(cs);
20424 CPUMIPSState *env = &cpu->env;
20425 int i;
20427 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
20428 " LO=0x" TARGET_FMT_lx " ds %04x "
20429 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
20430 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
20431 env->hflags, env->btarget, env->bcond);
20432 for (i = 0; i < 32; i++) {
20433 if ((i & 3) == 0)
20434 cpu_fprintf(f, "GPR%02d:", i);
20435 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
20436 if ((i & 3) == 3)
20437 cpu_fprintf(f, "\n");
20440 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
20441 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
20442 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
20443 PRIx64 "\n",
20444 env->CP0_Config0, env->CP0_Config1, env->lladdr);
20445 cpu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
20446 env->CP0_Config2, env->CP0_Config3);
20447 cpu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
20448 env->CP0_Config4, env->CP0_Config5);
20449 if (env->hflags & MIPS_HFLAG_FPU)
20450 fpu_dump_state(env, f, cpu_fprintf, flags);
20453 void mips_tcg_init(void)
20455 int i;
20456 static int inited;
20458 /* Initialize various static tables. */
20459 if (inited)
20460 return;
20462 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
20463 tcg_ctx.tcg_env = cpu_env;
20465 TCGV_UNUSED(cpu_gpr[0]);
20466 for (i = 1; i < 32; i++)
20467 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
20468 offsetof(CPUMIPSState, active_tc.gpr[i]),
20469 regnames[i]);
20471 for (i = 0; i < 32; i++) {
20472 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
20473 msa_wr_d[i * 2] =
20474 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
20475 /* The scalar floating-point unit (FPU) registers are mapped on
20476 * the MSA vector registers. */
20477 fpu_f64[i] = msa_wr_d[i * 2];
20478 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
20479 msa_wr_d[i * 2 + 1] =
20480 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
20483 cpu_PC = tcg_global_mem_new(cpu_env,
20484 offsetof(CPUMIPSState, active_tc.PC), "PC");
20485 for (i = 0; i < MIPS_DSP_ACC; i++) {
20486 cpu_HI[i] = tcg_global_mem_new(cpu_env,
20487 offsetof(CPUMIPSState, active_tc.HI[i]),
20488 regnames_HI[i]);
20489 cpu_LO[i] = tcg_global_mem_new(cpu_env,
20490 offsetof(CPUMIPSState, active_tc.LO[i]),
20491 regnames_LO[i]);
20493 cpu_dspctrl = tcg_global_mem_new(cpu_env,
20494 offsetof(CPUMIPSState, active_tc.DSPControl),
20495 "DSPControl");
20496 bcond = tcg_global_mem_new(cpu_env,
20497 offsetof(CPUMIPSState, bcond), "bcond");
20498 btarget = tcg_global_mem_new(cpu_env,
20499 offsetof(CPUMIPSState, btarget), "btarget");
20500 hflags = tcg_global_mem_new_i32(cpu_env,
20501 offsetof(CPUMIPSState, hflags), "hflags");
20503 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
20504 offsetof(CPUMIPSState, active_fpu.fcr0),
20505 "fcr0");
20506 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
20507 offsetof(CPUMIPSState, active_fpu.fcr31),
20508 "fcr31");
20510 inited = 1;
20513 #include "translate_init.c"
20515 void cpu_mips_realize_env(CPUMIPSState *env)
20517 env->exception_base = (int32_t)0xBFC00000;
20519 #ifndef CONFIG_USER_ONLY
20520 mmu_init(env, env->cpu_model);
20521 #endif
20522 fpu_init(env, env->cpu_model);
20523 mvp_init(env, env->cpu_model);
20526 bool cpu_supports_cps_smp(const char *cpu_model)
20528 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20529 if (!def) {
20530 return false;
20533 return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
20536 bool cpu_supports_isa(const char *cpu_model, unsigned int isa)
20538 const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
20539 if (!def) {
20540 return false;
20543 return (def->insn_flags & isa) != 0;
20546 void cpu_set_exception_base(int vp_index, target_ulong address)
20548 MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
20549 vp->env.exception_base = address;
20552 void cpu_state_reset(CPUMIPSState *env)
20554 MIPSCPU *cpu = mips_env_get_cpu(env);
20555 CPUState *cs = CPU(cpu);
20557 /* Reset registers to their default values */
20558 env->CP0_PRid = env->cpu_model->CP0_PRid;
20559 env->CP0_Config0 = env->cpu_model->CP0_Config0;
20560 #ifdef TARGET_WORDS_BIGENDIAN
20561 env->CP0_Config0 |= (1 << CP0C0_BE);
20562 #endif
20563 env->CP0_Config1 = env->cpu_model->CP0_Config1;
20564 env->CP0_Config2 = env->cpu_model->CP0_Config2;
20565 env->CP0_Config3 = env->cpu_model->CP0_Config3;
20566 env->CP0_Config4 = env->cpu_model->CP0_Config4;
20567 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
20568 env->CP0_Config5 = env->cpu_model->CP0_Config5;
20569 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
20570 env->CP0_Config6 = env->cpu_model->CP0_Config6;
20571 env->CP0_Config7 = env->cpu_model->CP0_Config7;
20572 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
20573 << env->cpu_model->CP0_LLAddr_shift;
20574 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
20575 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
20576 env->CCRes = env->cpu_model->CCRes;
20577 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
20578 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
20579 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
20580 env->current_tc = 0;
20581 env->SEGBITS = env->cpu_model->SEGBITS;
20582 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
20583 #if defined(TARGET_MIPS64)
20584 if (env->cpu_model->insn_flags & ISA_MIPS3) {
20585 env->SEGMask |= 3ULL << 62;
20587 #endif
20588 env->PABITS = env->cpu_model->PABITS;
20589 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
20590 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
20591 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
20592 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
20593 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
20594 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
20595 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
20596 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
20597 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
20598 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
20599 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
20600 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
20601 env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask;
20602 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
20603 env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
20604 env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
20605 env->msair = env->cpu_model->MSAIR;
20606 env->insn_flags = env->cpu_model->insn_flags;
20608 #if defined(CONFIG_USER_ONLY)
20609 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
20610 # ifdef TARGET_MIPS64
20611 /* Enable 64-bit register mode. */
20612 env->CP0_Status |= (1 << CP0St_PX);
20613 # endif
20614 # ifdef TARGET_ABI_MIPSN64
20615 /* Enable 64-bit address mode. */
20616 env->CP0_Status |= (1 << CP0St_UX);
20617 # endif
20618 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
20619 hardware registers. */
20620 env->CP0_HWREna |= 0x0000000F;
20621 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
20622 env->CP0_Status |= (1 << CP0St_CU1);
20624 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
20625 env->CP0_Status |= (1 << CP0St_MX);
20627 # if defined(TARGET_MIPS64)
20628 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
20629 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
20630 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
20631 env->CP0_Status |= (1 << CP0St_FR);
20633 # endif
20634 #else
20635 if (env->hflags & MIPS_HFLAG_BMASK) {
20636 /* If the exception was raised from a delay slot,
20637 come back to the jump. */
20638 env->CP0_ErrorEPC = (env->active_tc.PC
20639 - (env->hflags & MIPS_HFLAG_B16 ? 2 : 4));
20640 } else {
20641 env->CP0_ErrorEPC = env->active_tc.PC;
20643 env->active_tc.PC = env->exception_base;
20644 env->CP0_Random = env->tlb->nb_tlb - 1;
20645 env->tlb->tlb_in_use = env->tlb->nb_tlb;
20646 env->CP0_Wired = 0;
20647 env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId;
20648 env->CP0_EBase = (cs->cpu_index & 0x3FF);
20649 if (mips_um_ksegs_enabled()) {
20650 env->CP0_EBase |= 0x40000000;
20651 } else {
20652 env->CP0_EBase |= (int32_t)0x80000000;
20654 if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
20655 env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
20657 env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
20658 0x3ff : 0xff;
20659 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
20660 /* vectored interrupts not implemented, timer on int 7,
20661 no performance counters. */
20662 env->CP0_IntCtl = 0xe0000000;
20664 int i;
20666 for (i = 0; i < 7; i++) {
20667 env->CP0_WatchLo[i] = 0;
20668 env->CP0_WatchHi[i] = 0x80000000;
20670 env->CP0_WatchLo[7] = 0;
20671 env->CP0_WatchHi[7] = 0;
20673 /* Count register increments in debug mode, EJTAG version 1 */
20674 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
20676 cpu_mips_store_count(env, 1);
20678 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
20679 int i;
20681 /* Only TC0 on VPE 0 starts as active. */
20682 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
20683 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
20684 env->tcs[i].CP0_TCHalt = 1;
20686 env->active_tc.CP0_TCHalt = 1;
20687 cs->halted = 1;
20689 if (cs->cpu_index == 0) {
20690 /* VPE0 starts up enabled. */
20691 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
20692 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
20694 /* TC0 starts up unhalted. */
20695 cs->halted = 0;
20696 env->active_tc.CP0_TCHalt = 0;
20697 env->tcs[0].CP0_TCHalt = 0;
20698 /* With thread 0 active. */
20699 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
20700 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
20705 * Configure default legacy segmentation control. We use this regardless of
20706 * whether segmentation control is presented to the guest.
20708 /* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
20709 env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
20710 /* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
20711 env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
20712 /* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
20713 env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
20714 (2 << CP0SC_C);
20715 /* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
20716 env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
20717 (3 << CP0SC_C)) << 16;
20718 /* USeg (seg4 0x40000000..0x7FFFFFFF) */
20719 env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
20720 (1 << CP0SC_EU) | (2 << CP0SC_C);
20721 /* USeg (seg5 0x00000000..0x3FFFFFFF) */
20722 env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
20723 (1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
20724 /* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
20725 env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
20726 #endif
20727 if ((env->insn_flags & ISA_MIPS32R6) &&
20728 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
20729 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
20730 env->CP0_Status |= (1 << CP0St_FR);
20733 /* MSA */
20734 if (env->CP0_Config3 & (1 << CP0C3_MSAP)) {
20735 msa_reset(env);
20738 compute_hflags(env);
20739 restore_fp_status(env);
20740 restore_pamask(env);
20741 cs->exception_index = EXCP_NONE;
20743 if (semihosting_get_argc()) {
20744 /* UHI interface can be used to obtain argc and argv */
20745 env->active_tc.gpr[4] = -1;
20749 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
20750 target_ulong *data)
20752 env->active_tc.PC = data[0];
20753 env->hflags &= ~MIPS_HFLAG_BMASK;
20754 env->hflags |= data[1];
20755 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
20756 case MIPS_HFLAG_BR:
20757 break;
20758 case MIPS_HFLAG_BC:
20759 case MIPS_HFLAG_BL:
20760 case MIPS_HFLAG_B:
20761 env->btarget = data[2];
20762 break;