target/mips: Introduce ase_msa_available() helper
[qemu/ar7.git] / target / mips / translate.c
blobd87fbaf0ecd8a0c5ac16513d5e3087b938444089
1 /*
2 * MIPS emulation for QEMU - main translation routines
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 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 "tcg/tcg-op.h"
28 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "hw/semihosting/semihost.h"
33 #include "target/mips/trace.h"
34 #include "trace-tcg.h"
35 #include "exec/translator.h"
36 #include "exec/log.h"
37 #include "qemu/qemu-print.h"
38 #include "fpu_helper.h"
39 #include "translate.h"
41 enum {
42 /* indirect opcode tables */
43 OPC_SPECIAL = (0x00 << 26),
44 OPC_REGIMM = (0x01 << 26),
45 OPC_CP0 = (0x10 << 26),
46 OPC_CP2 = (0x12 << 26),
47 OPC_CP3 = (0x13 << 26),
48 OPC_SPECIAL2 = (0x1C << 26),
49 OPC_SPECIAL3 = (0x1F << 26),
50 /* arithmetic with immediate */
51 OPC_ADDI = (0x08 << 26),
52 OPC_ADDIU = (0x09 << 26),
53 OPC_SLTI = (0x0A << 26),
54 OPC_SLTIU = (0x0B << 26),
55 /* logic with immediate */
56 OPC_ANDI = (0x0C << 26),
57 OPC_ORI = (0x0D << 26),
58 OPC_XORI = (0x0E << 26),
59 OPC_LUI = (0x0F << 26),
60 /* arithmetic with immediate */
61 OPC_DADDI = (0x18 << 26),
62 OPC_DADDIU = (0x19 << 26),
63 /* Jump and branches */
64 OPC_J = (0x02 << 26),
65 OPC_JAL = (0x03 << 26),
66 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
67 OPC_BEQL = (0x14 << 26),
68 OPC_BNE = (0x05 << 26),
69 OPC_BNEL = (0x15 << 26),
70 OPC_BLEZ = (0x06 << 26),
71 OPC_BLEZL = (0x16 << 26),
72 OPC_BGTZ = (0x07 << 26),
73 OPC_BGTZL = (0x17 << 26),
74 OPC_JALX = (0x1D << 26),
75 OPC_DAUI = (0x1D << 26),
76 /* Load and stores */
77 OPC_LDL = (0x1A << 26),
78 OPC_LDR = (0x1B << 26),
79 OPC_LB = (0x20 << 26),
80 OPC_LH = (0x21 << 26),
81 OPC_LWL = (0x22 << 26),
82 OPC_LW = (0x23 << 26),
83 OPC_LWPC = OPC_LW | 0x5,
84 OPC_LBU = (0x24 << 26),
85 OPC_LHU = (0x25 << 26),
86 OPC_LWR = (0x26 << 26),
87 OPC_LWU = (0x27 << 26),
88 OPC_SB = (0x28 << 26),
89 OPC_SH = (0x29 << 26),
90 OPC_SWL = (0x2A << 26),
91 OPC_SW = (0x2B << 26),
92 OPC_SDL = (0x2C << 26),
93 OPC_SDR = (0x2D << 26),
94 OPC_SWR = (0x2E << 26),
95 OPC_LL = (0x30 << 26),
96 OPC_LLD = (0x34 << 26),
97 OPC_LD = (0x37 << 26),
98 OPC_LDPC = OPC_LD | 0x5,
99 OPC_SC = (0x38 << 26),
100 OPC_SCD = (0x3C << 26),
101 OPC_SD = (0x3F << 26),
102 /* Floating point load/store */
103 OPC_LWC1 = (0x31 << 26),
104 OPC_LWC2 = (0x32 << 26),
105 OPC_LDC1 = (0x35 << 26),
106 OPC_LDC2 = (0x36 << 26),
107 OPC_SWC1 = (0x39 << 26),
108 OPC_SWC2 = (0x3A << 26),
109 OPC_SDC1 = (0x3D << 26),
110 OPC_SDC2 = (0x3E << 26),
111 /* Compact Branches */
112 OPC_BLEZALC = (0x06 << 26),
113 OPC_BGEZALC = (0x06 << 26),
114 OPC_BGEUC = (0x06 << 26),
115 OPC_BGTZALC = (0x07 << 26),
116 OPC_BLTZALC = (0x07 << 26),
117 OPC_BLTUC = (0x07 << 26),
118 OPC_BOVC = (0x08 << 26),
119 OPC_BEQZALC = (0x08 << 26),
120 OPC_BEQC = (0x08 << 26),
121 OPC_BLEZC = (0x16 << 26),
122 OPC_BGEZC = (0x16 << 26),
123 OPC_BGEC = (0x16 << 26),
124 OPC_BGTZC = (0x17 << 26),
125 OPC_BLTZC = (0x17 << 26),
126 OPC_BLTC = (0x17 << 26),
127 OPC_BNVC = (0x18 << 26),
128 OPC_BNEZALC = (0x18 << 26),
129 OPC_BNEC = (0x18 << 26),
130 OPC_BC = (0x32 << 26),
131 OPC_BEQZC = (0x36 << 26),
132 OPC_JIC = (0x36 << 26),
133 OPC_BALC = (0x3A << 26),
134 OPC_BNEZC = (0x3E << 26),
135 OPC_JIALC = (0x3E << 26),
136 /* MDMX ASE specific */
137 OPC_MDMX = (0x1E << 26),
138 /* MSA ASE, same as MDMX */
139 OPC_MSA = OPC_MDMX,
140 /* Cache and prefetch */
141 OPC_CACHE = (0x2F << 26),
142 OPC_PREF = (0x33 << 26),
143 /* PC-relative address computation / loads */
144 OPC_PCREL = (0x3B << 26),
147 /* PC-relative address computation / loads */
148 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
149 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
150 enum {
151 /* Instructions determined by bits 19 and 20 */
152 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
153 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
154 OPC_LWUPC = OPC_PCREL | (2 << 19),
156 /* Instructions determined by bits 16 ... 20 */
157 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
158 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
160 /* Other */
161 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
164 /* MIPS special opcodes */
165 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
167 enum {
168 /* Shifts */
169 OPC_SLL = 0x00 | OPC_SPECIAL,
170 /* NOP is SLL r0, r0, 0 */
171 /* SSNOP is SLL r0, r0, 1 */
172 /* EHB is SLL r0, r0, 3 */
173 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
174 OPC_ROTR = OPC_SRL | (1 << 21),
175 OPC_SRA = 0x03 | OPC_SPECIAL,
176 OPC_SLLV = 0x04 | OPC_SPECIAL,
177 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
178 OPC_ROTRV = OPC_SRLV | (1 << 6),
179 OPC_SRAV = 0x07 | OPC_SPECIAL,
180 OPC_DSLLV = 0x14 | OPC_SPECIAL,
181 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
182 OPC_DROTRV = OPC_DSRLV | (1 << 6),
183 OPC_DSRAV = 0x17 | OPC_SPECIAL,
184 OPC_DSLL = 0x38 | OPC_SPECIAL,
185 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
186 OPC_DROTR = OPC_DSRL | (1 << 21),
187 OPC_DSRA = 0x3B | OPC_SPECIAL,
188 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
189 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
190 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
191 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
192 /* Multiplication / division */
193 OPC_MULT = 0x18 | OPC_SPECIAL,
194 OPC_MULTU = 0x19 | OPC_SPECIAL,
195 OPC_DIV = 0x1A | OPC_SPECIAL,
196 OPC_DIVU = 0x1B | OPC_SPECIAL,
197 OPC_DMULT = 0x1C | OPC_SPECIAL,
198 OPC_DMULTU = 0x1D | OPC_SPECIAL,
199 OPC_DDIV = 0x1E | OPC_SPECIAL,
200 OPC_DDIVU = 0x1F | OPC_SPECIAL,
202 /* 2 registers arithmetic / logic */
203 OPC_ADD = 0x20 | OPC_SPECIAL,
204 OPC_ADDU = 0x21 | OPC_SPECIAL,
205 OPC_SUB = 0x22 | OPC_SPECIAL,
206 OPC_SUBU = 0x23 | OPC_SPECIAL,
207 OPC_AND = 0x24 | OPC_SPECIAL,
208 OPC_OR = 0x25 | OPC_SPECIAL,
209 OPC_XOR = 0x26 | OPC_SPECIAL,
210 OPC_NOR = 0x27 | OPC_SPECIAL,
211 OPC_SLT = 0x2A | OPC_SPECIAL,
212 OPC_SLTU = 0x2B | OPC_SPECIAL,
213 OPC_DADD = 0x2C | OPC_SPECIAL,
214 OPC_DADDU = 0x2D | OPC_SPECIAL,
215 OPC_DSUB = 0x2E | OPC_SPECIAL,
216 OPC_DSUBU = 0x2F | OPC_SPECIAL,
217 /* Jumps */
218 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
219 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
220 /* Traps */
221 OPC_TGE = 0x30 | OPC_SPECIAL,
222 OPC_TGEU = 0x31 | OPC_SPECIAL,
223 OPC_TLT = 0x32 | OPC_SPECIAL,
224 OPC_TLTU = 0x33 | OPC_SPECIAL,
225 OPC_TEQ = 0x34 | OPC_SPECIAL,
226 OPC_TNE = 0x36 | OPC_SPECIAL,
227 /* HI / LO registers load & stores */
228 OPC_MFHI = 0x10 | OPC_SPECIAL,
229 OPC_MTHI = 0x11 | OPC_SPECIAL,
230 OPC_MFLO = 0x12 | OPC_SPECIAL,
231 OPC_MTLO = 0x13 | OPC_SPECIAL,
232 /* Conditional moves */
233 OPC_MOVZ = 0x0A | OPC_SPECIAL,
234 OPC_MOVN = 0x0B | OPC_SPECIAL,
236 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
237 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
239 OPC_MOVCI = 0x01 | OPC_SPECIAL,
241 /* Special */
242 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
243 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
244 OPC_BREAK = 0x0D | OPC_SPECIAL,
245 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
246 OPC_SYNC = 0x0F | OPC_SPECIAL,
248 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
249 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
250 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
251 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
255 * R6 Multiply and Divide instructions have the same opcode
256 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
258 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
260 enum {
261 R6_OPC_MUL = OPC_MULT | (2 << 6),
262 R6_OPC_MUH = OPC_MULT | (3 << 6),
263 R6_OPC_MULU = OPC_MULTU | (2 << 6),
264 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
265 R6_OPC_DIV = OPC_DIV | (2 << 6),
266 R6_OPC_MOD = OPC_DIV | (3 << 6),
267 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
268 R6_OPC_MODU = OPC_DIVU | (3 << 6),
270 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
271 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
272 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
273 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
274 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
275 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
276 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
277 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
279 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
280 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
281 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
282 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
283 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
285 OPC_LSA = 0x05 | OPC_SPECIAL,
286 OPC_DLSA = 0x15 | OPC_SPECIAL,
289 /* Multiplication variants of the vr54xx. */
290 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
292 enum {
293 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
294 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
295 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
296 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
297 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
298 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
299 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
300 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
301 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
302 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
303 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
304 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
305 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
306 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
309 /* REGIMM (rt field) opcodes */
310 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
312 enum {
313 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
314 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
315 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
316 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
317 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
318 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
319 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
320 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
321 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
322 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
323 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
324 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
325 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
326 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
327 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
328 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
330 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
331 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
334 /* Special2 opcodes */
335 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
337 enum {
338 /* Multiply & xxx operations */
339 OPC_MADD = 0x00 | OPC_SPECIAL2,
340 OPC_MADDU = 0x01 | OPC_SPECIAL2,
341 OPC_MUL = 0x02 | OPC_SPECIAL2,
342 OPC_MSUB = 0x04 | OPC_SPECIAL2,
343 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
344 /* Loongson 2F */
345 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
346 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
347 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
348 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
349 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
350 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
351 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
352 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
353 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
354 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
355 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
356 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
357 /* Misc */
358 OPC_CLZ = 0x20 | OPC_SPECIAL2,
359 OPC_CLO = 0x21 | OPC_SPECIAL2,
360 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
361 OPC_DCLO = 0x25 | OPC_SPECIAL2,
362 /* Special */
363 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
366 /* Special3 opcodes */
367 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
369 enum {
370 OPC_EXT = 0x00 | OPC_SPECIAL3,
371 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
372 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
373 OPC_DEXT = 0x03 | OPC_SPECIAL3,
374 OPC_INS = 0x04 | OPC_SPECIAL3,
375 OPC_DINSM = 0x05 | OPC_SPECIAL3,
376 OPC_DINSU = 0x06 | OPC_SPECIAL3,
377 OPC_DINS = 0x07 | OPC_SPECIAL3,
378 OPC_FORK = 0x08 | OPC_SPECIAL3,
379 OPC_YIELD = 0x09 | OPC_SPECIAL3,
380 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
381 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
382 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
383 OPC_GINV = 0x3D | OPC_SPECIAL3,
385 /* Loongson 2E */
386 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
387 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
388 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
389 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
390 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
391 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
392 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
393 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
394 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
395 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
396 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
397 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
399 /* MIPS DSP Load */
400 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
401 /* MIPS DSP Arithmetic */
402 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
403 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
404 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
405 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
406 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
407 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
408 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
409 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
410 /* MIPS DSP GPR-Based Shift Sub-class */
411 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
412 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
413 /* MIPS DSP Multiply Sub-class insns */
414 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
415 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
416 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
417 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
418 /* DSP Bit/Manipulation Sub-class */
419 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
420 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
421 /* MIPS DSP Append Sub-class */
422 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
423 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
424 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
425 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
426 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
428 /* EVA */
429 OPC_LWLE = 0x19 | OPC_SPECIAL3,
430 OPC_LWRE = 0x1A | OPC_SPECIAL3,
431 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
432 OPC_SBE = 0x1C | OPC_SPECIAL3,
433 OPC_SHE = 0x1D | OPC_SPECIAL3,
434 OPC_SCE = 0x1E | OPC_SPECIAL3,
435 OPC_SWE = 0x1F | OPC_SPECIAL3,
436 OPC_SWLE = 0x21 | OPC_SPECIAL3,
437 OPC_SWRE = 0x22 | OPC_SPECIAL3,
438 OPC_PREFE = 0x23 | OPC_SPECIAL3,
439 OPC_LBUE = 0x28 | OPC_SPECIAL3,
440 OPC_LHUE = 0x29 | OPC_SPECIAL3,
441 OPC_LBE = 0x2C | OPC_SPECIAL3,
442 OPC_LHE = 0x2D | OPC_SPECIAL3,
443 OPC_LLE = 0x2E | OPC_SPECIAL3,
444 OPC_LWE = 0x2F | OPC_SPECIAL3,
446 /* R6 */
447 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
448 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
449 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
450 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
451 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
452 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
455 /* Loongson EXT load/store quad word opcodes */
456 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
457 enum {
458 OPC_GSLQ = 0x0020 | OPC_LWC2,
459 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
460 OPC_GSSHFL = OPC_LWC2,
461 OPC_GSSQ = 0x0020 | OPC_SWC2,
462 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
463 OPC_GSSHFS = OPC_SWC2,
466 /* Loongson EXT shifted load/store opcodes */
467 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
468 enum {
469 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
470 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
471 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
472 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
473 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
474 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
475 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
476 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
479 /* Loongson EXT LDC2/SDC2 opcodes */
480 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
482 enum {
483 OPC_GSLBX = 0x0 | OPC_LDC2,
484 OPC_GSLHX = 0x1 | OPC_LDC2,
485 OPC_GSLWX = 0x2 | OPC_LDC2,
486 OPC_GSLDX = 0x3 | OPC_LDC2,
487 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
488 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
489 OPC_GSSBX = 0x0 | OPC_SDC2,
490 OPC_GSSHX = 0x1 | OPC_SDC2,
491 OPC_GSSWX = 0x2 | OPC_SDC2,
492 OPC_GSSDX = 0x3 | OPC_SDC2,
493 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
494 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
497 /* BSHFL opcodes */
498 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
500 enum {
501 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
502 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
503 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
504 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
505 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
506 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
507 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
508 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
511 /* DBSHFL opcodes */
512 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
514 enum {
515 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
516 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
517 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
518 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
519 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
520 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
521 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
522 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
523 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
524 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
525 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
528 /* MIPS DSP REGIMM opcodes */
529 enum {
530 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
531 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
534 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
535 /* MIPS DSP Load */
536 enum {
537 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
538 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
539 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
540 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
543 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
544 enum {
545 /* MIPS DSP Arithmetic Sub-class */
546 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
547 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
548 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
549 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
550 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
551 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
552 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
553 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
554 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
555 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
556 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
557 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
558 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
559 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
560 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
561 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
562 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
563 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
564 /* MIPS DSP Multiply Sub-class insns */
565 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
566 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
567 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
568 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
569 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
570 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
573 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
574 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
578 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
579 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
580 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
581 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
583 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
585 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
586 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
587 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
589 /* MIPS DSP Multiply Sub-class insns */
590 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
591 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
592 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
593 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
596 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
597 enum {
598 /* MIPS DSP Arithmetic Sub-class */
599 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
600 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
601 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
602 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
603 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
608 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
612 /* DSP Bit/Manipulation Sub-class */
613 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
616 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
617 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
620 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
621 enum {
622 /* MIPS DSP Arithmetic Sub-class */
623 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
624 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
625 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
626 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
627 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
630 /* DSP Compare-Pick Sub-class */
631 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
648 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
649 enum {
650 /* MIPS DSP GPR-Based Shift Sub-class */
651 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
652 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
653 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
654 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
655 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
675 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
676 enum {
677 /* MIPS DSP Multiply Sub-class insns */
678 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
679 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
680 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
681 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
682 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
692 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
695 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
696 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
698 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
699 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
702 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
703 enum {
704 /* DSP Bit/Manipulation Sub-class */
705 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
708 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
709 enum {
710 /* MIPS DSP Append Sub-class */
711 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
712 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
713 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
716 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
717 enum {
718 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
719 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
720 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
721 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
722 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
723 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
727 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
728 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
731 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
732 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
733 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
734 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
735 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
738 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
739 enum {
740 /* MIPS DSP Arithmetic Sub-class */
741 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
742 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
743 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
744 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
745 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
758 /* DSP Bit/Manipulation Sub-class */
759 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
762 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
763 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
767 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
768 enum {
769 /* MIPS DSP Multiply Sub-class insns */
770 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
771 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
772 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
773 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
774 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
775 /* MIPS DSP Arithmetic Sub-class */
776 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
777 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
778 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
779 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
780 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
783 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
784 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
785 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
787 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
788 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
789 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
790 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
793 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
794 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
795 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
799 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
800 enum {
801 /* DSP Compare-Pick Sub-class */
802 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
803 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
804 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
805 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
806 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
821 /* MIPS DSP Arithmetic Sub-class */
822 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
826 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
829 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
832 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
833 enum {
834 /* DSP Append Sub-class */
835 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
836 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
837 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
838 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
841 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
842 enum {
843 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
844 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
845 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
846 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
847 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
848 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
849 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
867 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
868 enum {
869 /* DSP Bit/Manipulation Sub-class */
870 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
873 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
874 enum {
875 /* MIPS DSP Multiply Sub-class insns */
876 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
877 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
878 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
879 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
880 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
904 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
905 enum {
906 /* MIPS DSP GPR-Based Shift Sub-class */
907 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
908 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
909 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
910 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
911 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
935 /* Coprocessor 0 (rs field) */
936 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
938 enum {
939 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
940 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
941 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
942 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
943 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
944 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
945 OPC_MFTR = (0x08 << 21) | OPC_CP0,
946 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
947 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
948 OPC_MTTR = (0x0C << 21) | OPC_CP0,
949 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
950 OPC_C0 = (0x10 << 21) | OPC_CP0,
951 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
952 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
953 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
954 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
955 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
956 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
957 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
958 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
959 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
960 OPC_C0_A = (0x1A << 21) | OPC_CP0,
961 OPC_C0_B = (0x1B << 21) | OPC_CP0,
962 OPC_C0_C = (0x1C << 21) | OPC_CP0,
963 OPC_C0_D = (0x1D << 21) | OPC_CP0,
964 OPC_C0_E = (0x1E << 21) | OPC_CP0,
965 OPC_C0_F = (0x1F << 21) | OPC_CP0,
968 /* MFMC0 opcodes */
969 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
971 enum {
972 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
973 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
974 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
975 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
976 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
977 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
978 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
979 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
982 /* Coprocessor 0 (with rs == C0) */
983 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
985 enum {
986 OPC_TLBR = 0x01 | OPC_C0,
987 OPC_TLBWI = 0x02 | OPC_C0,
988 OPC_TLBINV = 0x03 | OPC_C0,
989 OPC_TLBINVF = 0x04 | OPC_C0,
990 OPC_TLBWR = 0x06 | OPC_C0,
991 OPC_TLBP = 0x08 | OPC_C0,
992 OPC_RFE = 0x10 | OPC_C0,
993 OPC_ERET = 0x18 | OPC_C0,
994 OPC_DERET = 0x1F | OPC_C0,
995 OPC_WAIT = 0x20 | OPC_C0,
998 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1000 enum {
1001 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1002 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1003 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1004 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1005 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1006 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1007 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1008 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1009 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1010 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1011 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1014 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1016 enum {
1017 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1018 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1019 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1020 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1021 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1022 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1023 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1024 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1026 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1027 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1028 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1029 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1030 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1031 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1032 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1033 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1035 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1036 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1037 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1038 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1039 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1040 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1041 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1042 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1044 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1045 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1046 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1047 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1048 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1049 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1050 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1051 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1053 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1054 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1055 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1056 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1057 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1058 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1060 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1061 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1062 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1063 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1064 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1065 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1067 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1068 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1069 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1070 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1071 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1072 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1074 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1075 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1076 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1077 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1078 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1079 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1081 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1082 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1083 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1084 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1085 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1086 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1088 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1089 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1090 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1091 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1092 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1093 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1095 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1096 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1097 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1098 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1099 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1100 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1102 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1103 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1104 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1105 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1106 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1107 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1111 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1113 enum {
1114 OPC_LWXC1 = 0x00 | OPC_CP3,
1115 OPC_LDXC1 = 0x01 | OPC_CP3,
1116 OPC_LUXC1 = 0x05 | OPC_CP3,
1117 OPC_SWXC1 = 0x08 | OPC_CP3,
1118 OPC_SDXC1 = 0x09 | OPC_CP3,
1119 OPC_SUXC1 = 0x0D | OPC_CP3,
1120 OPC_PREFX = 0x0F | OPC_CP3,
1121 OPC_ALNV_PS = 0x1E | OPC_CP3,
1122 OPC_MADD_S = 0x20 | OPC_CP3,
1123 OPC_MADD_D = 0x21 | OPC_CP3,
1124 OPC_MADD_PS = 0x26 | OPC_CP3,
1125 OPC_MSUB_S = 0x28 | OPC_CP3,
1126 OPC_MSUB_D = 0x29 | OPC_CP3,
1127 OPC_MSUB_PS = 0x2E | OPC_CP3,
1128 OPC_NMADD_S = 0x30 | OPC_CP3,
1129 OPC_NMADD_D = 0x31 | OPC_CP3,
1130 OPC_NMADD_PS = 0x36 | OPC_CP3,
1131 OPC_NMSUB_S = 0x38 | OPC_CP3,
1132 OPC_NMSUB_D = 0x39 | OPC_CP3,
1133 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1136 /* MSA Opcodes */
1137 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1138 enum {
1139 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1140 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1141 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1142 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1143 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1144 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1145 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1146 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1147 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1148 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1149 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1150 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1151 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1152 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1153 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1154 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1155 OPC_MSA_ELM = 0x19 | OPC_MSA,
1156 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1157 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1158 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1159 OPC_MSA_VEC = 0x1E | OPC_MSA,
1161 /* MI10 instruction */
1162 OPC_LD_B = (0x20) | OPC_MSA,
1163 OPC_LD_H = (0x21) | OPC_MSA,
1164 OPC_LD_W = (0x22) | OPC_MSA,
1165 OPC_LD_D = (0x23) | OPC_MSA,
1166 OPC_ST_B = (0x24) | OPC_MSA,
1167 OPC_ST_H = (0x25) | OPC_MSA,
1168 OPC_ST_W = (0x26) | OPC_MSA,
1169 OPC_ST_D = (0x27) | OPC_MSA,
1172 enum {
1173 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1174 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1175 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1176 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1177 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1178 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1179 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1180 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1181 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1182 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1183 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1184 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1185 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1187 /* I8 instruction */
1188 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1189 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1190 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1191 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1192 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1193 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1194 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1195 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1196 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1197 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1199 /* VEC/2R/2RF instruction */
1200 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1201 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1202 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1203 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1204 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1205 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1206 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1208 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1209 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1211 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1212 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1213 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1214 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1215 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1217 /* 2RF instruction df(bit 16) = _w, _d */
1218 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1219 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1220 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1221 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1222 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1223 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1224 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1225 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1226 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1227 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1228 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1229 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1230 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1231 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1232 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1233 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1235 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1236 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1237 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1238 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1239 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1240 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1241 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1242 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1243 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1244 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1245 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1246 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1247 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1248 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1249 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1250 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1251 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1252 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1253 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1254 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1255 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1256 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1257 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1258 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1259 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1260 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1261 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1262 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1263 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1264 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1265 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1266 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1267 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1268 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1269 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1270 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1271 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1272 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1273 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1274 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1275 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1276 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1277 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1278 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1279 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1280 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1281 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1282 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1283 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1284 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1285 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1286 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1287 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1288 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1289 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1290 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1291 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1292 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1293 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1294 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1295 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1296 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1297 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1298 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1300 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1301 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1302 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1303 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1304 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1305 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1306 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1307 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1308 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1309 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1311 /* 3RF instruction _df(bit 21) = _w, _d */
1312 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1313 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1314 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1315 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1316 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1317 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1318 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1319 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1320 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1321 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1322 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1323 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1324 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1325 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1326 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1327 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1328 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1329 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1330 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1331 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1332 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1333 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1334 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1335 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1336 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1337 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1338 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1339 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1340 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1341 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1342 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1343 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1344 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1345 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1346 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1347 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1348 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1349 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1350 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1351 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1352 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1354 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1355 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1356 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1357 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1358 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1359 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1360 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1361 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1362 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1363 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1364 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1365 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1366 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1372 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1373 * ============================================
1376 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1377 * instructions set. It is designed to fit the needs of signal, graphical and
1378 * video processing applications. MXU instruction set is used in Xburst family
1379 * of microprocessors by Ingenic.
1381 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1382 * the control register.
1385 * The notation used in MXU assembler mnemonics
1386 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1388 * Register operands:
1390 * XRa, XRb, XRc, XRd - MXU registers
1391 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1393 * Non-register operands:
1395 * aptn1 - 1-bit accumulate add/subtract pattern
1396 * aptn2 - 2-bit accumulate add/subtract pattern
1397 * eptn2 - 2-bit execute add/subtract pattern
1398 * optn2 - 2-bit operand pattern
1399 * optn3 - 3-bit operand pattern
1400 * sft4 - 4-bit shift amount
1401 * strd2 - 2-bit stride amount
1403 * Prefixes:
1405 * Level of parallelism: Operand size:
1406 * S - single operation at a time 32 - word
1407 * D - two operations in parallel 16 - half word
1408 * Q - four operations in parallel 8 - byte
1410 * Operations:
1412 * ADD - Add or subtract
1413 * ADDC - Add with carry-in
1414 * ACC - Accumulate
1415 * ASUM - Sum together then accumulate (add or subtract)
1416 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1417 * AVG - Average between 2 operands
1418 * ABD - Absolute difference
1419 * ALN - Align data
1420 * AND - Logical bitwise 'and' operation
1421 * CPS - Copy sign
1422 * EXTR - Extract bits
1423 * I2M - Move from GPR register to MXU register
1424 * LDD - Load data from memory to XRF
1425 * LDI - Load data from memory to XRF (and increase the address base)
1426 * LUI - Load unsigned immediate
1427 * MUL - Multiply
1428 * MULU - Unsigned multiply
1429 * MADD - 64-bit operand add 32x32 product
1430 * MSUB - 64-bit operand subtract 32x32 product
1431 * MAC - Multiply and accumulate (add or subtract)
1432 * MAD - Multiply and add or subtract
1433 * MAX - Maximum between 2 operands
1434 * MIN - Minimum between 2 operands
1435 * M2I - Move from MXU register to GPR register
1436 * MOVZ - Move if zero
1437 * MOVN - Move if non-zero
1438 * NOR - Logical bitwise 'nor' operation
1439 * OR - Logical bitwise 'or' operation
1440 * STD - Store data from XRF to memory
1441 * SDI - Store data from XRF to memory (and increase the address base)
1442 * SLT - Set of less than comparison
1443 * SAD - Sum of absolute differences
1444 * SLL - Logical shift left
1445 * SLR - Logical shift right
1446 * SAR - Arithmetic shift right
1447 * SAT - Saturation
1448 * SFL - Shuffle
1449 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1450 * XOR - Logical bitwise 'exclusive or' operation
1452 * Suffixes:
1454 * E - Expand results
1455 * F - Fixed point multiplication
1456 * L - Low part result
1457 * R - Doing rounding
1458 * V - Variable instead of immediate
1459 * W - Combine above L and V
1462 * The list of MXU instructions grouped by functionality
1463 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1465 * Load/Store instructions Multiplication instructions
1466 * ----------------------- ---------------------------
1468 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1469 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1470 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1471 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1472 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1473 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1474 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1475 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1476 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1477 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1478 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1479 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1480 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1481 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1482 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1483 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1484 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1485 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1486 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1487 * S16SDI XRa, Rb, s10, eptn2
1488 * S8LDD XRa, Rb, s8, eptn3
1489 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1490 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1491 * S8SDI XRa, Rb, s8, eptn3
1492 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1493 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1494 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1495 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1496 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1497 * S32CPS XRa, XRb, XRc
1498 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1499 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1500 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1501 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1502 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1503 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1504 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1505 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1506 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1507 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1508 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1509 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1510 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1511 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1512 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1513 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1514 * Q8SLT XRa, XRb, XRc
1515 * Q8SLTU XRa, XRb, XRc
1516 * Q8MOVZ XRa, XRb, XRc Shift instructions
1517 * Q8MOVN XRa, XRb, XRc ------------------
1519 * D32SLL XRa, XRb, XRc, XRd, sft4
1520 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1521 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1522 * D32SARL XRa, XRb, XRc, sft4
1523 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1524 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1525 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1526 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1527 * Q16SLL XRa, XRb, XRc, XRd, sft4
1528 * Q16SLR XRa, XRb, XRc, XRd, sft4
1529 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1530 * ------------------------- Q16SLLV XRa, XRb, Rb
1531 * Q16SLRV XRa, XRb, Rb
1532 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1533 * S32ALN XRa, XRb, XRc, Rb
1534 * S32ALNI XRa, XRb, XRc, s3
1535 * S32LUI XRa, s8, optn3 Move instructions
1536 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1537 * S32EXTRV XRa, XRb, Rs, Rt
1538 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1539 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1542 * The opcode organization of MXU instructions
1543 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1545 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1546 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1547 * other bits up to the instruction level is as follows:
1549 * bits
1550 * 05..00
1552 * ┌─ 000000 ─ OPC_MXU_S32MADD
1553 * ├─ 000001 ─ OPC_MXU_S32MADDU
1554 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1555 * │
1556 * │ 20..18
1557 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1558 * │ ├─ 001 ─ OPC_MXU_S32MIN
1559 * │ ├─ 010 ─ OPC_MXU_D16MAX
1560 * │ ├─ 011 ─ OPC_MXU_D16MIN
1561 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1562 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1563 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1564 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1565 * ├─ 000100 ─ OPC_MXU_S32MSUB
1566 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1567 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1568 * │ ├─ 001 ─ OPC_MXU_D16SLT
1569 * │ ├─ 010 ─ OPC_MXU_D16AVG
1570 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1571 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1572 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1573 * │ └─ 111 ─ OPC_MXU_Q8ADD
1574 * │
1575 * │ 20..18
1576 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1577 * │ ├─ 010 ─ OPC_MXU_D16CPS
1578 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1579 * │ └─ 110 ─ OPC_MXU_Q16SAT
1580 * ├─ 001000 ─ OPC_MXU_D16MUL
1581 * │ 25..24
1582 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1583 * │ └─ 01 ─ OPC_MXU_D16MULE
1584 * ├─ 001010 ─ OPC_MXU_D16MAC
1585 * ├─ 001011 ─ OPC_MXU_D16MACF
1586 * ├─ 001100 ─ OPC_MXU_D16MADL
1587 * ├─ 001101 ─ OPC_MXU_S16MAD
1588 * ├─ 001110 ─ OPC_MXU_Q16ADD
1589 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1590 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1591 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1592 * │
1593 * │ 23
1594 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1595 * │ └─ 1 ─ OPC_MXU_S32STDR
1596 * │
1597 * │ 13..10
1598 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1599 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1600 * │
1601 * │ 13..10
1602 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1603 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1604 * │
1605 * │ 23
1606 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1607 * │ └─ 1 ─ OPC_MXU_S32LDIR
1608 * │
1609 * │ 23
1610 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1611 * │ └─ 1 ─ OPC_MXU_S32SDIR
1612 * │
1613 * │ 13..10
1614 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1615 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1616 * │
1617 * │ 13..10
1618 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1619 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1620 * ├─ 011000 ─ OPC_MXU_D32ADD
1621 * │ 23..22
1622 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1623 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1624 * │ └─ 10 ─ OPC_MXU_D32ASUM
1625 * ├─ 011010 ─ <not assigned>
1626 * │ 23..22
1627 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1628 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1629 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1630 * │
1631 * │ 23..22
1632 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1633 * │ ├─ 01 ─ OPC_MXU_D8SUM
1634 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1635 * ├─ 011110 ─ <not assigned>
1636 * ├─ 011111 ─ <not assigned>
1637 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1638 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1639 * ├─ 100010 ─ OPC_MXU_S8LDD
1640 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1641 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1642 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1643 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1644 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1645 * │
1646 * │ 20..18
1647 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1648 * │ ├─ 001 ─ OPC_MXU_S32ALN
1649 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1650 * │ ├─ 011 ─ OPC_MXU_S32LUI
1651 * │ ├─ 100 ─ OPC_MXU_S32NOR
1652 * │ ├─ 101 ─ OPC_MXU_S32AND
1653 * │ ├─ 110 ─ OPC_MXU_S32OR
1654 * │ └─ 111 ─ OPC_MXU_S32XOR
1655 * │
1656 * │ 7..5
1657 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1658 * │ ├─ 001 ─ OPC_MXU_LXH
1659 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1660 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1661 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1662 * ├─ 101100 ─ OPC_MXU_S16LDI
1663 * ├─ 101101 ─ OPC_MXU_S16SDI
1664 * ├─ 101110 ─ OPC_MXU_S32M2I
1665 * ├─ 101111 ─ OPC_MXU_S32I2M
1666 * ├─ 110000 ─ OPC_MXU_D32SLL
1667 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1668 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1669 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1670 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1671 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1672 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1673 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1674 * │
1675 * ├─ 110111 ─ OPC_MXU_Q16SAR
1676 * │ 23..22
1677 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1678 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1679 * │
1680 * │ 20..18
1681 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1682 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1683 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1684 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1685 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1686 * │ └─ 101 ─ OPC_MXU_S32MOVN
1687 * │
1688 * │ 23..22
1689 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1690 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1691 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1692 * ├─ 111100 ─ OPC_MXU_Q8MADL
1693 * ├─ 111101 ─ OPC_MXU_S32SFL
1694 * ├─ 111110 ─ OPC_MXU_Q8SAD
1695 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1698 * Compiled after:
1700 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1701 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1704 enum {
1705 OPC_MXU_S32MADD = 0x00,
1706 OPC_MXU_S32MADDU = 0x01,
1707 OPC__MXU_MUL = 0x02,
1708 OPC_MXU__POOL00 = 0x03,
1709 OPC_MXU_S32MSUB = 0x04,
1710 OPC_MXU_S32MSUBU = 0x05,
1711 OPC_MXU__POOL01 = 0x06,
1712 OPC_MXU__POOL02 = 0x07,
1713 OPC_MXU_D16MUL = 0x08,
1714 OPC_MXU__POOL03 = 0x09,
1715 OPC_MXU_D16MAC = 0x0A,
1716 OPC_MXU_D16MACF = 0x0B,
1717 OPC_MXU_D16MADL = 0x0C,
1718 OPC_MXU_S16MAD = 0x0D,
1719 OPC_MXU_Q16ADD = 0x0E,
1720 OPC_MXU_D16MACE = 0x0F,
1721 OPC_MXU__POOL04 = 0x10,
1722 OPC_MXU__POOL05 = 0x11,
1723 OPC_MXU__POOL06 = 0x12,
1724 OPC_MXU__POOL07 = 0x13,
1725 OPC_MXU__POOL08 = 0x14,
1726 OPC_MXU__POOL09 = 0x15,
1727 OPC_MXU__POOL10 = 0x16,
1728 OPC_MXU__POOL11 = 0x17,
1729 OPC_MXU_D32ADD = 0x18,
1730 OPC_MXU__POOL12 = 0x19,
1731 /* not assigned 0x1A */
1732 OPC_MXU__POOL13 = 0x1B,
1733 OPC_MXU__POOL14 = 0x1C,
1734 OPC_MXU_Q8ACCE = 0x1D,
1735 /* not assigned 0x1E */
1736 /* not assigned 0x1F */
1737 /* not assigned 0x20 */
1738 /* not assigned 0x21 */
1739 OPC_MXU_S8LDD = 0x22,
1740 OPC_MXU_S8STD = 0x23,
1741 OPC_MXU_S8LDI = 0x24,
1742 OPC_MXU_S8SDI = 0x25,
1743 OPC_MXU__POOL15 = 0x26,
1744 OPC_MXU__POOL16 = 0x27,
1745 OPC_MXU__POOL17 = 0x28,
1746 /* not assigned 0x29 */
1747 OPC_MXU_S16LDD = 0x2A,
1748 OPC_MXU_S16STD = 0x2B,
1749 OPC_MXU_S16LDI = 0x2C,
1750 OPC_MXU_S16SDI = 0x2D,
1751 OPC_MXU_S32M2I = 0x2E,
1752 OPC_MXU_S32I2M = 0x2F,
1753 OPC_MXU_D32SLL = 0x30,
1754 OPC_MXU_D32SLR = 0x31,
1755 OPC_MXU_D32SARL = 0x32,
1756 OPC_MXU_D32SAR = 0x33,
1757 OPC_MXU_Q16SLL = 0x34,
1758 OPC_MXU_Q16SLR = 0x35,
1759 OPC_MXU__POOL18 = 0x36,
1760 OPC_MXU_Q16SAR = 0x37,
1761 OPC_MXU__POOL19 = 0x38,
1762 OPC_MXU__POOL20 = 0x39,
1763 OPC_MXU__POOL21 = 0x3A,
1764 OPC_MXU_Q16SCOP = 0x3B,
1765 OPC_MXU_Q8MADL = 0x3C,
1766 OPC_MXU_S32SFL = 0x3D,
1767 OPC_MXU_Q8SAD = 0x3E,
1768 /* not assigned 0x3F */
1773 * MXU pool 00
1775 enum {
1776 OPC_MXU_S32MAX = 0x00,
1777 OPC_MXU_S32MIN = 0x01,
1778 OPC_MXU_D16MAX = 0x02,
1779 OPC_MXU_D16MIN = 0x03,
1780 OPC_MXU_Q8MAX = 0x04,
1781 OPC_MXU_Q8MIN = 0x05,
1782 OPC_MXU_Q8SLT = 0x06,
1783 OPC_MXU_Q8SLTU = 0x07,
1787 * MXU pool 01
1789 enum {
1790 OPC_MXU_S32SLT = 0x00,
1791 OPC_MXU_D16SLT = 0x01,
1792 OPC_MXU_D16AVG = 0x02,
1793 OPC_MXU_D16AVGR = 0x03,
1794 OPC_MXU_Q8AVG = 0x04,
1795 OPC_MXU_Q8AVGR = 0x05,
1796 OPC_MXU_Q8ADD = 0x07,
1800 * MXU pool 02
1802 enum {
1803 OPC_MXU_S32CPS = 0x00,
1804 OPC_MXU_D16CPS = 0x02,
1805 OPC_MXU_Q8ABD = 0x04,
1806 OPC_MXU_Q16SAT = 0x06,
1810 * MXU pool 03
1812 enum {
1813 OPC_MXU_D16MULF = 0x00,
1814 OPC_MXU_D16MULE = 0x01,
1818 * MXU pool 04
1820 enum {
1821 OPC_MXU_S32LDD = 0x00,
1822 OPC_MXU_S32LDDR = 0x01,
1826 * MXU pool 05
1828 enum {
1829 OPC_MXU_S32STD = 0x00,
1830 OPC_MXU_S32STDR = 0x01,
1834 * MXU pool 06
1836 enum {
1837 OPC_MXU_S32LDDV = 0x00,
1838 OPC_MXU_S32LDDVR = 0x01,
1842 * MXU pool 07
1844 enum {
1845 OPC_MXU_S32STDV = 0x00,
1846 OPC_MXU_S32STDVR = 0x01,
1850 * MXU pool 08
1852 enum {
1853 OPC_MXU_S32LDI = 0x00,
1854 OPC_MXU_S32LDIR = 0x01,
1858 * MXU pool 09
1860 enum {
1861 OPC_MXU_S32SDI = 0x00,
1862 OPC_MXU_S32SDIR = 0x01,
1866 * MXU pool 10
1868 enum {
1869 OPC_MXU_S32LDIV = 0x00,
1870 OPC_MXU_S32LDIVR = 0x01,
1874 * MXU pool 11
1876 enum {
1877 OPC_MXU_S32SDIV = 0x00,
1878 OPC_MXU_S32SDIVR = 0x01,
1882 * MXU pool 12
1884 enum {
1885 OPC_MXU_D32ACC = 0x00,
1886 OPC_MXU_D32ACCM = 0x01,
1887 OPC_MXU_D32ASUM = 0x02,
1891 * MXU pool 13
1893 enum {
1894 OPC_MXU_Q16ACC = 0x00,
1895 OPC_MXU_Q16ACCM = 0x01,
1896 OPC_MXU_Q16ASUM = 0x02,
1900 * MXU pool 14
1902 enum {
1903 OPC_MXU_Q8ADDE = 0x00,
1904 OPC_MXU_D8SUM = 0x01,
1905 OPC_MXU_D8SUMC = 0x02,
1909 * MXU pool 15
1911 enum {
1912 OPC_MXU_S32MUL = 0x00,
1913 OPC_MXU_S32MULU = 0x01,
1914 OPC_MXU_S32EXTR = 0x02,
1915 OPC_MXU_S32EXTRV = 0x03,
1919 * MXU pool 16
1921 enum {
1922 OPC_MXU_D32SARW = 0x00,
1923 OPC_MXU_S32ALN = 0x01,
1924 OPC_MXU_S32ALNI = 0x02,
1925 OPC_MXU_S32LUI = 0x03,
1926 OPC_MXU_S32NOR = 0x04,
1927 OPC_MXU_S32AND = 0x05,
1928 OPC_MXU_S32OR = 0x06,
1929 OPC_MXU_S32XOR = 0x07,
1933 * MXU pool 17
1935 enum {
1936 OPC_MXU_LXB = 0x00,
1937 OPC_MXU_LXH = 0x01,
1938 OPC_MXU_LXW = 0x03,
1939 OPC_MXU_LXBU = 0x04,
1940 OPC_MXU_LXHU = 0x05,
1944 * MXU pool 18
1946 enum {
1947 OPC_MXU_D32SLLV = 0x00,
1948 OPC_MXU_D32SLRV = 0x01,
1949 OPC_MXU_D32SARV = 0x03,
1950 OPC_MXU_Q16SLLV = 0x04,
1951 OPC_MXU_Q16SLRV = 0x05,
1952 OPC_MXU_Q16SARV = 0x07,
1956 * MXU pool 19
1958 enum {
1959 OPC_MXU_Q8MUL = 0x00,
1960 OPC_MXU_Q8MULSU = 0x01,
1964 * MXU pool 20
1966 enum {
1967 OPC_MXU_Q8MOVZ = 0x00,
1968 OPC_MXU_Q8MOVN = 0x01,
1969 OPC_MXU_D16MOVZ = 0x02,
1970 OPC_MXU_D16MOVN = 0x03,
1971 OPC_MXU_S32MOVZ = 0x04,
1972 OPC_MXU_S32MOVN = 0x05,
1976 * MXU pool 21
1978 enum {
1979 OPC_MXU_Q8MAC = 0x00,
1980 OPC_MXU_Q8MACSU = 0x01,
1984 * Overview of the TX79-specific instruction set
1985 * =============================================
1987 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
1988 * are only used by the specific quadword (128-bit) LQ/SQ load/store
1989 * instructions and certain multimedia instructions (MMIs). These MMIs
1990 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
1991 * or sixteen 8-bit paths.
1993 * Reference:
1995 * The Toshiba TX System RISC TX79 Core Architecture manual,
1996 * https://wiki.qemu.org/File:C790.pdf
1998 * Three-Operand Multiply and Multiply-Add (4 instructions)
1999 * --------------------------------------------------------
2000 * MADD [rd,] rs, rt Multiply/Add
2001 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2002 * MULT [rd,] rs, rt Multiply (3-operand)
2003 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2005 * Multiply Instructions for Pipeline 1 (10 instructions)
2006 * ------------------------------------------------------
2007 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2008 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2009 * DIV1 rs, rt Divide Pipeline 1
2010 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2011 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2012 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2013 * MFHI1 rd Move From HI1 Register
2014 * MFLO1 rd Move From LO1 Register
2015 * MTHI1 rs Move To HI1 Register
2016 * MTLO1 rs Move To LO1 Register
2018 * Arithmetic (19 instructions)
2019 * ----------------------------
2020 * PADDB rd, rs, rt Parallel Add Byte
2021 * PSUBB rd, rs, rt Parallel Subtract Byte
2022 * PADDH rd, rs, rt Parallel Add Halfword
2023 * PSUBH rd, rs, rt Parallel Subtract Halfword
2024 * PADDW rd, rs, rt Parallel Add Word
2025 * PSUBW rd, rs, rt Parallel Subtract Word
2026 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2027 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2028 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2029 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2030 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2031 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2032 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2033 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2034 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2035 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2036 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2037 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2038 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2040 * Min/Max (4 instructions)
2041 * ------------------------
2042 * PMAXH rd, rs, rt Parallel Maximum Halfword
2043 * PMINH rd, rs, rt Parallel Minimum Halfword
2044 * PMAXW rd, rs, rt Parallel Maximum Word
2045 * PMINW rd, rs, rt Parallel Minimum Word
2047 * Absolute (2 instructions)
2048 * -------------------------
2049 * PABSH rd, rt Parallel Absolute Halfword
2050 * PABSW rd, rt Parallel Absolute Word
2052 * Logical (4 instructions)
2053 * ------------------------
2054 * PAND rd, rs, rt Parallel AND
2055 * POR rd, rs, rt Parallel OR
2056 * PXOR rd, rs, rt Parallel XOR
2057 * PNOR rd, rs, rt Parallel NOR
2059 * Shift (9 instructions)
2060 * ----------------------
2061 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2062 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2063 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2064 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2065 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2066 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2067 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2068 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2069 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2071 * Compare (6 instructions)
2072 * ------------------------
2073 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2074 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2075 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2076 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2077 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2078 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2080 * LZC (1 instruction)
2081 * -------------------
2082 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2084 * Quadword Load and Store (2 instructions)
2085 * ----------------------------------------
2086 * LQ rt, offset(base) Load Quadword
2087 * SQ rt, offset(base) Store Quadword
2089 * Multiply and Divide (19 instructions)
2090 * -------------------------------------
2091 * PMULTW rd, rs, rt Parallel Multiply Word
2092 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2093 * PDIVW rs, rt Parallel Divide Word
2094 * PDIVUW rs, rt Parallel Divide Unsigned Word
2095 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2096 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2097 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2098 * PMULTH rd, rs, rt Parallel Multiply Halfword
2099 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2100 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2101 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2102 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2103 * PDIVBW rs, rt Parallel Divide Broadcast Word
2104 * PMFHI rd Parallel Move From HI Register
2105 * PMFLO rd Parallel Move From LO Register
2106 * PMTHI rs Parallel Move To HI Register
2107 * PMTLO rs Parallel Move To LO Register
2108 * PMFHL rd Parallel Move From HI/LO Register
2109 * PMTHL rs Parallel Move To HI/LO Register
2111 * Pack/Extend (11 instructions)
2112 * -----------------------------
2113 * PPAC5 rd, rt Parallel Pack to 5 bits
2114 * PPACB rd, rs, rt Parallel Pack to Byte
2115 * PPACH rd, rs, rt Parallel Pack to Halfword
2116 * PPACW rd, rs, rt Parallel Pack to Word
2117 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2118 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2119 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2120 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2121 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2122 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2123 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2125 * Others (16 instructions)
2126 * ------------------------
2127 * PCPYH rd, rt Parallel Copy Halfword
2128 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2129 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2130 * PREVH rd, rt Parallel Reverse Halfword
2131 * PINTH rd, rs, rt Parallel Interleave Halfword
2132 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2133 * PEXEH rd, rt Parallel Exchange Even Halfword
2134 * PEXCH rd, rt Parallel Exchange Center Halfword
2135 * PEXEW rd, rt Parallel Exchange Even Word
2136 * PEXCW rd, rt Parallel Exchange Center Word
2137 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2138 * MFSA rd Move from Shift Amount Register
2139 * MTSA rs Move to Shift Amount Register
2140 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2141 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2142 * PROT3W rd, rt Parallel Rotate 3 Words
2144 * MMI (MultiMedia Instruction) encodings
2145 * ======================================
2147 * MMI instructions encoding table keys:
2149 * * This code is reserved for future use. An attempt to execute it
2150 * causes a Reserved Instruction exception.
2151 * % This code indicates an instruction class. The instruction word
2152 * must be further decoded by examining additional tables that show
2153 * the values for other instruction fields.
2154 * # This code is reserved for the unsupported instructions DMULT,
2155 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2156 * to execute it causes a Reserved Instruction exception.
2158 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2160 * 31 26 0
2161 * +--------+----------------------------------------+
2162 * | opcode | |
2163 * +--------+----------------------------------------+
2165 * opcode bits 28..26
2166 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2167 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2168 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2169 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2170 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2171 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2172 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2173 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2174 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2175 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2176 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2179 enum {
2180 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2181 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2182 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2186 * MMI instructions with opcode field = MMI:
2188 * 31 26 5 0
2189 * +--------+-------------------------------+--------+
2190 * | MMI | |function|
2191 * +--------+-------------------------------+--------+
2193 * function bits 2..0
2194 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2195 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2196 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2197 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2198 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2199 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2200 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2201 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2202 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2203 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2204 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2207 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2208 enum {
2209 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2210 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2211 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2212 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2213 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2214 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2215 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2216 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2217 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2218 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2219 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2220 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2221 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2222 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2223 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2224 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2225 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2226 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2227 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2228 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2229 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2230 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2231 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2232 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2233 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2237 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2239 * 31 26 10 6 5 0
2240 * +--------+----------------------+--------+--------+
2241 * | MMI | |function| MMI0 |
2242 * +--------+----------------------+--------+--------+
2244 * function bits 7..6
2245 * bits | 0 | 1 | 2 | 3
2246 * 10..8 | 00 | 01 | 10 | 11
2247 * -------+-------+-------+-------+-------
2248 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2249 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2250 * 2 010 | PADDB | PSUBB | PCGTB | *
2251 * 3 011 | * | * | * | *
2252 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2253 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2254 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2255 * 7 111 | * | * | PEXT5 | PPAC5
2258 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2259 enum {
2260 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2261 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2262 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2263 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2264 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2265 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2266 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2267 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2268 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2269 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2270 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2271 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2272 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2273 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2274 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2275 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2276 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2277 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2278 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2279 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2280 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2281 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2282 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2283 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2284 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2288 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2290 * 31 26 10 6 5 0
2291 * +--------+----------------------+--------+--------+
2292 * | MMI | |function| MMI1 |
2293 * +--------+----------------------+--------+--------+
2295 * function bits 7..6
2296 * bits | 0 | 1 | 2 | 3
2297 * 10..8 | 00 | 01 | 10 | 11
2298 * -------+-------+-------+-------+-------
2299 * 0 000 | * | PABSW | PCEQW | PMINW
2300 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2301 * 2 010 | * | * | PCEQB | *
2302 * 3 011 | * | * | * | *
2303 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2304 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2305 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2306 * 7 111 | * | * | * | *
2309 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2310 enum {
2311 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2312 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2313 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2314 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2315 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2316 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2317 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2318 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2319 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2320 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2321 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2322 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2323 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2324 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2325 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2326 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2327 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2328 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2332 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2334 * 31 26 10 6 5 0
2335 * +--------+----------------------+--------+--------+
2336 * | MMI | |function| MMI2 |
2337 * +--------+----------------------+--------+--------+
2339 * function bits 7..6
2340 * bits | 0 | 1 | 2 | 3
2341 * 10..8 | 00 | 01 | 10 | 11
2342 * -------+-------+-------+-------+-------
2343 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2344 * 1 001 | PMSUBW| * | * | *
2345 * 2 010 | PMFHI | PMFLO | PINTH | *
2346 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2347 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2348 * 5 101 | PMSUBH| PHMSBH| * | *
2349 * 6 110 | * | * | PEXEH | PREVH
2350 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2353 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2354 enum {
2355 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2356 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2357 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2358 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2359 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2360 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2361 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2362 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2363 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2364 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2365 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2366 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2367 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2368 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2369 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2370 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2371 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2372 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2373 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2374 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2375 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2376 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2380 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2382 * 31 26 10 6 5 0
2383 * +--------+----------------------+--------+--------+
2384 * | MMI | |function| MMI3 |
2385 * +--------+----------------------+--------+--------+
2387 * function bits 7..6
2388 * bits | 0 | 1 | 2 | 3
2389 * 10..8 | 00 | 01 | 10 | 11
2390 * -------+-------+-------+-------+-------
2391 * 0 000 |PMADDUW| * | * | PSRAVW
2392 * 1 001 | * | * | * | *
2393 * 2 010 | PMTHI | PMTLO | PINTEH| *
2394 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2395 * 4 100 | * | * | POR | PNOR
2396 * 5 101 | * | * | * | *
2397 * 6 110 | * | * | PEXCH | PCPYH
2398 * 7 111 | * | * | PEXCW | *
2401 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2402 enum {
2403 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2404 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2405 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2406 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2407 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2408 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2409 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2410 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2411 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2412 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2413 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2414 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2415 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2418 /* global register indices */
2419 TCGv cpu_gpr[32], cpu_PC;
2420 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2421 static TCGv cpu_dspctrl, btarget;
2422 TCGv bcond;
2423 static TCGv cpu_lladdr, cpu_llval;
2424 static TCGv_i32 hflags;
2425 TCGv_i32 fpu_fcr0, fpu_fcr31;
2426 TCGv_i64 fpu_f64[32];
2427 static TCGv_i64 msa_wr_d[64];
2429 #if defined(TARGET_MIPS64)
2430 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2431 static TCGv_i64 cpu_mmr[32];
2432 #endif
2434 #if !defined(TARGET_MIPS64)
2435 /* MXU registers */
2436 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2437 static TCGv mxu_CR;
2438 #endif
2440 #include "exec/gen-icount.h"
2442 #define gen_helper_0e0i(name, arg) do { \
2443 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2444 gen_helper_##name(cpu_env, helper_tmp); \
2445 tcg_temp_free_i32(helper_tmp); \
2446 } while (0)
2448 #define gen_helper_0e1i(name, arg1, arg2) do { \
2449 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2450 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2451 tcg_temp_free_i32(helper_tmp); \
2452 } while (0)
2454 #define gen_helper_1e0i(name, ret, arg1) do { \
2455 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2456 gen_helper_##name(ret, cpu_env, helper_tmp); \
2457 tcg_temp_free_i32(helper_tmp); \
2458 } while (0)
2460 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2461 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2462 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2463 tcg_temp_free_i32(helper_tmp); \
2464 } while (0)
2466 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2467 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2468 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2469 tcg_temp_free_i32(helper_tmp); \
2470 } while (0)
2472 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2473 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2474 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2475 tcg_temp_free_i32(helper_tmp); \
2476 } while (0)
2478 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2479 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2480 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2481 tcg_temp_free_i32(helper_tmp); \
2482 } while (0)
2484 #define DISAS_STOP DISAS_TARGET_0
2485 #define DISAS_EXIT DISAS_TARGET_1
2487 static const char * const regnames[] = {
2488 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2489 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2490 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2491 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2494 static const char * const regnames_HI[] = {
2495 "HI0", "HI1", "HI2", "HI3",
2498 static const char * const regnames_LO[] = {
2499 "LO0", "LO1", "LO2", "LO3",
2502 static const char * const fregnames[] = {
2503 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2504 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2505 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2506 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2509 static const char * const msaregnames[] = {
2510 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2511 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2512 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2513 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2514 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2515 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2516 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2517 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2518 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2519 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2520 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2521 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2522 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2523 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2524 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2525 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2528 #if !defined(TARGET_MIPS64)
2529 static const char * const mxuregnames[] = {
2530 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2531 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2533 #endif
2535 /* General purpose registers moves. */
2536 void gen_load_gpr(TCGv t, int reg)
2538 if (reg == 0) {
2539 tcg_gen_movi_tl(t, 0);
2540 } else {
2541 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2545 void gen_store_gpr(TCGv t, int reg)
2547 if (reg != 0) {
2548 tcg_gen_mov_tl(cpu_gpr[reg], t);
2552 /* Moves to/from shadow registers. */
2553 static inline void gen_load_srsgpr(int from, int to)
2555 TCGv t0 = tcg_temp_new();
2557 if (from == 0) {
2558 tcg_gen_movi_tl(t0, 0);
2559 } else {
2560 TCGv_i32 t2 = tcg_temp_new_i32();
2561 TCGv_ptr addr = tcg_temp_new_ptr();
2563 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2564 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2565 tcg_gen_andi_i32(t2, t2, 0xf);
2566 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2567 tcg_gen_ext_i32_ptr(addr, t2);
2568 tcg_gen_add_ptr(addr, cpu_env, addr);
2570 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2571 tcg_temp_free_ptr(addr);
2572 tcg_temp_free_i32(t2);
2574 gen_store_gpr(t0, to);
2575 tcg_temp_free(t0);
2578 static inline void gen_store_srsgpr(int from, int to)
2580 if (to != 0) {
2581 TCGv t0 = tcg_temp_new();
2582 TCGv_i32 t2 = tcg_temp_new_i32();
2583 TCGv_ptr addr = tcg_temp_new_ptr();
2585 gen_load_gpr(t0, from);
2586 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2587 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2588 tcg_gen_andi_i32(t2, t2, 0xf);
2589 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2590 tcg_gen_ext_i32_ptr(addr, t2);
2591 tcg_gen_add_ptr(addr, cpu_env, addr);
2593 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2594 tcg_temp_free_ptr(addr);
2595 tcg_temp_free_i32(t2);
2596 tcg_temp_free(t0);
2600 #if !defined(TARGET_MIPS64)
2601 /* MXU General purpose registers moves. */
2602 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2604 if (reg == 0) {
2605 tcg_gen_movi_tl(t, 0);
2606 } else if (reg <= 15) {
2607 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2611 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2613 if (reg > 0 && reg <= 15) {
2614 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2618 /* MXU control register moves. */
2619 static inline void gen_load_mxu_cr(TCGv t)
2621 tcg_gen_mov_tl(t, mxu_CR);
2624 static inline void gen_store_mxu_cr(TCGv t)
2626 /* TODO: Add handling of RW rules for MXU_CR. */
2627 tcg_gen_mov_tl(mxu_CR, t);
2629 #endif
2632 /* Tests */
2633 static inline void gen_save_pc(target_ulong pc)
2635 tcg_gen_movi_tl(cpu_PC, pc);
2638 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2640 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2641 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2642 gen_save_pc(ctx->base.pc_next);
2643 ctx->saved_pc = ctx->base.pc_next;
2645 if (ctx->hflags != ctx->saved_hflags) {
2646 tcg_gen_movi_i32(hflags, ctx->hflags);
2647 ctx->saved_hflags = ctx->hflags;
2648 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2649 case MIPS_HFLAG_BR:
2650 break;
2651 case MIPS_HFLAG_BC:
2652 case MIPS_HFLAG_BL:
2653 case MIPS_HFLAG_B:
2654 tcg_gen_movi_tl(btarget, ctx->btarget);
2655 break;
2660 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2662 ctx->saved_hflags = ctx->hflags;
2663 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2664 case MIPS_HFLAG_BR:
2665 break;
2666 case MIPS_HFLAG_BC:
2667 case MIPS_HFLAG_BL:
2668 case MIPS_HFLAG_B:
2669 ctx->btarget = env->btarget;
2670 break;
2674 void generate_exception_err(DisasContext *ctx, int excp, int err)
2676 TCGv_i32 texcp = tcg_const_i32(excp);
2677 TCGv_i32 terr = tcg_const_i32(err);
2678 save_cpu_state(ctx, 1);
2679 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2680 tcg_temp_free_i32(terr);
2681 tcg_temp_free_i32(texcp);
2682 ctx->base.is_jmp = DISAS_NORETURN;
2685 void generate_exception(DisasContext *ctx, int excp)
2687 gen_helper_0e0i(raise_exception, excp);
2690 void generate_exception_end(DisasContext *ctx, int excp)
2692 generate_exception_err(ctx, excp, 0);
2695 void gen_reserved_instruction(DisasContext *ctx)
2697 generate_exception_end(ctx, EXCP_RI);
2700 /* Floating point register moves. */
2701 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2703 if (ctx->hflags & MIPS_HFLAG_FRE) {
2704 generate_exception(ctx, EXCP_RI);
2706 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2709 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2711 TCGv_i64 t64;
2712 if (ctx->hflags & MIPS_HFLAG_FRE) {
2713 generate_exception(ctx, EXCP_RI);
2715 t64 = tcg_temp_new_i64();
2716 tcg_gen_extu_i32_i64(t64, t);
2717 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2718 tcg_temp_free_i64(t64);
2721 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2723 if (ctx->hflags & MIPS_HFLAG_F64) {
2724 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2725 } else {
2726 gen_load_fpr32(ctx, t, reg | 1);
2730 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2732 if (ctx->hflags & MIPS_HFLAG_F64) {
2733 TCGv_i64 t64 = tcg_temp_new_i64();
2734 tcg_gen_extu_i32_i64(t64, t);
2735 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2736 tcg_temp_free_i64(t64);
2737 } else {
2738 gen_store_fpr32(ctx, t, reg | 1);
2742 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2744 if (ctx->hflags & MIPS_HFLAG_F64) {
2745 tcg_gen_mov_i64(t, fpu_f64[reg]);
2746 } else {
2747 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2751 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2753 if (ctx->hflags & MIPS_HFLAG_F64) {
2754 tcg_gen_mov_i64(fpu_f64[reg], t);
2755 } else {
2756 TCGv_i64 t0;
2757 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2758 t0 = tcg_temp_new_i64();
2759 tcg_gen_shri_i64(t0, t, 32);
2760 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2761 tcg_temp_free_i64(t0);
2765 int get_fp_bit(int cc)
2767 if (cc) {
2768 return 24 + cc;
2769 } else {
2770 return 23;
2774 /* Addresses computation */
2775 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
2777 tcg_gen_add_tl(ret, arg0, arg1);
2779 #if defined(TARGET_MIPS64)
2780 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2781 tcg_gen_ext32s_i64(ret, ret);
2783 #endif
2786 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2787 target_long ofs)
2789 tcg_gen_addi_tl(ret, base, ofs);
2791 #if defined(TARGET_MIPS64)
2792 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2793 tcg_gen_ext32s_i64(ret, ret);
2795 #endif
2798 /* Addresses computation (translation time) */
2799 static target_long addr_add(DisasContext *ctx, target_long base,
2800 target_long offset)
2802 target_long sum = base + offset;
2804 #if defined(TARGET_MIPS64)
2805 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2806 sum = (int32_t)sum;
2808 #endif
2809 return sum;
2812 /* Sign-extract the low 32-bits to a target_long. */
2813 void gen_move_low32(TCGv ret, TCGv_i64 arg)
2815 #if defined(TARGET_MIPS64)
2816 tcg_gen_ext32s_i64(ret, arg);
2817 #else
2818 tcg_gen_extrl_i64_i32(ret, arg);
2819 #endif
2822 /* Sign-extract the high 32-bits to a target_long. */
2823 void gen_move_high32(TCGv ret, TCGv_i64 arg)
2825 #if defined(TARGET_MIPS64)
2826 tcg_gen_sari_i64(ret, arg, 32);
2827 #else
2828 tcg_gen_extrh_i64_i32(ret, arg);
2829 #endif
2832 void check_cp0_enabled(DisasContext *ctx)
2834 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2835 generate_exception_end(ctx, EXCP_CpU);
2839 void check_cp1_enabled(DisasContext *ctx)
2841 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2842 generate_exception_err(ctx, EXCP_CpU, 1);
2847 * Verify that the processor is running with COP1X instructions enabled.
2848 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2849 * opcode tables.
2851 void check_cop1x(DisasContext *ctx)
2853 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2854 gen_reserved_instruction(ctx);
2859 * Verify that the processor is running with 64-bit floating-point
2860 * operations enabled.
2862 void check_cp1_64bitmode(DisasContext *ctx)
2864 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2865 gen_reserved_instruction(ctx);
2870 * Verify if floating point register is valid; an operation is not defined
2871 * if bit 0 of any register specification is set and the FR bit in the
2872 * Status register equals zero, since the register numbers specify an
2873 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2874 * in the Status register equals one, both even and odd register numbers
2875 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
2877 * Multiple 64 bit wide registers can be checked by calling
2878 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
2880 void check_cp1_registers(DisasContext *ctx, int regs)
2882 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
2883 gen_reserved_instruction(ctx);
2888 * Verify that the processor is running with DSP instructions enabled.
2889 * This is enabled by CP0 Status register MX(24) bit.
2891 static inline void check_dsp(DisasContext *ctx)
2893 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
2894 if (ctx->insn_flags & ASE_DSP) {
2895 generate_exception_end(ctx, EXCP_DSPDIS);
2896 } else {
2897 gen_reserved_instruction(ctx);
2902 static inline void check_dsp_r2(DisasContext *ctx)
2904 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
2905 if (ctx->insn_flags & ASE_DSP) {
2906 generate_exception_end(ctx, EXCP_DSPDIS);
2907 } else {
2908 gen_reserved_instruction(ctx);
2913 static inline void check_dsp_r3(DisasContext *ctx)
2915 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
2916 if (ctx->insn_flags & ASE_DSP) {
2917 generate_exception_end(ctx, EXCP_DSPDIS);
2918 } else {
2919 gen_reserved_instruction(ctx);
2925 * This code generates a "reserved instruction" exception if the
2926 * CPU does not support the instruction set corresponding to flags.
2928 void check_insn(DisasContext *ctx, uint64_t flags)
2930 if (unlikely(!(ctx->insn_flags & flags))) {
2931 gen_reserved_instruction(ctx);
2936 * This code generates a "reserved instruction" exception if the
2937 * CPU has corresponding flag set which indicates that the instruction
2938 * has been removed.
2940 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
2942 if (unlikely(ctx->insn_flags & flags)) {
2943 gen_reserved_instruction(ctx);
2948 * The Linux kernel traps certain reserved instruction exceptions to
2949 * emulate the corresponding instructions. QEMU is the kernel in user
2950 * mode, so those traps are emulated by accepting the instructions.
2952 * A reserved instruction exception is generated for flagged CPUs if
2953 * QEMU runs in system mode.
2955 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
2957 #ifndef CONFIG_USER_ONLY
2958 check_insn_opc_removed(ctx, flags);
2959 #endif
2963 * This code generates a "reserved instruction" exception if the
2964 * CPU does not support 64-bit paired-single (PS) floating point data type.
2966 static inline void check_ps(DisasContext *ctx)
2968 if (unlikely(!ctx->ps)) {
2969 generate_exception(ctx, EXCP_RI);
2971 check_cp1_64bitmode(ctx);
2975 * This code generates a "reserved instruction" exception if cpu is not
2976 * 64-bit or 64-bit instructions are not enabled.
2978 void check_mips_64(DisasContext *ctx)
2980 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
2981 gen_reserved_instruction(ctx);
2985 #ifndef CONFIG_USER_ONLY
2986 static inline void check_mvh(DisasContext *ctx)
2988 if (unlikely(!ctx->mvh)) {
2989 generate_exception(ctx, EXCP_RI);
2992 #endif
2995 * This code generates a "reserved instruction" exception if the
2996 * Config5 XNP bit is set.
2998 static inline void check_xnp(DisasContext *ctx)
3000 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3001 gen_reserved_instruction(ctx);
3005 #ifndef CONFIG_USER_ONLY
3007 * This code generates a "reserved instruction" exception if the
3008 * Config3 PW bit is NOT set.
3010 static inline void check_pw(DisasContext *ctx)
3012 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3013 gen_reserved_instruction(ctx);
3016 #endif
3019 * This code generates a "reserved instruction" exception if the
3020 * Config3 MT bit is NOT set.
3022 static inline void check_mt(DisasContext *ctx)
3024 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3025 gen_reserved_instruction(ctx);
3029 #ifndef CONFIG_USER_ONLY
3031 * This code generates a "coprocessor unusable" exception if CP0 is not
3032 * available, and, if that is not the case, generates a "reserved instruction"
3033 * exception if the Config5 MT bit is NOT set. This is needed for availability
3034 * control of some of MT ASE instructions.
3036 static inline void check_cp0_mt(DisasContext *ctx)
3038 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3039 generate_exception_end(ctx, EXCP_CpU);
3040 } else {
3041 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3042 gen_reserved_instruction(ctx);
3046 #endif
3049 * This code generates a "reserved instruction" exception if the
3050 * Config5 NMS bit is set.
3052 static inline void check_nms(DisasContext *ctx)
3054 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3055 gen_reserved_instruction(ctx);
3060 * This code generates a "reserved instruction" exception if the
3061 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3062 * Config2 TL, and Config5 L2C are unset.
3064 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3066 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3067 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3068 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3069 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3070 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3071 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3072 gen_reserved_instruction(ctx);
3077 * This code generates a "reserved instruction" exception if the
3078 * Config5 EVA bit is NOT set.
3080 static inline void check_eva(DisasContext *ctx)
3082 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3083 gen_reserved_instruction(ctx);
3089 * Define small wrappers for gen_load_fpr* so that we have a uniform
3090 * calling interface for 32 and 64-bit FPRs. No sense in changing
3091 * all callers for gen_load_fpr32 when we need the CTX parameter for
3092 * this one use.
3094 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3095 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3096 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3097 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3098 int ft, int fs, int cc) \
3100 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3101 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3102 switch (ifmt) { \
3103 case FMT_PS: \
3104 check_ps(ctx); \
3105 break; \
3106 case FMT_D: \
3107 if (abs) { \
3108 check_cop1x(ctx); \
3110 check_cp1_registers(ctx, fs | ft); \
3111 break; \
3112 case FMT_S: \
3113 if (abs) { \
3114 check_cop1x(ctx); \
3116 break; \
3118 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3119 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3120 switch (n) { \
3121 case 0: \
3122 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3123 break; \
3124 case 1: \
3125 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3126 break; \
3127 case 2: \
3128 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3129 break; \
3130 case 3: \
3131 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3132 break; \
3133 case 4: \
3134 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3135 break; \
3136 case 5: \
3137 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3138 break; \
3139 case 6: \
3140 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3141 break; \
3142 case 7: \
3143 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3144 break; \
3145 case 8: \
3146 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3147 break; \
3148 case 9: \
3149 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3150 break; \
3151 case 10: \
3152 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3153 break; \
3154 case 11: \
3155 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3156 break; \
3157 case 12: \
3158 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3159 break; \
3160 case 13: \
3161 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3162 break; \
3163 case 14: \
3164 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3165 break; \
3166 case 15: \
3167 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3168 break; \
3169 default: \
3170 abort(); \
3172 tcg_temp_free_i##bits(fp0); \
3173 tcg_temp_free_i##bits(fp1); \
3176 FOP_CONDS(, 0, d, FMT_D, 64)
3177 FOP_CONDS(abs, 1, d, FMT_D, 64)
3178 FOP_CONDS(, 0, s, FMT_S, 32)
3179 FOP_CONDS(abs, 1, s, FMT_S, 32)
3180 FOP_CONDS(, 0, ps, FMT_PS, 64)
3181 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3182 #undef FOP_CONDS
3184 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3185 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3186 int ft, int fs, int fd) \
3188 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3189 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3190 if (ifmt == FMT_D) { \
3191 check_cp1_registers(ctx, fs | ft | fd); \
3193 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3194 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3195 switch (n) { \
3196 case 0: \
3197 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3198 break; \
3199 case 1: \
3200 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3201 break; \
3202 case 2: \
3203 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3204 break; \
3205 case 3: \
3206 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3207 break; \
3208 case 4: \
3209 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3210 break; \
3211 case 5: \
3212 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3213 break; \
3214 case 6: \
3215 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3216 break; \
3217 case 7: \
3218 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3219 break; \
3220 case 8: \
3221 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3222 break; \
3223 case 9: \
3224 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3225 break; \
3226 case 10: \
3227 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3228 break; \
3229 case 11: \
3230 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3231 break; \
3232 case 12: \
3233 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3234 break; \
3235 case 13: \
3236 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3237 break; \
3238 case 14: \
3239 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3240 break; \
3241 case 15: \
3242 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3243 break; \
3244 case 17: \
3245 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3246 break; \
3247 case 18: \
3248 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3249 break; \
3250 case 19: \
3251 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3252 break; \
3253 case 25: \
3254 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3255 break; \
3256 case 26: \
3257 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3258 break; \
3259 case 27: \
3260 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3261 break; \
3262 default: \
3263 abort(); \
3265 STORE; \
3266 tcg_temp_free_i ## bits(fp0); \
3267 tcg_temp_free_i ## bits(fp1); \
3270 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3271 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3272 #undef FOP_CONDNS
3273 #undef gen_ldcmp_fpr32
3274 #undef gen_ldcmp_fpr64
3276 /* load/store instructions. */
3277 #ifdef CONFIG_USER_ONLY
3278 #define OP_LD_ATOMIC(insn, fname) \
3279 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3280 DisasContext *ctx) \
3282 TCGv t0 = tcg_temp_new(); \
3283 tcg_gen_mov_tl(t0, arg1); \
3284 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3285 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3286 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3287 tcg_temp_free(t0); \
3289 #else
3290 #define OP_LD_ATOMIC(insn, fname) \
3291 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3292 DisasContext *ctx) \
3294 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3296 #endif
3297 OP_LD_ATOMIC(ll, ld32s);
3298 #if defined(TARGET_MIPS64)
3299 OP_LD_ATOMIC(lld, ld64);
3300 #endif
3301 #undef OP_LD_ATOMIC
3303 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
3305 if (base == 0) {
3306 tcg_gen_movi_tl(addr, offset);
3307 } else if (offset == 0) {
3308 gen_load_gpr(addr, base);
3309 } else {
3310 tcg_gen_movi_tl(addr, offset);
3311 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3315 static target_ulong pc_relative_pc(DisasContext *ctx)
3317 target_ulong pc = ctx->base.pc_next;
3319 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3320 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3322 pc -= branch_bytes;
3325 pc &= ~(target_ulong)3;
3326 return pc;
3329 /* Load */
3330 static void gen_ld(DisasContext *ctx, uint32_t opc,
3331 int rt, int base, int offset)
3333 TCGv t0, t1, t2;
3334 int mem_idx = ctx->mem_idx;
3336 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3337 INSN_LOONGSON3A)) {
3339 * Loongson CPU uses a load to zero register for prefetch.
3340 * We emulate it as a NOP. On other CPU we must perform the
3341 * actual memory access.
3343 return;
3346 t0 = tcg_temp_new();
3347 gen_base_offset_addr(ctx, t0, base, offset);
3349 switch (opc) {
3350 #if defined(TARGET_MIPS64)
3351 case OPC_LWU:
3352 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3353 ctx->default_tcg_memop_mask);
3354 gen_store_gpr(t0, rt);
3355 break;
3356 case OPC_LD:
3357 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3358 ctx->default_tcg_memop_mask);
3359 gen_store_gpr(t0, rt);
3360 break;
3361 case OPC_LLD:
3362 case R6_OPC_LLD:
3363 op_ld_lld(t0, t0, mem_idx, ctx);
3364 gen_store_gpr(t0, rt);
3365 break;
3366 case OPC_LDL:
3367 t1 = tcg_temp_new();
3369 * Do a byte access to possibly trigger a page
3370 * fault with the unaligned address.
3372 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3373 tcg_gen_andi_tl(t1, t0, 7);
3374 #ifndef TARGET_WORDS_BIGENDIAN
3375 tcg_gen_xori_tl(t1, t1, 7);
3376 #endif
3377 tcg_gen_shli_tl(t1, t1, 3);
3378 tcg_gen_andi_tl(t0, t0, ~7);
3379 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3380 tcg_gen_shl_tl(t0, t0, t1);
3381 t2 = tcg_const_tl(-1);
3382 tcg_gen_shl_tl(t2, t2, t1);
3383 gen_load_gpr(t1, rt);
3384 tcg_gen_andc_tl(t1, t1, t2);
3385 tcg_temp_free(t2);
3386 tcg_gen_or_tl(t0, t0, t1);
3387 tcg_temp_free(t1);
3388 gen_store_gpr(t0, rt);
3389 break;
3390 case OPC_LDR:
3391 t1 = tcg_temp_new();
3393 * Do a byte access to possibly trigger a page
3394 * fault with the unaligned address.
3396 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3397 tcg_gen_andi_tl(t1, t0, 7);
3398 #ifdef TARGET_WORDS_BIGENDIAN
3399 tcg_gen_xori_tl(t1, t1, 7);
3400 #endif
3401 tcg_gen_shli_tl(t1, t1, 3);
3402 tcg_gen_andi_tl(t0, t0, ~7);
3403 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3404 tcg_gen_shr_tl(t0, t0, t1);
3405 tcg_gen_xori_tl(t1, t1, 63);
3406 t2 = tcg_const_tl(0xfffffffffffffffeull);
3407 tcg_gen_shl_tl(t2, t2, t1);
3408 gen_load_gpr(t1, rt);
3409 tcg_gen_and_tl(t1, t1, t2);
3410 tcg_temp_free(t2);
3411 tcg_gen_or_tl(t0, t0, t1);
3412 tcg_temp_free(t1);
3413 gen_store_gpr(t0, rt);
3414 break;
3415 case OPC_LDPC:
3416 t1 = tcg_const_tl(pc_relative_pc(ctx));
3417 gen_op_addr_add(ctx, t0, t0, t1);
3418 tcg_temp_free(t1);
3419 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3420 gen_store_gpr(t0, rt);
3421 break;
3422 #endif
3423 case OPC_LWPC:
3424 t1 = tcg_const_tl(pc_relative_pc(ctx));
3425 gen_op_addr_add(ctx, t0, t0, t1);
3426 tcg_temp_free(t1);
3427 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3428 gen_store_gpr(t0, rt);
3429 break;
3430 case OPC_LWE:
3431 mem_idx = MIPS_HFLAG_UM;
3432 /* fall through */
3433 case OPC_LW:
3434 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3435 ctx->default_tcg_memop_mask);
3436 gen_store_gpr(t0, rt);
3437 break;
3438 case OPC_LHE:
3439 mem_idx = MIPS_HFLAG_UM;
3440 /* fall through */
3441 case OPC_LH:
3442 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3443 ctx->default_tcg_memop_mask);
3444 gen_store_gpr(t0, rt);
3445 break;
3446 case OPC_LHUE:
3447 mem_idx = MIPS_HFLAG_UM;
3448 /* fall through */
3449 case OPC_LHU:
3450 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3451 ctx->default_tcg_memop_mask);
3452 gen_store_gpr(t0, rt);
3453 break;
3454 case OPC_LBE:
3455 mem_idx = MIPS_HFLAG_UM;
3456 /* fall through */
3457 case OPC_LB:
3458 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3459 gen_store_gpr(t0, rt);
3460 break;
3461 case OPC_LBUE:
3462 mem_idx = MIPS_HFLAG_UM;
3463 /* fall through */
3464 case OPC_LBU:
3465 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3466 gen_store_gpr(t0, rt);
3467 break;
3468 case OPC_LWLE:
3469 mem_idx = MIPS_HFLAG_UM;
3470 /* fall through */
3471 case OPC_LWL:
3472 t1 = tcg_temp_new();
3474 * Do a byte access to possibly trigger a page
3475 * fault with the unaligned address.
3477 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3478 tcg_gen_andi_tl(t1, t0, 3);
3479 #ifndef TARGET_WORDS_BIGENDIAN
3480 tcg_gen_xori_tl(t1, t1, 3);
3481 #endif
3482 tcg_gen_shli_tl(t1, t1, 3);
3483 tcg_gen_andi_tl(t0, t0, ~3);
3484 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3485 tcg_gen_shl_tl(t0, t0, t1);
3486 t2 = tcg_const_tl(-1);
3487 tcg_gen_shl_tl(t2, t2, t1);
3488 gen_load_gpr(t1, rt);
3489 tcg_gen_andc_tl(t1, t1, t2);
3490 tcg_temp_free(t2);
3491 tcg_gen_or_tl(t0, t0, t1);
3492 tcg_temp_free(t1);
3493 tcg_gen_ext32s_tl(t0, t0);
3494 gen_store_gpr(t0, rt);
3495 break;
3496 case OPC_LWRE:
3497 mem_idx = MIPS_HFLAG_UM;
3498 /* fall through */
3499 case OPC_LWR:
3500 t1 = tcg_temp_new();
3502 * Do a byte access to possibly trigger a page
3503 * fault with the unaligned address.
3505 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3506 tcg_gen_andi_tl(t1, t0, 3);
3507 #ifdef TARGET_WORDS_BIGENDIAN
3508 tcg_gen_xori_tl(t1, t1, 3);
3509 #endif
3510 tcg_gen_shli_tl(t1, t1, 3);
3511 tcg_gen_andi_tl(t0, t0, ~3);
3512 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3513 tcg_gen_shr_tl(t0, t0, t1);
3514 tcg_gen_xori_tl(t1, t1, 31);
3515 t2 = tcg_const_tl(0xfffffffeull);
3516 tcg_gen_shl_tl(t2, t2, t1);
3517 gen_load_gpr(t1, rt);
3518 tcg_gen_and_tl(t1, t1, t2);
3519 tcg_temp_free(t2);
3520 tcg_gen_or_tl(t0, t0, t1);
3521 tcg_temp_free(t1);
3522 tcg_gen_ext32s_tl(t0, t0);
3523 gen_store_gpr(t0, rt);
3524 break;
3525 case OPC_LLE:
3526 mem_idx = MIPS_HFLAG_UM;
3527 /* fall through */
3528 case OPC_LL:
3529 case R6_OPC_LL:
3530 op_ld_ll(t0, t0, mem_idx, ctx);
3531 gen_store_gpr(t0, rt);
3532 break;
3534 tcg_temp_free(t0);
3537 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3538 uint32_t reg1, uint32_t reg2)
3540 TCGv taddr = tcg_temp_new();
3541 TCGv_i64 tval = tcg_temp_new_i64();
3542 TCGv tmp1 = tcg_temp_new();
3543 TCGv tmp2 = tcg_temp_new();
3545 gen_base_offset_addr(ctx, taddr, base, offset);
3546 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3547 #ifdef TARGET_WORDS_BIGENDIAN
3548 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3549 #else
3550 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3551 #endif
3552 gen_store_gpr(tmp1, reg1);
3553 tcg_temp_free(tmp1);
3554 gen_store_gpr(tmp2, reg2);
3555 tcg_temp_free(tmp2);
3556 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3557 tcg_temp_free_i64(tval);
3558 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3559 tcg_temp_free(taddr);
3562 /* Store */
3563 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3564 int base, int offset)
3566 TCGv t0 = tcg_temp_new();
3567 TCGv t1 = tcg_temp_new();
3568 int mem_idx = ctx->mem_idx;
3570 gen_base_offset_addr(ctx, t0, base, offset);
3571 gen_load_gpr(t1, rt);
3572 switch (opc) {
3573 #if defined(TARGET_MIPS64)
3574 case OPC_SD:
3575 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3576 ctx->default_tcg_memop_mask);
3577 break;
3578 case OPC_SDL:
3579 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3580 break;
3581 case OPC_SDR:
3582 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3583 break;
3584 #endif
3585 case OPC_SWE:
3586 mem_idx = MIPS_HFLAG_UM;
3587 /* fall through */
3588 case OPC_SW:
3589 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3590 ctx->default_tcg_memop_mask);
3591 break;
3592 case OPC_SHE:
3593 mem_idx = MIPS_HFLAG_UM;
3594 /* fall through */
3595 case OPC_SH:
3596 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3597 ctx->default_tcg_memop_mask);
3598 break;
3599 case OPC_SBE:
3600 mem_idx = MIPS_HFLAG_UM;
3601 /* fall through */
3602 case OPC_SB:
3603 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3604 break;
3605 case OPC_SWLE:
3606 mem_idx = MIPS_HFLAG_UM;
3607 /* fall through */
3608 case OPC_SWL:
3609 gen_helper_0e2i(swl, t1, t0, mem_idx);
3610 break;
3611 case OPC_SWRE:
3612 mem_idx = MIPS_HFLAG_UM;
3613 /* fall through */
3614 case OPC_SWR:
3615 gen_helper_0e2i(swr, t1, t0, mem_idx);
3616 break;
3618 tcg_temp_free(t0);
3619 tcg_temp_free(t1);
3623 /* Store conditional */
3624 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3625 MemOp tcg_mo, bool eva)
3627 TCGv addr, t0, val;
3628 TCGLabel *l1 = gen_new_label();
3629 TCGLabel *done = gen_new_label();
3631 t0 = tcg_temp_new();
3632 addr = tcg_temp_new();
3633 /* compare the address against that of the preceding LL */
3634 gen_base_offset_addr(ctx, addr, base, offset);
3635 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3636 tcg_temp_free(addr);
3637 tcg_gen_movi_tl(t0, 0);
3638 gen_store_gpr(t0, rt);
3639 tcg_gen_br(done);
3641 gen_set_label(l1);
3642 /* generate cmpxchg */
3643 val = tcg_temp_new();
3644 gen_load_gpr(val, rt);
3645 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3646 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3647 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3648 gen_store_gpr(t0, rt);
3649 tcg_temp_free(val);
3651 gen_set_label(done);
3652 tcg_temp_free(t0);
3656 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3657 uint32_t reg1, uint32_t reg2, bool eva)
3659 TCGv taddr = tcg_temp_local_new();
3660 TCGv lladdr = tcg_temp_local_new();
3661 TCGv_i64 tval = tcg_temp_new_i64();
3662 TCGv_i64 llval = tcg_temp_new_i64();
3663 TCGv_i64 val = tcg_temp_new_i64();
3664 TCGv tmp1 = tcg_temp_new();
3665 TCGv tmp2 = tcg_temp_new();
3666 TCGLabel *lab_fail = gen_new_label();
3667 TCGLabel *lab_done = gen_new_label();
3669 gen_base_offset_addr(ctx, taddr, base, offset);
3671 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3672 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3674 gen_load_gpr(tmp1, reg1);
3675 gen_load_gpr(tmp2, reg2);
3677 #ifdef TARGET_WORDS_BIGENDIAN
3678 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3679 #else
3680 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3681 #endif
3683 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3684 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3685 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3686 if (reg1 != 0) {
3687 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3689 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3691 gen_set_label(lab_fail);
3693 if (reg1 != 0) {
3694 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3696 gen_set_label(lab_done);
3697 tcg_gen_movi_tl(lladdr, -1);
3698 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3701 /* Load and store */
3702 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3703 TCGv t0)
3706 * Don't do NOP if destination is zero: we must perform the actual
3707 * memory access.
3709 switch (opc) {
3710 case OPC_LWC1:
3712 TCGv_i32 fp0 = tcg_temp_new_i32();
3713 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3714 ctx->default_tcg_memop_mask);
3715 gen_store_fpr32(ctx, fp0, ft);
3716 tcg_temp_free_i32(fp0);
3718 break;
3719 case OPC_SWC1:
3721 TCGv_i32 fp0 = tcg_temp_new_i32();
3722 gen_load_fpr32(ctx, fp0, ft);
3723 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3724 ctx->default_tcg_memop_mask);
3725 tcg_temp_free_i32(fp0);
3727 break;
3728 case OPC_LDC1:
3730 TCGv_i64 fp0 = tcg_temp_new_i64();
3731 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3732 ctx->default_tcg_memop_mask);
3733 gen_store_fpr64(ctx, fp0, ft);
3734 tcg_temp_free_i64(fp0);
3736 break;
3737 case OPC_SDC1:
3739 TCGv_i64 fp0 = tcg_temp_new_i64();
3740 gen_load_fpr64(ctx, fp0, ft);
3741 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3742 ctx->default_tcg_memop_mask);
3743 tcg_temp_free_i64(fp0);
3745 break;
3746 default:
3747 MIPS_INVAL("flt_ldst");
3748 gen_reserved_instruction(ctx);
3749 break;
3753 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3754 int rs, int16_t imm)
3756 TCGv t0 = tcg_temp_new();
3758 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3759 check_cp1_enabled(ctx);
3760 switch (op) {
3761 case OPC_LDC1:
3762 case OPC_SDC1:
3763 check_insn(ctx, ISA_MIPS2);
3764 /* Fallthrough */
3765 default:
3766 gen_base_offset_addr(ctx, t0, rs, imm);
3767 gen_flt_ldst(ctx, op, rt, t0);
3769 } else {
3770 generate_exception_err(ctx, EXCP_CpU, 1);
3772 tcg_temp_free(t0);
3775 /* Arithmetic with immediate operand */
3776 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3777 int rt, int rs, int imm)
3779 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3781 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3783 * If no destination, treat it as a NOP.
3784 * For addi, we must generate the overflow exception when needed.
3786 return;
3788 switch (opc) {
3789 case OPC_ADDI:
3791 TCGv t0 = tcg_temp_local_new();
3792 TCGv t1 = tcg_temp_new();
3793 TCGv t2 = tcg_temp_new();
3794 TCGLabel *l1 = gen_new_label();
3796 gen_load_gpr(t1, rs);
3797 tcg_gen_addi_tl(t0, t1, uimm);
3798 tcg_gen_ext32s_tl(t0, t0);
3800 tcg_gen_xori_tl(t1, t1, ~uimm);
3801 tcg_gen_xori_tl(t2, t0, uimm);
3802 tcg_gen_and_tl(t1, t1, t2);
3803 tcg_temp_free(t2);
3804 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3805 tcg_temp_free(t1);
3806 /* operands of same sign, result different sign */
3807 generate_exception(ctx, EXCP_OVERFLOW);
3808 gen_set_label(l1);
3809 tcg_gen_ext32s_tl(t0, t0);
3810 gen_store_gpr(t0, rt);
3811 tcg_temp_free(t0);
3813 break;
3814 case OPC_ADDIU:
3815 if (rs != 0) {
3816 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3817 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3818 } else {
3819 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3821 break;
3822 #if defined(TARGET_MIPS64)
3823 case OPC_DADDI:
3825 TCGv t0 = tcg_temp_local_new();
3826 TCGv t1 = tcg_temp_new();
3827 TCGv t2 = tcg_temp_new();
3828 TCGLabel *l1 = gen_new_label();
3830 gen_load_gpr(t1, rs);
3831 tcg_gen_addi_tl(t0, t1, uimm);
3833 tcg_gen_xori_tl(t1, t1, ~uimm);
3834 tcg_gen_xori_tl(t2, t0, uimm);
3835 tcg_gen_and_tl(t1, t1, t2);
3836 tcg_temp_free(t2);
3837 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3838 tcg_temp_free(t1);
3839 /* operands of same sign, result different sign */
3840 generate_exception(ctx, EXCP_OVERFLOW);
3841 gen_set_label(l1);
3842 gen_store_gpr(t0, rt);
3843 tcg_temp_free(t0);
3845 break;
3846 case OPC_DADDIU:
3847 if (rs != 0) {
3848 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3849 } else {
3850 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3852 break;
3853 #endif
3857 /* Logic with immediate operand */
3858 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3859 int rt, int rs, int16_t imm)
3861 target_ulong uimm;
3863 if (rt == 0) {
3864 /* If no destination, treat it as a NOP. */
3865 return;
3867 uimm = (uint16_t)imm;
3868 switch (opc) {
3869 case OPC_ANDI:
3870 if (likely(rs != 0)) {
3871 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3872 } else {
3873 tcg_gen_movi_tl(cpu_gpr[rt], 0);
3875 break;
3876 case OPC_ORI:
3877 if (rs != 0) {
3878 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3879 } else {
3880 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3882 break;
3883 case OPC_XORI:
3884 if (likely(rs != 0)) {
3885 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3886 } else {
3887 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3889 break;
3890 case OPC_LUI:
3891 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
3892 /* OPC_AUI */
3893 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
3894 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3895 } else {
3896 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
3898 break;
3900 default:
3901 break;
3905 /* Set on less than with immediate operand */
3906 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
3907 int rt, int rs, int16_t imm)
3909 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3910 TCGv t0;
3912 if (rt == 0) {
3913 /* If no destination, treat it as a NOP. */
3914 return;
3916 t0 = tcg_temp_new();
3917 gen_load_gpr(t0, rs);
3918 switch (opc) {
3919 case OPC_SLTI:
3920 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
3921 break;
3922 case OPC_SLTIU:
3923 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
3924 break;
3926 tcg_temp_free(t0);
3929 /* Shifts with immediate operand */
3930 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
3931 int rt, int rs, int16_t imm)
3933 target_ulong uimm = ((uint16_t)imm) & 0x1f;
3934 TCGv t0;
3936 if (rt == 0) {
3937 /* If no destination, treat it as a NOP. */
3938 return;
3941 t0 = tcg_temp_new();
3942 gen_load_gpr(t0, rs);
3943 switch (opc) {
3944 case OPC_SLL:
3945 tcg_gen_shli_tl(t0, t0, uimm);
3946 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3947 break;
3948 case OPC_SRA:
3949 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3950 break;
3951 case OPC_SRL:
3952 if (uimm != 0) {
3953 tcg_gen_ext32u_tl(t0, t0);
3954 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3955 } else {
3956 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3958 break;
3959 case OPC_ROTR:
3960 if (uimm != 0) {
3961 TCGv_i32 t1 = tcg_temp_new_i32();
3963 tcg_gen_trunc_tl_i32(t1, t0);
3964 tcg_gen_rotri_i32(t1, t1, uimm);
3965 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
3966 tcg_temp_free_i32(t1);
3967 } else {
3968 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
3970 break;
3971 #if defined(TARGET_MIPS64)
3972 case OPC_DSLL:
3973 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
3974 break;
3975 case OPC_DSRA:
3976 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
3977 break;
3978 case OPC_DSRL:
3979 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
3980 break;
3981 case OPC_DROTR:
3982 if (uimm != 0) {
3983 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3984 } else {
3985 tcg_gen_mov_tl(cpu_gpr[rt], t0);
3987 break;
3988 case OPC_DSLL32:
3989 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
3990 break;
3991 case OPC_DSRA32:
3992 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
3993 break;
3994 case OPC_DSRL32:
3995 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
3996 break;
3997 case OPC_DROTR32:
3998 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
3999 break;
4000 #endif
4002 tcg_temp_free(t0);
4005 /* Arithmetic */
4006 static void gen_arith(DisasContext *ctx, uint32_t opc,
4007 int rd, int rs, int rt)
4009 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4010 && opc != OPC_DADD && opc != OPC_DSUB) {
4012 * If no destination, treat it as a NOP.
4013 * For add & sub, we must generate the overflow exception when needed.
4015 return;
4018 switch (opc) {
4019 case OPC_ADD:
4021 TCGv t0 = tcg_temp_local_new();
4022 TCGv t1 = tcg_temp_new();
4023 TCGv t2 = tcg_temp_new();
4024 TCGLabel *l1 = gen_new_label();
4026 gen_load_gpr(t1, rs);
4027 gen_load_gpr(t2, rt);
4028 tcg_gen_add_tl(t0, t1, t2);
4029 tcg_gen_ext32s_tl(t0, t0);
4030 tcg_gen_xor_tl(t1, t1, t2);
4031 tcg_gen_xor_tl(t2, t0, t2);
4032 tcg_gen_andc_tl(t1, t2, t1);
4033 tcg_temp_free(t2);
4034 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4035 tcg_temp_free(t1);
4036 /* operands of same sign, result different sign */
4037 generate_exception(ctx, EXCP_OVERFLOW);
4038 gen_set_label(l1);
4039 gen_store_gpr(t0, rd);
4040 tcg_temp_free(t0);
4042 break;
4043 case OPC_ADDU:
4044 if (rs != 0 && rt != 0) {
4045 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4046 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4047 } else if (rs == 0 && rt != 0) {
4048 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4049 } else if (rs != 0 && rt == 0) {
4050 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4051 } else {
4052 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4054 break;
4055 case OPC_SUB:
4057 TCGv t0 = tcg_temp_local_new();
4058 TCGv t1 = tcg_temp_new();
4059 TCGv t2 = tcg_temp_new();
4060 TCGLabel *l1 = gen_new_label();
4062 gen_load_gpr(t1, rs);
4063 gen_load_gpr(t2, rt);
4064 tcg_gen_sub_tl(t0, t1, t2);
4065 tcg_gen_ext32s_tl(t0, t0);
4066 tcg_gen_xor_tl(t2, t1, t2);
4067 tcg_gen_xor_tl(t1, t0, t1);
4068 tcg_gen_and_tl(t1, t1, t2);
4069 tcg_temp_free(t2);
4070 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4071 tcg_temp_free(t1);
4073 * operands of different sign, first operand and the result
4074 * of different sign
4076 generate_exception(ctx, EXCP_OVERFLOW);
4077 gen_set_label(l1);
4078 gen_store_gpr(t0, rd);
4079 tcg_temp_free(t0);
4081 break;
4082 case OPC_SUBU:
4083 if (rs != 0 && rt != 0) {
4084 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4085 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4086 } else if (rs == 0 && rt != 0) {
4087 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4088 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4089 } else if (rs != 0 && rt == 0) {
4090 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4091 } else {
4092 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4094 break;
4095 #if defined(TARGET_MIPS64)
4096 case OPC_DADD:
4098 TCGv t0 = tcg_temp_local_new();
4099 TCGv t1 = tcg_temp_new();
4100 TCGv t2 = tcg_temp_new();
4101 TCGLabel *l1 = gen_new_label();
4103 gen_load_gpr(t1, rs);
4104 gen_load_gpr(t2, rt);
4105 tcg_gen_add_tl(t0, t1, t2);
4106 tcg_gen_xor_tl(t1, t1, t2);
4107 tcg_gen_xor_tl(t2, t0, t2);
4108 tcg_gen_andc_tl(t1, t2, t1);
4109 tcg_temp_free(t2);
4110 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4111 tcg_temp_free(t1);
4112 /* operands of same sign, result different sign */
4113 generate_exception(ctx, EXCP_OVERFLOW);
4114 gen_set_label(l1);
4115 gen_store_gpr(t0, rd);
4116 tcg_temp_free(t0);
4118 break;
4119 case OPC_DADDU:
4120 if (rs != 0 && rt != 0) {
4121 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4122 } else if (rs == 0 && rt != 0) {
4123 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4124 } else if (rs != 0 && rt == 0) {
4125 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4126 } else {
4127 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4129 break;
4130 case OPC_DSUB:
4132 TCGv t0 = tcg_temp_local_new();
4133 TCGv t1 = tcg_temp_new();
4134 TCGv t2 = tcg_temp_new();
4135 TCGLabel *l1 = gen_new_label();
4137 gen_load_gpr(t1, rs);
4138 gen_load_gpr(t2, rt);
4139 tcg_gen_sub_tl(t0, t1, t2);
4140 tcg_gen_xor_tl(t2, t1, t2);
4141 tcg_gen_xor_tl(t1, t0, t1);
4142 tcg_gen_and_tl(t1, t1, t2);
4143 tcg_temp_free(t2);
4144 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4145 tcg_temp_free(t1);
4147 * Operands of different sign, first operand and result different
4148 * sign.
4150 generate_exception(ctx, EXCP_OVERFLOW);
4151 gen_set_label(l1);
4152 gen_store_gpr(t0, rd);
4153 tcg_temp_free(t0);
4155 break;
4156 case OPC_DSUBU:
4157 if (rs != 0 && rt != 0) {
4158 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4159 } else if (rs == 0 && rt != 0) {
4160 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4161 } else if (rs != 0 && rt == 0) {
4162 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4163 } else {
4164 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4166 break;
4167 #endif
4168 case OPC_MUL:
4169 if (likely(rs != 0 && rt != 0)) {
4170 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4171 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4172 } else {
4173 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4175 break;
4179 /* Conditional move */
4180 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4181 int rd, int rs, int rt)
4183 TCGv t0, t1, t2;
4185 if (rd == 0) {
4186 /* If no destination, treat it as a NOP. */
4187 return;
4190 t0 = tcg_temp_new();
4191 gen_load_gpr(t0, rt);
4192 t1 = tcg_const_tl(0);
4193 t2 = tcg_temp_new();
4194 gen_load_gpr(t2, rs);
4195 switch (opc) {
4196 case OPC_MOVN:
4197 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4198 break;
4199 case OPC_MOVZ:
4200 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4201 break;
4202 case OPC_SELNEZ:
4203 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4204 break;
4205 case OPC_SELEQZ:
4206 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4207 break;
4209 tcg_temp_free(t2);
4210 tcg_temp_free(t1);
4211 tcg_temp_free(t0);
4214 /* Logic */
4215 static void gen_logic(DisasContext *ctx, uint32_t opc,
4216 int rd, int rs, int rt)
4218 if (rd == 0) {
4219 /* If no destination, treat it as a NOP. */
4220 return;
4223 switch (opc) {
4224 case OPC_AND:
4225 if (likely(rs != 0 && rt != 0)) {
4226 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4227 } else {
4228 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4230 break;
4231 case OPC_NOR:
4232 if (rs != 0 && rt != 0) {
4233 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4234 } else if (rs == 0 && rt != 0) {
4235 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4236 } else if (rs != 0 && rt == 0) {
4237 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4238 } else {
4239 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4241 break;
4242 case OPC_OR:
4243 if (likely(rs != 0 && rt != 0)) {
4244 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4245 } else if (rs == 0 && rt != 0) {
4246 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4247 } else if (rs != 0 && rt == 0) {
4248 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4249 } else {
4250 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4252 break;
4253 case OPC_XOR:
4254 if (likely(rs != 0 && rt != 0)) {
4255 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4256 } else if (rs == 0 && rt != 0) {
4257 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4258 } else if (rs != 0 && rt == 0) {
4259 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4260 } else {
4261 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4263 break;
4267 /* Set on lower than */
4268 static void gen_slt(DisasContext *ctx, uint32_t opc,
4269 int rd, int rs, int rt)
4271 TCGv t0, t1;
4273 if (rd == 0) {
4274 /* If no destination, treat it as a NOP. */
4275 return;
4278 t0 = tcg_temp_new();
4279 t1 = tcg_temp_new();
4280 gen_load_gpr(t0, rs);
4281 gen_load_gpr(t1, rt);
4282 switch (opc) {
4283 case OPC_SLT:
4284 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4285 break;
4286 case OPC_SLTU:
4287 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4288 break;
4290 tcg_temp_free(t0);
4291 tcg_temp_free(t1);
4294 /* Shifts */
4295 static void gen_shift(DisasContext *ctx, uint32_t opc,
4296 int rd, int rs, int rt)
4298 TCGv t0, t1;
4300 if (rd == 0) {
4302 * If no destination, treat it as a NOP.
4303 * For add & sub, we must generate the overflow exception when needed.
4305 return;
4308 t0 = tcg_temp_new();
4309 t1 = tcg_temp_new();
4310 gen_load_gpr(t0, rs);
4311 gen_load_gpr(t1, rt);
4312 switch (opc) {
4313 case OPC_SLLV:
4314 tcg_gen_andi_tl(t0, t0, 0x1f);
4315 tcg_gen_shl_tl(t0, t1, t0);
4316 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4317 break;
4318 case OPC_SRAV:
4319 tcg_gen_andi_tl(t0, t0, 0x1f);
4320 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4321 break;
4322 case OPC_SRLV:
4323 tcg_gen_ext32u_tl(t1, t1);
4324 tcg_gen_andi_tl(t0, t0, 0x1f);
4325 tcg_gen_shr_tl(t0, t1, t0);
4326 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4327 break;
4328 case OPC_ROTRV:
4330 TCGv_i32 t2 = tcg_temp_new_i32();
4331 TCGv_i32 t3 = tcg_temp_new_i32();
4333 tcg_gen_trunc_tl_i32(t2, t0);
4334 tcg_gen_trunc_tl_i32(t3, t1);
4335 tcg_gen_andi_i32(t2, t2, 0x1f);
4336 tcg_gen_rotr_i32(t2, t3, t2);
4337 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4338 tcg_temp_free_i32(t2);
4339 tcg_temp_free_i32(t3);
4341 break;
4342 #if defined(TARGET_MIPS64)
4343 case OPC_DSLLV:
4344 tcg_gen_andi_tl(t0, t0, 0x3f);
4345 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4346 break;
4347 case OPC_DSRAV:
4348 tcg_gen_andi_tl(t0, t0, 0x3f);
4349 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4350 break;
4351 case OPC_DSRLV:
4352 tcg_gen_andi_tl(t0, t0, 0x3f);
4353 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4354 break;
4355 case OPC_DROTRV:
4356 tcg_gen_andi_tl(t0, t0, 0x3f);
4357 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4358 break;
4359 #endif
4361 tcg_temp_free(t0);
4362 tcg_temp_free(t1);
4365 #if defined(TARGET_MIPS64)
4366 /* Copy GPR to and from TX79 HI1/LO1 register. */
4367 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4369 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4370 /* Treat as NOP. */
4371 return;
4374 switch (opc) {
4375 case MMI_OPC_MFHI1:
4376 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4377 break;
4378 case MMI_OPC_MFLO1:
4379 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4380 break;
4381 case MMI_OPC_MTHI1:
4382 if (reg != 0) {
4383 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4384 } else {
4385 tcg_gen_movi_tl(cpu_HI[1], 0);
4387 break;
4388 case MMI_OPC_MTLO1:
4389 if (reg != 0) {
4390 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4391 } else {
4392 tcg_gen_movi_tl(cpu_LO[1], 0);
4394 break;
4395 default:
4396 MIPS_INVAL("mfthilo1 TX79");
4397 gen_reserved_instruction(ctx);
4398 break;
4401 #endif
4403 /* Arithmetic on HI/LO registers */
4404 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4406 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4407 /* Treat as NOP. */
4408 return;
4411 if (acc != 0) {
4412 check_dsp(ctx);
4415 switch (opc) {
4416 case OPC_MFHI:
4417 #if defined(TARGET_MIPS64)
4418 if (acc != 0) {
4419 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4420 } else
4421 #endif
4423 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4425 break;
4426 case OPC_MFLO:
4427 #if defined(TARGET_MIPS64)
4428 if (acc != 0) {
4429 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4430 } else
4431 #endif
4433 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4435 break;
4436 case OPC_MTHI:
4437 if (reg != 0) {
4438 #if defined(TARGET_MIPS64)
4439 if (acc != 0) {
4440 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4441 } else
4442 #endif
4444 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4446 } else {
4447 tcg_gen_movi_tl(cpu_HI[acc], 0);
4449 break;
4450 case OPC_MTLO:
4451 if (reg != 0) {
4452 #if defined(TARGET_MIPS64)
4453 if (acc != 0) {
4454 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4455 } else
4456 #endif
4458 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4460 } else {
4461 tcg_gen_movi_tl(cpu_LO[acc], 0);
4463 break;
4467 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4468 MemOp memop)
4470 TCGv t0 = tcg_const_tl(addr);
4471 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4472 gen_store_gpr(t0, reg);
4473 tcg_temp_free(t0);
4476 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4477 int rs)
4479 target_long offset;
4480 target_long addr;
4482 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4483 case OPC_ADDIUPC:
4484 if (rs != 0) {
4485 offset = sextract32(ctx->opcode << 2, 0, 21);
4486 addr = addr_add(ctx, pc, offset);
4487 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4489 break;
4490 case R6_OPC_LWPC:
4491 offset = sextract32(ctx->opcode << 2, 0, 21);
4492 addr = addr_add(ctx, pc, offset);
4493 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4494 break;
4495 #if defined(TARGET_MIPS64)
4496 case OPC_LWUPC:
4497 check_mips_64(ctx);
4498 offset = sextract32(ctx->opcode << 2, 0, 21);
4499 addr = addr_add(ctx, pc, offset);
4500 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4501 break;
4502 #endif
4503 default:
4504 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4505 case OPC_AUIPC:
4506 if (rs != 0) {
4507 offset = sextract32(ctx->opcode, 0, 16) << 16;
4508 addr = addr_add(ctx, pc, offset);
4509 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4511 break;
4512 case OPC_ALUIPC:
4513 if (rs != 0) {
4514 offset = sextract32(ctx->opcode, 0, 16) << 16;
4515 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4516 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4518 break;
4519 #if defined(TARGET_MIPS64)
4520 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4521 case R6_OPC_LDPC + (1 << 16):
4522 case R6_OPC_LDPC + (2 << 16):
4523 case R6_OPC_LDPC + (3 << 16):
4524 check_mips_64(ctx);
4525 offset = sextract32(ctx->opcode << 3, 0, 21);
4526 addr = addr_add(ctx, (pc & ~0x7), offset);
4527 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4528 break;
4529 #endif
4530 default:
4531 MIPS_INVAL("OPC_PCREL");
4532 gen_reserved_instruction(ctx);
4533 break;
4535 break;
4539 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4541 TCGv t0, t1;
4543 if (rd == 0) {
4544 /* Treat as NOP. */
4545 return;
4548 t0 = tcg_temp_new();
4549 t1 = tcg_temp_new();
4551 gen_load_gpr(t0, rs);
4552 gen_load_gpr(t1, rt);
4554 switch (opc) {
4555 case R6_OPC_DIV:
4557 TCGv t2 = tcg_temp_new();
4558 TCGv t3 = tcg_temp_new();
4559 tcg_gen_ext32s_tl(t0, t0);
4560 tcg_gen_ext32s_tl(t1, t1);
4561 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4562 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4563 tcg_gen_and_tl(t2, t2, t3);
4564 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4565 tcg_gen_or_tl(t2, t2, t3);
4566 tcg_gen_movi_tl(t3, 0);
4567 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4568 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4569 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4570 tcg_temp_free(t3);
4571 tcg_temp_free(t2);
4573 break;
4574 case R6_OPC_MOD:
4576 TCGv t2 = tcg_temp_new();
4577 TCGv t3 = tcg_temp_new();
4578 tcg_gen_ext32s_tl(t0, t0);
4579 tcg_gen_ext32s_tl(t1, t1);
4580 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4581 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4582 tcg_gen_and_tl(t2, t2, t3);
4583 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4584 tcg_gen_or_tl(t2, t2, t3);
4585 tcg_gen_movi_tl(t3, 0);
4586 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4587 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4588 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4589 tcg_temp_free(t3);
4590 tcg_temp_free(t2);
4592 break;
4593 case R6_OPC_DIVU:
4595 TCGv t2 = tcg_const_tl(0);
4596 TCGv t3 = tcg_const_tl(1);
4597 tcg_gen_ext32u_tl(t0, t0);
4598 tcg_gen_ext32u_tl(t1, t1);
4599 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4600 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4601 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4602 tcg_temp_free(t3);
4603 tcg_temp_free(t2);
4605 break;
4606 case R6_OPC_MODU:
4608 TCGv t2 = tcg_const_tl(0);
4609 TCGv t3 = tcg_const_tl(1);
4610 tcg_gen_ext32u_tl(t0, t0);
4611 tcg_gen_ext32u_tl(t1, t1);
4612 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4613 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4614 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4615 tcg_temp_free(t3);
4616 tcg_temp_free(t2);
4618 break;
4619 case R6_OPC_MUL:
4621 TCGv_i32 t2 = tcg_temp_new_i32();
4622 TCGv_i32 t3 = tcg_temp_new_i32();
4623 tcg_gen_trunc_tl_i32(t2, t0);
4624 tcg_gen_trunc_tl_i32(t3, t1);
4625 tcg_gen_mul_i32(t2, t2, t3);
4626 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4627 tcg_temp_free_i32(t2);
4628 tcg_temp_free_i32(t3);
4630 break;
4631 case R6_OPC_MUH:
4633 TCGv_i32 t2 = tcg_temp_new_i32();
4634 TCGv_i32 t3 = tcg_temp_new_i32();
4635 tcg_gen_trunc_tl_i32(t2, t0);
4636 tcg_gen_trunc_tl_i32(t3, t1);
4637 tcg_gen_muls2_i32(t2, t3, t2, t3);
4638 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4639 tcg_temp_free_i32(t2);
4640 tcg_temp_free_i32(t3);
4642 break;
4643 case R6_OPC_MULU:
4645 TCGv_i32 t2 = tcg_temp_new_i32();
4646 TCGv_i32 t3 = tcg_temp_new_i32();
4647 tcg_gen_trunc_tl_i32(t2, t0);
4648 tcg_gen_trunc_tl_i32(t3, t1);
4649 tcg_gen_mul_i32(t2, t2, t3);
4650 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4651 tcg_temp_free_i32(t2);
4652 tcg_temp_free_i32(t3);
4654 break;
4655 case R6_OPC_MUHU:
4657 TCGv_i32 t2 = tcg_temp_new_i32();
4658 TCGv_i32 t3 = tcg_temp_new_i32();
4659 tcg_gen_trunc_tl_i32(t2, t0);
4660 tcg_gen_trunc_tl_i32(t3, t1);
4661 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4662 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4663 tcg_temp_free_i32(t2);
4664 tcg_temp_free_i32(t3);
4666 break;
4667 #if defined(TARGET_MIPS64)
4668 case R6_OPC_DDIV:
4670 TCGv t2 = tcg_temp_new();
4671 TCGv t3 = tcg_temp_new();
4672 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4673 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4674 tcg_gen_and_tl(t2, t2, t3);
4675 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4676 tcg_gen_or_tl(t2, t2, t3);
4677 tcg_gen_movi_tl(t3, 0);
4678 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4679 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4680 tcg_temp_free(t3);
4681 tcg_temp_free(t2);
4683 break;
4684 case R6_OPC_DMOD:
4686 TCGv t2 = tcg_temp_new();
4687 TCGv t3 = tcg_temp_new();
4688 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4689 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4690 tcg_gen_and_tl(t2, t2, t3);
4691 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4692 tcg_gen_or_tl(t2, t2, t3);
4693 tcg_gen_movi_tl(t3, 0);
4694 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4695 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4696 tcg_temp_free(t3);
4697 tcg_temp_free(t2);
4699 break;
4700 case R6_OPC_DDIVU:
4702 TCGv t2 = tcg_const_tl(0);
4703 TCGv t3 = tcg_const_tl(1);
4704 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4705 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4706 tcg_temp_free(t3);
4707 tcg_temp_free(t2);
4709 break;
4710 case R6_OPC_DMODU:
4712 TCGv t2 = tcg_const_tl(0);
4713 TCGv t3 = tcg_const_tl(1);
4714 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4715 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4716 tcg_temp_free(t3);
4717 tcg_temp_free(t2);
4719 break;
4720 case R6_OPC_DMUL:
4721 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4722 break;
4723 case R6_OPC_DMUH:
4725 TCGv t2 = tcg_temp_new();
4726 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4727 tcg_temp_free(t2);
4729 break;
4730 case R6_OPC_DMULU:
4731 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4732 break;
4733 case R6_OPC_DMUHU:
4735 TCGv t2 = tcg_temp_new();
4736 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4737 tcg_temp_free(t2);
4739 break;
4740 #endif
4741 default:
4742 MIPS_INVAL("r6 mul/div");
4743 gen_reserved_instruction(ctx);
4744 goto out;
4746 out:
4747 tcg_temp_free(t0);
4748 tcg_temp_free(t1);
4751 #if defined(TARGET_MIPS64)
4752 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4754 TCGv t0, t1;
4756 t0 = tcg_temp_new();
4757 t1 = tcg_temp_new();
4759 gen_load_gpr(t0, rs);
4760 gen_load_gpr(t1, rt);
4762 switch (opc) {
4763 case MMI_OPC_DIV1:
4765 TCGv t2 = tcg_temp_new();
4766 TCGv t3 = tcg_temp_new();
4767 tcg_gen_ext32s_tl(t0, t0);
4768 tcg_gen_ext32s_tl(t1, t1);
4769 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4770 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4771 tcg_gen_and_tl(t2, t2, t3);
4772 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4773 tcg_gen_or_tl(t2, t2, t3);
4774 tcg_gen_movi_tl(t3, 0);
4775 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4776 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4777 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4778 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4779 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4780 tcg_temp_free(t3);
4781 tcg_temp_free(t2);
4783 break;
4784 case MMI_OPC_DIVU1:
4786 TCGv t2 = tcg_const_tl(0);
4787 TCGv t3 = tcg_const_tl(1);
4788 tcg_gen_ext32u_tl(t0, t0);
4789 tcg_gen_ext32u_tl(t1, t1);
4790 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4791 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4792 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4793 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4794 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4795 tcg_temp_free(t3);
4796 tcg_temp_free(t2);
4798 break;
4799 default:
4800 MIPS_INVAL("div1 TX79");
4801 gen_reserved_instruction(ctx);
4802 goto out;
4804 out:
4805 tcg_temp_free(t0);
4806 tcg_temp_free(t1);
4808 #endif
4810 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4811 int acc, int rs, int rt)
4813 TCGv t0, t1;
4815 t0 = tcg_temp_new();
4816 t1 = tcg_temp_new();
4818 gen_load_gpr(t0, rs);
4819 gen_load_gpr(t1, rt);
4821 if (acc != 0) {
4822 check_dsp(ctx);
4825 switch (opc) {
4826 case OPC_DIV:
4828 TCGv t2 = tcg_temp_new();
4829 TCGv t3 = tcg_temp_new();
4830 tcg_gen_ext32s_tl(t0, t0);
4831 tcg_gen_ext32s_tl(t1, t1);
4832 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4833 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4834 tcg_gen_and_tl(t2, t2, t3);
4835 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4836 tcg_gen_or_tl(t2, t2, t3);
4837 tcg_gen_movi_tl(t3, 0);
4838 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4839 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4840 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4841 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4842 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4843 tcg_temp_free(t3);
4844 tcg_temp_free(t2);
4846 break;
4847 case OPC_DIVU:
4849 TCGv t2 = tcg_const_tl(0);
4850 TCGv t3 = tcg_const_tl(1);
4851 tcg_gen_ext32u_tl(t0, t0);
4852 tcg_gen_ext32u_tl(t1, t1);
4853 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4854 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4855 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4856 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4857 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4858 tcg_temp_free(t3);
4859 tcg_temp_free(t2);
4861 break;
4862 case OPC_MULT:
4864 TCGv_i32 t2 = tcg_temp_new_i32();
4865 TCGv_i32 t3 = tcg_temp_new_i32();
4866 tcg_gen_trunc_tl_i32(t2, t0);
4867 tcg_gen_trunc_tl_i32(t3, t1);
4868 tcg_gen_muls2_i32(t2, t3, t2, t3);
4869 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4870 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4871 tcg_temp_free_i32(t2);
4872 tcg_temp_free_i32(t3);
4874 break;
4875 case OPC_MULTU:
4877 TCGv_i32 t2 = tcg_temp_new_i32();
4878 TCGv_i32 t3 = tcg_temp_new_i32();
4879 tcg_gen_trunc_tl_i32(t2, t0);
4880 tcg_gen_trunc_tl_i32(t3, t1);
4881 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4882 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4883 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4884 tcg_temp_free_i32(t2);
4885 tcg_temp_free_i32(t3);
4887 break;
4888 #if defined(TARGET_MIPS64)
4889 case OPC_DDIV:
4891 TCGv t2 = tcg_temp_new();
4892 TCGv t3 = tcg_temp_new();
4893 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4894 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4895 tcg_gen_and_tl(t2, t2, t3);
4896 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4897 tcg_gen_or_tl(t2, t2, t3);
4898 tcg_gen_movi_tl(t3, 0);
4899 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4900 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4901 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4902 tcg_temp_free(t3);
4903 tcg_temp_free(t2);
4905 break;
4906 case OPC_DDIVU:
4908 TCGv t2 = tcg_const_tl(0);
4909 TCGv t3 = tcg_const_tl(1);
4910 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4911 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
4912 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
4913 tcg_temp_free(t3);
4914 tcg_temp_free(t2);
4916 break;
4917 case OPC_DMULT:
4918 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4919 break;
4920 case OPC_DMULTU:
4921 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
4922 break;
4923 #endif
4924 case OPC_MADD:
4926 TCGv_i64 t2 = tcg_temp_new_i64();
4927 TCGv_i64 t3 = tcg_temp_new_i64();
4929 tcg_gen_ext_tl_i64(t2, t0);
4930 tcg_gen_ext_tl_i64(t3, t1);
4931 tcg_gen_mul_i64(t2, t2, t3);
4932 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4933 tcg_gen_add_i64(t2, t2, t3);
4934 tcg_temp_free_i64(t3);
4935 gen_move_low32(cpu_LO[acc], t2);
4936 gen_move_high32(cpu_HI[acc], t2);
4937 tcg_temp_free_i64(t2);
4939 break;
4940 case OPC_MADDU:
4942 TCGv_i64 t2 = tcg_temp_new_i64();
4943 TCGv_i64 t3 = tcg_temp_new_i64();
4945 tcg_gen_ext32u_tl(t0, t0);
4946 tcg_gen_ext32u_tl(t1, t1);
4947 tcg_gen_extu_tl_i64(t2, t0);
4948 tcg_gen_extu_tl_i64(t3, t1);
4949 tcg_gen_mul_i64(t2, t2, t3);
4950 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4951 tcg_gen_add_i64(t2, t2, t3);
4952 tcg_temp_free_i64(t3);
4953 gen_move_low32(cpu_LO[acc], t2);
4954 gen_move_high32(cpu_HI[acc], t2);
4955 tcg_temp_free_i64(t2);
4957 break;
4958 case OPC_MSUB:
4960 TCGv_i64 t2 = tcg_temp_new_i64();
4961 TCGv_i64 t3 = tcg_temp_new_i64();
4963 tcg_gen_ext_tl_i64(t2, t0);
4964 tcg_gen_ext_tl_i64(t3, t1);
4965 tcg_gen_mul_i64(t2, t2, t3);
4966 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4967 tcg_gen_sub_i64(t2, t3, t2);
4968 tcg_temp_free_i64(t3);
4969 gen_move_low32(cpu_LO[acc], t2);
4970 gen_move_high32(cpu_HI[acc], t2);
4971 tcg_temp_free_i64(t2);
4973 break;
4974 case OPC_MSUBU:
4976 TCGv_i64 t2 = tcg_temp_new_i64();
4977 TCGv_i64 t3 = tcg_temp_new_i64();
4979 tcg_gen_ext32u_tl(t0, t0);
4980 tcg_gen_ext32u_tl(t1, t1);
4981 tcg_gen_extu_tl_i64(t2, t0);
4982 tcg_gen_extu_tl_i64(t3, t1);
4983 tcg_gen_mul_i64(t2, t2, t3);
4984 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
4985 tcg_gen_sub_i64(t2, t3, t2);
4986 tcg_temp_free_i64(t3);
4987 gen_move_low32(cpu_LO[acc], t2);
4988 gen_move_high32(cpu_HI[acc], t2);
4989 tcg_temp_free_i64(t2);
4991 break;
4992 default:
4993 MIPS_INVAL("mul/div");
4994 gen_reserved_instruction(ctx);
4995 goto out;
4997 out:
4998 tcg_temp_free(t0);
4999 tcg_temp_free(t1);
5003 * These MULT[U] and MADD[U] instructions implemented in for example
5004 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5005 * architectures are special three-operand variants with the syntax
5007 * MULT[U][1] rd, rs, rt
5009 * such that
5011 * (rd, LO, HI) <- rs * rt
5013 * and
5015 * MADD[U][1] rd, rs, rt
5017 * such that
5019 * (rd, LO, HI) <- (LO, HI) + rs * rt
5021 * where the low-order 32-bits of the result is placed into both the
5022 * GPR rd and the special register LO. The high-order 32-bits of the
5023 * result is placed into the special register HI.
5025 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5026 * which is the zero register that always reads as 0.
5028 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5029 int rd, int rs, int rt)
5031 TCGv t0 = tcg_temp_new();
5032 TCGv t1 = tcg_temp_new();
5033 int acc = 0;
5035 gen_load_gpr(t0, rs);
5036 gen_load_gpr(t1, rt);
5038 switch (opc) {
5039 case MMI_OPC_MULT1:
5040 acc = 1;
5041 /* Fall through */
5042 case OPC_MULT:
5044 TCGv_i32 t2 = tcg_temp_new_i32();
5045 TCGv_i32 t3 = tcg_temp_new_i32();
5046 tcg_gen_trunc_tl_i32(t2, t0);
5047 tcg_gen_trunc_tl_i32(t3, t1);
5048 tcg_gen_muls2_i32(t2, t3, t2, t3);
5049 if (rd) {
5050 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5052 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5053 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5054 tcg_temp_free_i32(t2);
5055 tcg_temp_free_i32(t3);
5057 break;
5058 case MMI_OPC_MULTU1:
5059 acc = 1;
5060 /* Fall through */
5061 case OPC_MULTU:
5063 TCGv_i32 t2 = tcg_temp_new_i32();
5064 TCGv_i32 t3 = tcg_temp_new_i32();
5065 tcg_gen_trunc_tl_i32(t2, t0);
5066 tcg_gen_trunc_tl_i32(t3, t1);
5067 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5068 if (rd) {
5069 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5071 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5072 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5073 tcg_temp_free_i32(t2);
5074 tcg_temp_free_i32(t3);
5076 break;
5077 case MMI_OPC_MADD1:
5078 acc = 1;
5079 /* Fall through */
5080 case MMI_OPC_MADD:
5082 TCGv_i64 t2 = tcg_temp_new_i64();
5083 TCGv_i64 t3 = tcg_temp_new_i64();
5085 tcg_gen_ext_tl_i64(t2, t0);
5086 tcg_gen_ext_tl_i64(t3, t1);
5087 tcg_gen_mul_i64(t2, t2, t3);
5088 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5089 tcg_gen_add_i64(t2, t2, t3);
5090 tcg_temp_free_i64(t3);
5091 gen_move_low32(cpu_LO[acc], t2);
5092 gen_move_high32(cpu_HI[acc], t2);
5093 if (rd) {
5094 gen_move_low32(cpu_gpr[rd], t2);
5096 tcg_temp_free_i64(t2);
5098 break;
5099 case MMI_OPC_MADDU1:
5100 acc = 1;
5101 /* Fall through */
5102 case MMI_OPC_MADDU:
5104 TCGv_i64 t2 = tcg_temp_new_i64();
5105 TCGv_i64 t3 = tcg_temp_new_i64();
5107 tcg_gen_ext32u_tl(t0, t0);
5108 tcg_gen_ext32u_tl(t1, t1);
5109 tcg_gen_extu_tl_i64(t2, t0);
5110 tcg_gen_extu_tl_i64(t3, t1);
5111 tcg_gen_mul_i64(t2, t2, t3);
5112 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5113 tcg_gen_add_i64(t2, t2, t3);
5114 tcg_temp_free_i64(t3);
5115 gen_move_low32(cpu_LO[acc], t2);
5116 gen_move_high32(cpu_HI[acc], t2);
5117 if (rd) {
5118 gen_move_low32(cpu_gpr[rd], t2);
5120 tcg_temp_free_i64(t2);
5122 break;
5123 default:
5124 MIPS_INVAL("mul/madd TXx9");
5125 gen_reserved_instruction(ctx);
5126 goto out;
5129 out:
5130 tcg_temp_free(t0);
5131 tcg_temp_free(t1);
5134 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5135 int rd, int rs, int rt)
5137 TCGv t0 = tcg_temp_new();
5138 TCGv t1 = tcg_temp_new();
5140 gen_load_gpr(t0, rs);
5141 gen_load_gpr(t1, rt);
5143 switch (opc) {
5144 case OPC_VR54XX_MULS:
5145 gen_helper_muls(t0, cpu_env, t0, t1);
5146 break;
5147 case OPC_VR54XX_MULSU:
5148 gen_helper_mulsu(t0, cpu_env, t0, t1);
5149 break;
5150 case OPC_VR54XX_MACC:
5151 gen_helper_macc(t0, cpu_env, t0, t1);
5152 break;
5153 case OPC_VR54XX_MACCU:
5154 gen_helper_maccu(t0, cpu_env, t0, t1);
5155 break;
5156 case OPC_VR54XX_MSAC:
5157 gen_helper_msac(t0, cpu_env, t0, t1);
5158 break;
5159 case OPC_VR54XX_MSACU:
5160 gen_helper_msacu(t0, cpu_env, t0, t1);
5161 break;
5162 case OPC_VR54XX_MULHI:
5163 gen_helper_mulhi(t0, cpu_env, t0, t1);
5164 break;
5165 case OPC_VR54XX_MULHIU:
5166 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5167 break;
5168 case OPC_VR54XX_MULSHI:
5169 gen_helper_mulshi(t0, cpu_env, t0, t1);
5170 break;
5171 case OPC_VR54XX_MULSHIU:
5172 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5173 break;
5174 case OPC_VR54XX_MACCHI:
5175 gen_helper_macchi(t0, cpu_env, t0, t1);
5176 break;
5177 case OPC_VR54XX_MACCHIU:
5178 gen_helper_macchiu(t0, cpu_env, t0, t1);
5179 break;
5180 case OPC_VR54XX_MSACHI:
5181 gen_helper_msachi(t0, cpu_env, t0, t1);
5182 break;
5183 case OPC_VR54XX_MSACHIU:
5184 gen_helper_msachiu(t0, cpu_env, t0, t1);
5185 break;
5186 default:
5187 MIPS_INVAL("mul vr54xx");
5188 gen_reserved_instruction(ctx);
5189 goto out;
5191 gen_store_gpr(t0, rd);
5193 out:
5194 tcg_temp_free(t0);
5195 tcg_temp_free(t1);
5198 static void gen_cl(DisasContext *ctx, uint32_t opc,
5199 int rd, int rs)
5201 TCGv t0;
5203 if (rd == 0) {
5204 /* Treat as NOP. */
5205 return;
5207 t0 = cpu_gpr[rd];
5208 gen_load_gpr(t0, rs);
5210 switch (opc) {
5211 case OPC_CLO:
5212 case R6_OPC_CLO:
5213 #if defined(TARGET_MIPS64)
5214 case OPC_DCLO:
5215 case R6_OPC_DCLO:
5216 #endif
5217 tcg_gen_not_tl(t0, t0);
5218 break;
5221 switch (opc) {
5222 case OPC_CLO:
5223 case R6_OPC_CLO:
5224 case OPC_CLZ:
5225 case R6_OPC_CLZ:
5226 tcg_gen_ext32u_tl(t0, t0);
5227 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5228 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5229 break;
5230 #if defined(TARGET_MIPS64)
5231 case OPC_DCLO:
5232 case R6_OPC_DCLO:
5233 case OPC_DCLZ:
5234 case R6_OPC_DCLZ:
5235 tcg_gen_clzi_i64(t0, t0, 64);
5236 break;
5237 #endif
5241 /* Godson integer instructions */
5242 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5243 int rd, int rs, int rt)
5245 TCGv t0, t1;
5247 if (rd == 0) {
5248 /* Treat as NOP. */
5249 return;
5252 switch (opc) {
5253 case OPC_MULT_G_2E:
5254 case OPC_MULT_G_2F:
5255 case OPC_MULTU_G_2E:
5256 case OPC_MULTU_G_2F:
5257 #if defined(TARGET_MIPS64)
5258 case OPC_DMULT_G_2E:
5259 case OPC_DMULT_G_2F:
5260 case OPC_DMULTU_G_2E:
5261 case OPC_DMULTU_G_2F:
5262 #endif
5263 t0 = tcg_temp_new();
5264 t1 = tcg_temp_new();
5265 break;
5266 default:
5267 t0 = tcg_temp_local_new();
5268 t1 = tcg_temp_local_new();
5269 break;
5272 gen_load_gpr(t0, rs);
5273 gen_load_gpr(t1, rt);
5275 switch (opc) {
5276 case OPC_MULT_G_2E:
5277 case OPC_MULT_G_2F:
5278 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5279 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5280 break;
5281 case OPC_MULTU_G_2E:
5282 case OPC_MULTU_G_2F:
5283 tcg_gen_ext32u_tl(t0, t0);
5284 tcg_gen_ext32u_tl(t1, t1);
5285 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5286 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5287 break;
5288 case OPC_DIV_G_2E:
5289 case OPC_DIV_G_2F:
5291 TCGLabel *l1 = gen_new_label();
5292 TCGLabel *l2 = gen_new_label();
5293 TCGLabel *l3 = gen_new_label();
5294 tcg_gen_ext32s_tl(t0, t0);
5295 tcg_gen_ext32s_tl(t1, t1);
5296 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5297 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5298 tcg_gen_br(l3);
5299 gen_set_label(l1);
5300 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5301 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5302 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5303 tcg_gen_br(l3);
5304 gen_set_label(l2);
5305 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5306 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5307 gen_set_label(l3);
5309 break;
5310 case OPC_DIVU_G_2E:
5311 case OPC_DIVU_G_2F:
5313 TCGLabel *l1 = gen_new_label();
5314 TCGLabel *l2 = gen_new_label();
5315 tcg_gen_ext32u_tl(t0, t0);
5316 tcg_gen_ext32u_tl(t1, t1);
5317 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5318 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5319 tcg_gen_br(l2);
5320 gen_set_label(l1);
5321 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5322 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5323 gen_set_label(l2);
5325 break;
5326 case OPC_MOD_G_2E:
5327 case OPC_MOD_G_2F:
5329 TCGLabel *l1 = gen_new_label();
5330 TCGLabel *l2 = gen_new_label();
5331 TCGLabel *l3 = gen_new_label();
5332 tcg_gen_ext32u_tl(t0, t0);
5333 tcg_gen_ext32u_tl(t1, t1);
5334 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5335 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5336 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5337 gen_set_label(l1);
5338 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5339 tcg_gen_br(l3);
5340 gen_set_label(l2);
5341 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5342 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5343 gen_set_label(l3);
5345 break;
5346 case OPC_MODU_G_2E:
5347 case OPC_MODU_G_2F:
5349 TCGLabel *l1 = gen_new_label();
5350 TCGLabel *l2 = gen_new_label();
5351 tcg_gen_ext32u_tl(t0, t0);
5352 tcg_gen_ext32u_tl(t1, t1);
5353 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5354 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5355 tcg_gen_br(l2);
5356 gen_set_label(l1);
5357 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5358 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5359 gen_set_label(l2);
5361 break;
5362 #if defined(TARGET_MIPS64)
5363 case OPC_DMULT_G_2E:
5364 case OPC_DMULT_G_2F:
5365 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5366 break;
5367 case OPC_DMULTU_G_2E:
5368 case OPC_DMULTU_G_2F:
5369 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5370 break;
5371 case OPC_DDIV_G_2E:
5372 case OPC_DDIV_G_2F:
5374 TCGLabel *l1 = gen_new_label();
5375 TCGLabel *l2 = gen_new_label();
5376 TCGLabel *l3 = gen_new_label();
5377 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5378 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5379 tcg_gen_br(l3);
5380 gen_set_label(l1);
5381 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5382 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5383 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5384 tcg_gen_br(l3);
5385 gen_set_label(l2);
5386 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5387 gen_set_label(l3);
5389 break;
5390 case OPC_DDIVU_G_2E:
5391 case OPC_DDIVU_G_2F:
5393 TCGLabel *l1 = gen_new_label();
5394 TCGLabel *l2 = gen_new_label();
5395 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5396 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5397 tcg_gen_br(l2);
5398 gen_set_label(l1);
5399 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5400 gen_set_label(l2);
5402 break;
5403 case OPC_DMOD_G_2E:
5404 case OPC_DMOD_G_2F:
5406 TCGLabel *l1 = gen_new_label();
5407 TCGLabel *l2 = gen_new_label();
5408 TCGLabel *l3 = gen_new_label();
5409 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5410 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5411 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5412 gen_set_label(l1);
5413 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5414 tcg_gen_br(l3);
5415 gen_set_label(l2);
5416 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5417 gen_set_label(l3);
5419 break;
5420 case OPC_DMODU_G_2E:
5421 case OPC_DMODU_G_2F:
5423 TCGLabel *l1 = gen_new_label();
5424 TCGLabel *l2 = gen_new_label();
5425 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5426 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5427 tcg_gen_br(l2);
5428 gen_set_label(l1);
5429 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5430 gen_set_label(l2);
5432 break;
5433 #endif
5436 tcg_temp_free(t0);
5437 tcg_temp_free(t1);
5440 /* Loongson multimedia instructions */
5441 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5443 uint32_t opc, shift_max;
5444 TCGv_i64 t0, t1;
5445 TCGCond cond;
5447 opc = MASK_LMMI(ctx->opcode);
5448 switch (opc) {
5449 case OPC_ADD_CP2:
5450 case OPC_SUB_CP2:
5451 case OPC_DADD_CP2:
5452 case OPC_DSUB_CP2:
5453 t0 = tcg_temp_local_new_i64();
5454 t1 = tcg_temp_local_new_i64();
5455 break;
5456 default:
5457 t0 = tcg_temp_new_i64();
5458 t1 = tcg_temp_new_i64();
5459 break;
5462 check_cp1_enabled(ctx);
5463 gen_load_fpr64(ctx, t0, rs);
5464 gen_load_fpr64(ctx, t1, rt);
5466 switch (opc) {
5467 case OPC_PADDSH:
5468 gen_helper_paddsh(t0, t0, t1);
5469 break;
5470 case OPC_PADDUSH:
5471 gen_helper_paddush(t0, t0, t1);
5472 break;
5473 case OPC_PADDH:
5474 gen_helper_paddh(t0, t0, t1);
5475 break;
5476 case OPC_PADDW:
5477 gen_helper_paddw(t0, t0, t1);
5478 break;
5479 case OPC_PADDSB:
5480 gen_helper_paddsb(t0, t0, t1);
5481 break;
5482 case OPC_PADDUSB:
5483 gen_helper_paddusb(t0, t0, t1);
5484 break;
5485 case OPC_PADDB:
5486 gen_helper_paddb(t0, t0, t1);
5487 break;
5489 case OPC_PSUBSH:
5490 gen_helper_psubsh(t0, t0, t1);
5491 break;
5492 case OPC_PSUBUSH:
5493 gen_helper_psubush(t0, t0, t1);
5494 break;
5495 case OPC_PSUBH:
5496 gen_helper_psubh(t0, t0, t1);
5497 break;
5498 case OPC_PSUBW:
5499 gen_helper_psubw(t0, t0, t1);
5500 break;
5501 case OPC_PSUBSB:
5502 gen_helper_psubsb(t0, t0, t1);
5503 break;
5504 case OPC_PSUBUSB:
5505 gen_helper_psubusb(t0, t0, t1);
5506 break;
5507 case OPC_PSUBB:
5508 gen_helper_psubb(t0, t0, t1);
5509 break;
5511 case OPC_PSHUFH:
5512 gen_helper_pshufh(t0, t0, t1);
5513 break;
5514 case OPC_PACKSSWH:
5515 gen_helper_packsswh(t0, t0, t1);
5516 break;
5517 case OPC_PACKSSHB:
5518 gen_helper_packsshb(t0, t0, t1);
5519 break;
5520 case OPC_PACKUSHB:
5521 gen_helper_packushb(t0, t0, t1);
5522 break;
5524 case OPC_PUNPCKLHW:
5525 gen_helper_punpcklhw(t0, t0, t1);
5526 break;
5527 case OPC_PUNPCKHHW:
5528 gen_helper_punpckhhw(t0, t0, t1);
5529 break;
5530 case OPC_PUNPCKLBH:
5531 gen_helper_punpcklbh(t0, t0, t1);
5532 break;
5533 case OPC_PUNPCKHBH:
5534 gen_helper_punpckhbh(t0, t0, t1);
5535 break;
5536 case OPC_PUNPCKLWD:
5537 gen_helper_punpcklwd(t0, t0, t1);
5538 break;
5539 case OPC_PUNPCKHWD:
5540 gen_helper_punpckhwd(t0, t0, t1);
5541 break;
5543 case OPC_PAVGH:
5544 gen_helper_pavgh(t0, t0, t1);
5545 break;
5546 case OPC_PAVGB:
5547 gen_helper_pavgb(t0, t0, t1);
5548 break;
5549 case OPC_PMAXSH:
5550 gen_helper_pmaxsh(t0, t0, t1);
5551 break;
5552 case OPC_PMINSH:
5553 gen_helper_pminsh(t0, t0, t1);
5554 break;
5555 case OPC_PMAXUB:
5556 gen_helper_pmaxub(t0, t0, t1);
5557 break;
5558 case OPC_PMINUB:
5559 gen_helper_pminub(t0, t0, t1);
5560 break;
5562 case OPC_PCMPEQW:
5563 gen_helper_pcmpeqw(t0, t0, t1);
5564 break;
5565 case OPC_PCMPGTW:
5566 gen_helper_pcmpgtw(t0, t0, t1);
5567 break;
5568 case OPC_PCMPEQH:
5569 gen_helper_pcmpeqh(t0, t0, t1);
5570 break;
5571 case OPC_PCMPGTH:
5572 gen_helper_pcmpgth(t0, t0, t1);
5573 break;
5574 case OPC_PCMPEQB:
5575 gen_helper_pcmpeqb(t0, t0, t1);
5576 break;
5577 case OPC_PCMPGTB:
5578 gen_helper_pcmpgtb(t0, t0, t1);
5579 break;
5581 case OPC_PSLLW:
5582 gen_helper_psllw(t0, t0, t1);
5583 break;
5584 case OPC_PSLLH:
5585 gen_helper_psllh(t0, t0, t1);
5586 break;
5587 case OPC_PSRLW:
5588 gen_helper_psrlw(t0, t0, t1);
5589 break;
5590 case OPC_PSRLH:
5591 gen_helper_psrlh(t0, t0, t1);
5592 break;
5593 case OPC_PSRAW:
5594 gen_helper_psraw(t0, t0, t1);
5595 break;
5596 case OPC_PSRAH:
5597 gen_helper_psrah(t0, t0, t1);
5598 break;
5600 case OPC_PMULLH:
5601 gen_helper_pmullh(t0, t0, t1);
5602 break;
5603 case OPC_PMULHH:
5604 gen_helper_pmulhh(t0, t0, t1);
5605 break;
5606 case OPC_PMULHUH:
5607 gen_helper_pmulhuh(t0, t0, t1);
5608 break;
5609 case OPC_PMADDHW:
5610 gen_helper_pmaddhw(t0, t0, t1);
5611 break;
5613 case OPC_PASUBUB:
5614 gen_helper_pasubub(t0, t0, t1);
5615 break;
5616 case OPC_BIADD:
5617 gen_helper_biadd(t0, t0);
5618 break;
5619 case OPC_PMOVMSKB:
5620 gen_helper_pmovmskb(t0, t0);
5621 break;
5623 case OPC_PADDD:
5624 tcg_gen_add_i64(t0, t0, t1);
5625 break;
5626 case OPC_PSUBD:
5627 tcg_gen_sub_i64(t0, t0, t1);
5628 break;
5629 case OPC_XOR_CP2:
5630 tcg_gen_xor_i64(t0, t0, t1);
5631 break;
5632 case OPC_NOR_CP2:
5633 tcg_gen_nor_i64(t0, t0, t1);
5634 break;
5635 case OPC_AND_CP2:
5636 tcg_gen_and_i64(t0, t0, t1);
5637 break;
5638 case OPC_OR_CP2:
5639 tcg_gen_or_i64(t0, t0, t1);
5640 break;
5642 case OPC_PANDN:
5643 tcg_gen_andc_i64(t0, t1, t0);
5644 break;
5646 case OPC_PINSRH_0:
5647 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5648 break;
5649 case OPC_PINSRH_1:
5650 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5651 break;
5652 case OPC_PINSRH_2:
5653 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5654 break;
5655 case OPC_PINSRH_3:
5656 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5657 break;
5659 case OPC_PEXTRH:
5660 tcg_gen_andi_i64(t1, t1, 3);
5661 tcg_gen_shli_i64(t1, t1, 4);
5662 tcg_gen_shr_i64(t0, t0, t1);
5663 tcg_gen_ext16u_i64(t0, t0);
5664 break;
5666 case OPC_ADDU_CP2:
5667 tcg_gen_add_i64(t0, t0, t1);
5668 tcg_gen_ext32s_i64(t0, t0);
5669 break;
5670 case OPC_SUBU_CP2:
5671 tcg_gen_sub_i64(t0, t0, t1);
5672 tcg_gen_ext32s_i64(t0, t0);
5673 break;
5675 case OPC_SLL_CP2:
5676 shift_max = 32;
5677 goto do_shift;
5678 case OPC_SRL_CP2:
5679 shift_max = 32;
5680 goto do_shift;
5681 case OPC_SRA_CP2:
5682 shift_max = 32;
5683 goto do_shift;
5684 case OPC_DSLL_CP2:
5685 shift_max = 64;
5686 goto do_shift;
5687 case OPC_DSRL_CP2:
5688 shift_max = 64;
5689 goto do_shift;
5690 case OPC_DSRA_CP2:
5691 shift_max = 64;
5692 goto do_shift;
5693 do_shift:
5694 /* Make sure shift count isn't TCG undefined behaviour. */
5695 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5697 switch (opc) {
5698 case OPC_SLL_CP2:
5699 case OPC_DSLL_CP2:
5700 tcg_gen_shl_i64(t0, t0, t1);
5701 break;
5702 case OPC_SRA_CP2:
5703 case OPC_DSRA_CP2:
5705 * Since SRA is UndefinedResult without sign-extended inputs,
5706 * we can treat SRA and DSRA the same.
5708 tcg_gen_sar_i64(t0, t0, t1);
5709 break;
5710 case OPC_SRL_CP2:
5711 /* We want to shift in zeros for SRL; zero-extend first. */
5712 tcg_gen_ext32u_i64(t0, t0);
5713 /* FALLTHRU */
5714 case OPC_DSRL_CP2:
5715 tcg_gen_shr_i64(t0, t0, t1);
5716 break;
5719 if (shift_max == 32) {
5720 tcg_gen_ext32s_i64(t0, t0);
5723 /* Shifts larger than MAX produce zero. */
5724 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5725 tcg_gen_neg_i64(t1, t1);
5726 tcg_gen_and_i64(t0, t0, t1);
5727 break;
5729 case OPC_ADD_CP2:
5730 case OPC_DADD_CP2:
5732 TCGv_i64 t2 = tcg_temp_new_i64();
5733 TCGLabel *lab = gen_new_label();
5735 tcg_gen_mov_i64(t2, t0);
5736 tcg_gen_add_i64(t0, t1, t2);
5737 if (opc == OPC_ADD_CP2) {
5738 tcg_gen_ext32s_i64(t0, t0);
5740 tcg_gen_xor_i64(t1, t1, t2);
5741 tcg_gen_xor_i64(t2, t2, t0);
5742 tcg_gen_andc_i64(t1, t2, t1);
5743 tcg_temp_free_i64(t2);
5744 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5745 generate_exception(ctx, EXCP_OVERFLOW);
5746 gen_set_label(lab);
5747 break;
5750 case OPC_SUB_CP2:
5751 case OPC_DSUB_CP2:
5753 TCGv_i64 t2 = tcg_temp_new_i64();
5754 TCGLabel *lab = gen_new_label();
5756 tcg_gen_mov_i64(t2, t0);
5757 tcg_gen_sub_i64(t0, t1, t2);
5758 if (opc == OPC_SUB_CP2) {
5759 tcg_gen_ext32s_i64(t0, t0);
5761 tcg_gen_xor_i64(t1, t1, t2);
5762 tcg_gen_xor_i64(t2, t2, t0);
5763 tcg_gen_and_i64(t1, t1, t2);
5764 tcg_temp_free_i64(t2);
5765 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5766 generate_exception(ctx, EXCP_OVERFLOW);
5767 gen_set_label(lab);
5768 break;
5771 case OPC_PMULUW:
5772 tcg_gen_ext32u_i64(t0, t0);
5773 tcg_gen_ext32u_i64(t1, t1);
5774 tcg_gen_mul_i64(t0, t0, t1);
5775 break;
5777 case OPC_SEQU_CP2:
5778 case OPC_SEQ_CP2:
5779 cond = TCG_COND_EQ;
5780 goto do_cc_cond;
5781 break;
5782 case OPC_SLTU_CP2:
5783 cond = TCG_COND_LTU;
5784 goto do_cc_cond;
5785 break;
5786 case OPC_SLT_CP2:
5787 cond = TCG_COND_LT;
5788 goto do_cc_cond;
5789 break;
5790 case OPC_SLEU_CP2:
5791 cond = TCG_COND_LEU;
5792 goto do_cc_cond;
5793 break;
5794 case OPC_SLE_CP2:
5795 cond = TCG_COND_LE;
5796 do_cc_cond:
5798 int cc = (ctx->opcode >> 8) & 0x7;
5799 TCGv_i64 t64 = tcg_temp_new_i64();
5800 TCGv_i32 t32 = tcg_temp_new_i32();
5802 tcg_gen_setcond_i64(cond, t64, t0, t1);
5803 tcg_gen_extrl_i64_i32(t32, t64);
5804 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5805 get_fp_bit(cc), 1);
5807 tcg_temp_free_i32(t32);
5808 tcg_temp_free_i64(t64);
5810 goto no_rd;
5811 break;
5812 default:
5813 MIPS_INVAL("loongson_cp2");
5814 gen_reserved_instruction(ctx);
5815 return;
5818 gen_store_fpr64(ctx, t0, rd);
5820 no_rd:
5821 tcg_temp_free_i64(t0);
5822 tcg_temp_free_i64(t1);
5825 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5826 int rs, int rd)
5828 TCGv t0, t1, t2;
5829 TCGv_i32 fp0;
5830 #if defined(TARGET_MIPS64)
5831 int lsq_rt1 = ctx->opcode & 0x1f;
5832 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5833 #endif
5834 int shf_offset = sextract32(ctx->opcode, 6, 8);
5836 t0 = tcg_temp_new();
5838 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5839 #if defined(TARGET_MIPS64)
5840 case OPC_GSLQ:
5841 t1 = tcg_temp_new();
5842 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5843 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5844 ctx->default_tcg_memop_mask);
5845 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5846 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5847 ctx->default_tcg_memop_mask);
5848 gen_store_gpr(t1, rt);
5849 gen_store_gpr(t0, lsq_rt1);
5850 tcg_temp_free(t1);
5851 break;
5852 case OPC_GSLQC1:
5853 check_cp1_enabled(ctx);
5854 t1 = tcg_temp_new();
5855 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5856 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5857 ctx->default_tcg_memop_mask);
5858 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5859 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5860 ctx->default_tcg_memop_mask);
5861 gen_store_fpr64(ctx, t1, rt);
5862 gen_store_fpr64(ctx, t0, lsq_rt1);
5863 tcg_temp_free(t1);
5864 break;
5865 case OPC_GSSQ:
5866 t1 = tcg_temp_new();
5867 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5868 gen_load_gpr(t1, rt);
5869 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5870 ctx->default_tcg_memop_mask);
5871 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5872 gen_load_gpr(t1, lsq_rt1);
5873 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5874 ctx->default_tcg_memop_mask);
5875 tcg_temp_free(t1);
5876 break;
5877 case OPC_GSSQC1:
5878 check_cp1_enabled(ctx);
5879 t1 = tcg_temp_new();
5880 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5881 gen_load_fpr64(ctx, t1, rt);
5882 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5883 ctx->default_tcg_memop_mask);
5884 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5885 gen_load_fpr64(ctx, t1, lsq_rt1);
5886 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5887 ctx->default_tcg_memop_mask);
5888 tcg_temp_free(t1);
5889 break;
5890 #endif
5891 case OPC_GSSHFL:
5892 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
5893 case OPC_GSLWLC1:
5894 check_cp1_enabled(ctx);
5895 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5896 t1 = tcg_temp_new();
5897 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5898 tcg_gen_andi_tl(t1, t0, 3);
5899 #ifndef TARGET_WORDS_BIGENDIAN
5900 tcg_gen_xori_tl(t1, t1, 3);
5901 #endif
5902 tcg_gen_shli_tl(t1, t1, 3);
5903 tcg_gen_andi_tl(t0, t0, ~3);
5904 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5905 tcg_gen_shl_tl(t0, t0, t1);
5906 t2 = tcg_const_tl(-1);
5907 tcg_gen_shl_tl(t2, t2, t1);
5908 fp0 = tcg_temp_new_i32();
5909 gen_load_fpr32(ctx, fp0, rt);
5910 tcg_gen_ext_i32_tl(t1, fp0);
5911 tcg_gen_andc_tl(t1, t1, t2);
5912 tcg_temp_free(t2);
5913 tcg_gen_or_tl(t0, t0, t1);
5914 tcg_temp_free(t1);
5915 #if defined(TARGET_MIPS64)
5916 tcg_gen_extrl_i64_i32(fp0, t0);
5917 #else
5918 tcg_gen_ext32s_tl(fp0, t0);
5919 #endif
5920 gen_store_fpr32(ctx, fp0, rt);
5921 tcg_temp_free_i32(fp0);
5922 break;
5923 case OPC_GSLWRC1:
5924 check_cp1_enabled(ctx);
5925 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5926 t1 = tcg_temp_new();
5927 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5928 tcg_gen_andi_tl(t1, t0, 3);
5929 #ifdef TARGET_WORDS_BIGENDIAN
5930 tcg_gen_xori_tl(t1, t1, 3);
5931 #endif
5932 tcg_gen_shli_tl(t1, t1, 3);
5933 tcg_gen_andi_tl(t0, t0, ~3);
5934 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
5935 tcg_gen_shr_tl(t0, t0, t1);
5936 tcg_gen_xori_tl(t1, t1, 31);
5937 t2 = tcg_const_tl(0xfffffffeull);
5938 tcg_gen_shl_tl(t2, t2, t1);
5939 fp0 = tcg_temp_new_i32();
5940 gen_load_fpr32(ctx, fp0, rt);
5941 tcg_gen_ext_i32_tl(t1, fp0);
5942 tcg_gen_and_tl(t1, t1, t2);
5943 tcg_temp_free(t2);
5944 tcg_gen_or_tl(t0, t0, t1);
5945 tcg_temp_free(t1);
5946 #if defined(TARGET_MIPS64)
5947 tcg_gen_extrl_i64_i32(fp0, t0);
5948 #else
5949 tcg_gen_ext32s_tl(fp0, t0);
5950 #endif
5951 gen_store_fpr32(ctx, fp0, rt);
5952 tcg_temp_free_i32(fp0);
5953 break;
5954 #if defined(TARGET_MIPS64)
5955 case OPC_GSLDLC1:
5956 check_cp1_enabled(ctx);
5957 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5958 t1 = tcg_temp_new();
5959 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5960 tcg_gen_andi_tl(t1, t0, 7);
5961 #ifndef TARGET_WORDS_BIGENDIAN
5962 tcg_gen_xori_tl(t1, t1, 7);
5963 #endif
5964 tcg_gen_shli_tl(t1, t1, 3);
5965 tcg_gen_andi_tl(t0, t0, ~7);
5966 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5967 tcg_gen_shl_tl(t0, t0, t1);
5968 t2 = tcg_const_tl(-1);
5969 tcg_gen_shl_tl(t2, t2, t1);
5970 gen_load_fpr64(ctx, t1, rt);
5971 tcg_gen_andc_tl(t1, t1, t2);
5972 tcg_temp_free(t2);
5973 tcg_gen_or_tl(t0, t0, t1);
5974 tcg_temp_free(t1);
5975 gen_store_fpr64(ctx, t0, rt);
5976 break;
5977 case OPC_GSLDRC1:
5978 check_cp1_enabled(ctx);
5979 gen_base_offset_addr(ctx, t0, rs, shf_offset);
5980 t1 = tcg_temp_new();
5981 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
5982 tcg_gen_andi_tl(t1, t0, 7);
5983 #ifdef TARGET_WORDS_BIGENDIAN
5984 tcg_gen_xori_tl(t1, t1, 7);
5985 #endif
5986 tcg_gen_shli_tl(t1, t1, 3);
5987 tcg_gen_andi_tl(t0, t0, ~7);
5988 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
5989 tcg_gen_shr_tl(t0, t0, t1);
5990 tcg_gen_xori_tl(t1, t1, 63);
5991 t2 = tcg_const_tl(0xfffffffffffffffeull);
5992 tcg_gen_shl_tl(t2, t2, t1);
5993 gen_load_fpr64(ctx, t1, rt);
5994 tcg_gen_and_tl(t1, t1, t2);
5995 tcg_temp_free(t2);
5996 tcg_gen_or_tl(t0, t0, t1);
5997 tcg_temp_free(t1);
5998 gen_store_fpr64(ctx, t0, rt);
5999 break;
6000 #endif
6001 default:
6002 MIPS_INVAL("loongson_gsshfl");
6003 gen_reserved_instruction(ctx);
6004 break;
6006 break;
6007 case OPC_GSSHFS:
6008 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6009 case OPC_GSSWLC1:
6010 check_cp1_enabled(ctx);
6011 t1 = tcg_temp_new();
6012 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6013 fp0 = tcg_temp_new_i32();
6014 gen_load_fpr32(ctx, fp0, rt);
6015 tcg_gen_ext_i32_tl(t1, fp0);
6016 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
6017 tcg_temp_free_i32(fp0);
6018 tcg_temp_free(t1);
6019 break;
6020 case OPC_GSSWRC1:
6021 check_cp1_enabled(ctx);
6022 t1 = tcg_temp_new();
6023 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6024 fp0 = tcg_temp_new_i32();
6025 gen_load_fpr32(ctx, fp0, rt);
6026 tcg_gen_ext_i32_tl(t1, fp0);
6027 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
6028 tcg_temp_free_i32(fp0);
6029 tcg_temp_free(t1);
6030 break;
6031 #if defined(TARGET_MIPS64)
6032 case OPC_GSSDLC1:
6033 check_cp1_enabled(ctx);
6034 t1 = tcg_temp_new();
6035 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6036 gen_load_fpr64(ctx, t1, rt);
6037 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
6038 tcg_temp_free(t1);
6039 break;
6040 case OPC_GSSDRC1:
6041 check_cp1_enabled(ctx);
6042 t1 = tcg_temp_new();
6043 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6044 gen_load_fpr64(ctx, t1, rt);
6045 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
6046 tcg_temp_free(t1);
6047 break;
6048 #endif
6049 default:
6050 MIPS_INVAL("loongson_gsshfs");
6051 gen_reserved_instruction(ctx);
6052 break;
6054 break;
6055 default:
6056 MIPS_INVAL("loongson_gslsq");
6057 gen_reserved_instruction(ctx);
6058 break;
6060 tcg_temp_free(t0);
6063 /* Loongson EXT LDC2/SDC2 */
6064 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
6065 int rs, int rd)
6067 int offset = sextract32(ctx->opcode, 3, 8);
6068 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
6069 TCGv t0, t1;
6070 TCGv_i32 fp0;
6072 /* Pre-conditions */
6073 switch (opc) {
6074 case OPC_GSLBX:
6075 case OPC_GSLHX:
6076 case OPC_GSLWX:
6077 case OPC_GSLDX:
6078 /* prefetch, implement as NOP */
6079 if (rt == 0) {
6080 return;
6082 break;
6083 case OPC_GSSBX:
6084 case OPC_GSSHX:
6085 case OPC_GSSWX:
6086 case OPC_GSSDX:
6087 break;
6088 case OPC_GSLWXC1:
6089 #if defined(TARGET_MIPS64)
6090 case OPC_GSLDXC1:
6091 #endif
6092 check_cp1_enabled(ctx);
6093 /* prefetch, implement as NOP */
6094 if (rt == 0) {
6095 return;
6097 break;
6098 case OPC_GSSWXC1:
6099 #if defined(TARGET_MIPS64)
6100 case OPC_GSSDXC1:
6101 #endif
6102 check_cp1_enabled(ctx);
6103 break;
6104 default:
6105 MIPS_INVAL("loongson_lsdc2");
6106 gen_reserved_instruction(ctx);
6107 return;
6108 break;
6111 t0 = tcg_temp_new();
6113 gen_base_offset_addr(ctx, t0, rs, offset);
6114 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6116 switch (opc) {
6117 case OPC_GSLBX:
6118 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
6119 gen_store_gpr(t0, rt);
6120 break;
6121 case OPC_GSLHX:
6122 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
6123 ctx->default_tcg_memop_mask);
6124 gen_store_gpr(t0, rt);
6125 break;
6126 case OPC_GSLWX:
6127 gen_base_offset_addr(ctx, t0, rs, offset);
6128 if (rd) {
6129 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
6132 ctx->default_tcg_memop_mask);
6133 gen_store_gpr(t0, rt);
6134 break;
6135 #if defined(TARGET_MIPS64)
6136 case OPC_GSLDX:
6137 gen_base_offset_addr(ctx, t0, rs, offset);
6138 if (rd) {
6139 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6141 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6142 ctx->default_tcg_memop_mask);
6143 gen_store_gpr(t0, rt);
6144 break;
6145 #endif
6146 case OPC_GSLWXC1:
6147 check_cp1_enabled(ctx);
6148 gen_base_offset_addr(ctx, t0, rs, offset);
6149 if (rd) {
6150 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6152 fp0 = tcg_temp_new_i32();
6153 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
6154 ctx->default_tcg_memop_mask);
6155 gen_store_fpr32(ctx, fp0, rt);
6156 tcg_temp_free_i32(fp0);
6157 break;
6158 #if defined(TARGET_MIPS64)
6159 case OPC_GSLDXC1:
6160 check_cp1_enabled(ctx);
6161 gen_base_offset_addr(ctx, t0, rs, offset);
6162 if (rd) {
6163 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6165 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6166 ctx->default_tcg_memop_mask);
6167 gen_store_fpr64(ctx, t0, rt);
6168 break;
6169 #endif
6170 case OPC_GSSBX:
6171 t1 = tcg_temp_new();
6172 gen_load_gpr(t1, rt);
6173 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
6174 tcg_temp_free(t1);
6175 break;
6176 case OPC_GSSHX:
6177 t1 = tcg_temp_new();
6178 gen_load_gpr(t1, rt);
6179 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
6180 ctx->default_tcg_memop_mask);
6181 tcg_temp_free(t1);
6182 break;
6183 case OPC_GSSWX:
6184 t1 = tcg_temp_new();
6185 gen_load_gpr(t1, rt);
6186 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
6187 ctx->default_tcg_memop_mask);
6188 tcg_temp_free(t1);
6189 break;
6190 #if defined(TARGET_MIPS64)
6191 case OPC_GSSDX:
6192 t1 = tcg_temp_new();
6193 gen_load_gpr(t1, rt);
6194 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6195 ctx->default_tcg_memop_mask);
6196 tcg_temp_free(t1);
6197 break;
6198 #endif
6199 case OPC_GSSWXC1:
6200 fp0 = tcg_temp_new_i32();
6201 gen_load_fpr32(ctx, fp0, rt);
6202 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
6203 ctx->default_tcg_memop_mask);
6204 tcg_temp_free_i32(fp0);
6205 break;
6206 #if defined(TARGET_MIPS64)
6207 case OPC_GSSDXC1:
6208 t1 = tcg_temp_new();
6209 gen_load_fpr64(ctx, t1, rt);
6210 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
6211 ctx->default_tcg_memop_mask);
6212 tcg_temp_free(t1);
6213 break;
6214 #endif
6215 default:
6216 break;
6219 tcg_temp_free(t0);
6222 /* Traps */
6223 static void gen_trap(DisasContext *ctx, uint32_t opc,
6224 int rs, int rt, int16_t imm)
6226 int cond;
6227 TCGv t0 = tcg_temp_new();
6228 TCGv t1 = tcg_temp_new();
6230 cond = 0;
6231 /* Load needed operands */
6232 switch (opc) {
6233 case OPC_TEQ:
6234 case OPC_TGE:
6235 case OPC_TGEU:
6236 case OPC_TLT:
6237 case OPC_TLTU:
6238 case OPC_TNE:
6239 /* Compare two registers */
6240 if (rs != rt) {
6241 gen_load_gpr(t0, rs);
6242 gen_load_gpr(t1, rt);
6243 cond = 1;
6245 break;
6246 case OPC_TEQI:
6247 case OPC_TGEI:
6248 case OPC_TGEIU:
6249 case OPC_TLTI:
6250 case OPC_TLTIU:
6251 case OPC_TNEI:
6252 /* Compare register to immediate */
6253 if (rs != 0 || imm != 0) {
6254 gen_load_gpr(t0, rs);
6255 tcg_gen_movi_tl(t1, (int32_t)imm);
6256 cond = 1;
6258 break;
6260 if (cond == 0) {
6261 switch (opc) {
6262 case OPC_TEQ: /* rs == rs */
6263 case OPC_TEQI: /* r0 == 0 */
6264 case OPC_TGE: /* rs >= rs */
6265 case OPC_TGEI: /* r0 >= 0 */
6266 case OPC_TGEU: /* rs >= rs unsigned */
6267 case OPC_TGEIU: /* r0 >= 0 unsigned */
6268 /* Always trap */
6269 generate_exception_end(ctx, EXCP_TRAP);
6270 break;
6271 case OPC_TLT: /* rs < rs */
6272 case OPC_TLTI: /* r0 < 0 */
6273 case OPC_TLTU: /* rs < rs unsigned */
6274 case OPC_TLTIU: /* r0 < 0 unsigned */
6275 case OPC_TNE: /* rs != rs */
6276 case OPC_TNEI: /* r0 != 0 */
6277 /* Never trap: treat as NOP. */
6278 break;
6280 } else {
6281 TCGLabel *l1 = gen_new_label();
6283 switch (opc) {
6284 case OPC_TEQ:
6285 case OPC_TEQI:
6286 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6287 break;
6288 case OPC_TGE:
6289 case OPC_TGEI:
6290 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6291 break;
6292 case OPC_TGEU:
6293 case OPC_TGEIU:
6294 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6295 break;
6296 case OPC_TLT:
6297 case OPC_TLTI:
6298 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6299 break;
6300 case OPC_TLTU:
6301 case OPC_TLTIU:
6302 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6303 break;
6304 case OPC_TNE:
6305 case OPC_TNEI:
6306 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6307 break;
6309 generate_exception(ctx, EXCP_TRAP);
6310 gen_set_label(l1);
6312 tcg_temp_free(t0);
6313 tcg_temp_free(t1);
6316 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6318 if (unlikely(ctx->base.singlestep_enabled)) {
6319 return false;
6322 #ifndef CONFIG_USER_ONLY
6323 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6324 #else
6325 return true;
6326 #endif
6329 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6331 if (use_goto_tb(ctx, dest)) {
6332 tcg_gen_goto_tb(n);
6333 gen_save_pc(dest);
6334 tcg_gen_exit_tb(ctx->base.tb, n);
6335 } else {
6336 gen_save_pc(dest);
6337 if (ctx->base.singlestep_enabled) {
6338 save_cpu_state(ctx, 0);
6339 gen_helper_raise_exception_debug(cpu_env);
6341 tcg_gen_lookup_and_goto_ptr();
6345 /* Branches (before delay slot) */
6346 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6347 int insn_bytes,
6348 int rs, int rt, int32_t offset,
6349 int delayslot_size)
6351 target_ulong btgt = -1;
6352 int blink = 0;
6353 int bcond_compute = 0;
6354 TCGv t0 = tcg_temp_new();
6355 TCGv t1 = tcg_temp_new();
6357 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6358 #ifdef MIPS_DEBUG_DISAS
6359 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6360 TARGET_FMT_lx "\n", ctx->base.pc_next);
6361 #endif
6362 gen_reserved_instruction(ctx);
6363 goto out;
6366 /* Load needed operands */
6367 switch (opc) {
6368 case OPC_BEQ:
6369 case OPC_BEQL:
6370 case OPC_BNE:
6371 case OPC_BNEL:
6372 /* Compare two registers */
6373 if (rs != rt) {
6374 gen_load_gpr(t0, rs);
6375 gen_load_gpr(t1, rt);
6376 bcond_compute = 1;
6378 btgt = ctx->base.pc_next + insn_bytes + offset;
6379 break;
6380 case OPC_BGEZ:
6381 case OPC_BGEZAL:
6382 case OPC_BGEZALL:
6383 case OPC_BGEZL:
6384 case OPC_BGTZ:
6385 case OPC_BGTZL:
6386 case OPC_BLEZ:
6387 case OPC_BLEZL:
6388 case OPC_BLTZ:
6389 case OPC_BLTZAL:
6390 case OPC_BLTZALL:
6391 case OPC_BLTZL:
6392 /* Compare to zero */
6393 if (rs != 0) {
6394 gen_load_gpr(t0, rs);
6395 bcond_compute = 1;
6397 btgt = ctx->base.pc_next + insn_bytes + offset;
6398 break;
6399 case OPC_BPOSGE32:
6400 #if defined(TARGET_MIPS64)
6401 case OPC_BPOSGE64:
6402 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6403 #else
6404 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6405 #endif
6406 bcond_compute = 1;
6407 btgt = ctx->base.pc_next + insn_bytes + offset;
6408 break;
6409 case OPC_J:
6410 case OPC_JAL:
6411 case OPC_JALX:
6412 /* Jump to immediate */
6413 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6414 (uint32_t)offset;
6415 break;
6416 case OPC_JR:
6417 case OPC_JALR:
6418 /* Jump to register */
6419 if (offset != 0 && offset != 16) {
6421 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6422 * others are reserved.
6424 MIPS_INVAL("jump hint");
6425 gen_reserved_instruction(ctx);
6426 goto out;
6428 gen_load_gpr(btarget, rs);
6429 break;
6430 default:
6431 MIPS_INVAL("branch/jump");
6432 gen_reserved_instruction(ctx);
6433 goto out;
6435 if (bcond_compute == 0) {
6436 /* No condition to be computed */
6437 switch (opc) {
6438 case OPC_BEQ: /* rx == rx */
6439 case OPC_BEQL: /* rx == rx likely */
6440 case OPC_BGEZ: /* 0 >= 0 */
6441 case OPC_BGEZL: /* 0 >= 0 likely */
6442 case OPC_BLEZ: /* 0 <= 0 */
6443 case OPC_BLEZL: /* 0 <= 0 likely */
6444 /* Always take */
6445 ctx->hflags |= MIPS_HFLAG_B;
6446 break;
6447 case OPC_BGEZAL: /* 0 >= 0 */
6448 case OPC_BGEZALL: /* 0 >= 0 likely */
6449 /* Always take and link */
6450 blink = 31;
6451 ctx->hflags |= MIPS_HFLAG_B;
6452 break;
6453 case OPC_BNE: /* rx != rx */
6454 case OPC_BGTZ: /* 0 > 0 */
6455 case OPC_BLTZ: /* 0 < 0 */
6456 /* Treat as NOP. */
6457 goto out;
6458 case OPC_BLTZAL: /* 0 < 0 */
6460 * Handle as an unconditional branch to get correct delay
6461 * slot checking.
6463 blink = 31;
6464 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6465 ctx->hflags |= MIPS_HFLAG_B;
6466 break;
6467 case OPC_BLTZALL: /* 0 < 0 likely */
6468 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6469 /* Skip the instruction in the delay slot */
6470 ctx->base.pc_next += 4;
6471 goto out;
6472 case OPC_BNEL: /* rx != rx likely */
6473 case OPC_BGTZL: /* 0 > 0 likely */
6474 case OPC_BLTZL: /* 0 < 0 likely */
6475 /* Skip the instruction in the delay slot */
6476 ctx->base.pc_next += 4;
6477 goto out;
6478 case OPC_J:
6479 ctx->hflags |= MIPS_HFLAG_B;
6480 break;
6481 case OPC_JALX:
6482 ctx->hflags |= MIPS_HFLAG_BX;
6483 /* Fallthrough */
6484 case OPC_JAL:
6485 blink = 31;
6486 ctx->hflags |= MIPS_HFLAG_B;
6487 break;
6488 case OPC_JR:
6489 ctx->hflags |= MIPS_HFLAG_BR;
6490 break;
6491 case OPC_JALR:
6492 blink = rt;
6493 ctx->hflags |= MIPS_HFLAG_BR;
6494 break;
6495 default:
6496 MIPS_INVAL("branch/jump");
6497 gen_reserved_instruction(ctx);
6498 goto out;
6500 } else {
6501 switch (opc) {
6502 case OPC_BEQ:
6503 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6504 goto not_likely;
6505 case OPC_BEQL:
6506 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6507 goto likely;
6508 case OPC_BNE:
6509 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6510 goto not_likely;
6511 case OPC_BNEL:
6512 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6513 goto likely;
6514 case OPC_BGEZ:
6515 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6516 goto not_likely;
6517 case OPC_BGEZL:
6518 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6519 goto likely;
6520 case OPC_BGEZAL:
6521 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6522 blink = 31;
6523 goto not_likely;
6524 case OPC_BGEZALL:
6525 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6526 blink = 31;
6527 goto likely;
6528 case OPC_BGTZ:
6529 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6530 goto not_likely;
6531 case OPC_BGTZL:
6532 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6533 goto likely;
6534 case OPC_BLEZ:
6535 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6536 goto not_likely;
6537 case OPC_BLEZL:
6538 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6539 goto likely;
6540 case OPC_BLTZ:
6541 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6542 goto not_likely;
6543 case OPC_BLTZL:
6544 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6545 goto likely;
6546 case OPC_BPOSGE32:
6547 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6548 goto not_likely;
6549 #if defined(TARGET_MIPS64)
6550 case OPC_BPOSGE64:
6551 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6552 goto not_likely;
6553 #endif
6554 case OPC_BLTZAL:
6555 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6556 blink = 31;
6557 not_likely:
6558 ctx->hflags |= MIPS_HFLAG_BC;
6559 break;
6560 case OPC_BLTZALL:
6561 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6562 blink = 31;
6563 likely:
6564 ctx->hflags |= MIPS_HFLAG_BL;
6565 break;
6566 default:
6567 MIPS_INVAL("conditional branch/jump");
6568 gen_reserved_instruction(ctx);
6569 goto out;
6573 ctx->btarget = btgt;
6575 switch (delayslot_size) {
6576 case 2:
6577 ctx->hflags |= MIPS_HFLAG_BDS16;
6578 break;
6579 case 4:
6580 ctx->hflags |= MIPS_HFLAG_BDS32;
6581 break;
6584 if (blink > 0) {
6585 int post_delay = insn_bytes + delayslot_size;
6586 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6588 tcg_gen_movi_tl(cpu_gpr[blink],
6589 ctx->base.pc_next + post_delay + lowbit);
6592 out:
6593 if (insn_bytes == 2) {
6594 ctx->hflags |= MIPS_HFLAG_B16;
6596 tcg_temp_free(t0);
6597 tcg_temp_free(t1);
6601 /* nanoMIPS Branches */
6602 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6603 int insn_bytes,
6604 int rs, int rt, int32_t offset)
6606 target_ulong btgt = -1;
6607 int bcond_compute = 0;
6608 TCGv t0 = tcg_temp_new();
6609 TCGv t1 = tcg_temp_new();
6611 /* Load needed operands */
6612 switch (opc) {
6613 case OPC_BEQ:
6614 case OPC_BNE:
6615 /* Compare two registers */
6616 if (rs != rt) {
6617 gen_load_gpr(t0, rs);
6618 gen_load_gpr(t1, rt);
6619 bcond_compute = 1;
6621 btgt = ctx->base.pc_next + insn_bytes + offset;
6622 break;
6623 case OPC_BGEZAL:
6624 /* Compare to zero */
6625 if (rs != 0) {
6626 gen_load_gpr(t0, rs);
6627 bcond_compute = 1;
6629 btgt = ctx->base.pc_next + insn_bytes + offset;
6630 break;
6631 case OPC_BPOSGE32:
6632 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6633 bcond_compute = 1;
6634 btgt = ctx->base.pc_next + insn_bytes + offset;
6635 break;
6636 case OPC_JR:
6637 case OPC_JALR:
6638 /* Jump to register */
6639 if (offset != 0 && offset != 16) {
6641 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6642 * others are reserved.
6644 MIPS_INVAL("jump hint");
6645 gen_reserved_instruction(ctx);
6646 goto out;
6648 gen_load_gpr(btarget, rs);
6649 break;
6650 default:
6651 MIPS_INVAL("branch/jump");
6652 gen_reserved_instruction(ctx);
6653 goto out;
6655 if (bcond_compute == 0) {
6656 /* No condition to be computed */
6657 switch (opc) {
6658 case OPC_BEQ: /* rx == rx */
6659 /* Always take */
6660 ctx->hflags |= MIPS_HFLAG_B;
6661 break;
6662 case OPC_BGEZAL: /* 0 >= 0 */
6663 /* Always take and link */
6664 tcg_gen_movi_tl(cpu_gpr[31],
6665 ctx->base.pc_next + insn_bytes);
6666 ctx->hflags |= MIPS_HFLAG_B;
6667 break;
6668 case OPC_BNE: /* rx != rx */
6669 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6670 /* Skip the instruction in the delay slot */
6671 ctx->base.pc_next += 4;
6672 goto out;
6673 case OPC_JR:
6674 ctx->hflags |= MIPS_HFLAG_BR;
6675 break;
6676 case OPC_JALR:
6677 if (rt > 0) {
6678 tcg_gen_movi_tl(cpu_gpr[rt],
6679 ctx->base.pc_next + insn_bytes);
6681 ctx->hflags |= MIPS_HFLAG_BR;
6682 break;
6683 default:
6684 MIPS_INVAL("branch/jump");
6685 gen_reserved_instruction(ctx);
6686 goto out;
6688 } else {
6689 switch (opc) {
6690 case OPC_BEQ:
6691 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6692 goto not_likely;
6693 case OPC_BNE:
6694 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6695 goto not_likely;
6696 case OPC_BGEZAL:
6697 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6698 tcg_gen_movi_tl(cpu_gpr[31],
6699 ctx->base.pc_next + insn_bytes);
6700 goto not_likely;
6701 case OPC_BPOSGE32:
6702 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6703 not_likely:
6704 ctx->hflags |= MIPS_HFLAG_BC;
6705 break;
6706 default:
6707 MIPS_INVAL("conditional branch/jump");
6708 gen_reserved_instruction(ctx);
6709 goto out;
6713 ctx->btarget = btgt;
6715 out:
6716 if (insn_bytes == 2) {
6717 ctx->hflags |= MIPS_HFLAG_B16;
6719 tcg_temp_free(t0);
6720 tcg_temp_free(t1);
6724 /* special3 bitfield operations */
6725 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6726 int rs, int lsb, int msb)
6728 TCGv t0 = tcg_temp_new();
6729 TCGv t1 = tcg_temp_new();
6731 gen_load_gpr(t1, rs);
6732 switch (opc) {
6733 case OPC_EXT:
6734 if (lsb + msb > 31) {
6735 goto fail;
6737 if (msb != 31) {
6738 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6739 } else {
6741 * The two checks together imply that lsb == 0,
6742 * so this is a simple sign-extension.
6744 tcg_gen_ext32s_tl(t0, t1);
6746 break;
6747 #if defined(TARGET_MIPS64)
6748 case OPC_DEXTU:
6749 lsb += 32;
6750 goto do_dext;
6751 case OPC_DEXTM:
6752 msb += 32;
6753 goto do_dext;
6754 case OPC_DEXT:
6755 do_dext:
6756 if (lsb + msb > 63) {
6757 goto fail;
6759 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6760 break;
6761 #endif
6762 case OPC_INS:
6763 if (lsb > msb) {
6764 goto fail;
6766 gen_load_gpr(t0, rt);
6767 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6768 tcg_gen_ext32s_tl(t0, t0);
6769 break;
6770 #if defined(TARGET_MIPS64)
6771 case OPC_DINSU:
6772 lsb += 32;
6773 /* FALLTHRU */
6774 case OPC_DINSM:
6775 msb += 32;
6776 /* FALLTHRU */
6777 case OPC_DINS:
6778 if (lsb > msb) {
6779 goto fail;
6781 gen_load_gpr(t0, rt);
6782 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6783 break;
6784 #endif
6785 default:
6786 fail:
6787 MIPS_INVAL("bitops");
6788 gen_reserved_instruction(ctx);
6789 tcg_temp_free(t0);
6790 tcg_temp_free(t1);
6791 return;
6793 gen_store_gpr(t0, rt);
6794 tcg_temp_free(t0);
6795 tcg_temp_free(t1);
6798 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6800 TCGv t0;
6802 if (rd == 0) {
6803 /* If no destination, treat it as a NOP. */
6804 return;
6807 t0 = tcg_temp_new();
6808 gen_load_gpr(t0, rt);
6809 switch (op2) {
6810 case OPC_WSBH:
6812 TCGv t1 = tcg_temp_new();
6813 TCGv t2 = tcg_const_tl(0x00FF00FF);
6815 tcg_gen_shri_tl(t1, t0, 8);
6816 tcg_gen_and_tl(t1, t1, t2);
6817 tcg_gen_and_tl(t0, t0, t2);
6818 tcg_gen_shli_tl(t0, t0, 8);
6819 tcg_gen_or_tl(t0, t0, t1);
6820 tcg_temp_free(t2);
6821 tcg_temp_free(t1);
6822 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6824 break;
6825 case OPC_SEB:
6826 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6827 break;
6828 case OPC_SEH:
6829 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6830 break;
6831 #if defined(TARGET_MIPS64)
6832 case OPC_DSBH:
6834 TCGv t1 = tcg_temp_new();
6835 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6837 tcg_gen_shri_tl(t1, t0, 8);
6838 tcg_gen_and_tl(t1, t1, t2);
6839 tcg_gen_and_tl(t0, t0, t2);
6840 tcg_gen_shli_tl(t0, t0, 8);
6841 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6842 tcg_temp_free(t2);
6843 tcg_temp_free(t1);
6845 break;
6846 case OPC_DSHD:
6848 TCGv t1 = tcg_temp_new();
6849 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6851 tcg_gen_shri_tl(t1, t0, 16);
6852 tcg_gen_and_tl(t1, t1, t2);
6853 tcg_gen_and_tl(t0, t0, t2);
6854 tcg_gen_shli_tl(t0, t0, 16);
6855 tcg_gen_or_tl(t0, t0, t1);
6856 tcg_gen_shri_tl(t1, t0, 32);
6857 tcg_gen_shli_tl(t0, t0, 32);
6858 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6859 tcg_temp_free(t2);
6860 tcg_temp_free(t1);
6862 break;
6863 #endif
6864 default:
6865 MIPS_INVAL("bsfhl");
6866 gen_reserved_instruction(ctx);
6867 tcg_temp_free(t0);
6868 return;
6870 tcg_temp_free(t0);
6873 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
6874 int imm2)
6876 TCGv t0;
6877 TCGv t1;
6878 if (rd == 0) {
6879 /* Treat as NOP. */
6880 return;
6882 t0 = tcg_temp_new();
6883 t1 = tcg_temp_new();
6884 gen_load_gpr(t0, rs);
6885 gen_load_gpr(t1, rt);
6886 tcg_gen_shli_tl(t0, t0, imm2 + 1);
6887 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
6888 if (opc == OPC_LSA) {
6889 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
6892 tcg_temp_free(t1);
6893 tcg_temp_free(t0);
6895 return;
6898 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
6899 int rt, int bits)
6901 TCGv t0;
6902 if (rd == 0) {
6903 /* Treat as NOP. */
6904 return;
6906 t0 = tcg_temp_new();
6907 if (bits == 0 || bits == wordsz) {
6908 if (bits == 0) {
6909 gen_load_gpr(t0, rt);
6910 } else {
6911 gen_load_gpr(t0, rs);
6913 switch (wordsz) {
6914 case 32:
6915 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6916 break;
6917 #if defined(TARGET_MIPS64)
6918 case 64:
6919 tcg_gen_mov_tl(cpu_gpr[rd], t0);
6920 break;
6921 #endif
6923 } else {
6924 TCGv t1 = tcg_temp_new();
6925 gen_load_gpr(t0, rt);
6926 gen_load_gpr(t1, rs);
6927 switch (wordsz) {
6928 case 32:
6930 TCGv_i64 t2 = tcg_temp_new_i64();
6931 tcg_gen_concat_tl_i64(t2, t1, t0);
6932 tcg_gen_shri_i64(t2, t2, 32 - bits);
6933 gen_move_low32(cpu_gpr[rd], t2);
6934 tcg_temp_free_i64(t2);
6936 break;
6937 #if defined(TARGET_MIPS64)
6938 case 64:
6939 tcg_gen_shli_tl(t0, t0, bits);
6940 tcg_gen_shri_tl(t1, t1, 64 - bits);
6941 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
6942 break;
6943 #endif
6945 tcg_temp_free(t1);
6948 tcg_temp_free(t0);
6951 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6952 int bp)
6954 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
6957 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
6958 int shift)
6960 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
6963 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
6965 TCGv t0;
6966 if (rd == 0) {
6967 /* Treat as NOP. */
6968 return;
6970 t0 = tcg_temp_new();
6971 gen_load_gpr(t0, rt);
6972 switch (opc) {
6973 case OPC_BITSWAP:
6974 gen_helper_bitswap(cpu_gpr[rd], t0);
6975 break;
6976 #if defined(TARGET_MIPS64)
6977 case OPC_DBITSWAP:
6978 gen_helper_dbitswap(cpu_gpr[rd], t0);
6979 break;
6980 #endif
6982 tcg_temp_free(t0);
6985 #ifndef CONFIG_USER_ONLY
6986 /* CP0 (MMU and control) */
6987 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
6989 TCGv_i64 t0 = tcg_temp_new_i64();
6990 TCGv_i64 t1 = tcg_temp_new_i64();
6992 tcg_gen_ext_tl_i64(t0, arg);
6993 tcg_gen_ld_i64(t1, cpu_env, off);
6994 #if defined(TARGET_MIPS64)
6995 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
6996 #else
6997 tcg_gen_concat32_i64(t1, t1, t0);
6998 #endif
6999 tcg_gen_st_i64(t1, cpu_env, off);
7000 tcg_temp_free_i64(t1);
7001 tcg_temp_free_i64(t0);
7004 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
7006 TCGv_i64 t0 = tcg_temp_new_i64();
7007 TCGv_i64 t1 = tcg_temp_new_i64();
7009 tcg_gen_ext_tl_i64(t0, arg);
7010 tcg_gen_ld_i64(t1, cpu_env, off);
7011 tcg_gen_concat32_i64(t1, t1, t0);
7012 tcg_gen_st_i64(t1, cpu_env, off);
7013 tcg_temp_free_i64(t1);
7014 tcg_temp_free_i64(t0);
7017 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
7019 TCGv_i64 t0 = tcg_temp_new_i64();
7021 tcg_gen_ld_i64(t0, cpu_env, off);
7022 #if defined(TARGET_MIPS64)
7023 tcg_gen_shri_i64(t0, t0, 30);
7024 #else
7025 tcg_gen_shri_i64(t0, t0, 32);
7026 #endif
7027 gen_move_low32(arg, t0);
7028 tcg_temp_free_i64(t0);
7031 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
7033 TCGv_i64 t0 = tcg_temp_new_i64();
7035 tcg_gen_ld_i64(t0, cpu_env, off);
7036 tcg_gen_shri_i64(t0, t0, 32 + shift);
7037 gen_move_low32(arg, t0);
7038 tcg_temp_free_i64(t0);
7041 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
7043 TCGv_i32 t0 = tcg_temp_new_i32();
7045 tcg_gen_ld_i32(t0, cpu_env, off);
7046 tcg_gen_ext_i32_tl(arg, t0);
7047 tcg_temp_free_i32(t0);
7050 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
7052 tcg_gen_ld_tl(arg, cpu_env, off);
7053 tcg_gen_ext32s_tl(arg, arg);
7056 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
7058 TCGv_i32 t0 = tcg_temp_new_i32();
7060 tcg_gen_trunc_tl_i32(t0, arg);
7061 tcg_gen_st_i32(t0, cpu_env, off);
7062 tcg_temp_free_i32(t0);
7065 #define CP0_CHECK(c) \
7066 do { \
7067 if (!(c)) { \
7068 goto cp0_unimplemented; \
7070 } while (0)
7072 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7074 const char *register_name = "invalid";
7076 switch (reg) {
7077 case CP0_REGISTER_02:
7078 switch (sel) {
7079 case 0:
7080 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7081 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7082 register_name = "EntryLo0";
7083 break;
7084 default:
7085 goto cp0_unimplemented;
7087 break;
7088 case CP0_REGISTER_03:
7089 switch (sel) {
7090 case CP0_REG03__ENTRYLO1:
7091 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7092 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7093 register_name = "EntryLo1";
7094 break;
7095 default:
7096 goto cp0_unimplemented;
7098 break;
7099 case CP0_REGISTER_09:
7100 switch (sel) {
7101 case CP0_REG09__SAAR:
7102 CP0_CHECK(ctx->saar);
7103 gen_helper_mfhc0_saar(arg, cpu_env);
7104 register_name = "SAAR";
7105 break;
7106 default:
7107 goto cp0_unimplemented;
7109 break;
7110 case CP0_REGISTER_17:
7111 switch (sel) {
7112 case CP0_REG17__LLADDR:
7113 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
7114 ctx->CP0_LLAddr_shift);
7115 register_name = "LLAddr";
7116 break;
7117 case CP0_REG17__MAAR:
7118 CP0_CHECK(ctx->mrp);
7119 gen_helper_mfhc0_maar(arg, cpu_env);
7120 register_name = "MAAR";
7121 break;
7122 default:
7123 goto cp0_unimplemented;
7125 break;
7126 case CP0_REGISTER_19:
7127 switch (sel) {
7128 case CP0_REG19__WATCHHI0:
7129 case CP0_REG19__WATCHHI1:
7130 case CP0_REG19__WATCHHI2:
7131 case CP0_REG19__WATCHHI3:
7132 case CP0_REG19__WATCHHI4:
7133 case CP0_REG19__WATCHHI5:
7134 case CP0_REG19__WATCHHI6:
7135 case CP0_REG19__WATCHHI7:
7136 /* upper 32 bits are only available when Config5MI != 0 */
7137 CP0_CHECK(ctx->mi);
7138 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
7139 register_name = "WatchHi";
7140 break;
7141 default:
7142 goto cp0_unimplemented;
7144 break;
7145 case CP0_REGISTER_28:
7146 switch (sel) {
7147 case 0:
7148 case 2:
7149 case 4:
7150 case 6:
7151 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
7152 register_name = "TagLo";
7153 break;
7154 default:
7155 goto cp0_unimplemented;
7157 break;
7158 default:
7159 goto cp0_unimplemented;
7161 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
7162 return;
7164 cp0_unimplemented:
7165 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
7166 register_name, reg, sel);
7167 tcg_gen_movi_tl(arg, 0);
7170 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7172 const char *register_name = "invalid";
7173 uint64_t mask = ctx->PAMask >> 36;
7175 switch (reg) {
7176 case CP0_REGISTER_02:
7177 switch (sel) {
7178 case 0:
7179 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7180 tcg_gen_andi_tl(arg, arg, mask);
7181 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7182 register_name = "EntryLo0";
7183 break;
7184 default:
7185 goto cp0_unimplemented;
7187 break;
7188 case CP0_REGISTER_03:
7189 switch (sel) {
7190 case CP0_REG03__ENTRYLO1:
7191 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7192 tcg_gen_andi_tl(arg, arg, mask);
7193 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7194 register_name = "EntryLo1";
7195 break;
7196 default:
7197 goto cp0_unimplemented;
7199 break;
7200 case CP0_REGISTER_09:
7201 switch (sel) {
7202 case CP0_REG09__SAAR:
7203 CP0_CHECK(ctx->saar);
7204 gen_helper_mthc0_saar(cpu_env, arg);
7205 register_name = "SAAR";
7206 break;
7207 default:
7208 goto cp0_unimplemented;
7210 break;
7211 case CP0_REGISTER_17:
7212 switch (sel) {
7213 case CP0_REG17__LLADDR:
7215 * LLAddr is read-only (the only exception is bit 0 if LLB is
7216 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
7217 * relevant for modern MIPS cores supporting MTHC0, therefore
7218 * treating MTHC0 to LLAddr as NOP.
7220 register_name = "LLAddr";
7221 break;
7222 case CP0_REG17__MAAR:
7223 CP0_CHECK(ctx->mrp);
7224 gen_helper_mthc0_maar(cpu_env, arg);
7225 register_name = "MAAR";
7226 break;
7227 default:
7228 goto cp0_unimplemented;
7230 break;
7231 case CP0_REGISTER_19:
7232 switch (sel) {
7233 case CP0_REG19__WATCHHI0:
7234 case CP0_REG19__WATCHHI1:
7235 case CP0_REG19__WATCHHI2:
7236 case CP0_REG19__WATCHHI3:
7237 case CP0_REG19__WATCHHI4:
7238 case CP0_REG19__WATCHHI5:
7239 case CP0_REG19__WATCHHI6:
7240 case CP0_REG19__WATCHHI7:
7241 /* upper 32 bits are only available when Config5MI != 0 */
7242 CP0_CHECK(ctx->mi);
7243 gen_helper_0e1i(mthc0_watchhi, arg, sel);
7244 register_name = "WatchHi";
7245 break;
7246 default:
7247 goto cp0_unimplemented;
7249 break;
7250 case CP0_REGISTER_28:
7251 switch (sel) {
7252 case 0:
7253 case 2:
7254 case 4:
7255 case 6:
7256 tcg_gen_andi_tl(arg, arg, mask);
7257 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
7258 register_name = "TagLo";
7259 break;
7260 default:
7261 goto cp0_unimplemented;
7263 break;
7264 default:
7265 goto cp0_unimplemented;
7267 trace_mips_translate_c0("mthc0", register_name, reg, sel);
7269 cp0_unimplemented:
7270 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
7271 register_name, reg, sel);
7274 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
7276 if (ctx->insn_flags & ISA_MIPS_R6) {
7277 tcg_gen_movi_tl(arg, 0);
7278 } else {
7279 tcg_gen_movi_tl(arg, ~0);
7283 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7285 const char *register_name = "invalid";
7287 if (sel != 0) {
7288 check_insn(ctx, ISA_MIPS_R1);
7291 switch (reg) {
7292 case CP0_REGISTER_00:
7293 switch (sel) {
7294 case CP0_REG00__INDEX:
7295 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7296 register_name = "Index";
7297 break;
7298 case CP0_REG00__MVPCONTROL:
7299 CP0_CHECK(ctx->insn_flags & ASE_MT);
7300 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7301 register_name = "MVPControl";
7302 break;
7303 case CP0_REG00__MVPCONF0:
7304 CP0_CHECK(ctx->insn_flags & ASE_MT);
7305 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7306 register_name = "MVPConf0";
7307 break;
7308 case CP0_REG00__MVPCONF1:
7309 CP0_CHECK(ctx->insn_flags & ASE_MT);
7310 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7311 register_name = "MVPConf1";
7312 break;
7313 case CP0_REG00__VPCONTROL:
7314 CP0_CHECK(ctx->vp);
7315 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7316 register_name = "VPControl";
7317 break;
7318 default:
7319 goto cp0_unimplemented;
7321 break;
7322 case CP0_REGISTER_01:
7323 switch (sel) {
7324 case CP0_REG01__RANDOM:
7325 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7326 gen_helper_mfc0_random(arg, cpu_env);
7327 register_name = "Random";
7328 break;
7329 case CP0_REG01__VPECONTROL:
7330 CP0_CHECK(ctx->insn_flags & ASE_MT);
7331 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7332 register_name = "VPEControl";
7333 break;
7334 case CP0_REG01__VPECONF0:
7335 CP0_CHECK(ctx->insn_flags & ASE_MT);
7336 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7337 register_name = "VPEConf0";
7338 break;
7339 case CP0_REG01__VPECONF1:
7340 CP0_CHECK(ctx->insn_flags & ASE_MT);
7341 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7342 register_name = "VPEConf1";
7343 break;
7344 case CP0_REG01__YQMASK:
7345 CP0_CHECK(ctx->insn_flags & ASE_MT);
7346 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7347 register_name = "YQMask";
7348 break;
7349 case CP0_REG01__VPESCHEDULE:
7350 CP0_CHECK(ctx->insn_flags & ASE_MT);
7351 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7352 register_name = "VPESchedule";
7353 break;
7354 case CP0_REG01__VPESCHEFBACK:
7355 CP0_CHECK(ctx->insn_flags & ASE_MT);
7356 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7357 register_name = "VPEScheFBack";
7358 break;
7359 case CP0_REG01__VPEOPT:
7360 CP0_CHECK(ctx->insn_flags & ASE_MT);
7361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7362 register_name = "VPEOpt";
7363 break;
7364 default:
7365 goto cp0_unimplemented;
7367 break;
7368 case CP0_REGISTER_02:
7369 switch (sel) {
7370 case CP0_REG02__ENTRYLO0:
7372 TCGv_i64 tmp = tcg_temp_new_i64();
7373 tcg_gen_ld_i64(tmp, cpu_env,
7374 offsetof(CPUMIPSState, CP0_EntryLo0));
7375 #if defined(TARGET_MIPS64)
7376 if (ctx->rxi) {
7377 /* Move RI/XI fields to bits 31:30 */
7378 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7379 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7381 #endif
7382 gen_move_low32(arg, tmp);
7383 tcg_temp_free_i64(tmp);
7385 register_name = "EntryLo0";
7386 break;
7387 case CP0_REG02__TCSTATUS:
7388 CP0_CHECK(ctx->insn_flags & ASE_MT);
7389 gen_helper_mfc0_tcstatus(arg, cpu_env);
7390 register_name = "TCStatus";
7391 break;
7392 case CP0_REG02__TCBIND:
7393 CP0_CHECK(ctx->insn_flags & ASE_MT);
7394 gen_helper_mfc0_tcbind(arg, cpu_env);
7395 register_name = "TCBind";
7396 break;
7397 case CP0_REG02__TCRESTART:
7398 CP0_CHECK(ctx->insn_flags & ASE_MT);
7399 gen_helper_mfc0_tcrestart(arg, cpu_env);
7400 register_name = "TCRestart";
7401 break;
7402 case CP0_REG02__TCHALT:
7403 CP0_CHECK(ctx->insn_flags & ASE_MT);
7404 gen_helper_mfc0_tchalt(arg, cpu_env);
7405 register_name = "TCHalt";
7406 break;
7407 case CP0_REG02__TCCONTEXT:
7408 CP0_CHECK(ctx->insn_flags & ASE_MT);
7409 gen_helper_mfc0_tccontext(arg, cpu_env);
7410 register_name = "TCContext";
7411 break;
7412 case CP0_REG02__TCSCHEDULE:
7413 CP0_CHECK(ctx->insn_flags & ASE_MT);
7414 gen_helper_mfc0_tcschedule(arg, cpu_env);
7415 register_name = "TCSchedule";
7416 break;
7417 case CP0_REG02__TCSCHEFBACK:
7418 CP0_CHECK(ctx->insn_flags & ASE_MT);
7419 gen_helper_mfc0_tcschefback(arg, cpu_env);
7420 register_name = "TCScheFBack";
7421 break;
7422 default:
7423 goto cp0_unimplemented;
7425 break;
7426 case CP0_REGISTER_03:
7427 switch (sel) {
7428 case CP0_REG03__ENTRYLO1:
7430 TCGv_i64 tmp = tcg_temp_new_i64();
7431 tcg_gen_ld_i64(tmp, cpu_env,
7432 offsetof(CPUMIPSState, CP0_EntryLo1));
7433 #if defined(TARGET_MIPS64)
7434 if (ctx->rxi) {
7435 /* Move RI/XI fields to bits 31:30 */
7436 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7437 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7439 #endif
7440 gen_move_low32(arg, tmp);
7441 tcg_temp_free_i64(tmp);
7443 register_name = "EntryLo1";
7444 break;
7445 case CP0_REG03__GLOBALNUM:
7446 CP0_CHECK(ctx->vp);
7447 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7448 register_name = "GlobalNumber";
7449 break;
7450 default:
7451 goto cp0_unimplemented;
7453 break;
7454 case CP0_REGISTER_04:
7455 switch (sel) {
7456 case CP0_REG04__CONTEXT:
7457 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7458 tcg_gen_ext32s_tl(arg, arg);
7459 register_name = "Context";
7460 break;
7461 case CP0_REG04__CONTEXTCONFIG:
7462 /* SmartMIPS ASE */
7463 /* gen_helper_mfc0_contextconfig(arg); */
7464 register_name = "ContextConfig";
7465 goto cp0_unimplemented;
7466 case CP0_REG04__USERLOCAL:
7467 CP0_CHECK(ctx->ulri);
7468 tcg_gen_ld_tl(arg, cpu_env,
7469 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7470 tcg_gen_ext32s_tl(arg, arg);
7471 register_name = "UserLocal";
7472 break;
7473 case CP0_REG04__MMID:
7474 CP0_CHECK(ctx->mi);
7475 gen_helper_mtc0_memorymapid(cpu_env, arg);
7476 register_name = "MMID";
7477 break;
7478 default:
7479 goto cp0_unimplemented;
7481 break;
7482 case CP0_REGISTER_05:
7483 switch (sel) {
7484 case CP0_REG05__PAGEMASK:
7485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7486 register_name = "PageMask";
7487 break;
7488 case CP0_REG05__PAGEGRAIN:
7489 check_insn(ctx, ISA_MIPS_R2);
7490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7491 register_name = "PageGrain";
7492 break;
7493 case CP0_REG05__SEGCTL0:
7494 CP0_CHECK(ctx->sc);
7495 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7496 tcg_gen_ext32s_tl(arg, arg);
7497 register_name = "SegCtl0";
7498 break;
7499 case CP0_REG05__SEGCTL1:
7500 CP0_CHECK(ctx->sc);
7501 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7502 tcg_gen_ext32s_tl(arg, arg);
7503 register_name = "SegCtl1";
7504 break;
7505 case CP0_REG05__SEGCTL2:
7506 CP0_CHECK(ctx->sc);
7507 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7508 tcg_gen_ext32s_tl(arg, arg);
7509 register_name = "SegCtl2";
7510 break;
7511 case CP0_REG05__PWBASE:
7512 check_pw(ctx);
7513 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7514 register_name = "PWBase";
7515 break;
7516 case CP0_REG05__PWFIELD:
7517 check_pw(ctx);
7518 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7519 register_name = "PWField";
7520 break;
7521 case CP0_REG05__PWSIZE:
7522 check_pw(ctx);
7523 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7524 register_name = "PWSize";
7525 break;
7526 default:
7527 goto cp0_unimplemented;
7529 break;
7530 case CP0_REGISTER_06:
7531 switch (sel) {
7532 case CP0_REG06__WIRED:
7533 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7534 register_name = "Wired";
7535 break;
7536 case CP0_REG06__SRSCONF0:
7537 check_insn(ctx, ISA_MIPS_R2);
7538 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7539 register_name = "SRSConf0";
7540 break;
7541 case CP0_REG06__SRSCONF1:
7542 check_insn(ctx, ISA_MIPS_R2);
7543 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7544 register_name = "SRSConf1";
7545 break;
7546 case CP0_REG06__SRSCONF2:
7547 check_insn(ctx, ISA_MIPS_R2);
7548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7549 register_name = "SRSConf2";
7550 break;
7551 case CP0_REG06__SRSCONF3:
7552 check_insn(ctx, ISA_MIPS_R2);
7553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7554 register_name = "SRSConf3";
7555 break;
7556 case CP0_REG06__SRSCONF4:
7557 check_insn(ctx, ISA_MIPS_R2);
7558 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7559 register_name = "SRSConf4";
7560 break;
7561 case CP0_REG06__PWCTL:
7562 check_pw(ctx);
7563 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7564 register_name = "PWCtl";
7565 break;
7566 default:
7567 goto cp0_unimplemented;
7569 break;
7570 case CP0_REGISTER_07:
7571 switch (sel) {
7572 case CP0_REG07__HWRENA:
7573 check_insn(ctx, ISA_MIPS_R2);
7574 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7575 register_name = "HWREna";
7576 break;
7577 default:
7578 goto cp0_unimplemented;
7580 break;
7581 case CP0_REGISTER_08:
7582 switch (sel) {
7583 case CP0_REG08__BADVADDR:
7584 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7585 tcg_gen_ext32s_tl(arg, arg);
7586 register_name = "BadVAddr";
7587 break;
7588 case CP0_REG08__BADINSTR:
7589 CP0_CHECK(ctx->bi);
7590 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7591 register_name = "BadInstr";
7592 break;
7593 case CP0_REG08__BADINSTRP:
7594 CP0_CHECK(ctx->bp);
7595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7596 register_name = "BadInstrP";
7597 break;
7598 case CP0_REG08__BADINSTRX:
7599 CP0_CHECK(ctx->bi);
7600 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7601 tcg_gen_andi_tl(arg, arg, ~0xffff);
7602 register_name = "BadInstrX";
7603 break;
7604 default:
7605 goto cp0_unimplemented;
7607 break;
7608 case CP0_REGISTER_09:
7609 switch (sel) {
7610 case CP0_REG09__COUNT:
7611 /* Mark as an IO operation because we read the time. */
7612 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7613 gen_io_start();
7615 gen_helper_mfc0_count(arg, cpu_env);
7617 * Break the TB to be able to take timer interrupts immediately
7618 * after reading count. DISAS_STOP isn't sufficient, we need to
7619 * ensure we break completely out of translated code.
7621 gen_save_pc(ctx->base.pc_next + 4);
7622 ctx->base.is_jmp = DISAS_EXIT;
7623 register_name = "Count";
7624 break;
7625 case CP0_REG09__SAARI:
7626 CP0_CHECK(ctx->saar);
7627 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7628 register_name = "SAARI";
7629 break;
7630 case CP0_REG09__SAAR:
7631 CP0_CHECK(ctx->saar);
7632 gen_helper_mfc0_saar(arg, cpu_env);
7633 register_name = "SAAR";
7634 break;
7635 default:
7636 goto cp0_unimplemented;
7638 break;
7639 case CP0_REGISTER_10:
7640 switch (sel) {
7641 case CP0_REG10__ENTRYHI:
7642 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7643 tcg_gen_ext32s_tl(arg, arg);
7644 register_name = "EntryHi";
7645 break;
7646 default:
7647 goto cp0_unimplemented;
7649 break;
7650 case CP0_REGISTER_11:
7651 switch (sel) {
7652 case CP0_REG11__COMPARE:
7653 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7654 register_name = "Compare";
7655 break;
7656 /* 6,7 are implementation dependent */
7657 default:
7658 goto cp0_unimplemented;
7660 break;
7661 case CP0_REGISTER_12:
7662 switch (sel) {
7663 case CP0_REG12__STATUS:
7664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7665 register_name = "Status";
7666 break;
7667 case CP0_REG12__INTCTL:
7668 check_insn(ctx, ISA_MIPS_R2);
7669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7670 register_name = "IntCtl";
7671 break;
7672 case CP0_REG12__SRSCTL:
7673 check_insn(ctx, ISA_MIPS_R2);
7674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7675 register_name = "SRSCtl";
7676 break;
7677 case CP0_REG12__SRSMAP:
7678 check_insn(ctx, ISA_MIPS_R2);
7679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7680 register_name = "SRSMap";
7681 break;
7682 default:
7683 goto cp0_unimplemented;
7685 break;
7686 case CP0_REGISTER_13:
7687 switch (sel) {
7688 case CP0_REG13__CAUSE:
7689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7690 register_name = "Cause";
7691 break;
7692 default:
7693 goto cp0_unimplemented;
7695 break;
7696 case CP0_REGISTER_14:
7697 switch (sel) {
7698 case CP0_REG14__EPC:
7699 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7700 tcg_gen_ext32s_tl(arg, arg);
7701 register_name = "EPC";
7702 break;
7703 default:
7704 goto cp0_unimplemented;
7706 break;
7707 case CP0_REGISTER_15:
7708 switch (sel) {
7709 case CP0_REG15__PRID:
7710 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7711 register_name = "PRid";
7712 break;
7713 case CP0_REG15__EBASE:
7714 check_insn(ctx, ISA_MIPS_R2);
7715 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7716 tcg_gen_ext32s_tl(arg, arg);
7717 register_name = "EBase";
7718 break;
7719 case CP0_REG15__CMGCRBASE:
7720 check_insn(ctx, ISA_MIPS_R2);
7721 CP0_CHECK(ctx->cmgcr);
7722 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7723 tcg_gen_ext32s_tl(arg, arg);
7724 register_name = "CMGCRBase";
7725 break;
7726 default:
7727 goto cp0_unimplemented;
7729 break;
7730 case CP0_REGISTER_16:
7731 switch (sel) {
7732 case CP0_REG16__CONFIG:
7733 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7734 register_name = "Config";
7735 break;
7736 case CP0_REG16__CONFIG1:
7737 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7738 register_name = "Config1";
7739 break;
7740 case CP0_REG16__CONFIG2:
7741 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7742 register_name = "Config2";
7743 break;
7744 case CP0_REG16__CONFIG3:
7745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7746 register_name = "Config3";
7747 break;
7748 case CP0_REG16__CONFIG4:
7749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7750 register_name = "Config4";
7751 break;
7752 case CP0_REG16__CONFIG5:
7753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7754 register_name = "Config5";
7755 break;
7756 /* 6,7 are implementation dependent */
7757 case CP0_REG16__CONFIG6:
7758 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7759 register_name = "Config6";
7760 break;
7761 case CP0_REG16__CONFIG7:
7762 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7763 register_name = "Config7";
7764 break;
7765 default:
7766 goto cp0_unimplemented;
7768 break;
7769 case CP0_REGISTER_17:
7770 switch (sel) {
7771 case CP0_REG17__LLADDR:
7772 gen_helper_mfc0_lladdr(arg, cpu_env);
7773 register_name = "LLAddr";
7774 break;
7775 case CP0_REG17__MAAR:
7776 CP0_CHECK(ctx->mrp);
7777 gen_helper_mfc0_maar(arg, cpu_env);
7778 register_name = "MAAR";
7779 break;
7780 case CP0_REG17__MAARI:
7781 CP0_CHECK(ctx->mrp);
7782 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7783 register_name = "MAARI";
7784 break;
7785 default:
7786 goto cp0_unimplemented;
7788 break;
7789 case CP0_REGISTER_18:
7790 switch (sel) {
7791 case CP0_REG18__WATCHLO0:
7792 case CP0_REG18__WATCHLO1:
7793 case CP0_REG18__WATCHLO2:
7794 case CP0_REG18__WATCHLO3:
7795 case CP0_REG18__WATCHLO4:
7796 case CP0_REG18__WATCHLO5:
7797 case CP0_REG18__WATCHLO6:
7798 case CP0_REG18__WATCHLO7:
7799 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7800 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7801 register_name = "WatchLo";
7802 break;
7803 default:
7804 goto cp0_unimplemented;
7806 break;
7807 case CP0_REGISTER_19:
7808 switch (sel) {
7809 case CP0_REG19__WATCHHI0:
7810 case CP0_REG19__WATCHHI1:
7811 case CP0_REG19__WATCHHI2:
7812 case CP0_REG19__WATCHHI3:
7813 case CP0_REG19__WATCHHI4:
7814 case CP0_REG19__WATCHHI5:
7815 case CP0_REG19__WATCHHI6:
7816 case CP0_REG19__WATCHHI7:
7817 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7818 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7819 register_name = "WatchHi";
7820 break;
7821 default:
7822 goto cp0_unimplemented;
7824 break;
7825 case CP0_REGISTER_20:
7826 switch (sel) {
7827 case CP0_REG20__XCONTEXT:
7828 #if defined(TARGET_MIPS64)
7829 check_insn(ctx, ISA_MIPS3);
7830 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7831 tcg_gen_ext32s_tl(arg, arg);
7832 register_name = "XContext";
7833 break;
7834 #endif
7835 default:
7836 goto cp0_unimplemented;
7838 break;
7839 case CP0_REGISTER_21:
7840 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7841 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7842 switch (sel) {
7843 case 0:
7844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7845 register_name = "Framemask";
7846 break;
7847 default:
7848 goto cp0_unimplemented;
7850 break;
7851 case CP0_REGISTER_22:
7852 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7853 register_name = "'Diagnostic"; /* implementation dependent */
7854 break;
7855 case CP0_REGISTER_23:
7856 switch (sel) {
7857 case CP0_REG23__DEBUG:
7858 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7859 register_name = "Debug";
7860 break;
7861 case CP0_REG23__TRACECONTROL:
7862 /* PDtrace support */
7863 /* gen_helper_mfc0_tracecontrol(arg); */
7864 register_name = "TraceControl";
7865 goto cp0_unimplemented;
7866 case CP0_REG23__TRACECONTROL2:
7867 /* PDtrace support */
7868 /* gen_helper_mfc0_tracecontrol2(arg); */
7869 register_name = "TraceControl2";
7870 goto cp0_unimplemented;
7871 case CP0_REG23__USERTRACEDATA1:
7872 /* PDtrace support */
7873 /* gen_helper_mfc0_usertracedata1(arg);*/
7874 register_name = "UserTraceData1";
7875 goto cp0_unimplemented;
7876 case CP0_REG23__TRACEIBPC:
7877 /* PDtrace support */
7878 /* gen_helper_mfc0_traceibpc(arg); */
7879 register_name = "TraceIBPC";
7880 goto cp0_unimplemented;
7881 case CP0_REG23__TRACEDBPC:
7882 /* PDtrace support */
7883 /* gen_helper_mfc0_tracedbpc(arg); */
7884 register_name = "TraceDBPC";
7885 goto cp0_unimplemented;
7886 default:
7887 goto cp0_unimplemented;
7889 break;
7890 case CP0_REGISTER_24:
7891 switch (sel) {
7892 case CP0_REG24__DEPC:
7893 /* EJTAG support */
7894 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7895 tcg_gen_ext32s_tl(arg, arg);
7896 register_name = "DEPC";
7897 break;
7898 default:
7899 goto cp0_unimplemented;
7901 break;
7902 case CP0_REGISTER_25:
7903 switch (sel) {
7904 case CP0_REG25__PERFCTL0:
7905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7906 register_name = "Performance0";
7907 break;
7908 case CP0_REG25__PERFCNT0:
7909 /* gen_helper_mfc0_performance1(arg); */
7910 register_name = "Performance1";
7911 goto cp0_unimplemented;
7912 case CP0_REG25__PERFCTL1:
7913 /* gen_helper_mfc0_performance2(arg); */
7914 register_name = "Performance2";
7915 goto cp0_unimplemented;
7916 case CP0_REG25__PERFCNT1:
7917 /* gen_helper_mfc0_performance3(arg); */
7918 register_name = "Performance3";
7919 goto cp0_unimplemented;
7920 case CP0_REG25__PERFCTL2:
7921 /* gen_helper_mfc0_performance4(arg); */
7922 register_name = "Performance4";
7923 goto cp0_unimplemented;
7924 case CP0_REG25__PERFCNT2:
7925 /* gen_helper_mfc0_performance5(arg); */
7926 register_name = "Performance5";
7927 goto cp0_unimplemented;
7928 case CP0_REG25__PERFCTL3:
7929 /* gen_helper_mfc0_performance6(arg); */
7930 register_name = "Performance6";
7931 goto cp0_unimplemented;
7932 case CP0_REG25__PERFCNT3:
7933 /* gen_helper_mfc0_performance7(arg); */
7934 register_name = "Performance7";
7935 goto cp0_unimplemented;
7936 default:
7937 goto cp0_unimplemented;
7939 break;
7940 case CP0_REGISTER_26:
7941 switch (sel) {
7942 case CP0_REG26__ERRCTL:
7943 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7944 register_name = "ErrCtl";
7945 break;
7946 default:
7947 goto cp0_unimplemented;
7949 break;
7950 case CP0_REGISTER_27:
7951 switch (sel) {
7952 case CP0_REG27__CACHERR:
7953 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7954 register_name = "CacheErr";
7955 break;
7956 default:
7957 goto cp0_unimplemented;
7959 break;
7960 case CP0_REGISTER_28:
7961 switch (sel) {
7962 case CP0_REG28__TAGLO:
7963 case CP0_REG28__TAGLO1:
7964 case CP0_REG28__TAGLO2:
7965 case CP0_REG28__TAGLO3:
7967 TCGv_i64 tmp = tcg_temp_new_i64();
7968 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
7969 gen_move_low32(arg, tmp);
7970 tcg_temp_free_i64(tmp);
7972 register_name = "TagLo";
7973 break;
7974 case CP0_REG28__DATALO:
7975 case CP0_REG28__DATALO1:
7976 case CP0_REG28__DATALO2:
7977 case CP0_REG28__DATALO3:
7978 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7979 register_name = "DataLo";
7980 break;
7981 default:
7982 goto cp0_unimplemented;
7984 break;
7985 case CP0_REGISTER_29:
7986 switch (sel) {
7987 case CP0_REG29__TAGHI:
7988 case CP0_REG29__TAGHI1:
7989 case CP0_REG29__TAGHI2:
7990 case CP0_REG29__TAGHI3:
7991 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7992 register_name = "TagHi";
7993 break;
7994 case CP0_REG29__DATAHI:
7995 case CP0_REG29__DATAHI1:
7996 case CP0_REG29__DATAHI2:
7997 case CP0_REG29__DATAHI3:
7998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7999 register_name = "DataHi";
8000 break;
8001 default:
8002 goto cp0_unimplemented;
8004 break;
8005 case CP0_REGISTER_30:
8006 switch (sel) {
8007 case CP0_REG30__ERROREPC:
8008 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8009 tcg_gen_ext32s_tl(arg, arg);
8010 register_name = "ErrorEPC";
8011 break;
8012 default:
8013 goto cp0_unimplemented;
8015 break;
8016 case CP0_REGISTER_31:
8017 switch (sel) {
8018 case CP0_REG31__DESAVE:
8019 /* EJTAG support */
8020 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8021 register_name = "DESAVE";
8022 break;
8023 case CP0_REG31__KSCRATCH1:
8024 case CP0_REG31__KSCRATCH2:
8025 case CP0_REG31__KSCRATCH3:
8026 case CP0_REG31__KSCRATCH4:
8027 case CP0_REG31__KSCRATCH5:
8028 case CP0_REG31__KSCRATCH6:
8029 CP0_CHECK(ctx->kscrexist & (1 << sel));
8030 tcg_gen_ld_tl(arg, cpu_env,
8031 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8032 tcg_gen_ext32s_tl(arg, arg);
8033 register_name = "KScratch";
8034 break;
8035 default:
8036 goto cp0_unimplemented;
8038 break;
8039 default:
8040 goto cp0_unimplemented;
8042 trace_mips_translate_c0("mfc0", register_name, reg, sel);
8043 return;
8045 cp0_unimplemented:
8046 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
8047 register_name, reg, sel);
8048 gen_mfc0_unimplemented(ctx, arg);
8051 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8053 const char *register_name = "invalid";
8055 if (sel != 0) {
8056 check_insn(ctx, ISA_MIPS_R1);
8059 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8060 gen_io_start();
8063 switch (reg) {
8064 case CP0_REGISTER_00:
8065 switch (sel) {
8066 case CP0_REG00__INDEX:
8067 gen_helper_mtc0_index(cpu_env, arg);
8068 register_name = "Index";
8069 break;
8070 case CP0_REG00__MVPCONTROL:
8071 CP0_CHECK(ctx->insn_flags & ASE_MT);
8072 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8073 register_name = "MVPControl";
8074 break;
8075 case CP0_REG00__MVPCONF0:
8076 CP0_CHECK(ctx->insn_flags & ASE_MT);
8077 /* ignored */
8078 register_name = "MVPConf0";
8079 break;
8080 case CP0_REG00__MVPCONF1:
8081 CP0_CHECK(ctx->insn_flags & ASE_MT);
8082 /* ignored */
8083 register_name = "MVPConf1";
8084 break;
8085 case CP0_REG00__VPCONTROL:
8086 CP0_CHECK(ctx->vp);
8087 /* ignored */
8088 register_name = "VPControl";
8089 break;
8090 default:
8091 goto cp0_unimplemented;
8093 break;
8094 case CP0_REGISTER_01:
8095 switch (sel) {
8096 case CP0_REG01__RANDOM:
8097 /* ignored */
8098 register_name = "Random";
8099 break;
8100 case CP0_REG01__VPECONTROL:
8101 CP0_CHECK(ctx->insn_flags & ASE_MT);
8102 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8103 register_name = "VPEControl";
8104 break;
8105 case CP0_REG01__VPECONF0:
8106 CP0_CHECK(ctx->insn_flags & ASE_MT);
8107 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8108 register_name = "VPEConf0";
8109 break;
8110 case CP0_REG01__VPECONF1:
8111 CP0_CHECK(ctx->insn_flags & ASE_MT);
8112 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8113 register_name = "VPEConf1";
8114 break;
8115 case CP0_REG01__YQMASK:
8116 CP0_CHECK(ctx->insn_flags & ASE_MT);
8117 gen_helper_mtc0_yqmask(cpu_env, arg);
8118 register_name = "YQMask";
8119 break;
8120 case CP0_REG01__VPESCHEDULE:
8121 CP0_CHECK(ctx->insn_flags & ASE_MT);
8122 tcg_gen_st_tl(arg, cpu_env,
8123 offsetof(CPUMIPSState, CP0_VPESchedule));
8124 register_name = "VPESchedule";
8125 break;
8126 case CP0_REG01__VPESCHEFBACK:
8127 CP0_CHECK(ctx->insn_flags & ASE_MT);
8128 tcg_gen_st_tl(arg, cpu_env,
8129 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8130 register_name = "VPEScheFBack";
8131 break;
8132 case CP0_REG01__VPEOPT:
8133 CP0_CHECK(ctx->insn_flags & ASE_MT);
8134 gen_helper_mtc0_vpeopt(cpu_env, arg);
8135 register_name = "VPEOpt";
8136 break;
8137 default:
8138 goto cp0_unimplemented;
8140 break;
8141 case CP0_REGISTER_02:
8142 switch (sel) {
8143 case CP0_REG02__ENTRYLO0:
8144 gen_helper_mtc0_entrylo0(cpu_env, arg);
8145 register_name = "EntryLo0";
8146 break;
8147 case CP0_REG02__TCSTATUS:
8148 CP0_CHECK(ctx->insn_flags & ASE_MT);
8149 gen_helper_mtc0_tcstatus(cpu_env, arg);
8150 register_name = "TCStatus";
8151 break;
8152 case CP0_REG02__TCBIND:
8153 CP0_CHECK(ctx->insn_flags & ASE_MT);
8154 gen_helper_mtc0_tcbind(cpu_env, arg);
8155 register_name = "TCBind";
8156 break;
8157 case CP0_REG02__TCRESTART:
8158 CP0_CHECK(ctx->insn_flags & ASE_MT);
8159 gen_helper_mtc0_tcrestart(cpu_env, arg);
8160 register_name = "TCRestart";
8161 break;
8162 case CP0_REG02__TCHALT:
8163 CP0_CHECK(ctx->insn_flags & ASE_MT);
8164 gen_helper_mtc0_tchalt(cpu_env, arg);
8165 register_name = "TCHalt";
8166 break;
8167 case CP0_REG02__TCCONTEXT:
8168 CP0_CHECK(ctx->insn_flags & ASE_MT);
8169 gen_helper_mtc0_tccontext(cpu_env, arg);
8170 register_name = "TCContext";
8171 break;
8172 case CP0_REG02__TCSCHEDULE:
8173 CP0_CHECK(ctx->insn_flags & ASE_MT);
8174 gen_helper_mtc0_tcschedule(cpu_env, arg);
8175 register_name = "TCSchedule";
8176 break;
8177 case CP0_REG02__TCSCHEFBACK:
8178 CP0_CHECK(ctx->insn_flags & ASE_MT);
8179 gen_helper_mtc0_tcschefback(cpu_env, arg);
8180 register_name = "TCScheFBack";
8181 break;
8182 default:
8183 goto cp0_unimplemented;
8185 break;
8186 case CP0_REGISTER_03:
8187 switch (sel) {
8188 case CP0_REG03__ENTRYLO1:
8189 gen_helper_mtc0_entrylo1(cpu_env, arg);
8190 register_name = "EntryLo1";
8191 break;
8192 case CP0_REG03__GLOBALNUM:
8193 CP0_CHECK(ctx->vp);
8194 /* ignored */
8195 register_name = "GlobalNumber";
8196 break;
8197 default:
8198 goto cp0_unimplemented;
8200 break;
8201 case CP0_REGISTER_04:
8202 switch (sel) {
8203 case CP0_REG04__CONTEXT:
8204 gen_helper_mtc0_context(cpu_env, arg);
8205 register_name = "Context";
8206 break;
8207 case CP0_REG04__CONTEXTCONFIG:
8208 /* SmartMIPS ASE */
8209 /* gen_helper_mtc0_contextconfig(arg); */
8210 register_name = "ContextConfig";
8211 goto cp0_unimplemented;
8212 case CP0_REG04__USERLOCAL:
8213 CP0_CHECK(ctx->ulri);
8214 tcg_gen_st_tl(arg, cpu_env,
8215 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8216 register_name = "UserLocal";
8217 break;
8218 case CP0_REG04__MMID:
8219 CP0_CHECK(ctx->mi);
8220 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8221 register_name = "MMID";
8222 break;
8223 default:
8224 goto cp0_unimplemented;
8226 break;
8227 case CP0_REGISTER_05:
8228 switch (sel) {
8229 case CP0_REG05__PAGEMASK:
8230 gen_helper_mtc0_pagemask(cpu_env, arg);
8231 register_name = "PageMask";
8232 break;
8233 case CP0_REG05__PAGEGRAIN:
8234 check_insn(ctx, ISA_MIPS_R2);
8235 gen_helper_mtc0_pagegrain(cpu_env, arg);
8236 register_name = "PageGrain";
8237 ctx->base.is_jmp = DISAS_STOP;
8238 break;
8239 case CP0_REG05__SEGCTL0:
8240 CP0_CHECK(ctx->sc);
8241 gen_helper_mtc0_segctl0(cpu_env, arg);
8242 register_name = "SegCtl0";
8243 break;
8244 case CP0_REG05__SEGCTL1:
8245 CP0_CHECK(ctx->sc);
8246 gen_helper_mtc0_segctl1(cpu_env, arg);
8247 register_name = "SegCtl1";
8248 break;
8249 case CP0_REG05__SEGCTL2:
8250 CP0_CHECK(ctx->sc);
8251 gen_helper_mtc0_segctl2(cpu_env, arg);
8252 register_name = "SegCtl2";
8253 break;
8254 case CP0_REG05__PWBASE:
8255 check_pw(ctx);
8256 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
8257 register_name = "PWBase";
8258 break;
8259 case CP0_REG05__PWFIELD:
8260 check_pw(ctx);
8261 gen_helper_mtc0_pwfield(cpu_env, arg);
8262 register_name = "PWField";
8263 break;
8264 case CP0_REG05__PWSIZE:
8265 check_pw(ctx);
8266 gen_helper_mtc0_pwsize(cpu_env, arg);
8267 register_name = "PWSize";
8268 break;
8269 default:
8270 goto cp0_unimplemented;
8272 break;
8273 case CP0_REGISTER_06:
8274 switch (sel) {
8275 case CP0_REG06__WIRED:
8276 gen_helper_mtc0_wired(cpu_env, arg);
8277 register_name = "Wired";
8278 break;
8279 case CP0_REG06__SRSCONF0:
8280 check_insn(ctx, ISA_MIPS_R2);
8281 gen_helper_mtc0_srsconf0(cpu_env, arg);
8282 register_name = "SRSConf0";
8283 break;
8284 case CP0_REG06__SRSCONF1:
8285 check_insn(ctx, ISA_MIPS_R2);
8286 gen_helper_mtc0_srsconf1(cpu_env, arg);
8287 register_name = "SRSConf1";
8288 break;
8289 case CP0_REG06__SRSCONF2:
8290 check_insn(ctx, ISA_MIPS_R2);
8291 gen_helper_mtc0_srsconf2(cpu_env, arg);
8292 register_name = "SRSConf2";
8293 break;
8294 case CP0_REG06__SRSCONF3:
8295 check_insn(ctx, ISA_MIPS_R2);
8296 gen_helper_mtc0_srsconf3(cpu_env, arg);
8297 register_name = "SRSConf3";
8298 break;
8299 case CP0_REG06__SRSCONF4:
8300 check_insn(ctx, ISA_MIPS_R2);
8301 gen_helper_mtc0_srsconf4(cpu_env, arg);
8302 register_name = "SRSConf4";
8303 break;
8304 case CP0_REG06__PWCTL:
8305 check_pw(ctx);
8306 gen_helper_mtc0_pwctl(cpu_env, arg);
8307 register_name = "PWCtl";
8308 break;
8309 default:
8310 goto cp0_unimplemented;
8312 break;
8313 case CP0_REGISTER_07:
8314 switch (sel) {
8315 case CP0_REG07__HWRENA:
8316 check_insn(ctx, ISA_MIPS_R2);
8317 gen_helper_mtc0_hwrena(cpu_env, arg);
8318 ctx->base.is_jmp = DISAS_STOP;
8319 register_name = "HWREna";
8320 break;
8321 default:
8322 goto cp0_unimplemented;
8324 break;
8325 case CP0_REGISTER_08:
8326 switch (sel) {
8327 case CP0_REG08__BADVADDR:
8328 /* ignored */
8329 register_name = "BadVAddr";
8330 break;
8331 case CP0_REG08__BADINSTR:
8332 /* ignored */
8333 register_name = "BadInstr";
8334 break;
8335 case CP0_REG08__BADINSTRP:
8336 /* ignored */
8337 register_name = "BadInstrP";
8338 break;
8339 case CP0_REG08__BADINSTRX:
8340 /* ignored */
8341 register_name = "BadInstrX";
8342 break;
8343 default:
8344 goto cp0_unimplemented;
8346 break;
8347 case CP0_REGISTER_09:
8348 switch (sel) {
8349 case CP0_REG09__COUNT:
8350 gen_helper_mtc0_count(cpu_env, arg);
8351 register_name = "Count";
8352 break;
8353 case CP0_REG09__SAARI:
8354 CP0_CHECK(ctx->saar);
8355 gen_helper_mtc0_saari(cpu_env, arg);
8356 register_name = "SAARI";
8357 break;
8358 case CP0_REG09__SAAR:
8359 CP0_CHECK(ctx->saar);
8360 gen_helper_mtc0_saar(cpu_env, arg);
8361 register_name = "SAAR";
8362 break;
8363 default:
8364 goto cp0_unimplemented;
8366 break;
8367 case CP0_REGISTER_10:
8368 switch (sel) {
8369 case CP0_REG10__ENTRYHI:
8370 gen_helper_mtc0_entryhi(cpu_env, arg);
8371 register_name = "EntryHi";
8372 break;
8373 default:
8374 goto cp0_unimplemented;
8376 break;
8377 case CP0_REGISTER_11:
8378 switch (sel) {
8379 case CP0_REG11__COMPARE:
8380 gen_helper_mtc0_compare(cpu_env, arg);
8381 register_name = "Compare";
8382 break;
8383 /* 6,7 are implementation dependent */
8384 default:
8385 goto cp0_unimplemented;
8387 break;
8388 case CP0_REGISTER_12:
8389 switch (sel) {
8390 case CP0_REG12__STATUS:
8391 save_cpu_state(ctx, 1);
8392 gen_helper_mtc0_status(cpu_env, arg);
8393 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8394 gen_save_pc(ctx->base.pc_next + 4);
8395 ctx->base.is_jmp = DISAS_EXIT;
8396 register_name = "Status";
8397 break;
8398 case CP0_REG12__INTCTL:
8399 check_insn(ctx, ISA_MIPS_R2);
8400 gen_helper_mtc0_intctl(cpu_env, arg);
8401 /* Stop translation as we may have switched the execution mode */
8402 ctx->base.is_jmp = DISAS_STOP;
8403 register_name = "IntCtl";
8404 break;
8405 case CP0_REG12__SRSCTL:
8406 check_insn(ctx, ISA_MIPS_R2);
8407 gen_helper_mtc0_srsctl(cpu_env, arg);
8408 /* Stop translation as we may have switched the execution mode */
8409 ctx->base.is_jmp = DISAS_STOP;
8410 register_name = "SRSCtl";
8411 break;
8412 case CP0_REG12__SRSMAP:
8413 check_insn(ctx, ISA_MIPS_R2);
8414 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8415 /* Stop translation as we may have switched the execution mode */
8416 ctx->base.is_jmp = DISAS_STOP;
8417 register_name = "SRSMap";
8418 break;
8419 default:
8420 goto cp0_unimplemented;
8422 break;
8423 case CP0_REGISTER_13:
8424 switch (sel) {
8425 case CP0_REG13__CAUSE:
8426 save_cpu_state(ctx, 1);
8427 gen_helper_mtc0_cause(cpu_env, arg);
8429 * Stop translation as we may have triggered an interrupt.
8430 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8431 * translated code to check for pending interrupts.
8433 gen_save_pc(ctx->base.pc_next + 4);
8434 ctx->base.is_jmp = DISAS_EXIT;
8435 register_name = "Cause";
8436 break;
8437 default:
8438 goto cp0_unimplemented;
8440 break;
8441 case CP0_REGISTER_14:
8442 switch (sel) {
8443 case CP0_REG14__EPC:
8444 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8445 register_name = "EPC";
8446 break;
8447 default:
8448 goto cp0_unimplemented;
8450 break;
8451 case CP0_REGISTER_15:
8452 switch (sel) {
8453 case CP0_REG15__PRID:
8454 /* ignored */
8455 register_name = "PRid";
8456 break;
8457 case CP0_REG15__EBASE:
8458 check_insn(ctx, ISA_MIPS_R2);
8459 gen_helper_mtc0_ebase(cpu_env, arg);
8460 register_name = "EBase";
8461 break;
8462 default:
8463 goto cp0_unimplemented;
8465 break;
8466 case CP0_REGISTER_16:
8467 switch (sel) {
8468 case CP0_REG16__CONFIG:
8469 gen_helper_mtc0_config0(cpu_env, arg);
8470 register_name = "Config";
8471 /* Stop translation as we may have switched the execution mode */
8472 ctx->base.is_jmp = DISAS_STOP;
8473 break;
8474 case CP0_REG16__CONFIG1:
8475 /* ignored, read only */
8476 register_name = "Config1";
8477 break;
8478 case CP0_REG16__CONFIG2:
8479 gen_helper_mtc0_config2(cpu_env, arg);
8480 register_name = "Config2";
8481 /* Stop translation as we may have switched the execution mode */
8482 ctx->base.is_jmp = DISAS_STOP;
8483 break;
8484 case CP0_REG16__CONFIG3:
8485 gen_helper_mtc0_config3(cpu_env, arg);
8486 register_name = "Config3";
8487 /* Stop translation as we may have switched the execution mode */
8488 ctx->base.is_jmp = DISAS_STOP;
8489 break;
8490 case CP0_REG16__CONFIG4:
8491 gen_helper_mtc0_config4(cpu_env, arg);
8492 register_name = "Config4";
8493 ctx->base.is_jmp = DISAS_STOP;
8494 break;
8495 case CP0_REG16__CONFIG5:
8496 gen_helper_mtc0_config5(cpu_env, arg);
8497 register_name = "Config5";
8498 /* Stop translation as we may have switched the execution mode */
8499 ctx->base.is_jmp = DISAS_STOP;
8500 break;
8501 /* 6,7 are implementation dependent */
8502 case CP0_REG16__CONFIG6:
8503 /* ignored */
8504 register_name = "Config6";
8505 break;
8506 case CP0_REG16__CONFIG7:
8507 /* ignored */
8508 register_name = "Config7";
8509 break;
8510 default:
8511 register_name = "Invalid config selector";
8512 goto cp0_unimplemented;
8514 break;
8515 case CP0_REGISTER_17:
8516 switch (sel) {
8517 case CP0_REG17__LLADDR:
8518 gen_helper_mtc0_lladdr(cpu_env, arg);
8519 register_name = "LLAddr";
8520 break;
8521 case CP0_REG17__MAAR:
8522 CP0_CHECK(ctx->mrp);
8523 gen_helper_mtc0_maar(cpu_env, arg);
8524 register_name = "MAAR";
8525 break;
8526 case CP0_REG17__MAARI:
8527 CP0_CHECK(ctx->mrp);
8528 gen_helper_mtc0_maari(cpu_env, arg);
8529 register_name = "MAARI";
8530 break;
8531 default:
8532 goto cp0_unimplemented;
8534 break;
8535 case CP0_REGISTER_18:
8536 switch (sel) {
8537 case CP0_REG18__WATCHLO0:
8538 case CP0_REG18__WATCHLO1:
8539 case CP0_REG18__WATCHLO2:
8540 case CP0_REG18__WATCHLO3:
8541 case CP0_REG18__WATCHLO4:
8542 case CP0_REG18__WATCHLO5:
8543 case CP0_REG18__WATCHLO6:
8544 case CP0_REG18__WATCHLO7:
8545 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8546 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8547 register_name = "WatchLo";
8548 break;
8549 default:
8550 goto cp0_unimplemented;
8552 break;
8553 case CP0_REGISTER_19:
8554 switch (sel) {
8555 case CP0_REG19__WATCHHI0:
8556 case CP0_REG19__WATCHHI1:
8557 case CP0_REG19__WATCHHI2:
8558 case CP0_REG19__WATCHHI3:
8559 case CP0_REG19__WATCHHI4:
8560 case CP0_REG19__WATCHHI5:
8561 case CP0_REG19__WATCHHI6:
8562 case CP0_REG19__WATCHHI7:
8563 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8564 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8565 register_name = "WatchHi";
8566 break;
8567 default:
8568 goto cp0_unimplemented;
8570 break;
8571 case CP0_REGISTER_20:
8572 switch (sel) {
8573 case CP0_REG20__XCONTEXT:
8574 #if defined(TARGET_MIPS64)
8575 check_insn(ctx, ISA_MIPS3);
8576 gen_helper_mtc0_xcontext(cpu_env, arg);
8577 register_name = "XContext";
8578 break;
8579 #endif
8580 default:
8581 goto cp0_unimplemented;
8583 break;
8584 case CP0_REGISTER_21:
8585 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8586 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8587 switch (sel) {
8588 case 0:
8589 gen_helper_mtc0_framemask(cpu_env, arg);
8590 register_name = "Framemask";
8591 break;
8592 default:
8593 goto cp0_unimplemented;
8595 break;
8596 case CP0_REGISTER_22:
8597 /* ignored */
8598 register_name = "Diagnostic"; /* implementation dependent */
8599 break;
8600 case CP0_REGISTER_23:
8601 switch (sel) {
8602 case CP0_REG23__DEBUG:
8603 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8604 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8605 gen_save_pc(ctx->base.pc_next + 4);
8606 ctx->base.is_jmp = DISAS_EXIT;
8607 register_name = "Debug";
8608 break;
8609 case CP0_REG23__TRACECONTROL:
8610 /* PDtrace support */
8611 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8612 register_name = "TraceControl";
8613 /* Stop translation as we may have switched the execution mode */
8614 ctx->base.is_jmp = DISAS_STOP;
8615 goto cp0_unimplemented;
8616 case CP0_REG23__TRACECONTROL2:
8617 /* PDtrace support */
8618 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8619 register_name = "TraceControl2";
8620 /* Stop translation as we may have switched the execution mode */
8621 ctx->base.is_jmp = DISAS_STOP;
8622 goto cp0_unimplemented;
8623 case CP0_REG23__USERTRACEDATA1:
8624 /* Stop translation as we may have switched the execution mode */
8625 ctx->base.is_jmp = DISAS_STOP;
8626 /* PDtrace support */
8627 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8628 register_name = "UserTraceData";
8629 /* Stop translation as we may have switched the execution mode */
8630 ctx->base.is_jmp = DISAS_STOP;
8631 goto cp0_unimplemented;
8632 case CP0_REG23__TRACEIBPC:
8633 /* PDtrace support */
8634 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8635 /* Stop translation as we may have switched the execution mode */
8636 ctx->base.is_jmp = DISAS_STOP;
8637 register_name = "TraceIBPC";
8638 goto cp0_unimplemented;
8639 case CP0_REG23__TRACEDBPC:
8640 /* PDtrace support */
8641 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8642 /* Stop translation as we may have switched the execution mode */
8643 ctx->base.is_jmp = DISAS_STOP;
8644 register_name = "TraceDBPC";
8645 goto cp0_unimplemented;
8646 default:
8647 goto cp0_unimplemented;
8649 break;
8650 case CP0_REGISTER_24:
8651 switch (sel) {
8652 case CP0_REG24__DEPC:
8653 /* EJTAG support */
8654 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8655 register_name = "DEPC";
8656 break;
8657 default:
8658 goto cp0_unimplemented;
8660 break;
8661 case CP0_REGISTER_25:
8662 switch (sel) {
8663 case CP0_REG25__PERFCTL0:
8664 gen_helper_mtc0_performance0(cpu_env, arg);
8665 register_name = "Performance0";
8666 break;
8667 case CP0_REG25__PERFCNT0:
8668 /* gen_helper_mtc0_performance1(arg); */
8669 register_name = "Performance1";
8670 goto cp0_unimplemented;
8671 case CP0_REG25__PERFCTL1:
8672 /* gen_helper_mtc0_performance2(arg); */
8673 register_name = "Performance2";
8674 goto cp0_unimplemented;
8675 case CP0_REG25__PERFCNT1:
8676 /* gen_helper_mtc0_performance3(arg); */
8677 register_name = "Performance3";
8678 goto cp0_unimplemented;
8679 case CP0_REG25__PERFCTL2:
8680 /* gen_helper_mtc0_performance4(arg); */
8681 register_name = "Performance4";
8682 goto cp0_unimplemented;
8683 case CP0_REG25__PERFCNT2:
8684 /* gen_helper_mtc0_performance5(arg); */
8685 register_name = "Performance5";
8686 goto cp0_unimplemented;
8687 case CP0_REG25__PERFCTL3:
8688 /* gen_helper_mtc0_performance6(arg); */
8689 register_name = "Performance6";
8690 goto cp0_unimplemented;
8691 case CP0_REG25__PERFCNT3:
8692 /* gen_helper_mtc0_performance7(arg); */
8693 register_name = "Performance7";
8694 goto cp0_unimplemented;
8695 default:
8696 goto cp0_unimplemented;
8698 break;
8699 case CP0_REGISTER_26:
8700 switch (sel) {
8701 case CP0_REG26__ERRCTL:
8702 gen_helper_mtc0_errctl(cpu_env, arg);
8703 ctx->base.is_jmp = DISAS_STOP;
8704 register_name = "ErrCtl";
8705 break;
8706 default:
8707 goto cp0_unimplemented;
8709 break;
8710 case CP0_REGISTER_27:
8711 switch (sel) {
8712 case CP0_REG27__CACHERR:
8713 /* ignored */
8714 register_name = "CacheErr";
8715 break;
8716 default:
8717 goto cp0_unimplemented;
8719 break;
8720 case CP0_REGISTER_28:
8721 switch (sel) {
8722 case CP0_REG28__TAGLO:
8723 case CP0_REG28__TAGLO1:
8724 case CP0_REG28__TAGLO2:
8725 case CP0_REG28__TAGLO3:
8726 gen_helper_mtc0_taglo(cpu_env, arg);
8727 register_name = "TagLo";
8728 break;
8729 case CP0_REG28__DATALO:
8730 case CP0_REG28__DATALO1:
8731 case CP0_REG28__DATALO2:
8732 case CP0_REG28__DATALO3:
8733 gen_helper_mtc0_datalo(cpu_env, arg);
8734 register_name = "DataLo";
8735 break;
8736 default:
8737 goto cp0_unimplemented;
8739 break;
8740 case CP0_REGISTER_29:
8741 switch (sel) {
8742 case CP0_REG29__TAGHI:
8743 case CP0_REG29__TAGHI1:
8744 case CP0_REG29__TAGHI2:
8745 case CP0_REG29__TAGHI3:
8746 gen_helper_mtc0_taghi(cpu_env, arg);
8747 register_name = "TagHi";
8748 break;
8749 case CP0_REG29__DATAHI:
8750 case CP0_REG29__DATAHI1:
8751 case CP0_REG29__DATAHI2:
8752 case CP0_REG29__DATAHI3:
8753 gen_helper_mtc0_datahi(cpu_env, arg);
8754 register_name = "DataHi";
8755 break;
8756 default:
8757 register_name = "invalid sel";
8758 goto cp0_unimplemented;
8760 break;
8761 case CP0_REGISTER_30:
8762 switch (sel) {
8763 case CP0_REG30__ERROREPC:
8764 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8765 register_name = "ErrorEPC";
8766 break;
8767 default:
8768 goto cp0_unimplemented;
8770 break;
8771 case CP0_REGISTER_31:
8772 switch (sel) {
8773 case CP0_REG31__DESAVE:
8774 /* EJTAG support */
8775 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8776 register_name = "DESAVE";
8777 break;
8778 case CP0_REG31__KSCRATCH1:
8779 case CP0_REG31__KSCRATCH2:
8780 case CP0_REG31__KSCRATCH3:
8781 case CP0_REG31__KSCRATCH4:
8782 case CP0_REG31__KSCRATCH5:
8783 case CP0_REG31__KSCRATCH6:
8784 CP0_CHECK(ctx->kscrexist & (1 << sel));
8785 tcg_gen_st_tl(arg, cpu_env,
8786 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8787 register_name = "KScratch";
8788 break;
8789 default:
8790 goto cp0_unimplemented;
8792 break;
8793 default:
8794 goto cp0_unimplemented;
8796 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8798 /* For simplicity assume that all writes can cause interrupts. */
8799 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8801 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8802 * translated code to check for pending interrupts.
8804 gen_save_pc(ctx->base.pc_next + 4);
8805 ctx->base.is_jmp = DISAS_EXIT;
8807 return;
8809 cp0_unimplemented:
8810 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8811 register_name, reg, sel);
8814 #if defined(TARGET_MIPS64)
8815 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8817 const char *register_name = "invalid";
8819 if (sel != 0) {
8820 check_insn(ctx, ISA_MIPS_R1);
8823 switch (reg) {
8824 case CP0_REGISTER_00:
8825 switch (sel) {
8826 case CP0_REG00__INDEX:
8827 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8828 register_name = "Index";
8829 break;
8830 case CP0_REG00__MVPCONTROL:
8831 CP0_CHECK(ctx->insn_flags & ASE_MT);
8832 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8833 register_name = "MVPControl";
8834 break;
8835 case CP0_REG00__MVPCONF0:
8836 CP0_CHECK(ctx->insn_flags & ASE_MT);
8837 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8838 register_name = "MVPConf0";
8839 break;
8840 case CP0_REG00__MVPCONF1:
8841 CP0_CHECK(ctx->insn_flags & ASE_MT);
8842 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8843 register_name = "MVPConf1";
8844 break;
8845 case CP0_REG00__VPCONTROL:
8846 CP0_CHECK(ctx->vp);
8847 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8848 register_name = "VPControl";
8849 break;
8850 default:
8851 goto cp0_unimplemented;
8853 break;
8854 case CP0_REGISTER_01:
8855 switch (sel) {
8856 case CP0_REG01__RANDOM:
8857 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8858 gen_helper_mfc0_random(arg, cpu_env);
8859 register_name = "Random";
8860 break;
8861 case CP0_REG01__VPECONTROL:
8862 CP0_CHECK(ctx->insn_flags & ASE_MT);
8863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8864 register_name = "VPEControl";
8865 break;
8866 case CP0_REG01__VPECONF0:
8867 CP0_CHECK(ctx->insn_flags & ASE_MT);
8868 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8869 register_name = "VPEConf0";
8870 break;
8871 case CP0_REG01__VPECONF1:
8872 CP0_CHECK(ctx->insn_flags & ASE_MT);
8873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
8874 register_name = "VPEConf1";
8875 break;
8876 case CP0_REG01__YQMASK:
8877 CP0_CHECK(ctx->insn_flags & ASE_MT);
8878 tcg_gen_ld_tl(arg, cpu_env,
8879 offsetof(CPUMIPSState, CP0_YQMask));
8880 register_name = "YQMask";
8881 break;
8882 case CP0_REG01__VPESCHEDULE:
8883 CP0_CHECK(ctx->insn_flags & ASE_MT);
8884 tcg_gen_ld_tl(arg, cpu_env,
8885 offsetof(CPUMIPSState, CP0_VPESchedule));
8886 register_name = "VPESchedule";
8887 break;
8888 case CP0_REG01__VPESCHEFBACK:
8889 CP0_CHECK(ctx->insn_flags & ASE_MT);
8890 tcg_gen_ld_tl(arg, cpu_env,
8891 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8892 register_name = "VPEScheFBack";
8893 break;
8894 case CP0_REG01__VPEOPT:
8895 CP0_CHECK(ctx->insn_flags & ASE_MT);
8896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
8897 register_name = "VPEOpt";
8898 break;
8899 default:
8900 goto cp0_unimplemented;
8902 break;
8903 case CP0_REGISTER_02:
8904 switch (sel) {
8905 case CP0_REG02__ENTRYLO0:
8906 tcg_gen_ld_tl(arg, cpu_env,
8907 offsetof(CPUMIPSState, CP0_EntryLo0));
8908 register_name = "EntryLo0";
8909 break;
8910 case CP0_REG02__TCSTATUS:
8911 CP0_CHECK(ctx->insn_flags & ASE_MT);
8912 gen_helper_mfc0_tcstatus(arg, cpu_env);
8913 register_name = "TCStatus";
8914 break;
8915 case CP0_REG02__TCBIND:
8916 CP0_CHECK(ctx->insn_flags & ASE_MT);
8917 gen_helper_mfc0_tcbind(arg, cpu_env);
8918 register_name = "TCBind";
8919 break;
8920 case CP0_REG02__TCRESTART:
8921 CP0_CHECK(ctx->insn_flags & ASE_MT);
8922 gen_helper_dmfc0_tcrestart(arg, cpu_env);
8923 register_name = "TCRestart";
8924 break;
8925 case CP0_REG02__TCHALT:
8926 CP0_CHECK(ctx->insn_flags & ASE_MT);
8927 gen_helper_dmfc0_tchalt(arg, cpu_env);
8928 register_name = "TCHalt";
8929 break;
8930 case CP0_REG02__TCCONTEXT:
8931 CP0_CHECK(ctx->insn_flags & ASE_MT);
8932 gen_helper_dmfc0_tccontext(arg, cpu_env);
8933 register_name = "TCContext";
8934 break;
8935 case CP0_REG02__TCSCHEDULE:
8936 CP0_CHECK(ctx->insn_flags & ASE_MT);
8937 gen_helper_dmfc0_tcschedule(arg, cpu_env);
8938 register_name = "TCSchedule";
8939 break;
8940 case CP0_REG02__TCSCHEFBACK:
8941 CP0_CHECK(ctx->insn_flags & ASE_MT);
8942 gen_helper_dmfc0_tcschefback(arg, cpu_env);
8943 register_name = "TCScheFBack";
8944 break;
8945 default:
8946 goto cp0_unimplemented;
8948 break;
8949 case CP0_REGISTER_03:
8950 switch (sel) {
8951 case CP0_REG03__ENTRYLO1:
8952 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
8953 register_name = "EntryLo1";
8954 break;
8955 case CP0_REG03__GLOBALNUM:
8956 CP0_CHECK(ctx->vp);
8957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
8958 register_name = "GlobalNumber";
8959 break;
8960 default:
8961 goto cp0_unimplemented;
8963 break;
8964 case CP0_REGISTER_04:
8965 switch (sel) {
8966 case CP0_REG04__CONTEXT:
8967 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
8968 register_name = "Context";
8969 break;
8970 case CP0_REG04__CONTEXTCONFIG:
8971 /* SmartMIPS ASE */
8972 /* gen_helper_dmfc0_contextconfig(arg); */
8973 register_name = "ContextConfig";
8974 goto cp0_unimplemented;
8975 case CP0_REG04__USERLOCAL:
8976 CP0_CHECK(ctx->ulri);
8977 tcg_gen_ld_tl(arg, cpu_env,
8978 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8979 register_name = "UserLocal";
8980 break;
8981 case CP0_REG04__MMID:
8982 CP0_CHECK(ctx->mi);
8983 gen_helper_mtc0_memorymapid(cpu_env, arg);
8984 register_name = "MMID";
8985 break;
8986 default:
8987 goto cp0_unimplemented;
8989 break;
8990 case CP0_REGISTER_05:
8991 switch (sel) {
8992 case CP0_REG05__PAGEMASK:
8993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
8994 register_name = "PageMask";
8995 break;
8996 case CP0_REG05__PAGEGRAIN:
8997 check_insn(ctx, ISA_MIPS_R2);
8998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
8999 register_name = "PageGrain";
9000 break;
9001 case CP0_REG05__SEGCTL0:
9002 CP0_CHECK(ctx->sc);
9003 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
9004 register_name = "SegCtl0";
9005 break;
9006 case CP0_REG05__SEGCTL1:
9007 CP0_CHECK(ctx->sc);
9008 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
9009 register_name = "SegCtl1";
9010 break;
9011 case CP0_REG05__SEGCTL2:
9012 CP0_CHECK(ctx->sc);
9013 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
9014 register_name = "SegCtl2";
9015 break;
9016 case CP0_REG05__PWBASE:
9017 check_pw(ctx);
9018 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9019 register_name = "PWBase";
9020 break;
9021 case CP0_REG05__PWFIELD:
9022 check_pw(ctx);
9023 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
9024 register_name = "PWField";
9025 break;
9026 case CP0_REG05__PWSIZE:
9027 check_pw(ctx);
9028 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
9029 register_name = "PWSize";
9030 break;
9031 default:
9032 goto cp0_unimplemented;
9034 break;
9035 case CP0_REGISTER_06:
9036 switch (sel) {
9037 case CP0_REG06__WIRED:
9038 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
9039 register_name = "Wired";
9040 break;
9041 case CP0_REG06__SRSCONF0:
9042 check_insn(ctx, ISA_MIPS_R2);
9043 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
9044 register_name = "SRSConf0";
9045 break;
9046 case CP0_REG06__SRSCONF1:
9047 check_insn(ctx, ISA_MIPS_R2);
9048 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
9049 register_name = "SRSConf1";
9050 break;
9051 case CP0_REG06__SRSCONF2:
9052 check_insn(ctx, ISA_MIPS_R2);
9053 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
9054 register_name = "SRSConf2";
9055 break;
9056 case CP0_REG06__SRSCONF3:
9057 check_insn(ctx, ISA_MIPS_R2);
9058 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
9059 register_name = "SRSConf3";
9060 break;
9061 case CP0_REG06__SRSCONF4:
9062 check_insn(ctx, ISA_MIPS_R2);
9063 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
9064 register_name = "SRSConf4";
9065 break;
9066 case CP0_REG06__PWCTL:
9067 check_pw(ctx);
9068 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
9069 register_name = "PWCtl";
9070 break;
9071 default:
9072 goto cp0_unimplemented;
9074 break;
9075 case CP0_REGISTER_07:
9076 switch (sel) {
9077 case CP0_REG07__HWRENA:
9078 check_insn(ctx, ISA_MIPS_R2);
9079 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
9080 register_name = "HWREna";
9081 break;
9082 default:
9083 goto cp0_unimplemented;
9085 break;
9086 case CP0_REGISTER_08:
9087 switch (sel) {
9088 case CP0_REG08__BADVADDR:
9089 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
9090 register_name = "BadVAddr";
9091 break;
9092 case CP0_REG08__BADINSTR:
9093 CP0_CHECK(ctx->bi);
9094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
9095 register_name = "BadInstr";
9096 break;
9097 case CP0_REG08__BADINSTRP:
9098 CP0_CHECK(ctx->bp);
9099 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
9100 register_name = "BadInstrP";
9101 break;
9102 case CP0_REG08__BADINSTRX:
9103 CP0_CHECK(ctx->bi);
9104 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
9105 tcg_gen_andi_tl(arg, arg, ~0xffff);
9106 register_name = "BadInstrX";
9107 break;
9108 default:
9109 goto cp0_unimplemented;
9111 break;
9112 case CP0_REGISTER_09:
9113 switch (sel) {
9114 case CP0_REG09__COUNT:
9115 /* Mark as an IO operation because we read the time. */
9116 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9117 gen_io_start();
9119 gen_helper_mfc0_count(arg, cpu_env);
9121 * Break the TB to be able to take timer interrupts immediately
9122 * after reading count. DISAS_STOP isn't sufficient, we need to
9123 * ensure we break completely out of translated code.
9125 gen_save_pc(ctx->base.pc_next + 4);
9126 ctx->base.is_jmp = DISAS_EXIT;
9127 register_name = "Count";
9128 break;
9129 case CP0_REG09__SAARI:
9130 CP0_CHECK(ctx->saar);
9131 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
9132 register_name = "SAARI";
9133 break;
9134 case CP0_REG09__SAAR:
9135 CP0_CHECK(ctx->saar);
9136 gen_helper_dmfc0_saar(arg, cpu_env);
9137 register_name = "SAAR";
9138 break;
9139 default:
9140 goto cp0_unimplemented;
9142 break;
9143 case CP0_REGISTER_10:
9144 switch (sel) {
9145 case CP0_REG10__ENTRYHI:
9146 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
9147 register_name = "EntryHi";
9148 break;
9149 default:
9150 goto cp0_unimplemented;
9152 break;
9153 case CP0_REGISTER_11:
9154 switch (sel) {
9155 case CP0_REG11__COMPARE:
9156 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
9157 register_name = "Compare";
9158 break;
9159 /* 6,7 are implementation dependent */
9160 default:
9161 goto cp0_unimplemented;
9163 break;
9164 case CP0_REGISTER_12:
9165 switch (sel) {
9166 case CP0_REG12__STATUS:
9167 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
9168 register_name = "Status";
9169 break;
9170 case CP0_REG12__INTCTL:
9171 check_insn(ctx, ISA_MIPS_R2);
9172 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
9173 register_name = "IntCtl";
9174 break;
9175 case CP0_REG12__SRSCTL:
9176 check_insn(ctx, ISA_MIPS_R2);
9177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
9178 register_name = "SRSCtl";
9179 break;
9180 case CP0_REG12__SRSMAP:
9181 check_insn(ctx, ISA_MIPS_R2);
9182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9183 register_name = "SRSMap";
9184 break;
9185 default:
9186 goto cp0_unimplemented;
9188 break;
9189 case CP0_REGISTER_13:
9190 switch (sel) {
9191 case CP0_REG13__CAUSE:
9192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
9193 register_name = "Cause";
9194 break;
9195 default:
9196 goto cp0_unimplemented;
9198 break;
9199 case CP0_REGISTER_14:
9200 switch (sel) {
9201 case CP0_REG14__EPC:
9202 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9203 register_name = "EPC";
9204 break;
9205 default:
9206 goto cp0_unimplemented;
9208 break;
9209 case CP0_REGISTER_15:
9210 switch (sel) {
9211 case CP0_REG15__PRID:
9212 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
9213 register_name = "PRid";
9214 break;
9215 case CP0_REG15__EBASE:
9216 check_insn(ctx, ISA_MIPS_R2);
9217 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
9218 register_name = "EBase";
9219 break;
9220 case CP0_REG15__CMGCRBASE:
9221 check_insn(ctx, ISA_MIPS_R2);
9222 CP0_CHECK(ctx->cmgcr);
9223 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
9224 register_name = "CMGCRBase";
9225 break;
9226 default:
9227 goto cp0_unimplemented;
9229 break;
9230 case CP0_REGISTER_16:
9231 switch (sel) {
9232 case CP0_REG16__CONFIG:
9233 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9234 register_name = "Config";
9235 break;
9236 case CP0_REG16__CONFIG1:
9237 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9238 register_name = "Config1";
9239 break;
9240 case CP0_REG16__CONFIG2:
9241 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9242 register_name = "Config2";
9243 break;
9244 case CP0_REG16__CONFIG3:
9245 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9246 register_name = "Config3";
9247 break;
9248 case CP0_REG16__CONFIG4:
9249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
9250 register_name = "Config4";
9251 break;
9252 case CP0_REG16__CONFIG5:
9253 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
9254 register_name = "Config5";
9255 break;
9256 /* 6,7 are implementation dependent */
9257 case CP0_REG16__CONFIG6:
9258 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
9259 register_name = "Config6";
9260 break;
9261 case CP0_REG16__CONFIG7:
9262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
9263 register_name = "Config7";
9264 break;
9265 default:
9266 goto cp0_unimplemented;
9268 break;
9269 case CP0_REGISTER_17:
9270 switch (sel) {
9271 case CP0_REG17__LLADDR:
9272 gen_helper_dmfc0_lladdr(arg, cpu_env);
9273 register_name = "LLAddr";
9274 break;
9275 case CP0_REG17__MAAR:
9276 CP0_CHECK(ctx->mrp);
9277 gen_helper_dmfc0_maar(arg, cpu_env);
9278 register_name = "MAAR";
9279 break;
9280 case CP0_REG17__MAARI:
9281 CP0_CHECK(ctx->mrp);
9282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
9283 register_name = "MAARI";
9284 break;
9285 default:
9286 goto cp0_unimplemented;
9288 break;
9289 case CP0_REGISTER_18:
9290 switch (sel) {
9291 case CP0_REG18__WATCHLO0:
9292 case CP0_REG18__WATCHLO1:
9293 case CP0_REG18__WATCHLO2:
9294 case CP0_REG18__WATCHLO3:
9295 case CP0_REG18__WATCHLO4:
9296 case CP0_REG18__WATCHLO5:
9297 case CP0_REG18__WATCHLO6:
9298 case CP0_REG18__WATCHLO7:
9299 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9300 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
9301 register_name = "WatchLo";
9302 break;
9303 default:
9304 goto cp0_unimplemented;
9306 break;
9307 case CP0_REGISTER_19:
9308 switch (sel) {
9309 case CP0_REG19__WATCHHI0:
9310 case CP0_REG19__WATCHHI1:
9311 case CP0_REG19__WATCHHI2:
9312 case CP0_REG19__WATCHHI3:
9313 case CP0_REG19__WATCHHI4:
9314 case CP0_REG19__WATCHHI5:
9315 case CP0_REG19__WATCHHI6:
9316 case CP0_REG19__WATCHHI7:
9317 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9318 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9319 register_name = "WatchHi";
9320 break;
9321 default:
9322 goto cp0_unimplemented;
9324 break;
9325 case CP0_REGISTER_20:
9326 switch (sel) {
9327 case CP0_REG20__XCONTEXT:
9328 check_insn(ctx, ISA_MIPS3);
9329 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9330 register_name = "XContext";
9331 break;
9332 default:
9333 goto cp0_unimplemented;
9335 break;
9336 case CP0_REGISTER_21:
9337 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9338 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
9339 switch (sel) {
9340 case 0:
9341 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9342 register_name = "Framemask";
9343 break;
9344 default:
9345 goto cp0_unimplemented;
9347 break;
9348 case CP0_REGISTER_22:
9349 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9350 register_name = "'Diagnostic"; /* implementation dependent */
9351 break;
9352 case CP0_REGISTER_23:
9353 switch (sel) {
9354 case CP0_REG23__DEBUG:
9355 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9356 register_name = "Debug";
9357 break;
9358 case CP0_REG23__TRACECONTROL:
9359 /* PDtrace support */
9360 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9361 register_name = "TraceControl";
9362 goto cp0_unimplemented;
9363 case CP0_REG23__TRACECONTROL2:
9364 /* PDtrace support */
9365 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9366 register_name = "TraceControl2";
9367 goto cp0_unimplemented;
9368 case CP0_REG23__USERTRACEDATA1:
9369 /* PDtrace support */
9370 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9371 register_name = "UserTraceData1";
9372 goto cp0_unimplemented;
9373 case CP0_REG23__TRACEIBPC:
9374 /* PDtrace support */
9375 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9376 register_name = "TraceIBPC";
9377 goto cp0_unimplemented;
9378 case CP0_REG23__TRACEDBPC:
9379 /* PDtrace support */
9380 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9381 register_name = "TraceDBPC";
9382 goto cp0_unimplemented;
9383 default:
9384 goto cp0_unimplemented;
9386 break;
9387 case CP0_REGISTER_24:
9388 switch (sel) {
9389 case CP0_REG24__DEPC:
9390 /* EJTAG support */
9391 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9392 register_name = "DEPC";
9393 break;
9394 default:
9395 goto cp0_unimplemented;
9397 break;
9398 case CP0_REGISTER_25:
9399 switch (sel) {
9400 case CP0_REG25__PERFCTL0:
9401 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9402 register_name = "Performance0";
9403 break;
9404 case CP0_REG25__PERFCNT0:
9405 /* gen_helper_dmfc0_performance1(arg); */
9406 register_name = "Performance1";
9407 goto cp0_unimplemented;
9408 case CP0_REG25__PERFCTL1:
9409 /* gen_helper_dmfc0_performance2(arg); */
9410 register_name = "Performance2";
9411 goto cp0_unimplemented;
9412 case CP0_REG25__PERFCNT1:
9413 /* gen_helper_dmfc0_performance3(arg); */
9414 register_name = "Performance3";
9415 goto cp0_unimplemented;
9416 case CP0_REG25__PERFCTL2:
9417 /* gen_helper_dmfc0_performance4(arg); */
9418 register_name = "Performance4";
9419 goto cp0_unimplemented;
9420 case CP0_REG25__PERFCNT2:
9421 /* gen_helper_dmfc0_performance5(arg); */
9422 register_name = "Performance5";
9423 goto cp0_unimplemented;
9424 case CP0_REG25__PERFCTL3:
9425 /* gen_helper_dmfc0_performance6(arg); */
9426 register_name = "Performance6";
9427 goto cp0_unimplemented;
9428 case CP0_REG25__PERFCNT3:
9429 /* gen_helper_dmfc0_performance7(arg); */
9430 register_name = "Performance7";
9431 goto cp0_unimplemented;
9432 default:
9433 goto cp0_unimplemented;
9435 break;
9436 case CP0_REGISTER_26:
9437 switch (sel) {
9438 case CP0_REG26__ERRCTL:
9439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9440 register_name = "ErrCtl";
9441 break;
9442 default:
9443 goto cp0_unimplemented;
9445 break;
9446 case CP0_REGISTER_27:
9447 switch (sel) {
9448 /* ignored */
9449 case CP0_REG27__CACHERR:
9450 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9451 register_name = "CacheErr";
9452 break;
9453 default:
9454 goto cp0_unimplemented;
9456 break;
9457 case CP0_REGISTER_28:
9458 switch (sel) {
9459 case CP0_REG28__TAGLO:
9460 case CP0_REG28__TAGLO1:
9461 case CP0_REG28__TAGLO2:
9462 case CP0_REG28__TAGLO3:
9463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9464 register_name = "TagLo";
9465 break;
9466 case CP0_REG28__DATALO:
9467 case CP0_REG28__DATALO1:
9468 case CP0_REG28__DATALO2:
9469 case CP0_REG28__DATALO3:
9470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9471 register_name = "DataLo";
9472 break;
9473 default:
9474 goto cp0_unimplemented;
9476 break;
9477 case CP0_REGISTER_29:
9478 switch (sel) {
9479 case CP0_REG29__TAGHI:
9480 case CP0_REG29__TAGHI1:
9481 case CP0_REG29__TAGHI2:
9482 case CP0_REG29__TAGHI3:
9483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9484 register_name = "TagHi";
9485 break;
9486 case CP0_REG29__DATAHI:
9487 case CP0_REG29__DATAHI1:
9488 case CP0_REG29__DATAHI2:
9489 case CP0_REG29__DATAHI3:
9490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9491 register_name = "DataHi";
9492 break;
9493 default:
9494 goto cp0_unimplemented;
9496 break;
9497 case CP0_REGISTER_30:
9498 switch (sel) {
9499 case CP0_REG30__ERROREPC:
9500 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9501 register_name = "ErrorEPC";
9502 break;
9503 default:
9504 goto cp0_unimplemented;
9506 break;
9507 case CP0_REGISTER_31:
9508 switch (sel) {
9509 case CP0_REG31__DESAVE:
9510 /* EJTAG support */
9511 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9512 register_name = "DESAVE";
9513 break;
9514 case CP0_REG31__KSCRATCH1:
9515 case CP0_REG31__KSCRATCH2:
9516 case CP0_REG31__KSCRATCH3:
9517 case CP0_REG31__KSCRATCH4:
9518 case CP0_REG31__KSCRATCH5:
9519 case CP0_REG31__KSCRATCH6:
9520 CP0_CHECK(ctx->kscrexist & (1 << sel));
9521 tcg_gen_ld_tl(arg, cpu_env,
9522 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9523 register_name = "KScratch";
9524 break;
9525 default:
9526 goto cp0_unimplemented;
9528 break;
9529 default:
9530 goto cp0_unimplemented;
9532 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9533 return;
9535 cp0_unimplemented:
9536 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9537 register_name, reg, sel);
9538 gen_mfc0_unimplemented(ctx, arg);
9541 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9543 const char *register_name = "invalid";
9545 if (sel != 0) {
9546 check_insn(ctx, ISA_MIPS_R1);
9549 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9550 gen_io_start();
9553 switch (reg) {
9554 case CP0_REGISTER_00:
9555 switch (sel) {
9556 case CP0_REG00__INDEX:
9557 gen_helper_mtc0_index(cpu_env, arg);
9558 register_name = "Index";
9559 break;
9560 case CP0_REG00__MVPCONTROL:
9561 CP0_CHECK(ctx->insn_flags & ASE_MT);
9562 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9563 register_name = "MVPControl";
9564 break;
9565 case CP0_REG00__MVPCONF0:
9566 CP0_CHECK(ctx->insn_flags & ASE_MT);
9567 /* ignored */
9568 register_name = "MVPConf0";
9569 break;
9570 case CP0_REG00__MVPCONF1:
9571 CP0_CHECK(ctx->insn_flags & ASE_MT);
9572 /* ignored */
9573 register_name = "MVPConf1";
9574 break;
9575 case CP0_REG00__VPCONTROL:
9576 CP0_CHECK(ctx->vp);
9577 /* ignored */
9578 register_name = "VPControl";
9579 break;
9580 default:
9581 goto cp0_unimplemented;
9583 break;
9584 case CP0_REGISTER_01:
9585 switch (sel) {
9586 case CP0_REG01__RANDOM:
9587 /* ignored */
9588 register_name = "Random";
9589 break;
9590 case CP0_REG01__VPECONTROL:
9591 CP0_CHECK(ctx->insn_flags & ASE_MT);
9592 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9593 register_name = "VPEControl";
9594 break;
9595 case CP0_REG01__VPECONF0:
9596 CP0_CHECK(ctx->insn_flags & ASE_MT);
9597 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9598 register_name = "VPEConf0";
9599 break;
9600 case CP0_REG01__VPECONF1:
9601 CP0_CHECK(ctx->insn_flags & ASE_MT);
9602 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9603 register_name = "VPEConf1";
9604 break;
9605 case CP0_REG01__YQMASK:
9606 CP0_CHECK(ctx->insn_flags & ASE_MT);
9607 gen_helper_mtc0_yqmask(cpu_env, arg);
9608 register_name = "YQMask";
9609 break;
9610 case CP0_REG01__VPESCHEDULE:
9611 CP0_CHECK(ctx->insn_flags & ASE_MT);
9612 tcg_gen_st_tl(arg, cpu_env,
9613 offsetof(CPUMIPSState, CP0_VPESchedule));
9614 register_name = "VPESchedule";
9615 break;
9616 case CP0_REG01__VPESCHEFBACK:
9617 CP0_CHECK(ctx->insn_flags & ASE_MT);
9618 tcg_gen_st_tl(arg, cpu_env,
9619 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9620 register_name = "VPEScheFBack";
9621 break;
9622 case CP0_REG01__VPEOPT:
9623 CP0_CHECK(ctx->insn_flags & ASE_MT);
9624 gen_helper_mtc0_vpeopt(cpu_env, arg);
9625 register_name = "VPEOpt";
9626 break;
9627 default:
9628 goto cp0_unimplemented;
9630 break;
9631 case CP0_REGISTER_02:
9632 switch (sel) {
9633 case CP0_REG02__ENTRYLO0:
9634 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9635 register_name = "EntryLo0";
9636 break;
9637 case CP0_REG02__TCSTATUS:
9638 CP0_CHECK(ctx->insn_flags & ASE_MT);
9639 gen_helper_mtc0_tcstatus(cpu_env, arg);
9640 register_name = "TCStatus";
9641 break;
9642 case CP0_REG02__TCBIND:
9643 CP0_CHECK(ctx->insn_flags & ASE_MT);
9644 gen_helper_mtc0_tcbind(cpu_env, arg);
9645 register_name = "TCBind";
9646 break;
9647 case CP0_REG02__TCRESTART:
9648 CP0_CHECK(ctx->insn_flags & ASE_MT);
9649 gen_helper_mtc0_tcrestart(cpu_env, arg);
9650 register_name = "TCRestart";
9651 break;
9652 case CP0_REG02__TCHALT:
9653 CP0_CHECK(ctx->insn_flags & ASE_MT);
9654 gen_helper_mtc0_tchalt(cpu_env, arg);
9655 register_name = "TCHalt";
9656 break;
9657 case CP0_REG02__TCCONTEXT:
9658 CP0_CHECK(ctx->insn_flags & ASE_MT);
9659 gen_helper_mtc0_tccontext(cpu_env, arg);
9660 register_name = "TCContext";
9661 break;
9662 case CP0_REG02__TCSCHEDULE:
9663 CP0_CHECK(ctx->insn_flags & ASE_MT);
9664 gen_helper_mtc0_tcschedule(cpu_env, arg);
9665 register_name = "TCSchedule";
9666 break;
9667 case CP0_REG02__TCSCHEFBACK:
9668 CP0_CHECK(ctx->insn_flags & ASE_MT);
9669 gen_helper_mtc0_tcschefback(cpu_env, arg);
9670 register_name = "TCScheFBack";
9671 break;
9672 default:
9673 goto cp0_unimplemented;
9675 break;
9676 case CP0_REGISTER_03:
9677 switch (sel) {
9678 case CP0_REG03__ENTRYLO1:
9679 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9680 register_name = "EntryLo1";
9681 break;
9682 case CP0_REG03__GLOBALNUM:
9683 CP0_CHECK(ctx->vp);
9684 /* ignored */
9685 register_name = "GlobalNumber";
9686 break;
9687 default:
9688 goto cp0_unimplemented;
9690 break;
9691 case CP0_REGISTER_04:
9692 switch (sel) {
9693 case CP0_REG04__CONTEXT:
9694 gen_helper_mtc0_context(cpu_env, arg);
9695 register_name = "Context";
9696 break;
9697 case CP0_REG04__CONTEXTCONFIG:
9698 /* SmartMIPS ASE */
9699 /* gen_helper_dmtc0_contextconfig(arg); */
9700 register_name = "ContextConfig";
9701 goto cp0_unimplemented;
9702 case CP0_REG04__USERLOCAL:
9703 CP0_CHECK(ctx->ulri);
9704 tcg_gen_st_tl(arg, cpu_env,
9705 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9706 register_name = "UserLocal";
9707 break;
9708 case CP0_REG04__MMID:
9709 CP0_CHECK(ctx->mi);
9710 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9711 register_name = "MMID";
9712 break;
9713 default:
9714 goto cp0_unimplemented;
9716 break;
9717 case CP0_REGISTER_05:
9718 switch (sel) {
9719 case CP0_REG05__PAGEMASK:
9720 gen_helper_mtc0_pagemask(cpu_env, arg);
9721 register_name = "PageMask";
9722 break;
9723 case CP0_REG05__PAGEGRAIN:
9724 check_insn(ctx, ISA_MIPS_R2);
9725 gen_helper_mtc0_pagegrain(cpu_env, arg);
9726 register_name = "PageGrain";
9727 break;
9728 case CP0_REG05__SEGCTL0:
9729 CP0_CHECK(ctx->sc);
9730 gen_helper_mtc0_segctl0(cpu_env, arg);
9731 register_name = "SegCtl0";
9732 break;
9733 case CP0_REG05__SEGCTL1:
9734 CP0_CHECK(ctx->sc);
9735 gen_helper_mtc0_segctl1(cpu_env, arg);
9736 register_name = "SegCtl1";
9737 break;
9738 case CP0_REG05__SEGCTL2:
9739 CP0_CHECK(ctx->sc);
9740 gen_helper_mtc0_segctl2(cpu_env, arg);
9741 register_name = "SegCtl2";
9742 break;
9743 case CP0_REG05__PWBASE:
9744 check_pw(ctx);
9745 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9746 register_name = "PWBase";
9747 break;
9748 case CP0_REG05__PWFIELD:
9749 check_pw(ctx);
9750 gen_helper_mtc0_pwfield(cpu_env, arg);
9751 register_name = "PWField";
9752 break;
9753 case CP0_REG05__PWSIZE:
9754 check_pw(ctx);
9755 gen_helper_mtc0_pwsize(cpu_env, arg);
9756 register_name = "PWSize";
9757 break;
9758 default:
9759 goto cp0_unimplemented;
9761 break;
9762 case CP0_REGISTER_06:
9763 switch (sel) {
9764 case CP0_REG06__WIRED:
9765 gen_helper_mtc0_wired(cpu_env, arg);
9766 register_name = "Wired";
9767 break;
9768 case CP0_REG06__SRSCONF0:
9769 check_insn(ctx, ISA_MIPS_R2);
9770 gen_helper_mtc0_srsconf0(cpu_env, arg);
9771 register_name = "SRSConf0";
9772 break;
9773 case CP0_REG06__SRSCONF1:
9774 check_insn(ctx, ISA_MIPS_R2);
9775 gen_helper_mtc0_srsconf1(cpu_env, arg);
9776 register_name = "SRSConf1";
9777 break;
9778 case CP0_REG06__SRSCONF2:
9779 check_insn(ctx, ISA_MIPS_R2);
9780 gen_helper_mtc0_srsconf2(cpu_env, arg);
9781 register_name = "SRSConf2";
9782 break;
9783 case CP0_REG06__SRSCONF3:
9784 check_insn(ctx, ISA_MIPS_R2);
9785 gen_helper_mtc0_srsconf3(cpu_env, arg);
9786 register_name = "SRSConf3";
9787 break;
9788 case CP0_REG06__SRSCONF4:
9789 check_insn(ctx, ISA_MIPS_R2);
9790 gen_helper_mtc0_srsconf4(cpu_env, arg);
9791 register_name = "SRSConf4";
9792 break;
9793 case CP0_REG06__PWCTL:
9794 check_pw(ctx);
9795 gen_helper_mtc0_pwctl(cpu_env, arg);
9796 register_name = "PWCtl";
9797 break;
9798 default:
9799 goto cp0_unimplemented;
9801 break;
9802 case CP0_REGISTER_07:
9803 switch (sel) {
9804 case CP0_REG07__HWRENA:
9805 check_insn(ctx, ISA_MIPS_R2);
9806 gen_helper_mtc0_hwrena(cpu_env, arg);
9807 ctx->base.is_jmp = DISAS_STOP;
9808 register_name = "HWREna";
9809 break;
9810 default:
9811 goto cp0_unimplemented;
9813 break;
9814 case CP0_REGISTER_08:
9815 switch (sel) {
9816 case CP0_REG08__BADVADDR:
9817 /* ignored */
9818 register_name = "BadVAddr";
9819 break;
9820 case CP0_REG08__BADINSTR:
9821 /* ignored */
9822 register_name = "BadInstr";
9823 break;
9824 case CP0_REG08__BADINSTRP:
9825 /* ignored */
9826 register_name = "BadInstrP";
9827 break;
9828 case CP0_REG08__BADINSTRX:
9829 /* ignored */
9830 register_name = "BadInstrX";
9831 break;
9832 default:
9833 goto cp0_unimplemented;
9835 break;
9836 case CP0_REGISTER_09:
9837 switch (sel) {
9838 case CP0_REG09__COUNT:
9839 gen_helper_mtc0_count(cpu_env, arg);
9840 register_name = "Count";
9841 break;
9842 case CP0_REG09__SAARI:
9843 CP0_CHECK(ctx->saar);
9844 gen_helper_mtc0_saari(cpu_env, arg);
9845 register_name = "SAARI";
9846 break;
9847 case CP0_REG09__SAAR:
9848 CP0_CHECK(ctx->saar);
9849 gen_helper_mtc0_saar(cpu_env, arg);
9850 register_name = "SAAR";
9851 break;
9852 default:
9853 goto cp0_unimplemented;
9855 /* Stop translation as we may have switched the execution mode */
9856 ctx->base.is_jmp = DISAS_STOP;
9857 break;
9858 case CP0_REGISTER_10:
9859 switch (sel) {
9860 case CP0_REG10__ENTRYHI:
9861 gen_helper_mtc0_entryhi(cpu_env, arg);
9862 register_name = "EntryHi";
9863 break;
9864 default:
9865 goto cp0_unimplemented;
9867 break;
9868 case CP0_REGISTER_11:
9869 switch (sel) {
9870 case CP0_REG11__COMPARE:
9871 gen_helper_mtc0_compare(cpu_env, arg);
9872 register_name = "Compare";
9873 break;
9874 /* 6,7 are implementation dependent */
9875 default:
9876 goto cp0_unimplemented;
9878 /* Stop translation as we may have switched the execution mode */
9879 ctx->base.is_jmp = DISAS_STOP;
9880 break;
9881 case CP0_REGISTER_12:
9882 switch (sel) {
9883 case CP0_REG12__STATUS:
9884 save_cpu_state(ctx, 1);
9885 gen_helper_mtc0_status(cpu_env, arg);
9886 /* DISAS_STOP isn't good enough here, hflags may have changed. */
9887 gen_save_pc(ctx->base.pc_next + 4);
9888 ctx->base.is_jmp = DISAS_EXIT;
9889 register_name = "Status";
9890 break;
9891 case CP0_REG12__INTCTL:
9892 check_insn(ctx, ISA_MIPS_R2);
9893 gen_helper_mtc0_intctl(cpu_env, arg);
9894 /* Stop translation as we may have switched the execution mode */
9895 ctx->base.is_jmp = DISAS_STOP;
9896 register_name = "IntCtl";
9897 break;
9898 case CP0_REG12__SRSCTL:
9899 check_insn(ctx, ISA_MIPS_R2);
9900 gen_helper_mtc0_srsctl(cpu_env, arg);
9901 /* Stop translation as we may have switched the execution mode */
9902 ctx->base.is_jmp = DISAS_STOP;
9903 register_name = "SRSCtl";
9904 break;
9905 case CP0_REG12__SRSMAP:
9906 check_insn(ctx, ISA_MIPS_R2);
9907 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9908 /* Stop translation as we may have switched the execution mode */
9909 ctx->base.is_jmp = DISAS_STOP;
9910 register_name = "SRSMap";
9911 break;
9912 default:
9913 goto cp0_unimplemented;
9915 break;
9916 case CP0_REGISTER_13:
9917 switch (sel) {
9918 case CP0_REG13__CAUSE:
9919 save_cpu_state(ctx, 1);
9920 gen_helper_mtc0_cause(cpu_env, arg);
9922 * Stop translation as we may have triggered an interrupt.
9923 * DISAS_STOP isn't sufficient, we need to ensure we break out of
9924 * translated code to check for pending interrupts.
9926 gen_save_pc(ctx->base.pc_next + 4);
9927 ctx->base.is_jmp = DISAS_EXIT;
9928 register_name = "Cause";
9929 break;
9930 default:
9931 goto cp0_unimplemented;
9933 break;
9934 case CP0_REGISTER_14:
9935 switch (sel) {
9936 case CP0_REG14__EPC:
9937 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9938 register_name = "EPC";
9939 break;
9940 default:
9941 goto cp0_unimplemented;
9943 break;
9944 case CP0_REGISTER_15:
9945 switch (sel) {
9946 case CP0_REG15__PRID:
9947 /* ignored */
9948 register_name = "PRid";
9949 break;
9950 case CP0_REG15__EBASE:
9951 check_insn(ctx, ISA_MIPS_R2);
9952 gen_helper_mtc0_ebase(cpu_env, arg);
9953 register_name = "EBase";
9954 break;
9955 default:
9956 goto cp0_unimplemented;
9958 break;
9959 case CP0_REGISTER_16:
9960 switch (sel) {
9961 case CP0_REG16__CONFIG:
9962 gen_helper_mtc0_config0(cpu_env, arg);
9963 register_name = "Config";
9964 /* Stop translation as we may have switched the execution mode */
9965 ctx->base.is_jmp = DISAS_STOP;
9966 break;
9967 case CP0_REG16__CONFIG1:
9968 /* ignored, read only */
9969 register_name = "Config1";
9970 break;
9971 case CP0_REG16__CONFIG2:
9972 gen_helper_mtc0_config2(cpu_env, arg);
9973 register_name = "Config2";
9974 /* Stop translation as we may have switched the execution mode */
9975 ctx->base.is_jmp = DISAS_STOP;
9976 break;
9977 case CP0_REG16__CONFIG3:
9978 gen_helper_mtc0_config3(cpu_env, arg);
9979 register_name = "Config3";
9980 /* Stop translation as we may have switched the execution mode */
9981 ctx->base.is_jmp = DISAS_STOP;
9982 break;
9983 case CP0_REG16__CONFIG4:
9984 /* currently ignored */
9985 register_name = "Config4";
9986 break;
9987 case CP0_REG16__CONFIG5:
9988 gen_helper_mtc0_config5(cpu_env, arg);
9989 register_name = "Config5";
9990 /* Stop translation as we may have switched the execution mode */
9991 ctx->base.is_jmp = DISAS_STOP;
9992 break;
9993 /* 6,7 are implementation dependent */
9994 default:
9995 register_name = "Invalid config selector";
9996 goto cp0_unimplemented;
9998 break;
9999 case CP0_REGISTER_17:
10000 switch (sel) {
10001 case CP0_REG17__LLADDR:
10002 gen_helper_mtc0_lladdr(cpu_env, arg);
10003 register_name = "LLAddr";
10004 break;
10005 case CP0_REG17__MAAR:
10006 CP0_CHECK(ctx->mrp);
10007 gen_helper_mtc0_maar(cpu_env, arg);
10008 register_name = "MAAR";
10009 break;
10010 case CP0_REG17__MAARI:
10011 CP0_CHECK(ctx->mrp);
10012 gen_helper_mtc0_maari(cpu_env, arg);
10013 register_name = "MAARI";
10014 break;
10015 default:
10016 goto cp0_unimplemented;
10018 break;
10019 case CP0_REGISTER_18:
10020 switch (sel) {
10021 case CP0_REG18__WATCHLO0:
10022 case CP0_REG18__WATCHLO1:
10023 case CP0_REG18__WATCHLO2:
10024 case CP0_REG18__WATCHLO3:
10025 case CP0_REG18__WATCHLO4:
10026 case CP0_REG18__WATCHLO5:
10027 case CP0_REG18__WATCHLO6:
10028 case CP0_REG18__WATCHLO7:
10029 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10030 gen_helper_0e1i(mtc0_watchlo, arg, sel);
10031 register_name = "WatchLo";
10032 break;
10033 default:
10034 goto cp0_unimplemented;
10036 break;
10037 case CP0_REGISTER_19:
10038 switch (sel) {
10039 case CP0_REG19__WATCHHI0:
10040 case CP0_REG19__WATCHHI1:
10041 case CP0_REG19__WATCHHI2:
10042 case CP0_REG19__WATCHHI3:
10043 case CP0_REG19__WATCHHI4:
10044 case CP0_REG19__WATCHHI5:
10045 case CP0_REG19__WATCHHI6:
10046 case CP0_REG19__WATCHHI7:
10047 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10048 gen_helper_0e1i(mtc0_watchhi, arg, sel);
10049 register_name = "WatchHi";
10050 break;
10051 default:
10052 goto cp0_unimplemented;
10054 break;
10055 case CP0_REGISTER_20:
10056 switch (sel) {
10057 case CP0_REG20__XCONTEXT:
10058 check_insn(ctx, ISA_MIPS3);
10059 gen_helper_mtc0_xcontext(cpu_env, arg);
10060 register_name = "XContext";
10061 break;
10062 default:
10063 goto cp0_unimplemented;
10065 break;
10066 case CP0_REGISTER_21:
10067 /* Officially reserved, but sel 0 is used for R1x000 framemask */
10068 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
10069 switch (sel) {
10070 case 0:
10071 gen_helper_mtc0_framemask(cpu_env, arg);
10072 register_name = "Framemask";
10073 break;
10074 default:
10075 goto cp0_unimplemented;
10077 break;
10078 case CP0_REGISTER_22:
10079 /* ignored */
10080 register_name = "Diagnostic"; /* implementation dependent */
10081 break;
10082 case CP0_REGISTER_23:
10083 switch (sel) {
10084 case CP0_REG23__DEBUG:
10085 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
10086 /* DISAS_STOP isn't good enough here, hflags may have changed. */
10087 gen_save_pc(ctx->base.pc_next + 4);
10088 ctx->base.is_jmp = DISAS_EXIT;
10089 register_name = "Debug";
10090 break;
10091 case CP0_REG23__TRACECONTROL:
10092 /* PDtrace support */
10093 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
10094 /* Stop translation as we may have switched the execution mode */
10095 ctx->base.is_jmp = DISAS_STOP;
10096 register_name = "TraceControl";
10097 goto cp0_unimplemented;
10098 case CP0_REG23__TRACECONTROL2:
10099 /* PDtrace support */
10100 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
10101 /* Stop translation as we may have switched the execution mode */
10102 ctx->base.is_jmp = DISAS_STOP;
10103 register_name = "TraceControl2";
10104 goto cp0_unimplemented;
10105 case CP0_REG23__USERTRACEDATA1:
10106 /* PDtrace support */
10107 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
10108 /* Stop translation as we may have switched the execution mode */
10109 ctx->base.is_jmp = DISAS_STOP;
10110 register_name = "UserTraceData1";
10111 goto cp0_unimplemented;
10112 case CP0_REG23__TRACEIBPC:
10113 /* PDtrace support */
10114 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
10115 /* Stop translation as we may have switched the execution mode */
10116 ctx->base.is_jmp = DISAS_STOP;
10117 register_name = "TraceIBPC";
10118 goto cp0_unimplemented;
10119 case CP0_REG23__TRACEDBPC:
10120 /* PDtrace support */
10121 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
10122 /* Stop translation as we may have switched the execution mode */
10123 ctx->base.is_jmp = DISAS_STOP;
10124 register_name = "TraceDBPC";
10125 goto cp0_unimplemented;
10126 default:
10127 goto cp0_unimplemented;
10129 break;
10130 case CP0_REGISTER_24:
10131 switch (sel) {
10132 case CP0_REG24__DEPC:
10133 /* EJTAG support */
10134 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
10135 register_name = "DEPC";
10136 break;
10137 default:
10138 goto cp0_unimplemented;
10140 break;
10141 case CP0_REGISTER_25:
10142 switch (sel) {
10143 case CP0_REG25__PERFCTL0:
10144 gen_helper_mtc0_performance0(cpu_env, arg);
10145 register_name = "Performance0";
10146 break;
10147 case CP0_REG25__PERFCNT0:
10148 /* gen_helper_mtc0_performance1(cpu_env, arg); */
10149 register_name = "Performance1";
10150 goto cp0_unimplemented;
10151 case CP0_REG25__PERFCTL1:
10152 /* gen_helper_mtc0_performance2(cpu_env, arg); */
10153 register_name = "Performance2";
10154 goto cp0_unimplemented;
10155 case CP0_REG25__PERFCNT1:
10156 /* gen_helper_mtc0_performance3(cpu_env, arg); */
10157 register_name = "Performance3";
10158 goto cp0_unimplemented;
10159 case CP0_REG25__PERFCTL2:
10160 /* gen_helper_mtc0_performance4(cpu_env, arg); */
10161 register_name = "Performance4";
10162 goto cp0_unimplemented;
10163 case CP0_REG25__PERFCNT2:
10164 /* gen_helper_mtc0_performance5(cpu_env, arg); */
10165 register_name = "Performance5";
10166 goto cp0_unimplemented;
10167 case CP0_REG25__PERFCTL3:
10168 /* gen_helper_mtc0_performance6(cpu_env, arg); */
10169 register_name = "Performance6";
10170 goto cp0_unimplemented;
10171 case CP0_REG25__PERFCNT3:
10172 /* gen_helper_mtc0_performance7(cpu_env, arg); */
10173 register_name = "Performance7";
10174 goto cp0_unimplemented;
10175 default:
10176 goto cp0_unimplemented;
10178 break;
10179 case CP0_REGISTER_26:
10180 switch (sel) {
10181 case CP0_REG26__ERRCTL:
10182 gen_helper_mtc0_errctl(cpu_env, arg);
10183 ctx->base.is_jmp = DISAS_STOP;
10184 register_name = "ErrCtl";
10185 break;
10186 default:
10187 goto cp0_unimplemented;
10189 break;
10190 case CP0_REGISTER_27:
10191 switch (sel) {
10192 case CP0_REG27__CACHERR:
10193 /* ignored */
10194 register_name = "CacheErr";
10195 break;
10196 default:
10197 goto cp0_unimplemented;
10199 break;
10200 case CP0_REGISTER_28:
10201 switch (sel) {
10202 case CP0_REG28__TAGLO:
10203 case CP0_REG28__TAGLO1:
10204 case CP0_REG28__TAGLO2:
10205 case CP0_REG28__TAGLO3:
10206 gen_helper_mtc0_taglo(cpu_env, arg);
10207 register_name = "TagLo";
10208 break;
10209 case CP0_REG28__DATALO:
10210 case CP0_REG28__DATALO1:
10211 case CP0_REG28__DATALO2:
10212 case CP0_REG28__DATALO3:
10213 gen_helper_mtc0_datalo(cpu_env, arg);
10214 register_name = "DataLo";
10215 break;
10216 default:
10217 goto cp0_unimplemented;
10219 break;
10220 case CP0_REGISTER_29:
10221 switch (sel) {
10222 case CP0_REG29__TAGHI:
10223 case CP0_REG29__TAGHI1:
10224 case CP0_REG29__TAGHI2:
10225 case CP0_REG29__TAGHI3:
10226 gen_helper_mtc0_taghi(cpu_env, arg);
10227 register_name = "TagHi";
10228 break;
10229 case CP0_REG29__DATAHI:
10230 case CP0_REG29__DATAHI1:
10231 case CP0_REG29__DATAHI2:
10232 case CP0_REG29__DATAHI3:
10233 gen_helper_mtc0_datahi(cpu_env, arg);
10234 register_name = "DataHi";
10235 break;
10236 default:
10237 register_name = "invalid sel";
10238 goto cp0_unimplemented;
10240 break;
10241 case CP0_REGISTER_30:
10242 switch (sel) {
10243 case CP0_REG30__ERROREPC:
10244 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
10245 register_name = "ErrorEPC";
10246 break;
10247 default:
10248 goto cp0_unimplemented;
10250 break;
10251 case CP0_REGISTER_31:
10252 switch (sel) {
10253 case CP0_REG31__DESAVE:
10254 /* EJTAG support */
10255 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
10256 register_name = "DESAVE";
10257 break;
10258 case CP0_REG31__KSCRATCH1:
10259 case CP0_REG31__KSCRATCH2:
10260 case CP0_REG31__KSCRATCH3:
10261 case CP0_REG31__KSCRATCH4:
10262 case CP0_REG31__KSCRATCH5:
10263 case CP0_REG31__KSCRATCH6:
10264 CP0_CHECK(ctx->kscrexist & (1 << sel));
10265 tcg_gen_st_tl(arg, cpu_env,
10266 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
10267 register_name = "KScratch";
10268 break;
10269 default:
10270 goto cp0_unimplemented;
10272 break;
10273 default:
10274 goto cp0_unimplemented;
10276 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
10278 /* For simplicity assume that all writes can cause interrupts. */
10279 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
10281 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10282 * translated code to check for pending interrupts.
10284 gen_save_pc(ctx->base.pc_next + 4);
10285 ctx->base.is_jmp = DISAS_EXIT;
10287 return;
10289 cp0_unimplemented:
10290 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10291 register_name, reg, sel);
10293 #endif /* TARGET_MIPS64 */
10295 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
10296 int u, int sel, int h)
10298 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10299 TCGv t0 = tcg_temp_local_new();
10301 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10302 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10303 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10304 tcg_gen_movi_tl(t0, -1);
10305 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10306 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10307 tcg_gen_movi_tl(t0, -1);
10308 } else if (u == 0) {
10309 switch (rt) {
10310 case 1:
10311 switch (sel) {
10312 case 1:
10313 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10314 break;
10315 case 2:
10316 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10317 break;
10318 default:
10319 goto die;
10320 break;
10322 break;
10323 case 2:
10324 switch (sel) {
10325 case 1:
10326 gen_helper_mftc0_tcstatus(t0, cpu_env);
10327 break;
10328 case 2:
10329 gen_helper_mftc0_tcbind(t0, cpu_env);
10330 break;
10331 case 3:
10332 gen_helper_mftc0_tcrestart(t0, cpu_env);
10333 break;
10334 case 4:
10335 gen_helper_mftc0_tchalt(t0, cpu_env);
10336 break;
10337 case 5:
10338 gen_helper_mftc0_tccontext(t0, cpu_env);
10339 break;
10340 case 6:
10341 gen_helper_mftc0_tcschedule(t0, cpu_env);
10342 break;
10343 case 7:
10344 gen_helper_mftc0_tcschefback(t0, cpu_env);
10345 break;
10346 default:
10347 gen_mfc0(ctx, t0, rt, sel);
10348 break;
10350 break;
10351 case 10:
10352 switch (sel) {
10353 case 0:
10354 gen_helper_mftc0_entryhi(t0, cpu_env);
10355 break;
10356 default:
10357 gen_mfc0(ctx, t0, rt, sel);
10358 break;
10360 break;
10361 case 12:
10362 switch (sel) {
10363 case 0:
10364 gen_helper_mftc0_status(t0, cpu_env);
10365 break;
10366 default:
10367 gen_mfc0(ctx, t0, rt, sel);
10368 break;
10370 break;
10371 case 13:
10372 switch (sel) {
10373 case 0:
10374 gen_helper_mftc0_cause(t0, cpu_env);
10375 break;
10376 default:
10377 goto die;
10378 break;
10380 break;
10381 case 14:
10382 switch (sel) {
10383 case 0:
10384 gen_helper_mftc0_epc(t0, cpu_env);
10385 break;
10386 default:
10387 goto die;
10388 break;
10390 break;
10391 case 15:
10392 switch (sel) {
10393 case 1:
10394 gen_helper_mftc0_ebase(t0, cpu_env);
10395 break;
10396 default:
10397 goto die;
10398 break;
10400 break;
10401 case 16:
10402 switch (sel) {
10403 case 0:
10404 case 1:
10405 case 2:
10406 case 3:
10407 case 4:
10408 case 5:
10409 case 6:
10410 case 7:
10411 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10412 break;
10413 default:
10414 goto die;
10415 break;
10417 break;
10418 case 23:
10419 switch (sel) {
10420 case 0:
10421 gen_helper_mftc0_debug(t0, cpu_env);
10422 break;
10423 default:
10424 gen_mfc0(ctx, t0, rt, sel);
10425 break;
10427 break;
10428 default:
10429 gen_mfc0(ctx, t0, rt, sel);
10431 } else {
10432 switch (sel) {
10433 /* GPR registers. */
10434 case 0:
10435 gen_helper_1e0i(mftgpr, t0, rt);
10436 break;
10437 /* Auxiliary CPU registers */
10438 case 1:
10439 switch (rt) {
10440 case 0:
10441 gen_helper_1e0i(mftlo, t0, 0);
10442 break;
10443 case 1:
10444 gen_helper_1e0i(mfthi, t0, 0);
10445 break;
10446 case 2:
10447 gen_helper_1e0i(mftacx, t0, 0);
10448 break;
10449 case 4:
10450 gen_helper_1e0i(mftlo, t0, 1);
10451 break;
10452 case 5:
10453 gen_helper_1e0i(mfthi, t0, 1);
10454 break;
10455 case 6:
10456 gen_helper_1e0i(mftacx, t0, 1);
10457 break;
10458 case 8:
10459 gen_helper_1e0i(mftlo, t0, 2);
10460 break;
10461 case 9:
10462 gen_helper_1e0i(mfthi, t0, 2);
10463 break;
10464 case 10:
10465 gen_helper_1e0i(mftacx, t0, 2);
10466 break;
10467 case 12:
10468 gen_helper_1e0i(mftlo, t0, 3);
10469 break;
10470 case 13:
10471 gen_helper_1e0i(mfthi, t0, 3);
10472 break;
10473 case 14:
10474 gen_helper_1e0i(mftacx, t0, 3);
10475 break;
10476 case 16:
10477 gen_helper_mftdsp(t0, cpu_env);
10478 break;
10479 default:
10480 goto die;
10482 break;
10483 /* Floating point (COP1). */
10484 case 2:
10485 /* XXX: For now we support only a single FPU context. */
10486 if (h == 0) {
10487 TCGv_i32 fp0 = tcg_temp_new_i32();
10489 gen_load_fpr32(ctx, fp0, rt);
10490 tcg_gen_ext_i32_tl(t0, fp0);
10491 tcg_temp_free_i32(fp0);
10492 } else {
10493 TCGv_i32 fp0 = tcg_temp_new_i32();
10495 gen_load_fpr32h(ctx, fp0, rt);
10496 tcg_gen_ext_i32_tl(t0, fp0);
10497 tcg_temp_free_i32(fp0);
10499 break;
10500 case 3:
10501 /* XXX: For now we support only a single FPU context. */
10502 gen_helper_1e0i(cfc1, t0, rt);
10503 break;
10504 /* COP2: Not implemented. */
10505 case 4:
10506 case 5:
10507 /* fall through */
10508 default:
10509 goto die;
10512 trace_mips_translate_tr("mftr", rt, u, sel, h);
10513 gen_store_gpr(t0, rd);
10514 tcg_temp_free(t0);
10515 return;
10517 die:
10518 tcg_temp_free(t0);
10519 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10520 gen_reserved_instruction(ctx);
10523 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10524 int u, int sel, int h)
10526 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10527 TCGv t0 = tcg_temp_local_new();
10529 gen_load_gpr(t0, rt);
10530 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10531 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10532 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10533 /* NOP */
10535 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10536 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10537 /* NOP */
10539 } else if (u == 0) {
10540 switch (rd) {
10541 case 1:
10542 switch (sel) {
10543 case 1:
10544 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10545 break;
10546 case 2:
10547 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10548 break;
10549 default:
10550 goto die;
10551 break;
10553 break;
10554 case 2:
10555 switch (sel) {
10556 case 1:
10557 gen_helper_mttc0_tcstatus(cpu_env, t0);
10558 break;
10559 case 2:
10560 gen_helper_mttc0_tcbind(cpu_env, t0);
10561 break;
10562 case 3:
10563 gen_helper_mttc0_tcrestart(cpu_env, t0);
10564 break;
10565 case 4:
10566 gen_helper_mttc0_tchalt(cpu_env, t0);
10567 break;
10568 case 5:
10569 gen_helper_mttc0_tccontext(cpu_env, t0);
10570 break;
10571 case 6:
10572 gen_helper_mttc0_tcschedule(cpu_env, t0);
10573 break;
10574 case 7:
10575 gen_helper_mttc0_tcschefback(cpu_env, t0);
10576 break;
10577 default:
10578 gen_mtc0(ctx, t0, rd, sel);
10579 break;
10581 break;
10582 case 10:
10583 switch (sel) {
10584 case 0:
10585 gen_helper_mttc0_entryhi(cpu_env, t0);
10586 break;
10587 default:
10588 gen_mtc0(ctx, t0, rd, sel);
10589 break;
10591 break;
10592 case 12:
10593 switch (sel) {
10594 case 0:
10595 gen_helper_mttc0_status(cpu_env, t0);
10596 break;
10597 default:
10598 gen_mtc0(ctx, t0, rd, sel);
10599 break;
10601 break;
10602 case 13:
10603 switch (sel) {
10604 case 0:
10605 gen_helper_mttc0_cause(cpu_env, t0);
10606 break;
10607 default:
10608 goto die;
10609 break;
10611 break;
10612 case 15:
10613 switch (sel) {
10614 case 1:
10615 gen_helper_mttc0_ebase(cpu_env, t0);
10616 break;
10617 default:
10618 goto die;
10619 break;
10621 break;
10622 case 23:
10623 switch (sel) {
10624 case 0:
10625 gen_helper_mttc0_debug(cpu_env, t0);
10626 break;
10627 default:
10628 gen_mtc0(ctx, t0, rd, sel);
10629 break;
10631 break;
10632 default:
10633 gen_mtc0(ctx, t0, rd, sel);
10635 } else {
10636 switch (sel) {
10637 /* GPR registers. */
10638 case 0:
10639 gen_helper_0e1i(mttgpr, t0, rd);
10640 break;
10641 /* Auxiliary CPU registers */
10642 case 1:
10643 switch (rd) {
10644 case 0:
10645 gen_helper_0e1i(mttlo, t0, 0);
10646 break;
10647 case 1:
10648 gen_helper_0e1i(mtthi, t0, 0);
10649 break;
10650 case 2:
10651 gen_helper_0e1i(mttacx, t0, 0);
10652 break;
10653 case 4:
10654 gen_helper_0e1i(mttlo, t0, 1);
10655 break;
10656 case 5:
10657 gen_helper_0e1i(mtthi, t0, 1);
10658 break;
10659 case 6:
10660 gen_helper_0e1i(mttacx, t0, 1);
10661 break;
10662 case 8:
10663 gen_helper_0e1i(mttlo, t0, 2);
10664 break;
10665 case 9:
10666 gen_helper_0e1i(mtthi, t0, 2);
10667 break;
10668 case 10:
10669 gen_helper_0e1i(mttacx, t0, 2);
10670 break;
10671 case 12:
10672 gen_helper_0e1i(mttlo, t0, 3);
10673 break;
10674 case 13:
10675 gen_helper_0e1i(mtthi, t0, 3);
10676 break;
10677 case 14:
10678 gen_helper_0e1i(mttacx, t0, 3);
10679 break;
10680 case 16:
10681 gen_helper_mttdsp(cpu_env, t0);
10682 break;
10683 default:
10684 goto die;
10686 break;
10687 /* Floating point (COP1). */
10688 case 2:
10689 /* XXX: For now we support only a single FPU context. */
10690 if (h == 0) {
10691 TCGv_i32 fp0 = tcg_temp_new_i32();
10693 tcg_gen_trunc_tl_i32(fp0, t0);
10694 gen_store_fpr32(ctx, fp0, rd);
10695 tcg_temp_free_i32(fp0);
10696 } else {
10697 TCGv_i32 fp0 = tcg_temp_new_i32();
10699 tcg_gen_trunc_tl_i32(fp0, t0);
10700 gen_store_fpr32h(ctx, fp0, rd);
10701 tcg_temp_free_i32(fp0);
10703 break;
10704 case 3:
10705 /* XXX: For now we support only a single FPU context. */
10707 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10709 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10710 tcg_temp_free_i32(fs_tmp);
10712 /* Stop translation as we may have changed hflags */
10713 ctx->base.is_jmp = DISAS_STOP;
10714 break;
10715 /* COP2: Not implemented. */
10716 case 4:
10717 case 5:
10718 /* fall through */
10719 default:
10720 goto die;
10723 trace_mips_translate_tr("mttr", rd, u, sel, h);
10724 tcg_temp_free(t0);
10725 return;
10727 die:
10728 tcg_temp_free(t0);
10729 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10730 gen_reserved_instruction(ctx);
10733 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10734 int rt, int rd)
10736 const char *opn = "ldst";
10738 check_cp0_enabled(ctx);
10739 switch (opc) {
10740 case OPC_MFC0:
10741 if (rt == 0) {
10742 /* Treat as NOP. */
10743 return;
10745 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10746 opn = "mfc0";
10747 break;
10748 case OPC_MTC0:
10750 TCGv t0 = tcg_temp_new();
10752 gen_load_gpr(t0, rt);
10753 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10754 tcg_temp_free(t0);
10756 opn = "mtc0";
10757 break;
10758 #if defined(TARGET_MIPS64)
10759 case OPC_DMFC0:
10760 check_insn(ctx, ISA_MIPS3);
10761 if (rt == 0) {
10762 /* Treat as NOP. */
10763 return;
10765 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10766 opn = "dmfc0";
10767 break;
10768 case OPC_DMTC0:
10769 check_insn(ctx, ISA_MIPS3);
10771 TCGv t0 = tcg_temp_new();
10773 gen_load_gpr(t0, rt);
10774 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10775 tcg_temp_free(t0);
10777 opn = "dmtc0";
10778 break;
10779 #endif
10780 case OPC_MFHC0:
10781 check_mvh(ctx);
10782 if (rt == 0) {
10783 /* Treat as NOP. */
10784 return;
10786 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10787 opn = "mfhc0";
10788 break;
10789 case OPC_MTHC0:
10790 check_mvh(ctx);
10792 TCGv t0 = tcg_temp_new();
10793 gen_load_gpr(t0, rt);
10794 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10795 tcg_temp_free(t0);
10797 opn = "mthc0";
10798 break;
10799 case OPC_MFTR:
10800 check_cp0_enabled(ctx);
10801 if (rd == 0) {
10802 /* Treat as NOP. */
10803 return;
10805 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10806 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10807 opn = "mftr";
10808 break;
10809 case OPC_MTTR:
10810 check_cp0_enabled(ctx);
10811 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10812 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10813 opn = "mttr";
10814 break;
10815 case OPC_TLBWI:
10816 opn = "tlbwi";
10817 if (!env->tlb->helper_tlbwi) {
10818 goto die;
10820 gen_helper_tlbwi(cpu_env);
10821 break;
10822 case OPC_TLBINV:
10823 opn = "tlbinv";
10824 if (ctx->ie >= 2) {
10825 if (!env->tlb->helper_tlbinv) {
10826 goto die;
10828 gen_helper_tlbinv(cpu_env);
10829 } /* treat as nop if TLBINV not supported */
10830 break;
10831 case OPC_TLBINVF:
10832 opn = "tlbinvf";
10833 if (ctx->ie >= 2) {
10834 if (!env->tlb->helper_tlbinvf) {
10835 goto die;
10837 gen_helper_tlbinvf(cpu_env);
10838 } /* treat as nop if TLBINV not supported */
10839 break;
10840 case OPC_TLBWR:
10841 opn = "tlbwr";
10842 if (!env->tlb->helper_tlbwr) {
10843 goto die;
10845 gen_helper_tlbwr(cpu_env);
10846 break;
10847 case OPC_TLBP:
10848 opn = "tlbp";
10849 if (!env->tlb->helper_tlbp) {
10850 goto die;
10852 gen_helper_tlbp(cpu_env);
10853 break;
10854 case OPC_TLBR:
10855 opn = "tlbr";
10856 if (!env->tlb->helper_tlbr) {
10857 goto die;
10859 gen_helper_tlbr(cpu_env);
10860 break;
10861 case OPC_ERET: /* OPC_ERETNC */
10862 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10863 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10864 goto die;
10865 } else {
10866 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10867 if (ctx->opcode & (1 << bit_shift)) {
10868 /* OPC_ERETNC */
10869 opn = "eretnc";
10870 check_insn(ctx, ISA_MIPS_R5);
10871 gen_helper_eretnc(cpu_env);
10872 } else {
10873 /* OPC_ERET */
10874 opn = "eret";
10875 check_insn(ctx, ISA_MIPS2);
10876 gen_helper_eret(cpu_env);
10878 ctx->base.is_jmp = DISAS_EXIT;
10880 break;
10881 case OPC_DERET:
10882 opn = "deret";
10883 check_insn(ctx, ISA_MIPS_R1);
10884 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10885 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10886 goto die;
10888 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10889 MIPS_INVAL(opn);
10890 gen_reserved_instruction(ctx);
10891 } else {
10892 gen_helper_deret(cpu_env);
10893 ctx->base.is_jmp = DISAS_EXIT;
10895 break;
10896 case OPC_WAIT:
10897 opn = "wait";
10898 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
10899 if ((ctx->insn_flags & ISA_MIPS_R6) &&
10900 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10901 goto die;
10903 /* If we get an exception, we want to restart at next instruction */
10904 ctx->base.pc_next += 4;
10905 save_cpu_state(ctx, 1);
10906 ctx->base.pc_next -= 4;
10907 gen_helper_wait(cpu_env);
10908 ctx->base.is_jmp = DISAS_NORETURN;
10909 break;
10910 default:
10911 die:
10912 MIPS_INVAL(opn);
10913 gen_reserved_instruction(ctx);
10914 return;
10916 (void)opn; /* avoid a compiler warning */
10918 #endif /* !CONFIG_USER_ONLY */
10920 /* CP1 Branches (before delay slot) */
10921 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
10922 int32_t cc, int32_t offset)
10924 target_ulong btarget;
10925 TCGv_i32 t0 = tcg_temp_new_i32();
10927 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10928 gen_reserved_instruction(ctx);
10929 goto out;
10932 if (cc != 0) {
10933 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
10936 btarget = ctx->base.pc_next + 4 + offset;
10938 switch (op) {
10939 case OPC_BC1F:
10940 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10941 tcg_gen_not_i32(t0, t0);
10942 tcg_gen_andi_i32(t0, t0, 1);
10943 tcg_gen_extu_i32_tl(bcond, t0);
10944 goto not_likely;
10945 case OPC_BC1FL:
10946 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10947 tcg_gen_not_i32(t0, t0);
10948 tcg_gen_andi_i32(t0, t0, 1);
10949 tcg_gen_extu_i32_tl(bcond, t0);
10950 goto likely;
10951 case OPC_BC1T:
10952 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10953 tcg_gen_andi_i32(t0, t0, 1);
10954 tcg_gen_extu_i32_tl(bcond, t0);
10955 goto not_likely;
10956 case OPC_BC1TL:
10957 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10958 tcg_gen_andi_i32(t0, t0, 1);
10959 tcg_gen_extu_i32_tl(bcond, t0);
10960 likely:
10961 ctx->hflags |= MIPS_HFLAG_BL;
10962 break;
10963 case OPC_BC1FANY2:
10965 TCGv_i32 t1 = tcg_temp_new_i32();
10966 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10967 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10968 tcg_gen_nand_i32(t0, t0, t1);
10969 tcg_temp_free_i32(t1);
10970 tcg_gen_andi_i32(t0, t0, 1);
10971 tcg_gen_extu_i32_tl(bcond, t0);
10973 goto not_likely;
10974 case OPC_BC1TANY2:
10976 TCGv_i32 t1 = tcg_temp_new_i32();
10977 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10978 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10979 tcg_gen_or_i32(t0, t0, t1);
10980 tcg_temp_free_i32(t1);
10981 tcg_gen_andi_i32(t0, t0, 1);
10982 tcg_gen_extu_i32_tl(bcond, t0);
10984 goto not_likely;
10985 case OPC_BC1FANY4:
10987 TCGv_i32 t1 = tcg_temp_new_i32();
10988 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
10989 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
10990 tcg_gen_and_i32(t0, t0, t1);
10991 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
10992 tcg_gen_and_i32(t0, t0, t1);
10993 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
10994 tcg_gen_nand_i32(t0, t0, t1);
10995 tcg_temp_free_i32(t1);
10996 tcg_gen_andi_i32(t0, t0, 1);
10997 tcg_gen_extu_i32_tl(bcond, t0);
10999 goto not_likely;
11000 case OPC_BC1TANY4:
11002 TCGv_i32 t1 = tcg_temp_new_i32();
11003 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11004 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11005 tcg_gen_or_i32(t0, t0, t1);
11006 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11007 tcg_gen_or_i32(t0, t0, t1);
11008 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11009 tcg_gen_or_i32(t0, t0, t1);
11010 tcg_temp_free_i32(t1);
11011 tcg_gen_andi_i32(t0, t0, 1);
11012 tcg_gen_extu_i32_tl(bcond, t0);
11014 not_likely:
11015 ctx->hflags |= MIPS_HFLAG_BC;
11016 break;
11017 default:
11018 MIPS_INVAL("cp1 cond branch");
11019 gen_reserved_instruction(ctx);
11020 goto out;
11022 ctx->btarget = btarget;
11023 ctx->hflags |= MIPS_HFLAG_BDS32;
11024 out:
11025 tcg_temp_free_i32(t0);
11028 /* R6 CP1 Branches */
11029 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
11030 int32_t ft, int32_t offset,
11031 int delayslot_size)
11033 target_ulong btarget;
11034 TCGv_i64 t0 = tcg_temp_new_i64();
11036 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11037 #ifdef MIPS_DEBUG_DISAS
11038 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11039 "\n", ctx->base.pc_next);
11040 #endif
11041 gen_reserved_instruction(ctx);
11042 goto out;
11045 gen_load_fpr64(ctx, t0, ft);
11046 tcg_gen_andi_i64(t0, t0, 1);
11048 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11050 switch (op) {
11051 case OPC_BC1EQZ:
11052 tcg_gen_xori_i64(t0, t0, 1);
11053 ctx->hflags |= MIPS_HFLAG_BC;
11054 break;
11055 case OPC_BC1NEZ:
11056 /* t0 already set */
11057 ctx->hflags |= MIPS_HFLAG_BC;
11058 break;
11059 default:
11060 MIPS_INVAL("cp1 cond branch");
11061 gen_reserved_instruction(ctx);
11062 goto out;
11065 tcg_gen_trunc_i64_tl(bcond, t0);
11067 ctx->btarget = btarget;
11069 switch (delayslot_size) {
11070 case 2:
11071 ctx->hflags |= MIPS_HFLAG_BDS16;
11072 break;
11073 case 4:
11074 ctx->hflags |= MIPS_HFLAG_BDS32;
11075 break;
11078 out:
11079 tcg_temp_free_i64(t0);
11082 /* Coprocessor 1 (FPU) */
11084 #define FOP(func, fmt) (((fmt) << 21) | (func))
11086 enum fopcode {
11087 OPC_ADD_S = FOP(0, FMT_S),
11088 OPC_SUB_S = FOP(1, FMT_S),
11089 OPC_MUL_S = FOP(2, FMT_S),
11090 OPC_DIV_S = FOP(3, FMT_S),
11091 OPC_SQRT_S = FOP(4, FMT_S),
11092 OPC_ABS_S = FOP(5, FMT_S),
11093 OPC_MOV_S = FOP(6, FMT_S),
11094 OPC_NEG_S = FOP(7, FMT_S),
11095 OPC_ROUND_L_S = FOP(8, FMT_S),
11096 OPC_TRUNC_L_S = FOP(9, FMT_S),
11097 OPC_CEIL_L_S = FOP(10, FMT_S),
11098 OPC_FLOOR_L_S = FOP(11, FMT_S),
11099 OPC_ROUND_W_S = FOP(12, FMT_S),
11100 OPC_TRUNC_W_S = FOP(13, FMT_S),
11101 OPC_CEIL_W_S = FOP(14, FMT_S),
11102 OPC_FLOOR_W_S = FOP(15, FMT_S),
11103 OPC_SEL_S = FOP(16, FMT_S),
11104 OPC_MOVCF_S = FOP(17, FMT_S),
11105 OPC_MOVZ_S = FOP(18, FMT_S),
11106 OPC_MOVN_S = FOP(19, FMT_S),
11107 OPC_SELEQZ_S = FOP(20, FMT_S),
11108 OPC_RECIP_S = FOP(21, FMT_S),
11109 OPC_RSQRT_S = FOP(22, FMT_S),
11110 OPC_SELNEZ_S = FOP(23, FMT_S),
11111 OPC_MADDF_S = FOP(24, FMT_S),
11112 OPC_MSUBF_S = FOP(25, FMT_S),
11113 OPC_RINT_S = FOP(26, FMT_S),
11114 OPC_CLASS_S = FOP(27, FMT_S),
11115 OPC_MIN_S = FOP(28, FMT_S),
11116 OPC_RECIP2_S = FOP(28, FMT_S),
11117 OPC_MINA_S = FOP(29, FMT_S),
11118 OPC_RECIP1_S = FOP(29, FMT_S),
11119 OPC_MAX_S = FOP(30, FMT_S),
11120 OPC_RSQRT1_S = FOP(30, FMT_S),
11121 OPC_MAXA_S = FOP(31, FMT_S),
11122 OPC_RSQRT2_S = FOP(31, FMT_S),
11123 OPC_CVT_D_S = FOP(33, FMT_S),
11124 OPC_CVT_W_S = FOP(36, FMT_S),
11125 OPC_CVT_L_S = FOP(37, FMT_S),
11126 OPC_CVT_PS_S = FOP(38, FMT_S),
11127 OPC_CMP_F_S = FOP(48, FMT_S),
11128 OPC_CMP_UN_S = FOP(49, FMT_S),
11129 OPC_CMP_EQ_S = FOP(50, FMT_S),
11130 OPC_CMP_UEQ_S = FOP(51, FMT_S),
11131 OPC_CMP_OLT_S = FOP(52, FMT_S),
11132 OPC_CMP_ULT_S = FOP(53, FMT_S),
11133 OPC_CMP_OLE_S = FOP(54, FMT_S),
11134 OPC_CMP_ULE_S = FOP(55, FMT_S),
11135 OPC_CMP_SF_S = FOP(56, FMT_S),
11136 OPC_CMP_NGLE_S = FOP(57, FMT_S),
11137 OPC_CMP_SEQ_S = FOP(58, FMT_S),
11138 OPC_CMP_NGL_S = FOP(59, FMT_S),
11139 OPC_CMP_LT_S = FOP(60, FMT_S),
11140 OPC_CMP_NGE_S = FOP(61, FMT_S),
11141 OPC_CMP_LE_S = FOP(62, FMT_S),
11142 OPC_CMP_NGT_S = FOP(63, FMT_S),
11144 OPC_ADD_D = FOP(0, FMT_D),
11145 OPC_SUB_D = FOP(1, FMT_D),
11146 OPC_MUL_D = FOP(2, FMT_D),
11147 OPC_DIV_D = FOP(3, FMT_D),
11148 OPC_SQRT_D = FOP(4, FMT_D),
11149 OPC_ABS_D = FOP(5, FMT_D),
11150 OPC_MOV_D = FOP(6, FMT_D),
11151 OPC_NEG_D = FOP(7, FMT_D),
11152 OPC_ROUND_L_D = FOP(8, FMT_D),
11153 OPC_TRUNC_L_D = FOP(9, FMT_D),
11154 OPC_CEIL_L_D = FOP(10, FMT_D),
11155 OPC_FLOOR_L_D = FOP(11, FMT_D),
11156 OPC_ROUND_W_D = FOP(12, FMT_D),
11157 OPC_TRUNC_W_D = FOP(13, FMT_D),
11158 OPC_CEIL_W_D = FOP(14, FMT_D),
11159 OPC_FLOOR_W_D = FOP(15, FMT_D),
11160 OPC_SEL_D = FOP(16, FMT_D),
11161 OPC_MOVCF_D = FOP(17, FMT_D),
11162 OPC_MOVZ_D = FOP(18, FMT_D),
11163 OPC_MOVN_D = FOP(19, FMT_D),
11164 OPC_SELEQZ_D = FOP(20, FMT_D),
11165 OPC_RECIP_D = FOP(21, FMT_D),
11166 OPC_RSQRT_D = FOP(22, FMT_D),
11167 OPC_SELNEZ_D = FOP(23, FMT_D),
11168 OPC_MADDF_D = FOP(24, FMT_D),
11169 OPC_MSUBF_D = FOP(25, FMT_D),
11170 OPC_RINT_D = FOP(26, FMT_D),
11171 OPC_CLASS_D = FOP(27, FMT_D),
11172 OPC_MIN_D = FOP(28, FMT_D),
11173 OPC_RECIP2_D = FOP(28, FMT_D),
11174 OPC_MINA_D = FOP(29, FMT_D),
11175 OPC_RECIP1_D = FOP(29, FMT_D),
11176 OPC_MAX_D = FOP(30, FMT_D),
11177 OPC_RSQRT1_D = FOP(30, FMT_D),
11178 OPC_MAXA_D = FOP(31, FMT_D),
11179 OPC_RSQRT2_D = FOP(31, FMT_D),
11180 OPC_CVT_S_D = FOP(32, FMT_D),
11181 OPC_CVT_W_D = FOP(36, FMT_D),
11182 OPC_CVT_L_D = FOP(37, FMT_D),
11183 OPC_CMP_F_D = FOP(48, FMT_D),
11184 OPC_CMP_UN_D = FOP(49, FMT_D),
11185 OPC_CMP_EQ_D = FOP(50, FMT_D),
11186 OPC_CMP_UEQ_D = FOP(51, FMT_D),
11187 OPC_CMP_OLT_D = FOP(52, FMT_D),
11188 OPC_CMP_ULT_D = FOP(53, FMT_D),
11189 OPC_CMP_OLE_D = FOP(54, FMT_D),
11190 OPC_CMP_ULE_D = FOP(55, FMT_D),
11191 OPC_CMP_SF_D = FOP(56, FMT_D),
11192 OPC_CMP_NGLE_D = FOP(57, FMT_D),
11193 OPC_CMP_SEQ_D = FOP(58, FMT_D),
11194 OPC_CMP_NGL_D = FOP(59, FMT_D),
11195 OPC_CMP_LT_D = FOP(60, FMT_D),
11196 OPC_CMP_NGE_D = FOP(61, FMT_D),
11197 OPC_CMP_LE_D = FOP(62, FMT_D),
11198 OPC_CMP_NGT_D = FOP(63, FMT_D),
11200 OPC_CVT_S_W = FOP(32, FMT_W),
11201 OPC_CVT_D_W = FOP(33, FMT_W),
11202 OPC_CVT_S_L = FOP(32, FMT_L),
11203 OPC_CVT_D_L = FOP(33, FMT_L),
11204 OPC_CVT_PS_PW = FOP(38, FMT_W),
11206 OPC_ADD_PS = FOP(0, FMT_PS),
11207 OPC_SUB_PS = FOP(1, FMT_PS),
11208 OPC_MUL_PS = FOP(2, FMT_PS),
11209 OPC_DIV_PS = FOP(3, FMT_PS),
11210 OPC_ABS_PS = FOP(5, FMT_PS),
11211 OPC_MOV_PS = FOP(6, FMT_PS),
11212 OPC_NEG_PS = FOP(7, FMT_PS),
11213 OPC_MOVCF_PS = FOP(17, FMT_PS),
11214 OPC_MOVZ_PS = FOP(18, FMT_PS),
11215 OPC_MOVN_PS = FOP(19, FMT_PS),
11216 OPC_ADDR_PS = FOP(24, FMT_PS),
11217 OPC_MULR_PS = FOP(26, FMT_PS),
11218 OPC_RECIP2_PS = FOP(28, FMT_PS),
11219 OPC_RECIP1_PS = FOP(29, FMT_PS),
11220 OPC_RSQRT1_PS = FOP(30, FMT_PS),
11221 OPC_RSQRT2_PS = FOP(31, FMT_PS),
11223 OPC_CVT_S_PU = FOP(32, FMT_PS),
11224 OPC_CVT_PW_PS = FOP(36, FMT_PS),
11225 OPC_CVT_S_PL = FOP(40, FMT_PS),
11226 OPC_PLL_PS = FOP(44, FMT_PS),
11227 OPC_PLU_PS = FOP(45, FMT_PS),
11228 OPC_PUL_PS = FOP(46, FMT_PS),
11229 OPC_PUU_PS = FOP(47, FMT_PS),
11230 OPC_CMP_F_PS = FOP(48, FMT_PS),
11231 OPC_CMP_UN_PS = FOP(49, FMT_PS),
11232 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
11233 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
11234 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
11235 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
11236 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
11237 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
11238 OPC_CMP_SF_PS = FOP(56, FMT_PS),
11239 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
11240 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
11241 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
11242 OPC_CMP_LT_PS = FOP(60, FMT_PS),
11243 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
11244 OPC_CMP_LE_PS = FOP(62, FMT_PS),
11245 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
11248 enum r6_f_cmp_op {
11249 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
11250 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
11251 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
11252 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
11253 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
11254 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
11255 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
11256 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
11257 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
11258 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
11259 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
11260 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
11261 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
11262 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
11263 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
11264 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
11265 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
11266 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
11267 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
11268 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
11269 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
11270 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
11272 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
11273 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
11274 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
11275 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
11276 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
11277 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
11278 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
11279 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
11280 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
11281 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
11282 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11283 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11284 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11285 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11286 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11287 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11288 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11289 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11290 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11291 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11292 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11293 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11296 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
11298 TCGv t0 = tcg_temp_new();
11300 switch (opc) {
11301 case OPC_MFC1:
11303 TCGv_i32 fp0 = tcg_temp_new_i32();
11305 gen_load_fpr32(ctx, fp0, fs);
11306 tcg_gen_ext_i32_tl(t0, fp0);
11307 tcg_temp_free_i32(fp0);
11309 gen_store_gpr(t0, rt);
11310 break;
11311 case OPC_MTC1:
11312 gen_load_gpr(t0, rt);
11314 TCGv_i32 fp0 = tcg_temp_new_i32();
11316 tcg_gen_trunc_tl_i32(fp0, t0);
11317 gen_store_fpr32(ctx, fp0, fs);
11318 tcg_temp_free_i32(fp0);
11320 break;
11321 case OPC_CFC1:
11322 gen_helper_1e0i(cfc1, t0, fs);
11323 gen_store_gpr(t0, rt);
11324 break;
11325 case OPC_CTC1:
11326 gen_load_gpr(t0, rt);
11327 save_cpu_state(ctx, 0);
11329 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11331 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11332 tcg_temp_free_i32(fs_tmp);
11334 /* Stop translation as we may have changed hflags */
11335 ctx->base.is_jmp = DISAS_STOP;
11336 break;
11337 #if defined(TARGET_MIPS64)
11338 case OPC_DMFC1:
11339 gen_load_fpr64(ctx, t0, fs);
11340 gen_store_gpr(t0, rt);
11341 break;
11342 case OPC_DMTC1:
11343 gen_load_gpr(t0, rt);
11344 gen_store_fpr64(ctx, t0, fs);
11345 break;
11346 #endif
11347 case OPC_MFHC1:
11349 TCGv_i32 fp0 = tcg_temp_new_i32();
11351 gen_load_fpr32h(ctx, fp0, fs);
11352 tcg_gen_ext_i32_tl(t0, fp0);
11353 tcg_temp_free_i32(fp0);
11355 gen_store_gpr(t0, rt);
11356 break;
11357 case OPC_MTHC1:
11358 gen_load_gpr(t0, rt);
11360 TCGv_i32 fp0 = tcg_temp_new_i32();
11362 tcg_gen_trunc_tl_i32(fp0, t0);
11363 gen_store_fpr32h(ctx, fp0, fs);
11364 tcg_temp_free_i32(fp0);
11366 break;
11367 default:
11368 MIPS_INVAL("cp1 move");
11369 gen_reserved_instruction(ctx);
11370 goto out;
11373 out:
11374 tcg_temp_free(t0);
11377 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11379 TCGLabel *l1;
11380 TCGCond cond;
11381 TCGv_i32 t0;
11383 if (rd == 0) {
11384 /* Treat as NOP. */
11385 return;
11388 if (tf) {
11389 cond = TCG_COND_EQ;
11390 } else {
11391 cond = TCG_COND_NE;
11394 l1 = gen_new_label();
11395 t0 = tcg_temp_new_i32();
11396 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11397 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11398 tcg_temp_free_i32(t0);
11399 if (rs == 0) {
11400 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11401 } else {
11402 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11404 gen_set_label(l1);
11407 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11408 int tf)
11410 int cond;
11411 TCGv_i32 t0 = tcg_temp_new_i32();
11412 TCGLabel *l1 = gen_new_label();
11414 if (tf) {
11415 cond = TCG_COND_EQ;
11416 } else {
11417 cond = TCG_COND_NE;
11420 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11421 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11422 gen_load_fpr32(ctx, t0, fs);
11423 gen_store_fpr32(ctx, t0, fd);
11424 gen_set_label(l1);
11425 tcg_temp_free_i32(t0);
11428 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11429 int tf)
11431 int cond;
11432 TCGv_i32 t0 = tcg_temp_new_i32();
11433 TCGv_i64 fp0;
11434 TCGLabel *l1 = gen_new_label();
11436 if (tf) {
11437 cond = TCG_COND_EQ;
11438 } else {
11439 cond = TCG_COND_NE;
11442 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11443 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11444 tcg_temp_free_i32(t0);
11445 fp0 = tcg_temp_new_i64();
11446 gen_load_fpr64(ctx, fp0, fs);
11447 gen_store_fpr64(ctx, fp0, fd);
11448 tcg_temp_free_i64(fp0);
11449 gen_set_label(l1);
11452 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11453 int cc, int tf)
11455 int cond;
11456 TCGv_i32 t0 = tcg_temp_new_i32();
11457 TCGLabel *l1 = gen_new_label();
11458 TCGLabel *l2 = gen_new_label();
11460 if (tf) {
11461 cond = TCG_COND_EQ;
11462 } else {
11463 cond = TCG_COND_NE;
11466 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11467 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11468 gen_load_fpr32(ctx, t0, fs);
11469 gen_store_fpr32(ctx, t0, fd);
11470 gen_set_label(l1);
11472 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11473 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11474 gen_load_fpr32h(ctx, t0, fs);
11475 gen_store_fpr32h(ctx, t0, fd);
11476 tcg_temp_free_i32(t0);
11477 gen_set_label(l2);
11480 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11481 int fs)
11483 TCGv_i32 t1 = tcg_const_i32(0);
11484 TCGv_i32 fp0 = tcg_temp_new_i32();
11485 TCGv_i32 fp1 = tcg_temp_new_i32();
11486 TCGv_i32 fp2 = tcg_temp_new_i32();
11487 gen_load_fpr32(ctx, fp0, fd);
11488 gen_load_fpr32(ctx, fp1, ft);
11489 gen_load_fpr32(ctx, fp2, fs);
11491 switch (op1) {
11492 case OPC_SEL_S:
11493 tcg_gen_andi_i32(fp0, fp0, 1);
11494 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11495 break;
11496 case OPC_SELEQZ_S:
11497 tcg_gen_andi_i32(fp1, fp1, 1);
11498 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11499 break;
11500 case OPC_SELNEZ_S:
11501 tcg_gen_andi_i32(fp1, fp1, 1);
11502 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11503 break;
11504 default:
11505 MIPS_INVAL("gen_sel_s");
11506 gen_reserved_instruction(ctx);
11507 break;
11510 gen_store_fpr32(ctx, fp0, fd);
11511 tcg_temp_free_i32(fp2);
11512 tcg_temp_free_i32(fp1);
11513 tcg_temp_free_i32(fp0);
11514 tcg_temp_free_i32(t1);
11517 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11518 int fs)
11520 TCGv_i64 t1 = tcg_const_i64(0);
11521 TCGv_i64 fp0 = tcg_temp_new_i64();
11522 TCGv_i64 fp1 = tcg_temp_new_i64();
11523 TCGv_i64 fp2 = tcg_temp_new_i64();
11524 gen_load_fpr64(ctx, fp0, fd);
11525 gen_load_fpr64(ctx, fp1, ft);
11526 gen_load_fpr64(ctx, fp2, fs);
11528 switch (op1) {
11529 case OPC_SEL_D:
11530 tcg_gen_andi_i64(fp0, fp0, 1);
11531 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11532 break;
11533 case OPC_SELEQZ_D:
11534 tcg_gen_andi_i64(fp1, fp1, 1);
11535 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11536 break;
11537 case OPC_SELNEZ_D:
11538 tcg_gen_andi_i64(fp1, fp1, 1);
11539 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11540 break;
11541 default:
11542 MIPS_INVAL("gen_sel_d");
11543 gen_reserved_instruction(ctx);
11544 break;
11547 gen_store_fpr64(ctx, fp0, fd);
11548 tcg_temp_free_i64(fp2);
11549 tcg_temp_free_i64(fp1);
11550 tcg_temp_free_i64(fp0);
11551 tcg_temp_free_i64(t1);
11554 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11555 int ft, int fs, int fd, int cc)
11557 uint32_t func = ctx->opcode & 0x3f;
11558 switch (op1) {
11559 case OPC_ADD_S:
11561 TCGv_i32 fp0 = tcg_temp_new_i32();
11562 TCGv_i32 fp1 = tcg_temp_new_i32();
11564 gen_load_fpr32(ctx, fp0, fs);
11565 gen_load_fpr32(ctx, fp1, ft);
11566 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11567 tcg_temp_free_i32(fp1);
11568 gen_store_fpr32(ctx, fp0, fd);
11569 tcg_temp_free_i32(fp0);
11571 break;
11572 case OPC_SUB_S:
11574 TCGv_i32 fp0 = tcg_temp_new_i32();
11575 TCGv_i32 fp1 = tcg_temp_new_i32();
11577 gen_load_fpr32(ctx, fp0, fs);
11578 gen_load_fpr32(ctx, fp1, ft);
11579 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11580 tcg_temp_free_i32(fp1);
11581 gen_store_fpr32(ctx, fp0, fd);
11582 tcg_temp_free_i32(fp0);
11584 break;
11585 case OPC_MUL_S:
11587 TCGv_i32 fp0 = tcg_temp_new_i32();
11588 TCGv_i32 fp1 = tcg_temp_new_i32();
11590 gen_load_fpr32(ctx, fp0, fs);
11591 gen_load_fpr32(ctx, fp1, ft);
11592 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11593 tcg_temp_free_i32(fp1);
11594 gen_store_fpr32(ctx, fp0, fd);
11595 tcg_temp_free_i32(fp0);
11597 break;
11598 case OPC_DIV_S:
11600 TCGv_i32 fp0 = tcg_temp_new_i32();
11601 TCGv_i32 fp1 = tcg_temp_new_i32();
11603 gen_load_fpr32(ctx, fp0, fs);
11604 gen_load_fpr32(ctx, fp1, ft);
11605 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11606 tcg_temp_free_i32(fp1);
11607 gen_store_fpr32(ctx, fp0, fd);
11608 tcg_temp_free_i32(fp0);
11610 break;
11611 case OPC_SQRT_S:
11613 TCGv_i32 fp0 = tcg_temp_new_i32();
11615 gen_load_fpr32(ctx, fp0, fs);
11616 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11617 gen_store_fpr32(ctx, fp0, fd);
11618 tcg_temp_free_i32(fp0);
11620 break;
11621 case OPC_ABS_S:
11623 TCGv_i32 fp0 = tcg_temp_new_i32();
11625 gen_load_fpr32(ctx, fp0, fs);
11626 if (ctx->abs2008) {
11627 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11628 } else {
11629 gen_helper_float_abs_s(fp0, fp0);
11631 gen_store_fpr32(ctx, fp0, fd);
11632 tcg_temp_free_i32(fp0);
11634 break;
11635 case OPC_MOV_S:
11637 TCGv_i32 fp0 = tcg_temp_new_i32();
11639 gen_load_fpr32(ctx, fp0, fs);
11640 gen_store_fpr32(ctx, fp0, fd);
11641 tcg_temp_free_i32(fp0);
11643 break;
11644 case OPC_NEG_S:
11646 TCGv_i32 fp0 = tcg_temp_new_i32();
11648 gen_load_fpr32(ctx, fp0, fs);
11649 if (ctx->abs2008) {
11650 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11651 } else {
11652 gen_helper_float_chs_s(fp0, fp0);
11654 gen_store_fpr32(ctx, fp0, fd);
11655 tcg_temp_free_i32(fp0);
11657 break;
11658 case OPC_ROUND_L_S:
11659 check_cp1_64bitmode(ctx);
11661 TCGv_i32 fp32 = tcg_temp_new_i32();
11662 TCGv_i64 fp64 = tcg_temp_new_i64();
11664 gen_load_fpr32(ctx, fp32, fs);
11665 if (ctx->nan2008) {
11666 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11667 } else {
11668 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11670 tcg_temp_free_i32(fp32);
11671 gen_store_fpr64(ctx, fp64, fd);
11672 tcg_temp_free_i64(fp64);
11674 break;
11675 case OPC_TRUNC_L_S:
11676 check_cp1_64bitmode(ctx);
11678 TCGv_i32 fp32 = tcg_temp_new_i32();
11679 TCGv_i64 fp64 = tcg_temp_new_i64();
11681 gen_load_fpr32(ctx, fp32, fs);
11682 if (ctx->nan2008) {
11683 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11684 } else {
11685 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11687 tcg_temp_free_i32(fp32);
11688 gen_store_fpr64(ctx, fp64, fd);
11689 tcg_temp_free_i64(fp64);
11691 break;
11692 case OPC_CEIL_L_S:
11693 check_cp1_64bitmode(ctx);
11695 TCGv_i32 fp32 = tcg_temp_new_i32();
11696 TCGv_i64 fp64 = tcg_temp_new_i64();
11698 gen_load_fpr32(ctx, fp32, fs);
11699 if (ctx->nan2008) {
11700 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11701 } else {
11702 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11704 tcg_temp_free_i32(fp32);
11705 gen_store_fpr64(ctx, fp64, fd);
11706 tcg_temp_free_i64(fp64);
11708 break;
11709 case OPC_FLOOR_L_S:
11710 check_cp1_64bitmode(ctx);
11712 TCGv_i32 fp32 = tcg_temp_new_i32();
11713 TCGv_i64 fp64 = tcg_temp_new_i64();
11715 gen_load_fpr32(ctx, fp32, fs);
11716 if (ctx->nan2008) {
11717 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11718 } else {
11719 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11721 tcg_temp_free_i32(fp32);
11722 gen_store_fpr64(ctx, fp64, fd);
11723 tcg_temp_free_i64(fp64);
11725 break;
11726 case OPC_ROUND_W_S:
11728 TCGv_i32 fp0 = tcg_temp_new_i32();
11730 gen_load_fpr32(ctx, fp0, fs);
11731 if (ctx->nan2008) {
11732 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11733 } else {
11734 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11736 gen_store_fpr32(ctx, fp0, fd);
11737 tcg_temp_free_i32(fp0);
11739 break;
11740 case OPC_TRUNC_W_S:
11742 TCGv_i32 fp0 = tcg_temp_new_i32();
11744 gen_load_fpr32(ctx, fp0, fs);
11745 if (ctx->nan2008) {
11746 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11747 } else {
11748 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11750 gen_store_fpr32(ctx, fp0, fd);
11751 tcg_temp_free_i32(fp0);
11753 break;
11754 case OPC_CEIL_W_S:
11756 TCGv_i32 fp0 = tcg_temp_new_i32();
11758 gen_load_fpr32(ctx, fp0, fs);
11759 if (ctx->nan2008) {
11760 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11761 } else {
11762 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11764 gen_store_fpr32(ctx, fp0, fd);
11765 tcg_temp_free_i32(fp0);
11767 break;
11768 case OPC_FLOOR_W_S:
11770 TCGv_i32 fp0 = tcg_temp_new_i32();
11772 gen_load_fpr32(ctx, fp0, fs);
11773 if (ctx->nan2008) {
11774 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11775 } else {
11776 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11778 gen_store_fpr32(ctx, fp0, fd);
11779 tcg_temp_free_i32(fp0);
11781 break;
11782 case OPC_SEL_S:
11783 check_insn(ctx, ISA_MIPS_R6);
11784 gen_sel_s(ctx, op1, fd, ft, fs);
11785 break;
11786 case OPC_SELEQZ_S:
11787 check_insn(ctx, ISA_MIPS_R6);
11788 gen_sel_s(ctx, op1, fd, ft, fs);
11789 break;
11790 case OPC_SELNEZ_S:
11791 check_insn(ctx, ISA_MIPS_R6);
11792 gen_sel_s(ctx, op1, fd, ft, fs);
11793 break;
11794 case OPC_MOVCF_S:
11795 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11796 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11797 break;
11798 case OPC_MOVZ_S:
11799 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11801 TCGLabel *l1 = gen_new_label();
11802 TCGv_i32 fp0;
11804 if (ft != 0) {
11805 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11807 fp0 = tcg_temp_new_i32();
11808 gen_load_fpr32(ctx, fp0, fs);
11809 gen_store_fpr32(ctx, fp0, fd);
11810 tcg_temp_free_i32(fp0);
11811 gen_set_label(l1);
11813 break;
11814 case OPC_MOVN_S:
11815 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11817 TCGLabel *l1 = gen_new_label();
11818 TCGv_i32 fp0;
11820 if (ft != 0) {
11821 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11822 fp0 = tcg_temp_new_i32();
11823 gen_load_fpr32(ctx, fp0, fs);
11824 gen_store_fpr32(ctx, fp0, fd);
11825 tcg_temp_free_i32(fp0);
11826 gen_set_label(l1);
11829 break;
11830 case OPC_RECIP_S:
11832 TCGv_i32 fp0 = tcg_temp_new_i32();
11834 gen_load_fpr32(ctx, fp0, fs);
11835 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11836 gen_store_fpr32(ctx, fp0, fd);
11837 tcg_temp_free_i32(fp0);
11839 break;
11840 case OPC_RSQRT_S:
11842 TCGv_i32 fp0 = tcg_temp_new_i32();
11844 gen_load_fpr32(ctx, fp0, fs);
11845 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11846 gen_store_fpr32(ctx, fp0, fd);
11847 tcg_temp_free_i32(fp0);
11849 break;
11850 case OPC_MADDF_S:
11851 check_insn(ctx, ISA_MIPS_R6);
11853 TCGv_i32 fp0 = tcg_temp_new_i32();
11854 TCGv_i32 fp1 = tcg_temp_new_i32();
11855 TCGv_i32 fp2 = tcg_temp_new_i32();
11856 gen_load_fpr32(ctx, fp0, fs);
11857 gen_load_fpr32(ctx, fp1, ft);
11858 gen_load_fpr32(ctx, fp2, fd);
11859 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11860 gen_store_fpr32(ctx, fp2, fd);
11861 tcg_temp_free_i32(fp2);
11862 tcg_temp_free_i32(fp1);
11863 tcg_temp_free_i32(fp0);
11865 break;
11866 case OPC_MSUBF_S:
11867 check_insn(ctx, ISA_MIPS_R6);
11869 TCGv_i32 fp0 = tcg_temp_new_i32();
11870 TCGv_i32 fp1 = tcg_temp_new_i32();
11871 TCGv_i32 fp2 = tcg_temp_new_i32();
11872 gen_load_fpr32(ctx, fp0, fs);
11873 gen_load_fpr32(ctx, fp1, ft);
11874 gen_load_fpr32(ctx, fp2, fd);
11875 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
11876 gen_store_fpr32(ctx, fp2, fd);
11877 tcg_temp_free_i32(fp2);
11878 tcg_temp_free_i32(fp1);
11879 tcg_temp_free_i32(fp0);
11881 break;
11882 case OPC_RINT_S:
11883 check_insn(ctx, ISA_MIPS_R6);
11885 TCGv_i32 fp0 = tcg_temp_new_i32();
11886 gen_load_fpr32(ctx, fp0, fs);
11887 gen_helper_float_rint_s(fp0, cpu_env, fp0);
11888 gen_store_fpr32(ctx, fp0, fd);
11889 tcg_temp_free_i32(fp0);
11891 break;
11892 case OPC_CLASS_S:
11893 check_insn(ctx, ISA_MIPS_R6);
11895 TCGv_i32 fp0 = tcg_temp_new_i32();
11896 gen_load_fpr32(ctx, fp0, fs);
11897 gen_helper_float_class_s(fp0, cpu_env, fp0);
11898 gen_store_fpr32(ctx, fp0, fd);
11899 tcg_temp_free_i32(fp0);
11901 break;
11902 case OPC_MIN_S: /* OPC_RECIP2_S */
11903 if (ctx->insn_flags & ISA_MIPS_R6) {
11904 /* OPC_MIN_S */
11905 TCGv_i32 fp0 = tcg_temp_new_i32();
11906 TCGv_i32 fp1 = tcg_temp_new_i32();
11907 TCGv_i32 fp2 = tcg_temp_new_i32();
11908 gen_load_fpr32(ctx, fp0, fs);
11909 gen_load_fpr32(ctx, fp1, ft);
11910 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
11911 gen_store_fpr32(ctx, fp2, fd);
11912 tcg_temp_free_i32(fp2);
11913 tcg_temp_free_i32(fp1);
11914 tcg_temp_free_i32(fp0);
11915 } else {
11916 /* OPC_RECIP2_S */
11917 check_cp1_64bitmode(ctx);
11919 TCGv_i32 fp0 = tcg_temp_new_i32();
11920 TCGv_i32 fp1 = tcg_temp_new_i32();
11922 gen_load_fpr32(ctx, fp0, fs);
11923 gen_load_fpr32(ctx, fp1, ft);
11924 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
11925 tcg_temp_free_i32(fp1);
11926 gen_store_fpr32(ctx, fp0, fd);
11927 tcg_temp_free_i32(fp0);
11930 break;
11931 case OPC_MINA_S: /* OPC_RECIP1_S */
11932 if (ctx->insn_flags & ISA_MIPS_R6) {
11933 /* OPC_MINA_S */
11934 TCGv_i32 fp0 = tcg_temp_new_i32();
11935 TCGv_i32 fp1 = tcg_temp_new_i32();
11936 TCGv_i32 fp2 = tcg_temp_new_i32();
11937 gen_load_fpr32(ctx, fp0, fs);
11938 gen_load_fpr32(ctx, fp1, ft);
11939 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
11940 gen_store_fpr32(ctx, fp2, fd);
11941 tcg_temp_free_i32(fp2);
11942 tcg_temp_free_i32(fp1);
11943 tcg_temp_free_i32(fp0);
11944 } else {
11945 /* OPC_RECIP1_S */
11946 check_cp1_64bitmode(ctx);
11948 TCGv_i32 fp0 = tcg_temp_new_i32();
11950 gen_load_fpr32(ctx, fp0, fs);
11951 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
11952 gen_store_fpr32(ctx, fp0, fd);
11953 tcg_temp_free_i32(fp0);
11956 break;
11957 case OPC_MAX_S: /* OPC_RSQRT1_S */
11958 if (ctx->insn_flags & ISA_MIPS_R6) {
11959 /* OPC_MAX_S */
11960 TCGv_i32 fp0 = tcg_temp_new_i32();
11961 TCGv_i32 fp1 = tcg_temp_new_i32();
11962 gen_load_fpr32(ctx, fp0, fs);
11963 gen_load_fpr32(ctx, fp1, ft);
11964 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
11965 gen_store_fpr32(ctx, fp1, fd);
11966 tcg_temp_free_i32(fp1);
11967 tcg_temp_free_i32(fp0);
11968 } else {
11969 /* OPC_RSQRT1_S */
11970 check_cp1_64bitmode(ctx);
11972 TCGv_i32 fp0 = tcg_temp_new_i32();
11974 gen_load_fpr32(ctx, fp0, fs);
11975 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
11976 gen_store_fpr32(ctx, fp0, fd);
11977 tcg_temp_free_i32(fp0);
11980 break;
11981 case OPC_MAXA_S: /* OPC_RSQRT2_S */
11982 if (ctx->insn_flags & ISA_MIPS_R6) {
11983 /* OPC_MAXA_S */
11984 TCGv_i32 fp0 = tcg_temp_new_i32();
11985 TCGv_i32 fp1 = tcg_temp_new_i32();
11986 gen_load_fpr32(ctx, fp0, fs);
11987 gen_load_fpr32(ctx, fp1, ft);
11988 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
11989 gen_store_fpr32(ctx, fp1, fd);
11990 tcg_temp_free_i32(fp1);
11991 tcg_temp_free_i32(fp0);
11992 } else {
11993 /* OPC_RSQRT2_S */
11994 check_cp1_64bitmode(ctx);
11996 TCGv_i32 fp0 = tcg_temp_new_i32();
11997 TCGv_i32 fp1 = tcg_temp_new_i32();
11999 gen_load_fpr32(ctx, fp0, fs);
12000 gen_load_fpr32(ctx, fp1, ft);
12001 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
12002 tcg_temp_free_i32(fp1);
12003 gen_store_fpr32(ctx, fp0, fd);
12004 tcg_temp_free_i32(fp0);
12007 break;
12008 case OPC_CVT_D_S:
12009 check_cp1_registers(ctx, fd);
12011 TCGv_i32 fp32 = tcg_temp_new_i32();
12012 TCGv_i64 fp64 = tcg_temp_new_i64();
12014 gen_load_fpr32(ctx, fp32, fs);
12015 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
12016 tcg_temp_free_i32(fp32);
12017 gen_store_fpr64(ctx, fp64, fd);
12018 tcg_temp_free_i64(fp64);
12020 break;
12021 case OPC_CVT_W_S:
12023 TCGv_i32 fp0 = tcg_temp_new_i32();
12025 gen_load_fpr32(ctx, fp0, fs);
12026 if (ctx->nan2008) {
12027 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
12028 } else {
12029 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
12031 gen_store_fpr32(ctx, fp0, fd);
12032 tcg_temp_free_i32(fp0);
12034 break;
12035 case OPC_CVT_L_S:
12036 check_cp1_64bitmode(ctx);
12038 TCGv_i32 fp32 = tcg_temp_new_i32();
12039 TCGv_i64 fp64 = tcg_temp_new_i64();
12041 gen_load_fpr32(ctx, fp32, fs);
12042 if (ctx->nan2008) {
12043 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
12044 } else {
12045 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
12047 tcg_temp_free_i32(fp32);
12048 gen_store_fpr64(ctx, fp64, fd);
12049 tcg_temp_free_i64(fp64);
12051 break;
12052 case OPC_CVT_PS_S:
12053 check_ps(ctx);
12055 TCGv_i64 fp64 = tcg_temp_new_i64();
12056 TCGv_i32 fp32_0 = tcg_temp_new_i32();
12057 TCGv_i32 fp32_1 = tcg_temp_new_i32();
12059 gen_load_fpr32(ctx, fp32_0, fs);
12060 gen_load_fpr32(ctx, fp32_1, ft);
12061 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
12062 tcg_temp_free_i32(fp32_1);
12063 tcg_temp_free_i32(fp32_0);
12064 gen_store_fpr64(ctx, fp64, fd);
12065 tcg_temp_free_i64(fp64);
12067 break;
12068 case OPC_CMP_F_S:
12069 case OPC_CMP_UN_S:
12070 case OPC_CMP_EQ_S:
12071 case OPC_CMP_UEQ_S:
12072 case OPC_CMP_OLT_S:
12073 case OPC_CMP_ULT_S:
12074 case OPC_CMP_OLE_S:
12075 case OPC_CMP_ULE_S:
12076 case OPC_CMP_SF_S:
12077 case OPC_CMP_NGLE_S:
12078 case OPC_CMP_SEQ_S:
12079 case OPC_CMP_NGL_S:
12080 case OPC_CMP_LT_S:
12081 case OPC_CMP_NGE_S:
12082 case OPC_CMP_LE_S:
12083 case OPC_CMP_NGT_S:
12084 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12085 if (ctx->opcode & (1 << 6)) {
12086 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
12087 } else {
12088 gen_cmp_s(ctx, func - 48, ft, fs, cc);
12090 break;
12091 case OPC_ADD_D:
12092 check_cp1_registers(ctx, fs | ft | fd);
12094 TCGv_i64 fp0 = tcg_temp_new_i64();
12095 TCGv_i64 fp1 = tcg_temp_new_i64();
12097 gen_load_fpr64(ctx, fp0, fs);
12098 gen_load_fpr64(ctx, fp1, ft);
12099 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
12100 tcg_temp_free_i64(fp1);
12101 gen_store_fpr64(ctx, fp0, fd);
12102 tcg_temp_free_i64(fp0);
12104 break;
12105 case OPC_SUB_D:
12106 check_cp1_registers(ctx, fs | ft | fd);
12108 TCGv_i64 fp0 = tcg_temp_new_i64();
12109 TCGv_i64 fp1 = tcg_temp_new_i64();
12111 gen_load_fpr64(ctx, fp0, fs);
12112 gen_load_fpr64(ctx, fp1, ft);
12113 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
12114 tcg_temp_free_i64(fp1);
12115 gen_store_fpr64(ctx, fp0, fd);
12116 tcg_temp_free_i64(fp0);
12118 break;
12119 case OPC_MUL_D:
12120 check_cp1_registers(ctx, fs | ft | fd);
12122 TCGv_i64 fp0 = tcg_temp_new_i64();
12123 TCGv_i64 fp1 = tcg_temp_new_i64();
12125 gen_load_fpr64(ctx, fp0, fs);
12126 gen_load_fpr64(ctx, fp1, ft);
12127 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
12128 tcg_temp_free_i64(fp1);
12129 gen_store_fpr64(ctx, fp0, fd);
12130 tcg_temp_free_i64(fp0);
12132 break;
12133 case OPC_DIV_D:
12134 check_cp1_registers(ctx, fs | ft | fd);
12136 TCGv_i64 fp0 = tcg_temp_new_i64();
12137 TCGv_i64 fp1 = tcg_temp_new_i64();
12139 gen_load_fpr64(ctx, fp0, fs);
12140 gen_load_fpr64(ctx, fp1, ft);
12141 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
12142 tcg_temp_free_i64(fp1);
12143 gen_store_fpr64(ctx, fp0, fd);
12144 tcg_temp_free_i64(fp0);
12146 break;
12147 case OPC_SQRT_D:
12148 check_cp1_registers(ctx, fs | fd);
12150 TCGv_i64 fp0 = tcg_temp_new_i64();
12152 gen_load_fpr64(ctx, fp0, fs);
12153 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
12154 gen_store_fpr64(ctx, fp0, fd);
12155 tcg_temp_free_i64(fp0);
12157 break;
12158 case OPC_ABS_D:
12159 check_cp1_registers(ctx, fs | fd);
12161 TCGv_i64 fp0 = tcg_temp_new_i64();
12163 gen_load_fpr64(ctx, fp0, fs);
12164 if (ctx->abs2008) {
12165 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
12166 } else {
12167 gen_helper_float_abs_d(fp0, fp0);
12169 gen_store_fpr64(ctx, fp0, fd);
12170 tcg_temp_free_i64(fp0);
12172 break;
12173 case OPC_MOV_D:
12174 check_cp1_registers(ctx, fs | fd);
12176 TCGv_i64 fp0 = tcg_temp_new_i64();
12178 gen_load_fpr64(ctx, fp0, fs);
12179 gen_store_fpr64(ctx, fp0, fd);
12180 tcg_temp_free_i64(fp0);
12182 break;
12183 case OPC_NEG_D:
12184 check_cp1_registers(ctx, fs | fd);
12186 TCGv_i64 fp0 = tcg_temp_new_i64();
12188 gen_load_fpr64(ctx, fp0, fs);
12189 if (ctx->abs2008) {
12190 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
12191 } else {
12192 gen_helper_float_chs_d(fp0, fp0);
12194 gen_store_fpr64(ctx, fp0, fd);
12195 tcg_temp_free_i64(fp0);
12197 break;
12198 case OPC_ROUND_L_D:
12199 check_cp1_64bitmode(ctx);
12201 TCGv_i64 fp0 = tcg_temp_new_i64();
12203 gen_load_fpr64(ctx, fp0, fs);
12204 if (ctx->nan2008) {
12205 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
12206 } else {
12207 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
12209 gen_store_fpr64(ctx, fp0, fd);
12210 tcg_temp_free_i64(fp0);
12212 break;
12213 case OPC_TRUNC_L_D:
12214 check_cp1_64bitmode(ctx);
12216 TCGv_i64 fp0 = tcg_temp_new_i64();
12218 gen_load_fpr64(ctx, fp0, fs);
12219 if (ctx->nan2008) {
12220 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
12221 } else {
12222 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
12224 gen_store_fpr64(ctx, fp0, fd);
12225 tcg_temp_free_i64(fp0);
12227 break;
12228 case OPC_CEIL_L_D:
12229 check_cp1_64bitmode(ctx);
12231 TCGv_i64 fp0 = tcg_temp_new_i64();
12233 gen_load_fpr64(ctx, fp0, fs);
12234 if (ctx->nan2008) {
12235 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
12236 } else {
12237 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
12239 gen_store_fpr64(ctx, fp0, fd);
12240 tcg_temp_free_i64(fp0);
12242 break;
12243 case OPC_FLOOR_L_D:
12244 check_cp1_64bitmode(ctx);
12246 TCGv_i64 fp0 = tcg_temp_new_i64();
12248 gen_load_fpr64(ctx, fp0, fs);
12249 if (ctx->nan2008) {
12250 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
12251 } else {
12252 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
12254 gen_store_fpr64(ctx, fp0, fd);
12255 tcg_temp_free_i64(fp0);
12257 break;
12258 case OPC_ROUND_W_D:
12259 check_cp1_registers(ctx, fs);
12261 TCGv_i32 fp32 = tcg_temp_new_i32();
12262 TCGv_i64 fp64 = tcg_temp_new_i64();
12264 gen_load_fpr64(ctx, fp64, fs);
12265 if (ctx->nan2008) {
12266 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
12267 } else {
12268 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
12270 tcg_temp_free_i64(fp64);
12271 gen_store_fpr32(ctx, fp32, fd);
12272 tcg_temp_free_i32(fp32);
12274 break;
12275 case OPC_TRUNC_W_D:
12276 check_cp1_registers(ctx, fs);
12278 TCGv_i32 fp32 = tcg_temp_new_i32();
12279 TCGv_i64 fp64 = tcg_temp_new_i64();
12281 gen_load_fpr64(ctx, fp64, fs);
12282 if (ctx->nan2008) {
12283 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12284 } else {
12285 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12287 tcg_temp_free_i64(fp64);
12288 gen_store_fpr32(ctx, fp32, fd);
12289 tcg_temp_free_i32(fp32);
12291 break;
12292 case OPC_CEIL_W_D:
12293 check_cp1_registers(ctx, fs);
12295 TCGv_i32 fp32 = tcg_temp_new_i32();
12296 TCGv_i64 fp64 = tcg_temp_new_i64();
12298 gen_load_fpr64(ctx, fp64, fs);
12299 if (ctx->nan2008) {
12300 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12301 } else {
12302 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12304 tcg_temp_free_i64(fp64);
12305 gen_store_fpr32(ctx, fp32, fd);
12306 tcg_temp_free_i32(fp32);
12308 break;
12309 case OPC_FLOOR_W_D:
12310 check_cp1_registers(ctx, fs);
12312 TCGv_i32 fp32 = tcg_temp_new_i32();
12313 TCGv_i64 fp64 = tcg_temp_new_i64();
12315 gen_load_fpr64(ctx, fp64, fs);
12316 if (ctx->nan2008) {
12317 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12318 } else {
12319 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12321 tcg_temp_free_i64(fp64);
12322 gen_store_fpr32(ctx, fp32, fd);
12323 tcg_temp_free_i32(fp32);
12325 break;
12326 case OPC_SEL_D:
12327 check_insn(ctx, ISA_MIPS_R6);
12328 gen_sel_d(ctx, op1, fd, ft, fs);
12329 break;
12330 case OPC_SELEQZ_D:
12331 check_insn(ctx, ISA_MIPS_R6);
12332 gen_sel_d(ctx, op1, fd, ft, fs);
12333 break;
12334 case OPC_SELNEZ_D:
12335 check_insn(ctx, ISA_MIPS_R6);
12336 gen_sel_d(ctx, op1, fd, ft, fs);
12337 break;
12338 case OPC_MOVCF_D:
12339 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12340 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12341 break;
12342 case OPC_MOVZ_D:
12343 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12345 TCGLabel *l1 = gen_new_label();
12346 TCGv_i64 fp0;
12348 if (ft != 0) {
12349 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12351 fp0 = tcg_temp_new_i64();
12352 gen_load_fpr64(ctx, fp0, fs);
12353 gen_store_fpr64(ctx, fp0, fd);
12354 tcg_temp_free_i64(fp0);
12355 gen_set_label(l1);
12357 break;
12358 case OPC_MOVN_D:
12359 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12361 TCGLabel *l1 = gen_new_label();
12362 TCGv_i64 fp0;
12364 if (ft != 0) {
12365 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12366 fp0 = tcg_temp_new_i64();
12367 gen_load_fpr64(ctx, fp0, fs);
12368 gen_store_fpr64(ctx, fp0, fd);
12369 tcg_temp_free_i64(fp0);
12370 gen_set_label(l1);
12373 break;
12374 case OPC_RECIP_D:
12375 check_cp1_registers(ctx, fs | fd);
12377 TCGv_i64 fp0 = tcg_temp_new_i64();
12379 gen_load_fpr64(ctx, fp0, fs);
12380 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12381 gen_store_fpr64(ctx, fp0, fd);
12382 tcg_temp_free_i64(fp0);
12384 break;
12385 case OPC_RSQRT_D:
12386 check_cp1_registers(ctx, fs | fd);
12388 TCGv_i64 fp0 = tcg_temp_new_i64();
12390 gen_load_fpr64(ctx, fp0, fs);
12391 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12392 gen_store_fpr64(ctx, fp0, fd);
12393 tcg_temp_free_i64(fp0);
12395 break;
12396 case OPC_MADDF_D:
12397 check_insn(ctx, ISA_MIPS_R6);
12399 TCGv_i64 fp0 = tcg_temp_new_i64();
12400 TCGv_i64 fp1 = tcg_temp_new_i64();
12401 TCGv_i64 fp2 = tcg_temp_new_i64();
12402 gen_load_fpr64(ctx, fp0, fs);
12403 gen_load_fpr64(ctx, fp1, ft);
12404 gen_load_fpr64(ctx, fp2, fd);
12405 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12406 gen_store_fpr64(ctx, fp2, fd);
12407 tcg_temp_free_i64(fp2);
12408 tcg_temp_free_i64(fp1);
12409 tcg_temp_free_i64(fp0);
12411 break;
12412 case OPC_MSUBF_D:
12413 check_insn(ctx, ISA_MIPS_R6);
12415 TCGv_i64 fp0 = tcg_temp_new_i64();
12416 TCGv_i64 fp1 = tcg_temp_new_i64();
12417 TCGv_i64 fp2 = tcg_temp_new_i64();
12418 gen_load_fpr64(ctx, fp0, fs);
12419 gen_load_fpr64(ctx, fp1, ft);
12420 gen_load_fpr64(ctx, fp2, fd);
12421 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12422 gen_store_fpr64(ctx, fp2, fd);
12423 tcg_temp_free_i64(fp2);
12424 tcg_temp_free_i64(fp1);
12425 tcg_temp_free_i64(fp0);
12427 break;
12428 case OPC_RINT_D:
12429 check_insn(ctx, ISA_MIPS_R6);
12431 TCGv_i64 fp0 = tcg_temp_new_i64();
12432 gen_load_fpr64(ctx, fp0, fs);
12433 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12434 gen_store_fpr64(ctx, fp0, fd);
12435 tcg_temp_free_i64(fp0);
12437 break;
12438 case OPC_CLASS_D:
12439 check_insn(ctx, ISA_MIPS_R6);
12441 TCGv_i64 fp0 = tcg_temp_new_i64();
12442 gen_load_fpr64(ctx, fp0, fs);
12443 gen_helper_float_class_d(fp0, cpu_env, fp0);
12444 gen_store_fpr64(ctx, fp0, fd);
12445 tcg_temp_free_i64(fp0);
12447 break;
12448 case OPC_MIN_D: /* OPC_RECIP2_D */
12449 if (ctx->insn_flags & ISA_MIPS_R6) {
12450 /* OPC_MIN_D */
12451 TCGv_i64 fp0 = tcg_temp_new_i64();
12452 TCGv_i64 fp1 = tcg_temp_new_i64();
12453 gen_load_fpr64(ctx, fp0, fs);
12454 gen_load_fpr64(ctx, fp1, ft);
12455 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12456 gen_store_fpr64(ctx, fp1, fd);
12457 tcg_temp_free_i64(fp1);
12458 tcg_temp_free_i64(fp0);
12459 } else {
12460 /* OPC_RECIP2_D */
12461 check_cp1_64bitmode(ctx);
12463 TCGv_i64 fp0 = tcg_temp_new_i64();
12464 TCGv_i64 fp1 = tcg_temp_new_i64();
12466 gen_load_fpr64(ctx, fp0, fs);
12467 gen_load_fpr64(ctx, fp1, ft);
12468 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12469 tcg_temp_free_i64(fp1);
12470 gen_store_fpr64(ctx, fp0, fd);
12471 tcg_temp_free_i64(fp0);
12474 break;
12475 case OPC_MINA_D: /* OPC_RECIP1_D */
12476 if (ctx->insn_flags & ISA_MIPS_R6) {
12477 /* OPC_MINA_D */
12478 TCGv_i64 fp0 = tcg_temp_new_i64();
12479 TCGv_i64 fp1 = tcg_temp_new_i64();
12480 gen_load_fpr64(ctx, fp0, fs);
12481 gen_load_fpr64(ctx, fp1, ft);
12482 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12483 gen_store_fpr64(ctx, fp1, fd);
12484 tcg_temp_free_i64(fp1);
12485 tcg_temp_free_i64(fp0);
12486 } else {
12487 /* OPC_RECIP1_D */
12488 check_cp1_64bitmode(ctx);
12490 TCGv_i64 fp0 = tcg_temp_new_i64();
12492 gen_load_fpr64(ctx, fp0, fs);
12493 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12494 gen_store_fpr64(ctx, fp0, fd);
12495 tcg_temp_free_i64(fp0);
12498 break;
12499 case OPC_MAX_D: /* OPC_RSQRT1_D */
12500 if (ctx->insn_flags & ISA_MIPS_R6) {
12501 /* OPC_MAX_D */
12502 TCGv_i64 fp0 = tcg_temp_new_i64();
12503 TCGv_i64 fp1 = tcg_temp_new_i64();
12504 gen_load_fpr64(ctx, fp0, fs);
12505 gen_load_fpr64(ctx, fp1, ft);
12506 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12507 gen_store_fpr64(ctx, fp1, fd);
12508 tcg_temp_free_i64(fp1);
12509 tcg_temp_free_i64(fp0);
12510 } else {
12511 /* OPC_RSQRT1_D */
12512 check_cp1_64bitmode(ctx);
12514 TCGv_i64 fp0 = tcg_temp_new_i64();
12516 gen_load_fpr64(ctx, fp0, fs);
12517 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12518 gen_store_fpr64(ctx, fp0, fd);
12519 tcg_temp_free_i64(fp0);
12522 break;
12523 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12524 if (ctx->insn_flags & ISA_MIPS_R6) {
12525 /* OPC_MAXA_D */
12526 TCGv_i64 fp0 = tcg_temp_new_i64();
12527 TCGv_i64 fp1 = tcg_temp_new_i64();
12528 gen_load_fpr64(ctx, fp0, fs);
12529 gen_load_fpr64(ctx, fp1, ft);
12530 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12531 gen_store_fpr64(ctx, fp1, fd);
12532 tcg_temp_free_i64(fp1);
12533 tcg_temp_free_i64(fp0);
12534 } else {
12535 /* OPC_RSQRT2_D */
12536 check_cp1_64bitmode(ctx);
12538 TCGv_i64 fp0 = tcg_temp_new_i64();
12539 TCGv_i64 fp1 = tcg_temp_new_i64();
12541 gen_load_fpr64(ctx, fp0, fs);
12542 gen_load_fpr64(ctx, fp1, ft);
12543 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12544 tcg_temp_free_i64(fp1);
12545 gen_store_fpr64(ctx, fp0, fd);
12546 tcg_temp_free_i64(fp0);
12549 break;
12550 case OPC_CMP_F_D:
12551 case OPC_CMP_UN_D:
12552 case OPC_CMP_EQ_D:
12553 case OPC_CMP_UEQ_D:
12554 case OPC_CMP_OLT_D:
12555 case OPC_CMP_ULT_D:
12556 case OPC_CMP_OLE_D:
12557 case OPC_CMP_ULE_D:
12558 case OPC_CMP_SF_D:
12559 case OPC_CMP_NGLE_D:
12560 case OPC_CMP_SEQ_D:
12561 case OPC_CMP_NGL_D:
12562 case OPC_CMP_LT_D:
12563 case OPC_CMP_NGE_D:
12564 case OPC_CMP_LE_D:
12565 case OPC_CMP_NGT_D:
12566 check_insn_opc_removed(ctx, ISA_MIPS_R6);
12567 if (ctx->opcode & (1 << 6)) {
12568 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12569 } else {
12570 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12572 break;
12573 case OPC_CVT_S_D:
12574 check_cp1_registers(ctx, fs);
12576 TCGv_i32 fp32 = tcg_temp_new_i32();
12577 TCGv_i64 fp64 = tcg_temp_new_i64();
12579 gen_load_fpr64(ctx, fp64, fs);
12580 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12581 tcg_temp_free_i64(fp64);
12582 gen_store_fpr32(ctx, fp32, fd);
12583 tcg_temp_free_i32(fp32);
12585 break;
12586 case OPC_CVT_W_D:
12587 check_cp1_registers(ctx, fs);
12589 TCGv_i32 fp32 = tcg_temp_new_i32();
12590 TCGv_i64 fp64 = tcg_temp_new_i64();
12592 gen_load_fpr64(ctx, fp64, fs);
12593 if (ctx->nan2008) {
12594 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12595 } else {
12596 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12598 tcg_temp_free_i64(fp64);
12599 gen_store_fpr32(ctx, fp32, fd);
12600 tcg_temp_free_i32(fp32);
12602 break;
12603 case OPC_CVT_L_D:
12604 check_cp1_64bitmode(ctx);
12606 TCGv_i64 fp0 = tcg_temp_new_i64();
12608 gen_load_fpr64(ctx, fp0, fs);
12609 if (ctx->nan2008) {
12610 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12611 } else {
12612 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12614 gen_store_fpr64(ctx, fp0, fd);
12615 tcg_temp_free_i64(fp0);
12617 break;
12618 case OPC_CVT_S_W:
12620 TCGv_i32 fp0 = tcg_temp_new_i32();
12622 gen_load_fpr32(ctx, fp0, fs);
12623 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12624 gen_store_fpr32(ctx, fp0, fd);
12625 tcg_temp_free_i32(fp0);
12627 break;
12628 case OPC_CVT_D_W:
12629 check_cp1_registers(ctx, fd);
12631 TCGv_i32 fp32 = tcg_temp_new_i32();
12632 TCGv_i64 fp64 = tcg_temp_new_i64();
12634 gen_load_fpr32(ctx, fp32, fs);
12635 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12636 tcg_temp_free_i32(fp32);
12637 gen_store_fpr64(ctx, fp64, fd);
12638 tcg_temp_free_i64(fp64);
12640 break;
12641 case OPC_CVT_S_L:
12642 check_cp1_64bitmode(ctx);
12644 TCGv_i32 fp32 = tcg_temp_new_i32();
12645 TCGv_i64 fp64 = tcg_temp_new_i64();
12647 gen_load_fpr64(ctx, fp64, fs);
12648 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12649 tcg_temp_free_i64(fp64);
12650 gen_store_fpr32(ctx, fp32, fd);
12651 tcg_temp_free_i32(fp32);
12653 break;
12654 case OPC_CVT_D_L:
12655 check_cp1_64bitmode(ctx);
12657 TCGv_i64 fp0 = tcg_temp_new_i64();
12659 gen_load_fpr64(ctx, fp0, fs);
12660 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12661 gen_store_fpr64(ctx, fp0, fd);
12662 tcg_temp_free_i64(fp0);
12664 break;
12665 case OPC_CVT_PS_PW:
12666 check_ps(ctx);
12668 TCGv_i64 fp0 = tcg_temp_new_i64();
12670 gen_load_fpr64(ctx, fp0, fs);
12671 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12672 gen_store_fpr64(ctx, fp0, fd);
12673 tcg_temp_free_i64(fp0);
12675 break;
12676 case OPC_ADD_PS:
12677 check_ps(ctx);
12679 TCGv_i64 fp0 = tcg_temp_new_i64();
12680 TCGv_i64 fp1 = tcg_temp_new_i64();
12682 gen_load_fpr64(ctx, fp0, fs);
12683 gen_load_fpr64(ctx, fp1, ft);
12684 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12685 tcg_temp_free_i64(fp1);
12686 gen_store_fpr64(ctx, fp0, fd);
12687 tcg_temp_free_i64(fp0);
12689 break;
12690 case OPC_SUB_PS:
12691 check_ps(ctx);
12693 TCGv_i64 fp0 = tcg_temp_new_i64();
12694 TCGv_i64 fp1 = tcg_temp_new_i64();
12696 gen_load_fpr64(ctx, fp0, fs);
12697 gen_load_fpr64(ctx, fp1, ft);
12698 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12699 tcg_temp_free_i64(fp1);
12700 gen_store_fpr64(ctx, fp0, fd);
12701 tcg_temp_free_i64(fp0);
12703 break;
12704 case OPC_MUL_PS:
12705 check_ps(ctx);
12707 TCGv_i64 fp0 = tcg_temp_new_i64();
12708 TCGv_i64 fp1 = tcg_temp_new_i64();
12710 gen_load_fpr64(ctx, fp0, fs);
12711 gen_load_fpr64(ctx, fp1, ft);
12712 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12713 tcg_temp_free_i64(fp1);
12714 gen_store_fpr64(ctx, fp0, fd);
12715 tcg_temp_free_i64(fp0);
12717 break;
12718 case OPC_ABS_PS:
12719 check_ps(ctx);
12721 TCGv_i64 fp0 = tcg_temp_new_i64();
12723 gen_load_fpr64(ctx, fp0, fs);
12724 gen_helper_float_abs_ps(fp0, fp0);
12725 gen_store_fpr64(ctx, fp0, fd);
12726 tcg_temp_free_i64(fp0);
12728 break;
12729 case OPC_MOV_PS:
12730 check_ps(ctx);
12732 TCGv_i64 fp0 = tcg_temp_new_i64();
12734 gen_load_fpr64(ctx, fp0, fs);
12735 gen_store_fpr64(ctx, fp0, fd);
12736 tcg_temp_free_i64(fp0);
12738 break;
12739 case OPC_NEG_PS:
12740 check_ps(ctx);
12742 TCGv_i64 fp0 = tcg_temp_new_i64();
12744 gen_load_fpr64(ctx, fp0, fs);
12745 gen_helper_float_chs_ps(fp0, fp0);
12746 gen_store_fpr64(ctx, fp0, fd);
12747 tcg_temp_free_i64(fp0);
12749 break;
12750 case OPC_MOVCF_PS:
12751 check_ps(ctx);
12752 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12753 break;
12754 case OPC_MOVZ_PS:
12755 check_ps(ctx);
12757 TCGLabel *l1 = gen_new_label();
12758 TCGv_i64 fp0;
12760 if (ft != 0) {
12761 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12763 fp0 = tcg_temp_new_i64();
12764 gen_load_fpr64(ctx, fp0, fs);
12765 gen_store_fpr64(ctx, fp0, fd);
12766 tcg_temp_free_i64(fp0);
12767 gen_set_label(l1);
12769 break;
12770 case OPC_MOVN_PS:
12771 check_ps(ctx);
12773 TCGLabel *l1 = gen_new_label();
12774 TCGv_i64 fp0;
12776 if (ft != 0) {
12777 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12778 fp0 = tcg_temp_new_i64();
12779 gen_load_fpr64(ctx, fp0, fs);
12780 gen_store_fpr64(ctx, fp0, fd);
12781 tcg_temp_free_i64(fp0);
12782 gen_set_label(l1);
12785 break;
12786 case OPC_ADDR_PS:
12787 check_ps(ctx);
12789 TCGv_i64 fp0 = tcg_temp_new_i64();
12790 TCGv_i64 fp1 = tcg_temp_new_i64();
12792 gen_load_fpr64(ctx, fp0, ft);
12793 gen_load_fpr64(ctx, fp1, fs);
12794 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12795 tcg_temp_free_i64(fp1);
12796 gen_store_fpr64(ctx, fp0, fd);
12797 tcg_temp_free_i64(fp0);
12799 break;
12800 case OPC_MULR_PS:
12801 check_ps(ctx);
12803 TCGv_i64 fp0 = tcg_temp_new_i64();
12804 TCGv_i64 fp1 = tcg_temp_new_i64();
12806 gen_load_fpr64(ctx, fp0, ft);
12807 gen_load_fpr64(ctx, fp1, fs);
12808 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12809 tcg_temp_free_i64(fp1);
12810 gen_store_fpr64(ctx, fp0, fd);
12811 tcg_temp_free_i64(fp0);
12813 break;
12814 case OPC_RECIP2_PS:
12815 check_ps(ctx);
12817 TCGv_i64 fp0 = tcg_temp_new_i64();
12818 TCGv_i64 fp1 = tcg_temp_new_i64();
12820 gen_load_fpr64(ctx, fp0, fs);
12821 gen_load_fpr64(ctx, fp1, ft);
12822 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12823 tcg_temp_free_i64(fp1);
12824 gen_store_fpr64(ctx, fp0, fd);
12825 tcg_temp_free_i64(fp0);
12827 break;
12828 case OPC_RECIP1_PS:
12829 check_ps(ctx);
12831 TCGv_i64 fp0 = tcg_temp_new_i64();
12833 gen_load_fpr64(ctx, fp0, fs);
12834 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12835 gen_store_fpr64(ctx, fp0, fd);
12836 tcg_temp_free_i64(fp0);
12838 break;
12839 case OPC_RSQRT1_PS:
12840 check_ps(ctx);
12842 TCGv_i64 fp0 = tcg_temp_new_i64();
12844 gen_load_fpr64(ctx, fp0, fs);
12845 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12846 gen_store_fpr64(ctx, fp0, fd);
12847 tcg_temp_free_i64(fp0);
12849 break;
12850 case OPC_RSQRT2_PS:
12851 check_ps(ctx);
12853 TCGv_i64 fp0 = tcg_temp_new_i64();
12854 TCGv_i64 fp1 = tcg_temp_new_i64();
12856 gen_load_fpr64(ctx, fp0, fs);
12857 gen_load_fpr64(ctx, fp1, ft);
12858 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12859 tcg_temp_free_i64(fp1);
12860 gen_store_fpr64(ctx, fp0, fd);
12861 tcg_temp_free_i64(fp0);
12863 break;
12864 case OPC_CVT_S_PU:
12865 check_cp1_64bitmode(ctx);
12867 TCGv_i32 fp0 = tcg_temp_new_i32();
12869 gen_load_fpr32h(ctx, fp0, fs);
12870 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12871 gen_store_fpr32(ctx, fp0, fd);
12872 tcg_temp_free_i32(fp0);
12874 break;
12875 case OPC_CVT_PW_PS:
12876 check_ps(ctx);
12878 TCGv_i64 fp0 = tcg_temp_new_i64();
12880 gen_load_fpr64(ctx, fp0, fs);
12881 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
12882 gen_store_fpr64(ctx, fp0, fd);
12883 tcg_temp_free_i64(fp0);
12885 break;
12886 case OPC_CVT_S_PL:
12887 check_cp1_64bitmode(ctx);
12889 TCGv_i32 fp0 = tcg_temp_new_i32();
12891 gen_load_fpr32(ctx, fp0, fs);
12892 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
12893 gen_store_fpr32(ctx, fp0, fd);
12894 tcg_temp_free_i32(fp0);
12896 break;
12897 case OPC_PLL_PS:
12898 check_ps(ctx);
12900 TCGv_i32 fp0 = tcg_temp_new_i32();
12901 TCGv_i32 fp1 = tcg_temp_new_i32();
12903 gen_load_fpr32(ctx, fp0, fs);
12904 gen_load_fpr32(ctx, fp1, ft);
12905 gen_store_fpr32h(ctx, fp0, fd);
12906 gen_store_fpr32(ctx, fp1, fd);
12907 tcg_temp_free_i32(fp0);
12908 tcg_temp_free_i32(fp1);
12910 break;
12911 case OPC_PLU_PS:
12912 check_ps(ctx);
12914 TCGv_i32 fp0 = tcg_temp_new_i32();
12915 TCGv_i32 fp1 = tcg_temp_new_i32();
12917 gen_load_fpr32(ctx, fp0, fs);
12918 gen_load_fpr32h(ctx, fp1, ft);
12919 gen_store_fpr32(ctx, fp1, fd);
12920 gen_store_fpr32h(ctx, fp0, fd);
12921 tcg_temp_free_i32(fp0);
12922 tcg_temp_free_i32(fp1);
12924 break;
12925 case OPC_PUL_PS:
12926 check_ps(ctx);
12928 TCGv_i32 fp0 = tcg_temp_new_i32();
12929 TCGv_i32 fp1 = tcg_temp_new_i32();
12931 gen_load_fpr32h(ctx, fp0, fs);
12932 gen_load_fpr32(ctx, fp1, ft);
12933 gen_store_fpr32(ctx, fp1, fd);
12934 gen_store_fpr32h(ctx, fp0, fd);
12935 tcg_temp_free_i32(fp0);
12936 tcg_temp_free_i32(fp1);
12938 break;
12939 case OPC_PUU_PS:
12940 check_ps(ctx);
12942 TCGv_i32 fp0 = tcg_temp_new_i32();
12943 TCGv_i32 fp1 = tcg_temp_new_i32();
12945 gen_load_fpr32h(ctx, fp0, fs);
12946 gen_load_fpr32h(ctx, fp1, ft);
12947 gen_store_fpr32(ctx, fp1, fd);
12948 gen_store_fpr32h(ctx, fp0, fd);
12949 tcg_temp_free_i32(fp0);
12950 tcg_temp_free_i32(fp1);
12952 break;
12953 case OPC_CMP_F_PS:
12954 case OPC_CMP_UN_PS:
12955 case OPC_CMP_EQ_PS:
12956 case OPC_CMP_UEQ_PS:
12957 case OPC_CMP_OLT_PS:
12958 case OPC_CMP_ULT_PS:
12959 case OPC_CMP_OLE_PS:
12960 case OPC_CMP_ULE_PS:
12961 case OPC_CMP_SF_PS:
12962 case OPC_CMP_NGLE_PS:
12963 case OPC_CMP_SEQ_PS:
12964 case OPC_CMP_NGL_PS:
12965 case OPC_CMP_LT_PS:
12966 case OPC_CMP_NGE_PS:
12967 case OPC_CMP_LE_PS:
12968 case OPC_CMP_NGT_PS:
12969 if (ctx->opcode & (1 << 6)) {
12970 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
12971 } else {
12972 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
12974 break;
12975 default:
12976 MIPS_INVAL("farith");
12977 gen_reserved_instruction(ctx);
12978 return;
12982 /* Coprocessor 3 (FPU) */
12983 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
12984 int fd, int fs, int base, int index)
12986 TCGv t0 = tcg_temp_new();
12988 if (base == 0) {
12989 gen_load_gpr(t0, index);
12990 } else if (index == 0) {
12991 gen_load_gpr(t0, base);
12992 } else {
12993 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
12996 * Don't do NOP if destination is zero: we must perform the actual
12997 * memory access.
12999 switch (opc) {
13000 case OPC_LWXC1:
13001 check_cop1x(ctx);
13003 TCGv_i32 fp0 = tcg_temp_new_i32();
13005 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
13006 tcg_gen_trunc_tl_i32(fp0, t0);
13007 gen_store_fpr32(ctx, fp0, fd);
13008 tcg_temp_free_i32(fp0);
13010 break;
13011 case OPC_LDXC1:
13012 check_cop1x(ctx);
13013 check_cp1_registers(ctx, fd);
13015 TCGv_i64 fp0 = tcg_temp_new_i64();
13016 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13017 gen_store_fpr64(ctx, fp0, fd);
13018 tcg_temp_free_i64(fp0);
13020 break;
13021 case OPC_LUXC1:
13022 check_cp1_64bitmode(ctx);
13023 tcg_gen_andi_tl(t0, t0, ~0x7);
13025 TCGv_i64 fp0 = tcg_temp_new_i64();
13027 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13028 gen_store_fpr64(ctx, fp0, fd);
13029 tcg_temp_free_i64(fp0);
13031 break;
13032 case OPC_SWXC1:
13033 check_cop1x(ctx);
13035 TCGv_i32 fp0 = tcg_temp_new_i32();
13036 gen_load_fpr32(ctx, fp0, fs);
13037 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
13038 tcg_temp_free_i32(fp0);
13040 break;
13041 case OPC_SDXC1:
13042 check_cop1x(ctx);
13043 check_cp1_registers(ctx, fs);
13045 TCGv_i64 fp0 = tcg_temp_new_i64();
13046 gen_load_fpr64(ctx, fp0, fs);
13047 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13048 tcg_temp_free_i64(fp0);
13050 break;
13051 case OPC_SUXC1:
13052 check_cp1_64bitmode(ctx);
13053 tcg_gen_andi_tl(t0, t0, ~0x7);
13055 TCGv_i64 fp0 = tcg_temp_new_i64();
13056 gen_load_fpr64(ctx, fp0, fs);
13057 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13058 tcg_temp_free_i64(fp0);
13060 break;
13062 tcg_temp_free(t0);
13065 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
13066 int fd, int fr, int fs, int ft)
13068 switch (opc) {
13069 case OPC_ALNV_PS:
13070 check_ps(ctx);
13072 TCGv t0 = tcg_temp_local_new();
13073 TCGv_i32 fp = tcg_temp_new_i32();
13074 TCGv_i32 fph = tcg_temp_new_i32();
13075 TCGLabel *l1 = gen_new_label();
13076 TCGLabel *l2 = gen_new_label();
13078 gen_load_gpr(t0, fr);
13079 tcg_gen_andi_tl(t0, t0, 0x7);
13081 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
13082 gen_load_fpr32(ctx, fp, fs);
13083 gen_load_fpr32h(ctx, fph, fs);
13084 gen_store_fpr32(ctx, fp, fd);
13085 gen_store_fpr32h(ctx, fph, fd);
13086 tcg_gen_br(l2);
13087 gen_set_label(l1);
13088 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
13089 tcg_temp_free(t0);
13090 #ifdef TARGET_WORDS_BIGENDIAN
13091 gen_load_fpr32(ctx, fp, fs);
13092 gen_load_fpr32h(ctx, fph, ft);
13093 gen_store_fpr32h(ctx, fp, fd);
13094 gen_store_fpr32(ctx, fph, fd);
13095 #else
13096 gen_load_fpr32h(ctx, fph, fs);
13097 gen_load_fpr32(ctx, fp, ft);
13098 gen_store_fpr32(ctx, fph, fd);
13099 gen_store_fpr32h(ctx, fp, fd);
13100 #endif
13101 gen_set_label(l2);
13102 tcg_temp_free_i32(fp);
13103 tcg_temp_free_i32(fph);
13105 break;
13106 case OPC_MADD_S:
13107 check_cop1x(ctx);
13109 TCGv_i32 fp0 = tcg_temp_new_i32();
13110 TCGv_i32 fp1 = tcg_temp_new_i32();
13111 TCGv_i32 fp2 = tcg_temp_new_i32();
13113 gen_load_fpr32(ctx, fp0, fs);
13114 gen_load_fpr32(ctx, fp1, ft);
13115 gen_load_fpr32(ctx, fp2, fr);
13116 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
13117 tcg_temp_free_i32(fp0);
13118 tcg_temp_free_i32(fp1);
13119 gen_store_fpr32(ctx, fp2, fd);
13120 tcg_temp_free_i32(fp2);
13122 break;
13123 case OPC_MADD_D:
13124 check_cop1x(ctx);
13125 check_cp1_registers(ctx, fd | fs | ft | fr);
13127 TCGv_i64 fp0 = tcg_temp_new_i64();
13128 TCGv_i64 fp1 = tcg_temp_new_i64();
13129 TCGv_i64 fp2 = tcg_temp_new_i64();
13131 gen_load_fpr64(ctx, fp0, fs);
13132 gen_load_fpr64(ctx, fp1, ft);
13133 gen_load_fpr64(ctx, fp2, fr);
13134 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
13135 tcg_temp_free_i64(fp0);
13136 tcg_temp_free_i64(fp1);
13137 gen_store_fpr64(ctx, fp2, fd);
13138 tcg_temp_free_i64(fp2);
13140 break;
13141 case OPC_MADD_PS:
13142 check_ps(ctx);
13144 TCGv_i64 fp0 = tcg_temp_new_i64();
13145 TCGv_i64 fp1 = tcg_temp_new_i64();
13146 TCGv_i64 fp2 = tcg_temp_new_i64();
13148 gen_load_fpr64(ctx, fp0, fs);
13149 gen_load_fpr64(ctx, fp1, ft);
13150 gen_load_fpr64(ctx, fp2, fr);
13151 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
13152 tcg_temp_free_i64(fp0);
13153 tcg_temp_free_i64(fp1);
13154 gen_store_fpr64(ctx, fp2, fd);
13155 tcg_temp_free_i64(fp2);
13157 break;
13158 case OPC_MSUB_S:
13159 check_cop1x(ctx);
13161 TCGv_i32 fp0 = tcg_temp_new_i32();
13162 TCGv_i32 fp1 = tcg_temp_new_i32();
13163 TCGv_i32 fp2 = tcg_temp_new_i32();
13165 gen_load_fpr32(ctx, fp0, fs);
13166 gen_load_fpr32(ctx, fp1, ft);
13167 gen_load_fpr32(ctx, fp2, fr);
13168 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
13169 tcg_temp_free_i32(fp0);
13170 tcg_temp_free_i32(fp1);
13171 gen_store_fpr32(ctx, fp2, fd);
13172 tcg_temp_free_i32(fp2);
13174 break;
13175 case OPC_MSUB_D:
13176 check_cop1x(ctx);
13177 check_cp1_registers(ctx, fd | fs | ft | fr);
13179 TCGv_i64 fp0 = tcg_temp_new_i64();
13180 TCGv_i64 fp1 = tcg_temp_new_i64();
13181 TCGv_i64 fp2 = tcg_temp_new_i64();
13183 gen_load_fpr64(ctx, fp0, fs);
13184 gen_load_fpr64(ctx, fp1, ft);
13185 gen_load_fpr64(ctx, fp2, fr);
13186 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
13187 tcg_temp_free_i64(fp0);
13188 tcg_temp_free_i64(fp1);
13189 gen_store_fpr64(ctx, fp2, fd);
13190 tcg_temp_free_i64(fp2);
13192 break;
13193 case OPC_MSUB_PS:
13194 check_ps(ctx);
13196 TCGv_i64 fp0 = tcg_temp_new_i64();
13197 TCGv_i64 fp1 = tcg_temp_new_i64();
13198 TCGv_i64 fp2 = tcg_temp_new_i64();
13200 gen_load_fpr64(ctx, fp0, fs);
13201 gen_load_fpr64(ctx, fp1, ft);
13202 gen_load_fpr64(ctx, fp2, fr);
13203 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
13204 tcg_temp_free_i64(fp0);
13205 tcg_temp_free_i64(fp1);
13206 gen_store_fpr64(ctx, fp2, fd);
13207 tcg_temp_free_i64(fp2);
13209 break;
13210 case OPC_NMADD_S:
13211 check_cop1x(ctx);
13213 TCGv_i32 fp0 = tcg_temp_new_i32();
13214 TCGv_i32 fp1 = tcg_temp_new_i32();
13215 TCGv_i32 fp2 = tcg_temp_new_i32();
13217 gen_load_fpr32(ctx, fp0, fs);
13218 gen_load_fpr32(ctx, fp1, ft);
13219 gen_load_fpr32(ctx, fp2, fr);
13220 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
13221 tcg_temp_free_i32(fp0);
13222 tcg_temp_free_i32(fp1);
13223 gen_store_fpr32(ctx, fp2, fd);
13224 tcg_temp_free_i32(fp2);
13226 break;
13227 case OPC_NMADD_D:
13228 check_cop1x(ctx);
13229 check_cp1_registers(ctx, fd | fs | ft | fr);
13231 TCGv_i64 fp0 = tcg_temp_new_i64();
13232 TCGv_i64 fp1 = tcg_temp_new_i64();
13233 TCGv_i64 fp2 = tcg_temp_new_i64();
13235 gen_load_fpr64(ctx, fp0, fs);
13236 gen_load_fpr64(ctx, fp1, ft);
13237 gen_load_fpr64(ctx, fp2, fr);
13238 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
13239 tcg_temp_free_i64(fp0);
13240 tcg_temp_free_i64(fp1);
13241 gen_store_fpr64(ctx, fp2, fd);
13242 tcg_temp_free_i64(fp2);
13244 break;
13245 case OPC_NMADD_PS:
13246 check_ps(ctx);
13248 TCGv_i64 fp0 = tcg_temp_new_i64();
13249 TCGv_i64 fp1 = tcg_temp_new_i64();
13250 TCGv_i64 fp2 = tcg_temp_new_i64();
13252 gen_load_fpr64(ctx, fp0, fs);
13253 gen_load_fpr64(ctx, fp1, ft);
13254 gen_load_fpr64(ctx, fp2, fr);
13255 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
13256 tcg_temp_free_i64(fp0);
13257 tcg_temp_free_i64(fp1);
13258 gen_store_fpr64(ctx, fp2, fd);
13259 tcg_temp_free_i64(fp2);
13261 break;
13262 case OPC_NMSUB_S:
13263 check_cop1x(ctx);
13265 TCGv_i32 fp0 = tcg_temp_new_i32();
13266 TCGv_i32 fp1 = tcg_temp_new_i32();
13267 TCGv_i32 fp2 = tcg_temp_new_i32();
13269 gen_load_fpr32(ctx, fp0, fs);
13270 gen_load_fpr32(ctx, fp1, ft);
13271 gen_load_fpr32(ctx, fp2, fr);
13272 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
13273 tcg_temp_free_i32(fp0);
13274 tcg_temp_free_i32(fp1);
13275 gen_store_fpr32(ctx, fp2, fd);
13276 tcg_temp_free_i32(fp2);
13278 break;
13279 case OPC_NMSUB_D:
13280 check_cop1x(ctx);
13281 check_cp1_registers(ctx, fd | fs | ft | fr);
13283 TCGv_i64 fp0 = tcg_temp_new_i64();
13284 TCGv_i64 fp1 = tcg_temp_new_i64();
13285 TCGv_i64 fp2 = tcg_temp_new_i64();
13287 gen_load_fpr64(ctx, fp0, fs);
13288 gen_load_fpr64(ctx, fp1, ft);
13289 gen_load_fpr64(ctx, fp2, fr);
13290 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
13291 tcg_temp_free_i64(fp0);
13292 tcg_temp_free_i64(fp1);
13293 gen_store_fpr64(ctx, fp2, fd);
13294 tcg_temp_free_i64(fp2);
13296 break;
13297 case OPC_NMSUB_PS:
13298 check_ps(ctx);
13300 TCGv_i64 fp0 = tcg_temp_new_i64();
13301 TCGv_i64 fp1 = tcg_temp_new_i64();
13302 TCGv_i64 fp2 = tcg_temp_new_i64();
13304 gen_load_fpr64(ctx, fp0, fs);
13305 gen_load_fpr64(ctx, fp1, ft);
13306 gen_load_fpr64(ctx, fp2, fr);
13307 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
13308 tcg_temp_free_i64(fp0);
13309 tcg_temp_free_i64(fp1);
13310 gen_store_fpr64(ctx, fp2, fd);
13311 tcg_temp_free_i64(fp2);
13313 break;
13314 default:
13315 MIPS_INVAL("flt3_arith");
13316 gen_reserved_instruction(ctx);
13317 return;
13321 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13323 TCGv t0;
13325 #if !defined(CONFIG_USER_ONLY)
13327 * The Linux kernel will emulate rdhwr if it's not supported natively.
13328 * Therefore only check the ISA in system mode.
13330 check_insn(ctx, ISA_MIPS_R2);
13331 #endif
13332 t0 = tcg_temp_new();
13334 switch (rd) {
13335 case 0:
13336 gen_helper_rdhwr_cpunum(t0, cpu_env);
13337 gen_store_gpr(t0, rt);
13338 break;
13339 case 1:
13340 gen_helper_rdhwr_synci_step(t0, cpu_env);
13341 gen_store_gpr(t0, rt);
13342 break;
13343 case 2:
13344 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13345 gen_io_start();
13347 gen_helper_rdhwr_cc(t0, cpu_env);
13348 gen_store_gpr(t0, rt);
13350 * Break the TB to be able to take timer interrupts immediately
13351 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13352 * we break completely out of translated code.
13354 gen_save_pc(ctx->base.pc_next + 4);
13355 ctx->base.is_jmp = DISAS_EXIT;
13356 break;
13357 case 3:
13358 gen_helper_rdhwr_ccres(t0, cpu_env);
13359 gen_store_gpr(t0, rt);
13360 break;
13361 case 4:
13362 check_insn(ctx, ISA_MIPS_R6);
13363 if (sel != 0) {
13365 * Performance counter registers are not implemented other than
13366 * control register 0.
13368 generate_exception(ctx, EXCP_RI);
13370 gen_helper_rdhwr_performance(t0, cpu_env);
13371 gen_store_gpr(t0, rt);
13372 break;
13373 case 5:
13374 check_insn(ctx, ISA_MIPS_R6);
13375 gen_helper_rdhwr_xnp(t0, cpu_env);
13376 gen_store_gpr(t0, rt);
13377 break;
13378 case 29:
13379 #if defined(CONFIG_USER_ONLY)
13380 tcg_gen_ld_tl(t0, cpu_env,
13381 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13382 gen_store_gpr(t0, rt);
13383 break;
13384 #else
13385 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13386 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13387 tcg_gen_ld_tl(t0, cpu_env,
13388 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13389 gen_store_gpr(t0, rt);
13390 } else {
13391 gen_reserved_instruction(ctx);
13393 break;
13394 #endif
13395 default: /* Invalid */
13396 MIPS_INVAL("rdhwr");
13397 gen_reserved_instruction(ctx);
13398 break;
13400 tcg_temp_free(t0);
13403 static inline void clear_branch_hflags(DisasContext *ctx)
13405 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13406 if (ctx->base.is_jmp == DISAS_NEXT) {
13407 save_cpu_state(ctx, 0);
13408 } else {
13410 * It is not safe to save ctx->hflags as hflags may be changed
13411 * in execution time by the instruction in delay / forbidden slot.
13413 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13417 static void gen_branch(DisasContext *ctx, int insn_bytes)
13419 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13420 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13421 /* Branches completion */
13422 clear_branch_hflags(ctx);
13423 ctx->base.is_jmp = DISAS_NORETURN;
13424 /* FIXME: Need to clear can_do_io. */
13425 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13426 case MIPS_HFLAG_FBNSLOT:
13427 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13428 break;
13429 case MIPS_HFLAG_B:
13430 /* unconditional branch */
13431 if (proc_hflags & MIPS_HFLAG_BX) {
13432 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13434 gen_goto_tb(ctx, 0, ctx->btarget);
13435 break;
13436 case MIPS_HFLAG_BL:
13437 /* blikely taken case */
13438 gen_goto_tb(ctx, 0, ctx->btarget);
13439 break;
13440 case MIPS_HFLAG_BC:
13441 /* Conditional branch */
13443 TCGLabel *l1 = gen_new_label();
13445 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13446 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13447 gen_set_label(l1);
13448 gen_goto_tb(ctx, 0, ctx->btarget);
13450 break;
13451 case MIPS_HFLAG_BR:
13452 /* unconditional branch to register */
13453 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13454 TCGv t0 = tcg_temp_new();
13455 TCGv_i32 t1 = tcg_temp_new_i32();
13457 tcg_gen_andi_tl(t0, btarget, 0x1);
13458 tcg_gen_trunc_tl_i32(t1, t0);
13459 tcg_temp_free(t0);
13460 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13461 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13462 tcg_gen_or_i32(hflags, hflags, t1);
13463 tcg_temp_free_i32(t1);
13465 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13466 } else {
13467 tcg_gen_mov_tl(cpu_PC, btarget);
13469 if (ctx->base.singlestep_enabled) {
13470 save_cpu_state(ctx, 0);
13471 gen_helper_raise_exception_debug(cpu_env);
13473 tcg_gen_lookup_and_goto_ptr();
13474 break;
13475 default:
13476 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13477 abort();
13482 /* Compact Branches */
13483 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13484 int rs, int rt, int32_t offset)
13486 int bcond_compute = 0;
13487 TCGv t0 = tcg_temp_new();
13488 TCGv t1 = tcg_temp_new();
13489 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13491 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13492 #ifdef MIPS_DEBUG_DISAS
13493 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13494 "\n", ctx->base.pc_next);
13495 #endif
13496 gen_reserved_instruction(ctx);
13497 goto out;
13500 /* Load needed operands and calculate btarget */
13501 switch (opc) {
13502 /* compact branch */
13503 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13504 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13505 gen_load_gpr(t0, rs);
13506 gen_load_gpr(t1, rt);
13507 bcond_compute = 1;
13508 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13509 if (rs <= rt && rs == 0) {
13510 /* OPC_BEQZALC, OPC_BNEZALC */
13511 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13513 break;
13514 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13515 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13516 gen_load_gpr(t0, rs);
13517 gen_load_gpr(t1, rt);
13518 bcond_compute = 1;
13519 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13520 break;
13521 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13522 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13523 if (rs == 0 || rs == rt) {
13524 /* OPC_BLEZALC, OPC_BGEZALC */
13525 /* OPC_BGTZALC, OPC_BLTZALC */
13526 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13528 gen_load_gpr(t0, rs);
13529 gen_load_gpr(t1, rt);
13530 bcond_compute = 1;
13531 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13532 break;
13533 case OPC_BC:
13534 case OPC_BALC:
13535 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13536 break;
13537 case OPC_BEQZC:
13538 case OPC_BNEZC:
13539 if (rs != 0) {
13540 /* OPC_BEQZC, OPC_BNEZC */
13541 gen_load_gpr(t0, rs);
13542 bcond_compute = 1;
13543 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13544 } else {
13545 /* OPC_JIC, OPC_JIALC */
13546 TCGv tbase = tcg_temp_new();
13547 TCGv toffset = tcg_temp_new();
13549 gen_load_gpr(tbase, rt);
13550 tcg_gen_movi_tl(toffset, offset);
13551 gen_op_addr_add(ctx, btarget, tbase, toffset);
13552 tcg_temp_free(tbase);
13553 tcg_temp_free(toffset);
13555 break;
13556 default:
13557 MIPS_INVAL("Compact branch/jump");
13558 gen_reserved_instruction(ctx);
13559 goto out;
13562 if (bcond_compute == 0) {
13563 /* Uncoditional compact branch */
13564 switch (opc) {
13565 case OPC_JIALC:
13566 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13567 /* Fallthrough */
13568 case OPC_JIC:
13569 ctx->hflags |= MIPS_HFLAG_BR;
13570 break;
13571 case OPC_BALC:
13572 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13573 /* Fallthrough */
13574 case OPC_BC:
13575 ctx->hflags |= MIPS_HFLAG_B;
13576 break;
13577 default:
13578 MIPS_INVAL("Compact branch/jump");
13579 gen_reserved_instruction(ctx);
13580 goto out;
13583 /* Generating branch here as compact branches don't have delay slot */
13584 gen_branch(ctx, 4);
13585 } else {
13586 /* Conditional compact branch */
13587 TCGLabel *fs = gen_new_label();
13588 save_cpu_state(ctx, 0);
13590 switch (opc) {
13591 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13592 if (rs == 0 && rt != 0) {
13593 /* OPC_BLEZALC */
13594 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13595 } else if (rs != 0 && rt != 0 && rs == rt) {
13596 /* OPC_BGEZALC */
13597 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13598 } else {
13599 /* OPC_BGEUC */
13600 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13602 break;
13603 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13604 if (rs == 0 && rt != 0) {
13605 /* OPC_BGTZALC */
13606 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13607 } else if (rs != 0 && rt != 0 && rs == rt) {
13608 /* OPC_BLTZALC */
13609 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13610 } else {
13611 /* OPC_BLTUC */
13612 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13614 break;
13615 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13616 if (rs == 0 && rt != 0) {
13617 /* OPC_BLEZC */
13618 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13619 } else if (rs != 0 && rt != 0 && rs == rt) {
13620 /* OPC_BGEZC */
13621 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13622 } else {
13623 /* OPC_BGEC */
13624 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13626 break;
13627 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13628 if (rs == 0 && rt != 0) {
13629 /* OPC_BGTZC */
13630 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13631 } else if (rs != 0 && rt != 0 && rs == rt) {
13632 /* OPC_BLTZC */
13633 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13634 } else {
13635 /* OPC_BLTC */
13636 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13638 break;
13639 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13640 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13641 if (rs >= rt) {
13642 /* OPC_BOVC, OPC_BNVC */
13643 TCGv t2 = tcg_temp_new();
13644 TCGv t3 = tcg_temp_new();
13645 TCGv t4 = tcg_temp_new();
13646 TCGv input_overflow = tcg_temp_new();
13648 gen_load_gpr(t0, rs);
13649 gen_load_gpr(t1, rt);
13650 tcg_gen_ext32s_tl(t2, t0);
13651 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13652 tcg_gen_ext32s_tl(t3, t1);
13653 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13654 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13656 tcg_gen_add_tl(t4, t2, t3);
13657 tcg_gen_ext32s_tl(t4, t4);
13658 tcg_gen_xor_tl(t2, t2, t3);
13659 tcg_gen_xor_tl(t3, t4, t3);
13660 tcg_gen_andc_tl(t2, t3, t2);
13661 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13662 tcg_gen_or_tl(t4, t4, input_overflow);
13663 if (opc == OPC_BOVC) {
13664 /* OPC_BOVC */
13665 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13666 } else {
13667 /* OPC_BNVC */
13668 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13670 tcg_temp_free(input_overflow);
13671 tcg_temp_free(t4);
13672 tcg_temp_free(t3);
13673 tcg_temp_free(t2);
13674 } else if (rs < rt && rs == 0) {
13675 /* OPC_BEQZALC, OPC_BNEZALC */
13676 if (opc == OPC_BEQZALC) {
13677 /* OPC_BEQZALC */
13678 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13679 } else {
13680 /* OPC_BNEZALC */
13681 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13683 } else {
13684 /* OPC_BEQC, OPC_BNEC */
13685 if (opc == OPC_BEQC) {
13686 /* OPC_BEQC */
13687 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13688 } else {
13689 /* OPC_BNEC */
13690 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13693 break;
13694 case OPC_BEQZC:
13695 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13696 break;
13697 case OPC_BNEZC:
13698 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13699 break;
13700 default:
13701 MIPS_INVAL("Compact conditional branch/jump");
13702 gen_reserved_instruction(ctx);
13703 goto out;
13706 /* Generating branch here as compact branches don't have delay slot */
13707 gen_goto_tb(ctx, 1, ctx->btarget);
13708 gen_set_label(fs);
13710 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13713 out:
13714 tcg_temp_free(t0);
13715 tcg_temp_free(t1);
13718 /* ISA extensions (ASEs) */
13719 /* MIPS16 extension to MIPS32 */
13721 /* MIPS16 major opcodes */
13722 enum {
13723 M16_OPC_ADDIUSP = 0x00,
13724 M16_OPC_ADDIUPC = 0x01,
13725 M16_OPC_B = 0x02,
13726 M16_OPC_JAL = 0x03,
13727 M16_OPC_BEQZ = 0x04,
13728 M16_OPC_BNEQZ = 0x05,
13729 M16_OPC_SHIFT = 0x06,
13730 M16_OPC_LD = 0x07,
13731 M16_OPC_RRIA = 0x08,
13732 M16_OPC_ADDIU8 = 0x09,
13733 M16_OPC_SLTI = 0x0a,
13734 M16_OPC_SLTIU = 0x0b,
13735 M16_OPC_I8 = 0x0c,
13736 M16_OPC_LI = 0x0d,
13737 M16_OPC_CMPI = 0x0e,
13738 M16_OPC_SD = 0x0f,
13739 M16_OPC_LB = 0x10,
13740 M16_OPC_LH = 0x11,
13741 M16_OPC_LWSP = 0x12,
13742 M16_OPC_LW = 0x13,
13743 M16_OPC_LBU = 0x14,
13744 M16_OPC_LHU = 0x15,
13745 M16_OPC_LWPC = 0x16,
13746 M16_OPC_LWU = 0x17,
13747 M16_OPC_SB = 0x18,
13748 M16_OPC_SH = 0x19,
13749 M16_OPC_SWSP = 0x1a,
13750 M16_OPC_SW = 0x1b,
13751 M16_OPC_RRR = 0x1c,
13752 M16_OPC_RR = 0x1d,
13753 M16_OPC_EXTEND = 0x1e,
13754 M16_OPC_I64 = 0x1f
13757 /* I8 funct field */
13758 enum {
13759 I8_BTEQZ = 0x0,
13760 I8_BTNEZ = 0x1,
13761 I8_SWRASP = 0x2,
13762 I8_ADJSP = 0x3,
13763 I8_SVRS = 0x4,
13764 I8_MOV32R = 0x5,
13765 I8_MOVR32 = 0x7
13768 /* RRR f field */
13769 enum {
13770 RRR_DADDU = 0x0,
13771 RRR_ADDU = 0x1,
13772 RRR_DSUBU = 0x2,
13773 RRR_SUBU = 0x3
13776 /* RR funct field */
13777 enum {
13778 RR_JR = 0x00,
13779 RR_SDBBP = 0x01,
13780 RR_SLT = 0x02,
13781 RR_SLTU = 0x03,
13782 RR_SLLV = 0x04,
13783 RR_BREAK = 0x05,
13784 RR_SRLV = 0x06,
13785 RR_SRAV = 0x07,
13786 RR_DSRL = 0x08,
13787 RR_CMP = 0x0a,
13788 RR_NEG = 0x0b,
13789 RR_AND = 0x0c,
13790 RR_OR = 0x0d,
13791 RR_XOR = 0x0e,
13792 RR_NOT = 0x0f,
13793 RR_MFHI = 0x10,
13794 RR_CNVT = 0x11,
13795 RR_MFLO = 0x12,
13796 RR_DSRA = 0x13,
13797 RR_DSLLV = 0x14,
13798 RR_DSRLV = 0x16,
13799 RR_DSRAV = 0x17,
13800 RR_MULT = 0x18,
13801 RR_MULTU = 0x19,
13802 RR_DIV = 0x1a,
13803 RR_DIVU = 0x1b,
13804 RR_DMULT = 0x1c,
13805 RR_DMULTU = 0x1d,
13806 RR_DDIV = 0x1e,
13807 RR_DDIVU = 0x1f
13810 /* I64 funct field */
13811 enum {
13812 I64_LDSP = 0x0,
13813 I64_SDSP = 0x1,
13814 I64_SDRASP = 0x2,
13815 I64_DADJSP = 0x3,
13816 I64_LDPC = 0x4,
13817 I64_DADDIU5 = 0x5,
13818 I64_DADDIUPC = 0x6,
13819 I64_DADDIUSP = 0x7
13822 /* RR ry field for CNVT */
13823 enum {
13824 RR_RY_CNVT_ZEB = 0x0,
13825 RR_RY_CNVT_ZEH = 0x1,
13826 RR_RY_CNVT_ZEW = 0x2,
13827 RR_RY_CNVT_SEB = 0x4,
13828 RR_RY_CNVT_SEH = 0x5,
13829 RR_RY_CNVT_SEW = 0x6,
13832 static int xlat(int r)
13834 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13836 return map[r];
13839 static void gen_mips16_save(DisasContext *ctx,
13840 int xsregs, int aregs,
13841 int do_ra, int do_s0, int do_s1,
13842 int framesize)
13844 TCGv t0 = tcg_temp_new();
13845 TCGv t1 = tcg_temp_new();
13846 TCGv t2 = tcg_temp_new();
13847 int args, astatic;
13849 switch (aregs) {
13850 case 0:
13851 case 1:
13852 case 2:
13853 case 3:
13854 case 11:
13855 args = 0;
13856 break;
13857 case 4:
13858 case 5:
13859 case 6:
13860 case 7:
13861 args = 1;
13862 break;
13863 case 8:
13864 case 9:
13865 case 10:
13866 args = 2;
13867 break;
13868 case 12:
13869 case 13:
13870 args = 3;
13871 break;
13872 case 14:
13873 args = 4;
13874 break;
13875 default:
13876 gen_reserved_instruction(ctx);
13877 return;
13880 switch (args) {
13881 case 4:
13882 gen_base_offset_addr(ctx, t0, 29, 12);
13883 gen_load_gpr(t1, 7);
13884 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13885 /* Fall through */
13886 case 3:
13887 gen_base_offset_addr(ctx, t0, 29, 8);
13888 gen_load_gpr(t1, 6);
13889 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13890 /* Fall through */
13891 case 2:
13892 gen_base_offset_addr(ctx, t0, 29, 4);
13893 gen_load_gpr(t1, 5);
13894 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13895 /* Fall through */
13896 case 1:
13897 gen_base_offset_addr(ctx, t0, 29, 0);
13898 gen_load_gpr(t1, 4);
13899 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
13902 gen_load_gpr(t0, 29);
13904 #define DECR_AND_STORE(reg) do { \
13905 tcg_gen_movi_tl(t2, -4); \
13906 gen_op_addr_add(ctx, t0, t0, t2); \
13907 gen_load_gpr(t1, reg); \
13908 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
13909 } while (0)
13911 if (do_ra) {
13912 DECR_AND_STORE(31);
13915 switch (xsregs) {
13916 case 7:
13917 DECR_AND_STORE(30);
13918 /* Fall through */
13919 case 6:
13920 DECR_AND_STORE(23);
13921 /* Fall through */
13922 case 5:
13923 DECR_AND_STORE(22);
13924 /* Fall through */
13925 case 4:
13926 DECR_AND_STORE(21);
13927 /* Fall through */
13928 case 3:
13929 DECR_AND_STORE(20);
13930 /* Fall through */
13931 case 2:
13932 DECR_AND_STORE(19);
13933 /* Fall through */
13934 case 1:
13935 DECR_AND_STORE(18);
13938 if (do_s1) {
13939 DECR_AND_STORE(17);
13941 if (do_s0) {
13942 DECR_AND_STORE(16);
13945 switch (aregs) {
13946 case 0:
13947 case 4:
13948 case 8:
13949 case 12:
13950 case 14:
13951 astatic = 0;
13952 break;
13953 case 1:
13954 case 5:
13955 case 9:
13956 case 13:
13957 astatic = 1;
13958 break;
13959 case 2:
13960 case 6:
13961 case 10:
13962 astatic = 2;
13963 break;
13964 case 3:
13965 case 7:
13966 astatic = 3;
13967 break;
13968 case 11:
13969 astatic = 4;
13970 break;
13971 default:
13972 gen_reserved_instruction(ctx);
13973 return;
13976 if (astatic > 0) {
13977 DECR_AND_STORE(7);
13978 if (astatic > 1) {
13979 DECR_AND_STORE(6);
13980 if (astatic > 2) {
13981 DECR_AND_STORE(5);
13982 if (astatic > 3) {
13983 DECR_AND_STORE(4);
13988 #undef DECR_AND_STORE
13990 tcg_gen_movi_tl(t2, -framesize);
13991 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
13992 tcg_temp_free(t0);
13993 tcg_temp_free(t1);
13994 tcg_temp_free(t2);
13997 static void gen_mips16_restore(DisasContext *ctx,
13998 int xsregs, int aregs,
13999 int do_ra, int do_s0, int do_s1,
14000 int framesize)
14002 int astatic;
14003 TCGv t0 = tcg_temp_new();
14004 TCGv t1 = tcg_temp_new();
14005 TCGv t2 = tcg_temp_new();
14007 tcg_gen_movi_tl(t2, framesize);
14008 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
14010 #define DECR_AND_LOAD(reg) do { \
14011 tcg_gen_movi_tl(t2, -4); \
14012 gen_op_addr_add(ctx, t0, t0, t2); \
14013 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
14014 gen_store_gpr(t1, reg); \
14015 } while (0)
14017 if (do_ra) {
14018 DECR_AND_LOAD(31);
14021 switch (xsregs) {
14022 case 7:
14023 DECR_AND_LOAD(30);
14024 /* Fall through */
14025 case 6:
14026 DECR_AND_LOAD(23);
14027 /* Fall through */
14028 case 5:
14029 DECR_AND_LOAD(22);
14030 /* Fall through */
14031 case 4:
14032 DECR_AND_LOAD(21);
14033 /* Fall through */
14034 case 3:
14035 DECR_AND_LOAD(20);
14036 /* Fall through */
14037 case 2:
14038 DECR_AND_LOAD(19);
14039 /* Fall through */
14040 case 1:
14041 DECR_AND_LOAD(18);
14044 if (do_s1) {
14045 DECR_AND_LOAD(17);
14047 if (do_s0) {
14048 DECR_AND_LOAD(16);
14051 switch (aregs) {
14052 case 0:
14053 case 4:
14054 case 8:
14055 case 12:
14056 case 14:
14057 astatic = 0;
14058 break;
14059 case 1:
14060 case 5:
14061 case 9:
14062 case 13:
14063 astatic = 1;
14064 break;
14065 case 2:
14066 case 6:
14067 case 10:
14068 astatic = 2;
14069 break;
14070 case 3:
14071 case 7:
14072 astatic = 3;
14073 break;
14074 case 11:
14075 astatic = 4;
14076 break;
14077 default:
14078 gen_reserved_instruction(ctx);
14079 return;
14082 if (astatic > 0) {
14083 DECR_AND_LOAD(7);
14084 if (astatic > 1) {
14085 DECR_AND_LOAD(6);
14086 if (astatic > 2) {
14087 DECR_AND_LOAD(5);
14088 if (astatic > 3) {
14089 DECR_AND_LOAD(4);
14094 #undef DECR_AND_LOAD
14096 tcg_gen_movi_tl(t2, framesize);
14097 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14098 tcg_temp_free(t0);
14099 tcg_temp_free(t1);
14100 tcg_temp_free(t2);
14103 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
14104 int is_64_bit, int extended)
14106 TCGv t0;
14108 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14109 gen_reserved_instruction(ctx);
14110 return;
14113 t0 = tcg_temp_new();
14115 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
14116 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
14117 if (!is_64_bit) {
14118 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14121 tcg_temp_free(t0);
14124 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
14125 int16_t offset)
14127 TCGv_i32 t0 = tcg_const_i32(op);
14128 TCGv t1 = tcg_temp_new();
14129 gen_base_offset_addr(ctx, t1, base, offset);
14130 gen_helper_cache(cpu_env, t1, t0);
14133 #if defined(TARGET_MIPS64)
14134 static void decode_i64_mips16(DisasContext *ctx,
14135 int ry, int funct, int16_t offset,
14136 int extended)
14138 switch (funct) {
14139 case I64_LDSP:
14140 check_insn(ctx, ISA_MIPS3);
14141 check_mips_64(ctx);
14142 offset = extended ? offset : offset << 3;
14143 gen_ld(ctx, OPC_LD, ry, 29, offset);
14144 break;
14145 case I64_SDSP:
14146 check_insn(ctx, ISA_MIPS3);
14147 check_mips_64(ctx);
14148 offset = extended ? offset : offset << 3;
14149 gen_st(ctx, OPC_SD, ry, 29, offset);
14150 break;
14151 case I64_SDRASP:
14152 check_insn(ctx, ISA_MIPS3);
14153 check_mips_64(ctx);
14154 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
14155 gen_st(ctx, OPC_SD, 31, 29, offset);
14156 break;
14157 case I64_DADJSP:
14158 check_insn(ctx, ISA_MIPS3);
14159 check_mips_64(ctx);
14160 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
14161 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
14162 break;
14163 case I64_LDPC:
14164 check_insn(ctx, ISA_MIPS3);
14165 check_mips_64(ctx);
14166 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14167 gen_reserved_instruction(ctx);
14168 } else {
14169 offset = extended ? offset : offset << 3;
14170 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
14172 break;
14173 case I64_DADDIU5:
14174 check_insn(ctx, ISA_MIPS3);
14175 check_mips_64(ctx);
14176 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
14177 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
14178 break;
14179 case I64_DADDIUPC:
14180 check_insn(ctx, ISA_MIPS3);
14181 check_mips_64(ctx);
14182 offset = extended ? offset : offset << 2;
14183 gen_addiupc(ctx, ry, offset, 1, extended);
14184 break;
14185 case I64_DADDIUSP:
14186 check_insn(ctx, ISA_MIPS3);
14187 check_mips_64(ctx);
14188 offset = extended ? offset : offset << 2;
14189 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
14190 break;
14193 #endif
14195 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14197 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
14198 int op, rx, ry, funct, sa;
14199 int16_t imm, offset;
14201 ctx->opcode = (ctx->opcode << 16) | extend;
14202 op = (ctx->opcode >> 11) & 0x1f;
14203 sa = (ctx->opcode >> 22) & 0x1f;
14204 funct = (ctx->opcode >> 8) & 0x7;
14205 rx = xlat((ctx->opcode >> 8) & 0x7);
14206 ry = xlat((ctx->opcode >> 5) & 0x7);
14207 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
14208 | ((ctx->opcode >> 21) & 0x3f) << 5
14209 | (ctx->opcode & 0x1f));
14212 * The extended opcodes cleverly reuse the opcodes from their 16-bit
14213 * counterparts.
14215 switch (op) {
14216 case M16_OPC_ADDIUSP:
14217 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14218 break;
14219 case M16_OPC_ADDIUPC:
14220 gen_addiupc(ctx, rx, imm, 0, 1);
14221 break;
14222 case M16_OPC_B:
14223 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
14224 /* No delay slot, so just process as a normal instruction */
14225 break;
14226 case M16_OPC_BEQZ:
14227 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
14228 /* No delay slot, so just process as a normal instruction */
14229 break;
14230 case M16_OPC_BNEQZ:
14231 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
14232 /* No delay slot, so just process as a normal instruction */
14233 break;
14234 case M16_OPC_SHIFT:
14235 switch (ctx->opcode & 0x3) {
14236 case 0x0:
14237 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14238 break;
14239 case 0x1:
14240 #if defined(TARGET_MIPS64)
14241 check_mips_64(ctx);
14242 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14243 #else
14244 gen_reserved_instruction(ctx);
14245 #endif
14246 break;
14247 case 0x2:
14248 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14249 break;
14250 case 0x3:
14251 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14252 break;
14254 break;
14255 #if defined(TARGET_MIPS64)
14256 case M16_OPC_LD:
14257 check_insn(ctx, ISA_MIPS3);
14258 check_mips_64(ctx);
14259 gen_ld(ctx, OPC_LD, ry, rx, offset);
14260 break;
14261 #endif
14262 case M16_OPC_RRIA:
14263 imm = ctx->opcode & 0xf;
14264 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
14265 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
14266 imm = (int16_t) (imm << 1) >> 1;
14267 if ((ctx->opcode >> 4) & 0x1) {
14268 #if defined(TARGET_MIPS64)
14269 check_mips_64(ctx);
14270 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14271 #else
14272 gen_reserved_instruction(ctx);
14273 #endif
14274 } else {
14275 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14277 break;
14278 case M16_OPC_ADDIU8:
14279 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14280 break;
14281 case M16_OPC_SLTI:
14282 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14283 break;
14284 case M16_OPC_SLTIU:
14285 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14286 break;
14287 case M16_OPC_I8:
14288 switch (funct) {
14289 case I8_BTEQZ:
14290 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
14291 break;
14292 case I8_BTNEZ:
14293 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
14294 break;
14295 case I8_SWRASP:
14296 gen_st(ctx, OPC_SW, 31, 29, imm);
14297 break;
14298 case I8_ADJSP:
14299 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
14300 break;
14301 case I8_SVRS:
14302 check_insn(ctx, ISA_MIPS_R1);
14304 int xsregs = (ctx->opcode >> 24) & 0x7;
14305 int aregs = (ctx->opcode >> 16) & 0xf;
14306 int do_ra = (ctx->opcode >> 6) & 0x1;
14307 int do_s0 = (ctx->opcode >> 5) & 0x1;
14308 int do_s1 = (ctx->opcode >> 4) & 0x1;
14309 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14310 | (ctx->opcode & 0xf)) << 3;
14312 if (ctx->opcode & (1 << 7)) {
14313 gen_mips16_save(ctx, xsregs, aregs,
14314 do_ra, do_s0, do_s1,
14315 framesize);
14316 } else {
14317 gen_mips16_restore(ctx, xsregs, aregs,
14318 do_ra, do_s0, do_s1,
14319 framesize);
14322 break;
14323 default:
14324 gen_reserved_instruction(ctx);
14325 break;
14327 break;
14328 case M16_OPC_LI:
14329 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14330 break;
14331 case M16_OPC_CMPI:
14332 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14333 break;
14334 #if defined(TARGET_MIPS64)
14335 case M16_OPC_SD:
14336 check_insn(ctx, ISA_MIPS3);
14337 check_mips_64(ctx);
14338 gen_st(ctx, OPC_SD, ry, rx, offset);
14339 break;
14340 #endif
14341 case M16_OPC_LB:
14342 gen_ld(ctx, OPC_LB, ry, rx, offset);
14343 break;
14344 case M16_OPC_LH:
14345 gen_ld(ctx, OPC_LH, ry, rx, offset);
14346 break;
14347 case M16_OPC_LWSP:
14348 gen_ld(ctx, OPC_LW, rx, 29, offset);
14349 break;
14350 case M16_OPC_LW:
14351 gen_ld(ctx, OPC_LW, ry, rx, offset);
14352 break;
14353 case M16_OPC_LBU:
14354 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14355 break;
14356 case M16_OPC_LHU:
14357 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14358 break;
14359 case M16_OPC_LWPC:
14360 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14361 break;
14362 #if defined(TARGET_MIPS64)
14363 case M16_OPC_LWU:
14364 check_insn(ctx, ISA_MIPS3);
14365 check_mips_64(ctx);
14366 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14367 break;
14368 #endif
14369 case M16_OPC_SB:
14370 gen_st(ctx, OPC_SB, ry, rx, offset);
14371 break;
14372 case M16_OPC_SH:
14373 gen_st(ctx, OPC_SH, ry, rx, offset);
14374 break;
14375 case M16_OPC_SWSP:
14376 gen_st(ctx, OPC_SW, rx, 29, offset);
14377 break;
14378 case M16_OPC_SW:
14379 gen_st(ctx, OPC_SW, ry, rx, offset);
14380 break;
14381 #if defined(TARGET_MIPS64)
14382 case M16_OPC_I64:
14383 decode_i64_mips16(ctx, ry, funct, offset, 1);
14384 break;
14385 #endif
14386 default:
14387 gen_reserved_instruction(ctx);
14388 break;
14391 return 4;
14394 static inline bool is_uhi(int sdbbp_code)
14396 #ifdef CONFIG_USER_ONLY
14397 return false;
14398 #else
14399 return semihosting_enabled() && sdbbp_code == 1;
14400 #endif
14403 #ifdef CONFIG_USER_ONLY
14404 /* The above should dead-code away any calls to this..*/
14405 static inline void gen_helper_do_semihosting(void *env)
14407 g_assert_not_reached();
14409 #endif
14411 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14413 int rx, ry;
14414 int sa;
14415 int op, cnvt_op, op1, offset;
14416 int funct;
14417 int n_bytes;
14419 op = (ctx->opcode >> 11) & 0x1f;
14420 sa = (ctx->opcode >> 2) & 0x7;
14421 sa = sa == 0 ? 8 : sa;
14422 rx = xlat((ctx->opcode >> 8) & 0x7);
14423 cnvt_op = (ctx->opcode >> 5) & 0x7;
14424 ry = xlat((ctx->opcode >> 5) & 0x7);
14425 op1 = offset = ctx->opcode & 0x1f;
14427 n_bytes = 2;
14429 switch (op) {
14430 case M16_OPC_ADDIUSP:
14432 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14434 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14436 break;
14437 case M16_OPC_ADDIUPC:
14438 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14439 break;
14440 case M16_OPC_B:
14441 offset = (ctx->opcode & 0x7ff) << 1;
14442 offset = (int16_t)(offset << 4) >> 4;
14443 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14444 /* No delay slot, so just process as a normal instruction */
14445 break;
14446 case M16_OPC_JAL:
14447 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14448 offset = (((ctx->opcode & 0x1f) << 21)
14449 | ((ctx->opcode >> 5) & 0x1f) << 16
14450 | offset) << 2;
14451 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14452 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14453 n_bytes = 4;
14454 break;
14455 case M16_OPC_BEQZ:
14456 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14457 ((int8_t)ctx->opcode) << 1, 0);
14458 /* No delay slot, so just process as a normal instruction */
14459 break;
14460 case M16_OPC_BNEQZ:
14461 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14462 ((int8_t)ctx->opcode) << 1, 0);
14463 /* No delay slot, so just process as a normal instruction */
14464 break;
14465 case M16_OPC_SHIFT:
14466 switch (ctx->opcode & 0x3) {
14467 case 0x0:
14468 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14469 break;
14470 case 0x1:
14471 #if defined(TARGET_MIPS64)
14472 check_insn(ctx, ISA_MIPS3);
14473 check_mips_64(ctx);
14474 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14475 #else
14476 gen_reserved_instruction(ctx);
14477 #endif
14478 break;
14479 case 0x2:
14480 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14481 break;
14482 case 0x3:
14483 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14484 break;
14486 break;
14487 #if defined(TARGET_MIPS64)
14488 case M16_OPC_LD:
14489 check_insn(ctx, ISA_MIPS3);
14490 check_mips_64(ctx);
14491 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14492 break;
14493 #endif
14494 case M16_OPC_RRIA:
14496 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14498 if ((ctx->opcode >> 4) & 1) {
14499 #if defined(TARGET_MIPS64)
14500 check_insn(ctx, ISA_MIPS3);
14501 check_mips_64(ctx);
14502 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14503 #else
14504 gen_reserved_instruction(ctx);
14505 #endif
14506 } else {
14507 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14510 break;
14511 case M16_OPC_ADDIU8:
14513 int16_t imm = (int8_t) ctx->opcode;
14515 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14517 break;
14518 case M16_OPC_SLTI:
14520 int16_t imm = (uint8_t) ctx->opcode;
14521 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14523 break;
14524 case M16_OPC_SLTIU:
14526 int16_t imm = (uint8_t) ctx->opcode;
14527 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14529 break;
14530 case M16_OPC_I8:
14532 int reg32;
14534 funct = (ctx->opcode >> 8) & 0x7;
14535 switch (funct) {
14536 case I8_BTEQZ:
14537 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14538 ((int8_t)ctx->opcode) << 1, 0);
14539 break;
14540 case I8_BTNEZ:
14541 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14542 ((int8_t)ctx->opcode) << 1, 0);
14543 break;
14544 case I8_SWRASP:
14545 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14546 break;
14547 case I8_ADJSP:
14548 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14549 ((int8_t)ctx->opcode) << 3);
14550 break;
14551 case I8_SVRS:
14552 check_insn(ctx, ISA_MIPS_R1);
14554 int do_ra = ctx->opcode & (1 << 6);
14555 int do_s0 = ctx->opcode & (1 << 5);
14556 int do_s1 = ctx->opcode & (1 << 4);
14557 int framesize = ctx->opcode & 0xf;
14559 if (framesize == 0) {
14560 framesize = 128;
14561 } else {
14562 framesize = framesize << 3;
14565 if (ctx->opcode & (1 << 7)) {
14566 gen_mips16_save(ctx, 0, 0,
14567 do_ra, do_s0, do_s1, framesize);
14568 } else {
14569 gen_mips16_restore(ctx, 0, 0,
14570 do_ra, do_s0, do_s1, framesize);
14573 break;
14574 case I8_MOV32R:
14576 int rz = xlat(ctx->opcode & 0x7);
14578 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14579 ((ctx->opcode >> 5) & 0x7);
14580 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14582 break;
14583 case I8_MOVR32:
14584 reg32 = ctx->opcode & 0x1f;
14585 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14586 break;
14587 default:
14588 gen_reserved_instruction(ctx);
14589 break;
14592 break;
14593 case M16_OPC_LI:
14595 int16_t imm = (uint8_t) ctx->opcode;
14597 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14599 break;
14600 case M16_OPC_CMPI:
14602 int16_t imm = (uint8_t) ctx->opcode;
14603 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14605 break;
14606 #if defined(TARGET_MIPS64)
14607 case M16_OPC_SD:
14608 check_insn(ctx, ISA_MIPS3);
14609 check_mips_64(ctx);
14610 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14611 break;
14612 #endif
14613 case M16_OPC_LB:
14614 gen_ld(ctx, OPC_LB, ry, rx, offset);
14615 break;
14616 case M16_OPC_LH:
14617 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14618 break;
14619 case M16_OPC_LWSP:
14620 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14621 break;
14622 case M16_OPC_LW:
14623 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14624 break;
14625 case M16_OPC_LBU:
14626 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14627 break;
14628 case M16_OPC_LHU:
14629 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14630 break;
14631 case M16_OPC_LWPC:
14632 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14633 break;
14634 #if defined(TARGET_MIPS64)
14635 case M16_OPC_LWU:
14636 check_insn(ctx, ISA_MIPS3);
14637 check_mips_64(ctx);
14638 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14639 break;
14640 #endif
14641 case M16_OPC_SB:
14642 gen_st(ctx, OPC_SB, ry, rx, offset);
14643 break;
14644 case M16_OPC_SH:
14645 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14646 break;
14647 case M16_OPC_SWSP:
14648 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14649 break;
14650 case M16_OPC_SW:
14651 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14652 break;
14653 case M16_OPC_RRR:
14655 int rz = xlat((ctx->opcode >> 2) & 0x7);
14656 int mips32_op;
14658 switch (ctx->opcode & 0x3) {
14659 case RRR_ADDU:
14660 mips32_op = OPC_ADDU;
14661 break;
14662 case RRR_SUBU:
14663 mips32_op = OPC_SUBU;
14664 break;
14665 #if defined(TARGET_MIPS64)
14666 case RRR_DADDU:
14667 mips32_op = OPC_DADDU;
14668 check_insn(ctx, ISA_MIPS3);
14669 check_mips_64(ctx);
14670 break;
14671 case RRR_DSUBU:
14672 mips32_op = OPC_DSUBU;
14673 check_insn(ctx, ISA_MIPS3);
14674 check_mips_64(ctx);
14675 break;
14676 #endif
14677 default:
14678 gen_reserved_instruction(ctx);
14679 goto done;
14682 gen_arith(ctx, mips32_op, rz, rx, ry);
14683 done:
14686 break;
14687 case M16_OPC_RR:
14688 switch (op1) {
14689 case RR_JR:
14691 int nd = (ctx->opcode >> 7) & 0x1;
14692 int link = (ctx->opcode >> 6) & 0x1;
14693 int ra = (ctx->opcode >> 5) & 0x1;
14695 if (nd) {
14696 check_insn(ctx, ISA_MIPS_R1);
14699 if (link) {
14700 op = OPC_JALR;
14701 } else {
14702 op = OPC_JR;
14705 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14706 (nd ? 0 : 2));
14708 break;
14709 case RR_SDBBP:
14710 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14711 gen_helper_do_semihosting(cpu_env);
14712 } else {
14714 * XXX: not clear which exception should be raised
14715 * when in debug mode...
14717 check_insn(ctx, ISA_MIPS_R1);
14718 generate_exception_end(ctx, EXCP_DBp);
14720 break;
14721 case RR_SLT:
14722 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14723 break;
14724 case RR_SLTU:
14725 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14726 break;
14727 case RR_BREAK:
14728 generate_exception_end(ctx, EXCP_BREAK);
14729 break;
14730 case RR_SLLV:
14731 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14732 break;
14733 case RR_SRLV:
14734 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14735 break;
14736 case RR_SRAV:
14737 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14738 break;
14739 #if defined(TARGET_MIPS64)
14740 case RR_DSRL:
14741 check_insn(ctx, ISA_MIPS3);
14742 check_mips_64(ctx);
14743 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14744 break;
14745 #endif
14746 case RR_CMP:
14747 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14748 break;
14749 case RR_NEG:
14750 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14751 break;
14752 case RR_AND:
14753 gen_logic(ctx, OPC_AND, rx, rx, ry);
14754 break;
14755 case RR_OR:
14756 gen_logic(ctx, OPC_OR, rx, rx, ry);
14757 break;
14758 case RR_XOR:
14759 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14760 break;
14761 case RR_NOT:
14762 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14763 break;
14764 case RR_MFHI:
14765 gen_HILO(ctx, OPC_MFHI, 0, rx);
14766 break;
14767 case RR_CNVT:
14768 check_insn(ctx, ISA_MIPS_R1);
14769 switch (cnvt_op) {
14770 case RR_RY_CNVT_ZEB:
14771 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14772 break;
14773 case RR_RY_CNVT_ZEH:
14774 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14775 break;
14776 case RR_RY_CNVT_SEB:
14777 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14778 break;
14779 case RR_RY_CNVT_SEH:
14780 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14781 break;
14782 #if defined(TARGET_MIPS64)
14783 case RR_RY_CNVT_ZEW:
14784 check_insn(ctx, ISA_MIPS_R1);
14785 check_mips_64(ctx);
14786 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14787 break;
14788 case RR_RY_CNVT_SEW:
14789 check_insn(ctx, ISA_MIPS_R1);
14790 check_mips_64(ctx);
14791 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14792 break;
14793 #endif
14794 default:
14795 gen_reserved_instruction(ctx);
14796 break;
14798 break;
14799 case RR_MFLO:
14800 gen_HILO(ctx, OPC_MFLO, 0, rx);
14801 break;
14802 #if defined(TARGET_MIPS64)
14803 case RR_DSRA:
14804 check_insn(ctx, ISA_MIPS3);
14805 check_mips_64(ctx);
14806 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14807 break;
14808 case RR_DSLLV:
14809 check_insn(ctx, ISA_MIPS3);
14810 check_mips_64(ctx);
14811 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14812 break;
14813 case RR_DSRLV:
14814 check_insn(ctx, ISA_MIPS3);
14815 check_mips_64(ctx);
14816 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14817 break;
14818 case RR_DSRAV:
14819 check_insn(ctx, ISA_MIPS3);
14820 check_mips_64(ctx);
14821 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14822 break;
14823 #endif
14824 case RR_MULT:
14825 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14826 break;
14827 case RR_MULTU:
14828 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14829 break;
14830 case RR_DIV:
14831 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14832 break;
14833 case RR_DIVU:
14834 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14835 break;
14836 #if defined(TARGET_MIPS64)
14837 case RR_DMULT:
14838 check_insn(ctx, ISA_MIPS3);
14839 check_mips_64(ctx);
14840 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14841 break;
14842 case RR_DMULTU:
14843 check_insn(ctx, ISA_MIPS3);
14844 check_mips_64(ctx);
14845 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14846 break;
14847 case RR_DDIV:
14848 check_insn(ctx, ISA_MIPS3);
14849 check_mips_64(ctx);
14850 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14851 break;
14852 case RR_DDIVU:
14853 check_insn(ctx, ISA_MIPS3);
14854 check_mips_64(ctx);
14855 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14856 break;
14857 #endif
14858 default:
14859 gen_reserved_instruction(ctx);
14860 break;
14862 break;
14863 case M16_OPC_EXTEND:
14864 decode_extended_mips16_opc(env, ctx);
14865 n_bytes = 4;
14866 break;
14867 #if defined(TARGET_MIPS64)
14868 case M16_OPC_I64:
14869 funct = (ctx->opcode >> 8) & 0x7;
14870 decode_i64_mips16(ctx, ry, funct, offset, 0);
14871 break;
14872 #endif
14873 default:
14874 gen_reserved_instruction(ctx);
14875 break;
14878 return n_bytes;
14881 /* microMIPS extension to MIPS32/MIPS64 */
14884 * microMIPS32/microMIPS64 major opcodes
14886 * 1. MIPS Architecture for Programmers Volume II-B:
14887 * The microMIPS32 Instruction Set (Revision 3.05)
14889 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
14891 * 2. MIPS Architecture For Programmers Volume II-A:
14892 * The MIPS64 Instruction Set (Revision 3.51)
14895 enum {
14896 POOL32A = 0x00,
14897 POOL16A = 0x01,
14898 LBU16 = 0x02,
14899 MOVE16 = 0x03,
14900 ADDI32 = 0x04,
14901 R6_LUI = 0x04,
14902 AUI = 0x04,
14903 LBU32 = 0x05,
14904 SB32 = 0x06,
14905 LB32 = 0x07,
14907 POOL32B = 0x08,
14908 POOL16B = 0x09,
14909 LHU16 = 0x0a,
14910 ANDI16 = 0x0b,
14911 ADDIU32 = 0x0c,
14912 LHU32 = 0x0d,
14913 SH32 = 0x0e,
14914 LH32 = 0x0f,
14916 POOL32I = 0x10,
14917 POOL16C = 0x11,
14918 LWSP16 = 0x12,
14919 POOL16D = 0x13,
14920 ORI32 = 0x14,
14921 POOL32F = 0x15,
14922 POOL32S = 0x16, /* MIPS64 */
14923 DADDIU32 = 0x17, /* MIPS64 */
14925 POOL32C = 0x18,
14926 LWGP16 = 0x19,
14927 LW16 = 0x1a,
14928 POOL16E = 0x1b,
14929 XORI32 = 0x1c,
14930 JALS32 = 0x1d,
14931 BOVC = 0x1d,
14932 BEQC = 0x1d,
14933 BEQZALC = 0x1d,
14934 ADDIUPC = 0x1e,
14935 PCREL = 0x1e,
14936 BNVC = 0x1f,
14937 BNEC = 0x1f,
14938 BNEZALC = 0x1f,
14940 R6_BEQZC = 0x20,
14941 JIC = 0x20,
14942 POOL16F = 0x21,
14943 SB16 = 0x22,
14944 BEQZ16 = 0x23,
14945 BEQZC16 = 0x23,
14946 SLTI32 = 0x24,
14947 BEQ32 = 0x25,
14948 BC = 0x25,
14949 SWC132 = 0x26,
14950 LWC132 = 0x27,
14952 /* 0x29 is reserved */
14953 RES_29 = 0x29,
14954 R6_BNEZC = 0x28,
14955 JIALC = 0x28,
14956 SH16 = 0x2a,
14957 BNEZ16 = 0x2b,
14958 BNEZC16 = 0x2b,
14959 SLTIU32 = 0x2c,
14960 BNE32 = 0x2d,
14961 BALC = 0x2d,
14962 SDC132 = 0x2e,
14963 LDC132 = 0x2f,
14965 /* 0x31 is reserved */
14966 RES_31 = 0x31,
14967 BLEZALC = 0x30,
14968 BGEZALC = 0x30,
14969 BGEUC = 0x30,
14970 SWSP16 = 0x32,
14971 B16 = 0x33,
14972 BC16 = 0x33,
14973 ANDI32 = 0x34,
14974 J32 = 0x35,
14975 BGTZC = 0x35,
14976 BLTZC = 0x35,
14977 BLTC = 0x35,
14978 SD32 = 0x36, /* MIPS64 */
14979 LD32 = 0x37, /* MIPS64 */
14981 /* 0x39 is reserved */
14982 RES_39 = 0x39,
14983 BGTZALC = 0x38,
14984 BLTZALC = 0x38,
14985 BLTUC = 0x38,
14986 SW16 = 0x3a,
14987 LI16 = 0x3b,
14988 JALX32 = 0x3c,
14989 JAL32 = 0x3d,
14990 BLEZC = 0x3d,
14991 BGEZC = 0x3d,
14992 BGEC = 0x3d,
14993 SW32 = 0x3e,
14994 LW32 = 0x3f
14997 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
14998 enum {
14999 ADDIUPC_00 = 0x00,
15000 ADDIUPC_01 = 0x01,
15001 ADDIUPC_02 = 0x02,
15002 ADDIUPC_03 = 0x03,
15003 ADDIUPC_04 = 0x04,
15004 ADDIUPC_05 = 0x05,
15005 ADDIUPC_06 = 0x06,
15006 ADDIUPC_07 = 0x07,
15007 AUIPC = 0x1e,
15008 ALUIPC = 0x1f,
15009 LWPC_08 = 0x08,
15010 LWPC_09 = 0x09,
15011 LWPC_0A = 0x0A,
15012 LWPC_0B = 0x0B,
15013 LWPC_0C = 0x0C,
15014 LWPC_0D = 0x0D,
15015 LWPC_0E = 0x0E,
15016 LWPC_0F = 0x0F,
15019 /* POOL32A encoding of minor opcode field */
15021 enum {
15023 * These opcodes are distinguished only by bits 9..6; those bits are
15024 * what are recorded below.
15026 SLL32 = 0x0,
15027 SRL32 = 0x1,
15028 SRA = 0x2,
15029 ROTR = 0x3,
15030 SELEQZ = 0x5,
15031 SELNEZ = 0x6,
15032 R6_RDHWR = 0x7,
15034 SLLV = 0x0,
15035 SRLV = 0x1,
15036 SRAV = 0x2,
15037 ROTRV = 0x3,
15038 ADD = 0x4,
15039 ADDU32 = 0x5,
15040 SUB = 0x6,
15041 SUBU32 = 0x7,
15042 MUL = 0x8,
15043 AND = 0x9,
15044 OR32 = 0xa,
15045 NOR = 0xb,
15046 XOR32 = 0xc,
15047 SLT = 0xd,
15048 SLTU = 0xe,
15050 MOVN = 0x0,
15051 R6_MUL = 0x0,
15052 MOVZ = 0x1,
15053 MUH = 0x1,
15054 MULU = 0x2,
15055 MUHU = 0x3,
15056 LWXS = 0x4,
15057 R6_DIV = 0x4,
15058 MOD = 0x5,
15059 R6_DIVU = 0x6,
15060 MODU = 0x7,
15062 /* The following can be distinguished by their lower 6 bits. */
15063 BREAK32 = 0x07,
15064 INS = 0x0c,
15065 LSA = 0x0f,
15066 ALIGN = 0x1f,
15067 EXT = 0x2c,
15068 POOL32AXF = 0x3c,
15069 SIGRIE = 0x3f
15072 /* POOL32AXF encoding of minor opcode field extension */
15075 * 1. MIPS Architecture for Programmers Volume II-B:
15076 * The microMIPS32 Instruction Set (Revision 3.05)
15078 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
15080 * 2. MIPS Architecture for Programmers VolumeIV-e:
15081 * The MIPS DSP Application-Specific Extension
15082 * to the microMIPS32 Architecture (Revision 2.34)
15084 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
15087 enum {
15088 /* bits 11..6 */
15089 TEQ = 0x00,
15090 TGE = 0x08,
15091 TGEU = 0x10,
15092 TLT = 0x20,
15093 TLTU = 0x28,
15094 TNE = 0x30,
15096 MFC0 = 0x03,
15097 MTC0 = 0x0b,
15099 /* begin of microMIPS32 DSP */
15101 /* bits 13..12 for 0x01 */
15102 MFHI_ACC = 0x0,
15103 MFLO_ACC = 0x1,
15104 MTHI_ACC = 0x2,
15105 MTLO_ACC = 0x3,
15107 /* bits 13..12 for 0x2a */
15108 MADD_ACC = 0x0,
15109 MADDU_ACC = 0x1,
15110 MSUB_ACC = 0x2,
15111 MSUBU_ACC = 0x3,
15113 /* bits 13..12 for 0x32 */
15114 MULT_ACC = 0x0,
15115 MULTU_ACC = 0x1,
15117 /* end of microMIPS32 DSP */
15119 /* bits 15..12 for 0x2c */
15120 BITSWAP = 0x0,
15121 SEB = 0x2,
15122 SEH = 0x3,
15123 CLO = 0x4,
15124 CLZ = 0x5,
15125 RDHWR = 0x6,
15126 WSBH = 0x7,
15127 MULT = 0x8,
15128 MULTU = 0x9,
15129 DIV = 0xa,
15130 DIVU = 0xb,
15131 MADD = 0xc,
15132 MADDU = 0xd,
15133 MSUB = 0xe,
15134 MSUBU = 0xf,
15136 /* bits 15..12 for 0x34 */
15137 MFC2 = 0x4,
15138 MTC2 = 0x5,
15139 MFHC2 = 0x8,
15140 MTHC2 = 0x9,
15141 CFC2 = 0xc,
15142 CTC2 = 0xd,
15144 /* bits 15..12 for 0x3c */
15145 JALR = 0x0,
15146 JR = 0x0, /* alias */
15147 JALRC = 0x0,
15148 JRC = 0x0,
15149 JALR_HB = 0x1,
15150 JALRC_HB = 0x1,
15151 JALRS = 0x4,
15152 JALRS_HB = 0x5,
15154 /* bits 15..12 for 0x05 */
15155 RDPGPR = 0xe,
15156 WRPGPR = 0xf,
15158 /* bits 15..12 for 0x0d */
15159 TLBP = 0x0,
15160 TLBR = 0x1,
15161 TLBWI = 0x2,
15162 TLBWR = 0x3,
15163 TLBINV = 0x4,
15164 TLBINVF = 0x5,
15165 WAIT = 0x9,
15166 IRET = 0xd,
15167 DERET = 0xe,
15168 ERET = 0xf,
15170 /* bits 15..12 for 0x15 */
15171 DMT = 0x0,
15172 DVPE = 0x1,
15173 EMT = 0x2,
15174 EVPE = 0x3,
15176 /* bits 15..12 for 0x1d */
15177 DI = 0x4,
15178 EI = 0x5,
15180 /* bits 15..12 for 0x2d */
15181 SYNC = 0x6,
15182 SYSCALL = 0x8,
15183 SDBBP = 0xd,
15185 /* bits 15..12 for 0x35 */
15186 MFHI32 = 0x0,
15187 MFLO32 = 0x1,
15188 MTHI32 = 0x2,
15189 MTLO32 = 0x3,
15192 /* POOL32B encoding of minor opcode field (bits 15..12) */
15194 enum {
15195 LWC2 = 0x0,
15196 LWP = 0x1,
15197 LDP = 0x4,
15198 LWM32 = 0x5,
15199 CACHE = 0x6,
15200 LDM = 0x7,
15201 SWC2 = 0x8,
15202 SWP = 0x9,
15203 SDP = 0xc,
15204 SWM32 = 0xd,
15205 SDM = 0xf
15208 /* POOL32C encoding of minor opcode field (bits 15..12) */
15210 enum {
15211 LWL = 0x0,
15212 SWL = 0x8,
15213 LWR = 0x1,
15214 SWR = 0x9,
15215 PREF = 0x2,
15216 ST_EVA = 0xa,
15217 LL = 0x3,
15218 SC = 0xb,
15219 LDL = 0x4,
15220 SDL = 0xc,
15221 LDR = 0x5,
15222 SDR = 0xd,
15223 LD_EVA = 0x6,
15224 LWU = 0xe,
15225 LLD = 0x7,
15226 SCD = 0xf
15229 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
15231 enum {
15232 LBUE = 0x0,
15233 LHUE = 0x1,
15234 LWLE = 0x2,
15235 LWRE = 0x3,
15236 LBE = 0x4,
15237 LHE = 0x5,
15238 LLE = 0x6,
15239 LWE = 0x7,
15242 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
15244 enum {
15245 SWLE = 0x0,
15246 SWRE = 0x1,
15247 PREFE = 0x2,
15248 CACHEE = 0x3,
15249 SBE = 0x4,
15250 SHE = 0x5,
15251 SCE = 0x6,
15252 SWE = 0x7,
15255 /* POOL32F encoding of minor opcode field (bits 5..0) */
15257 enum {
15258 /* These are the bit 7..6 values */
15259 ADD_FMT = 0x0,
15261 SUB_FMT = 0x1,
15263 MUL_FMT = 0x2,
15265 DIV_FMT = 0x3,
15267 /* These are the bit 8..6 values */
15268 MOVN_FMT = 0x0,
15269 RSQRT2_FMT = 0x0,
15270 MOVF_FMT = 0x0,
15271 RINT_FMT = 0x0,
15272 SELNEZ_FMT = 0x0,
15274 MOVZ_FMT = 0x1,
15275 LWXC1 = 0x1,
15276 MOVT_FMT = 0x1,
15277 CLASS_FMT = 0x1,
15278 SELEQZ_FMT = 0x1,
15280 PLL_PS = 0x2,
15281 SWXC1 = 0x2,
15282 SEL_FMT = 0x2,
15284 PLU_PS = 0x3,
15285 LDXC1 = 0x3,
15287 MOVN_FMT_04 = 0x4,
15288 PUL_PS = 0x4,
15289 SDXC1 = 0x4,
15290 RECIP2_FMT = 0x4,
15292 MOVZ_FMT_05 = 0x05,
15293 PUU_PS = 0x5,
15294 LUXC1 = 0x5,
15296 CVT_PS_S = 0x6,
15297 SUXC1 = 0x6,
15298 ADDR_PS = 0x6,
15299 PREFX = 0x6,
15300 MADDF_FMT = 0x6,
15302 MULR_PS = 0x7,
15303 MSUBF_FMT = 0x7,
15305 MADD_S = 0x01,
15306 MADD_D = 0x09,
15307 MADD_PS = 0x11,
15308 ALNV_PS = 0x19,
15309 MSUB_S = 0x21,
15310 MSUB_D = 0x29,
15311 MSUB_PS = 0x31,
15313 NMADD_S = 0x02,
15314 NMADD_D = 0x0a,
15315 NMADD_PS = 0x12,
15316 NMSUB_S = 0x22,
15317 NMSUB_D = 0x2a,
15318 NMSUB_PS = 0x32,
15320 MIN_FMT = 0x3,
15321 MAX_FMT = 0xb,
15322 MINA_FMT = 0x23,
15323 MAXA_FMT = 0x2b,
15324 POOL32FXF = 0x3b,
15326 CABS_COND_FMT = 0x1c, /* MIPS3D */
15327 C_COND_FMT = 0x3c,
15329 CMP_CONDN_S = 0x5,
15330 CMP_CONDN_D = 0x15
15333 /* POOL32Fxf encoding of minor opcode extension field */
15335 enum {
15336 CVT_L = 0x04,
15337 RSQRT_FMT = 0x08,
15338 FLOOR_L = 0x0c,
15339 CVT_PW_PS = 0x1c,
15340 CVT_W = 0x24,
15341 SQRT_FMT = 0x28,
15342 FLOOR_W = 0x2c,
15343 CVT_PS_PW = 0x3c,
15344 CFC1 = 0x40,
15345 RECIP_FMT = 0x48,
15346 CEIL_L = 0x4c,
15347 CTC1 = 0x60,
15348 CEIL_W = 0x6c,
15349 MFC1 = 0x80,
15350 CVT_S_PL = 0x84,
15351 TRUNC_L = 0x8c,
15352 MTC1 = 0xa0,
15353 CVT_S_PU = 0xa4,
15354 TRUNC_W = 0xac,
15355 MFHC1 = 0xc0,
15356 ROUND_L = 0xcc,
15357 MTHC1 = 0xe0,
15358 ROUND_W = 0xec,
15360 MOV_FMT = 0x01,
15361 MOVF = 0x05,
15362 ABS_FMT = 0x0d,
15363 RSQRT1_FMT = 0x1d,
15364 MOVT = 0x25,
15365 NEG_FMT = 0x2d,
15366 CVT_D = 0x4d,
15367 RECIP1_FMT = 0x5d,
15368 CVT_S = 0x6d
15371 /* POOL32I encoding of minor opcode field (bits 25..21) */
15373 enum {
15374 BLTZ = 0x00,
15375 BLTZAL = 0x01,
15376 BGEZ = 0x02,
15377 BGEZAL = 0x03,
15378 BLEZ = 0x04,
15379 BNEZC = 0x05,
15380 BGTZ = 0x06,
15381 BEQZC = 0x07,
15382 TLTI = 0x08,
15383 BC1EQZC = 0x08,
15384 TGEI = 0x09,
15385 BC1NEZC = 0x09,
15386 TLTIU = 0x0a,
15387 BC2EQZC = 0x0a,
15388 TGEIU = 0x0b,
15389 BC2NEZC = 0x0a,
15390 TNEI = 0x0c,
15391 R6_SYNCI = 0x0c,
15392 LUI = 0x0d,
15393 TEQI = 0x0e,
15394 SYNCI = 0x10,
15395 BLTZALS = 0x11,
15396 BGEZALS = 0x13,
15397 BC2F = 0x14,
15398 BC2T = 0x15,
15399 BPOSGE64 = 0x1a,
15400 BPOSGE32 = 0x1b,
15401 /* These overlap and are distinguished by bit16 of the instruction */
15402 BC1F = 0x1c,
15403 BC1T = 0x1d,
15404 BC1ANY2F = 0x1c,
15405 BC1ANY2T = 0x1d,
15406 BC1ANY4F = 0x1e,
15407 BC1ANY4T = 0x1f
15410 /* POOL16A encoding of minor opcode field */
15412 enum {
15413 ADDU16 = 0x0,
15414 SUBU16 = 0x1
15417 /* POOL16B encoding of minor opcode field */
15419 enum {
15420 SLL16 = 0x0,
15421 SRL16 = 0x1
15424 /* POOL16C encoding of minor opcode field */
15426 enum {
15427 NOT16 = 0x00,
15428 XOR16 = 0x04,
15429 AND16 = 0x08,
15430 OR16 = 0x0c,
15431 LWM16 = 0x10,
15432 SWM16 = 0x14,
15433 JR16 = 0x18,
15434 JRC16 = 0x1a,
15435 JALR16 = 0x1c,
15436 JALR16S = 0x1e,
15437 MFHI16 = 0x20,
15438 MFLO16 = 0x24,
15439 BREAK16 = 0x28,
15440 SDBBP16 = 0x2c,
15441 JRADDIUSP = 0x30
15444 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15446 enum {
15447 R6_NOT16 = 0x00,
15448 R6_AND16 = 0x01,
15449 R6_LWM16 = 0x02,
15450 R6_JRC16 = 0x03,
15451 MOVEP = 0x04,
15452 MOVEP_05 = 0x05,
15453 MOVEP_06 = 0x06,
15454 MOVEP_07 = 0x07,
15455 R6_XOR16 = 0x08,
15456 R6_OR16 = 0x09,
15457 R6_SWM16 = 0x0a,
15458 JALRC16 = 0x0b,
15459 MOVEP_0C = 0x0c,
15460 MOVEP_0D = 0x0d,
15461 MOVEP_0E = 0x0e,
15462 MOVEP_0F = 0x0f,
15463 JRCADDIUSP = 0x13,
15464 R6_BREAK16 = 0x1b,
15465 R6_SDBBP16 = 0x3b
15468 /* POOL16D encoding of minor opcode field */
15470 enum {
15471 ADDIUS5 = 0x0,
15472 ADDIUSP = 0x1
15475 /* POOL16E encoding of minor opcode field */
15477 enum {
15478 ADDIUR2 = 0x0,
15479 ADDIUR1SP = 0x1
15482 static int mmreg(int r)
15484 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15486 return map[r];
15489 /* Used for 16-bit store instructions. */
15490 static int mmreg2(int r)
15492 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15494 return map[r];
15497 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15498 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15499 #define uMIPS_RS2(op) uMIPS_RS(op)
15500 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15501 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15502 #define uMIPS_RS5(op) (op & 0x1f)
15504 /* Signed immediate */
15505 #define SIMM(op, start, width) \
15506 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15507 << (32 - width)) \
15508 >> (32 - width))
15509 /* Zero-extended immediate */
15510 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15512 static void gen_addiur1sp(DisasContext *ctx)
15514 int rd = mmreg(uMIPS_RD(ctx->opcode));
15516 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15519 static void gen_addiur2(DisasContext *ctx)
15521 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15522 int rd = mmreg(uMIPS_RD(ctx->opcode));
15523 int rs = mmreg(uMIPS_RS(ctx->opcode));
15525 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15528 static void gen_addiusp(DisasContext *ctx)
15530 int encoded = ZIMM(ctx->opcode, 1, 9);
15531 int decoded;
15533 if (encoded <= 1) {
15534 decoded = 256 + encoded;
15535 } else if (encoded <= 255) {
15536 decoded = encoded;
15537 } else if (encoded <= 509) {
15538 decoded = encoded - 512;
15539 } else {
15540 decoded = encoded - 768;
15543 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15546 static void gen_addius5(DisasContext *ctx)
15548 int imm = SIMM(ctx->opcode, 1, 4);
15549 int rd = (ctx->opcode >> 5) & 0x1f;
15551 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15554 static void gen_andi16(DisasContext *ctx)
15556 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15557 31, 32, 63, 64, 255, 32768, 65535 };
15558 int rd = mmreg(uMIPS_RD(ctx->opcode));
15559 int rs = mmreg(uMIPS_RS(ctx->opcode));
15560 int encoded = ZIMM(ctx->opcode, 0, 4);
15562 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15565 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15566 int base, int16_t offset)
15568 TCGv t0, t1;
15569 TCGv_i32 t2;
15571 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15572 gen_reserved_instruction(ctx);
15573 return;
15576 t0 = tcg_temp_new();
15578 gen_base_offset_addr(ctx, t0, base, offset);
15580 t1 = tcg_const_tl(reglist);
15581 t2 = tcg_const_i32(ctx->mem_idx);
15583 save_cpu_state(ctx, 1);
15584 switch (opc) {
15585 case LWM32:
15586 gen_helper_lwm(cpu_env, t0, t1, t2);
15587 break;
15588 case SWM32:
15589 gen_helper_swm(cpu_env, t0, t1, t2);
15590 break;
15591 #ifdef TARGET_MIPS64
15592 case LDM:
15593 gen_helper_ldm(cpu_env, t0, t1, t2);
15594 break;
15595 case SDM:
15596 gen_helper_sdm(cpu_env, t0, t1, t2);
15597 break;
15598 #endif
15600 tcg_temp_free(t0);
15601 tcg_temp_free(t1);
15602 tcg_temp_free_i32(t2);
15606 static void gen_pool16c_insn(DisasContext *ctx)
15608 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15609 int rs = mmreg(ctx->opcode & 0x7);
15611 switch (((ctx->opcode) >> 4) & 0x3f) {
15612 case NOT16 + 0:
15613 case NOT16 + 1:
15614 case NOT16 + 2:
15615 case NOT16 + 3:
15616 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15617 break;
15618 case XOR16 + 0:
15619 case XOR16 + 1:
15620 case XOR16 + 2:
15621 case XOR16 + 3:
15622 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15623 break;
15624 case AND16 + 0:
15625 case AND16 + 1:
15626 case AND16 + 2:
15627 case AND16 + 3:
15628 gen_logic(ctx, OPC_AND, rd, rd, rs);
15629 break;
15630 case OR16 + 0:
15631 case OR16 + 1:
15632 case OR16 + 2:
15633 case OR16 + 3:
15634 gen_logic(ctx, OPC_OR, rd, rd, rs);
15635 break;
15636 case LWM16 + 0:
15637 case LWM16 + 1:
15638 case LWM16 + 2:
15639 case LWM16 + 3:
15641 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15642 int offset = ZIMM(ctx->opcode, 0, 4);
15644 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15645 29, offset << 2);
15647 break;
15648 case SWM16 + 0:
15649 case SWM16 + 1:
15650 case SWM16 + 2:
15651 case SWM16 + 3:
15653 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15654 int offset = ZIMM(ctx->opcode, 0, 4);
15656 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15657 29, offset << 2);
15659 break;
15660 case JR16 + 0:
15661 case JR16 + 1:
15663 int reg = ctx->opcode & 0x1f;
15665 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15667 break;
15668 case JRC16 + 0:
15669 case JRC16 + 1:
15671 int reg = ctx->opcode & 0x1f;
15672 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15674 * Let normal delay slot handling in our caller take us
15675 * to the branch target.
15678 break;
15679 case JALR16 + 0:
15680 case JALR16 + 1:
15681 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15682 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15683 break;
15684 case JALR16S + 0:
15685 case JALR16S + 1:
15686 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15687 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15688 break;
15689 case MFHI16 + 0:
15690 case MFHI16 + 1:
15691 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15692 break;
15693 case MFLO16 + 0:
15694 case MFLO16 + 1:
15695 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15696 break;
15697 case BREAK16:
15698 generate_exception_end(ctx, EXCP_BREAK);
15699 break;
15700 case SDBBP16:
15701 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15702 gen_helper_do_semihosting(cpu_env);
15703 } else {
15705 * XXX: not clear which exception should be raised
15706 * when in debug mode...
15708 check_insn(ctx, ISA_MIPS_R1);
15709 generate_exception_end(ctx, EXCP_DBp);
15711 break;
15712 case JRADDIUSP + 0:
15713 case JRADDIUSP + 1:
15715 int imm = ZIMM(ctx->opcode, 0, 5);
15716 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15717 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15719 * Let normal delay slot handling in our caller take us
15720 * to the branch target.
15723 break;
15724 default:
15725 gen_reserved_instruction(ctx);
15726 break;
15730 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15731 int enc_rs)
15733 int rd, rs, re, rt;
15734 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15735 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15736 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15737 rd = rd_enc[enc_dest];
15738 re = re_enc[enc_dest];
15739 rs = rs_rt_enc[enc_rs];
15740 rt = rs_rt_enc[enc_rt];
15741 if (rs) {
15742 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15743 } else {
15744 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15746 if (rt) {
15747 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15748 } else {
15749 tcg_gen_movi_tl(cpu_gpr[re], 0);
15753 static void gen_pool16c_r6_insn(DisasContext *ctx)
15755 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15756 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15758 switch (ctx->opcode & 0xf) {
15759 case R6_NOT16:
15760 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15761 break;
15762 case R6_AND16:
15763 gen_logic(ctx, OPC_AND, rt, rt, rs);
15764 break;
15765 case R6_LWM16:
15767 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15768 int offset = extract32(ctx->opcode, 4, 4);
15769 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15771 break;
15772 case R6_JRC16: /* JRCADDIUSP */
15773 if ((ctx->opcode >> 4) & 1) {
15774 /* JRCADDIUSP */
15775 int imm = extract32(ctx->opcode, 5, 5);
15776 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15777 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15778 } else {
15779 /* JRC16 */
15780 rs = extract32(ctx->opcode, 5, 5);
15781 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15783 break;
15784 case MOVEP:
15785 case MOVEP_05:
15786 case MOVEP_06:
15787 case MOVEP_07:
15788 case MOVEP_0C:
15789 case MOVEP_0D:
15790 case MOVEP_0E:
15791 case MOVEP_0F:
15793 int enc_dest = uMIPS_RD(ctx->opcode);
15794 int enc_rt = uMIPS_RS2(ctx->opcode);
15795 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15796 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15798 break;
15799 case R6_XOR16:
15800 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15801 break;
15802 case R6_OR16:
15803 gen_logic(ctx, OPC_OR, rt, rt, rs);
15804 break;
15805 case R6_SWM16:
15807 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15808 int offset = extract32(ctx->opcode, 4, 4);
15809 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15811 break;
15812 case JALRC16: /* BREAK16, SDBBP16 */
15813 switch (ctx->opcode & 0x3f) {
15814 case JALRC16:
15815 case JALRC16 + 0x20:
15816 /* JALRC16 */
15817 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15818 31, 0, 0);
15819 break;
15820 case R6_BREAK16:
15821 /* BREAK16 */
15822 generate_exception(ctx, EXCP_BREAK);
15823 break;
15824 case R6_SDBBP16:
15825 /* SDBBP16 */
15826 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15827 gen_helper_do_semihosting(cpu_env);
15828 } else {
15829 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15830 generate_exception(ctx, EXCP_RI);
15831 } else {
15832 generate_exception(ctx, EXCP_DBp);
15835 break;
15837 break;
15838 default:
15839 generate_exception(ctx, EXCP_RI);
15840 break;
15844 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15846 TCGv t0 = tcg_temp_new();
15847 TCGv t1 = tcg_temp_new();
15849 gen_load_gpr(t0, base);
15851 if (index != 0) {
15852 gen_load_gpr(t1, index);
15853 tcg_gen_shli_tl(t1, t1, 2);
15854 gen_op_addr_add(ctx, t0, t1, t0);
15857 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15858 gen_store_gpr(t1, rd);
15860 tcg_temp_free(t0);
15861 tcg_temp_free(t1);
15864 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15865 int base, int16_t offset)
15867 TCGv t0, t1;
15869 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15870 gen_reserved_instruction(ctx);
15871 return;
15874 t0 = tcg_temp_new();
15875 t1 = tcg_temp_new();
15877 gen_base_offset_addr(ctx, t0, base, offset);
15879 switch (opc) {
15880 case LWP:
15881 if (rd == base) {
15882 gen_reserved_instruction(ctx);
15883 return;
15885 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15886 gen_store_gpr(t1, rd);
15887 tcg_gen_movi_tl(t1, 4);
15888 gen_op_addr_add(ctx, t0, t0, t1);
15889 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15890 gen_store_gpr(t1, rd + 1);
15891 break;
15892 case SWP:
15893 gen_load_gpr(t1, rd);
15894 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15895 tcg_gen_movi_tl(t1, 4);
15896 gen_op_addr_add(ctx, t0, t0, t1);
15897 gen_load_gpr(t1, rd + 1);
15898 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
15899 break;
15900 #ifdef TARGET_MIPS64
15901 case LDP:
15902 if (rd == base) {
15903 gen_reserved_instruction(ctx);
15904 return;
15906 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15907 gen_store_gpr(t1, rd);
15908 tcg_gen_movi_tl(t1, 8);
15909 gen_op_addr_add(ctx, t0, t0, t1);
15910 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15911 gen_store_gpr(t1, rd + 1);
15912 break;
15913 case SDP:
15914 gen_load_gpr(t1, rd);
15915 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15916 tcg_gen_movi_tl(t1, 8);
15917 gen_op_addr_add(ctx, t0, t0, t1);
15918 gen_load_gpr(t1, rd + 1);
15919 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
15920 break;
15921 #endif
15923 tcg_temp_free(t0);
15924 tcg_temp_free(t1);
15927 static void gen_sync(int stype)
15929 TCGBar tcg_mo = TCG_BAR_SC;
15931 switch (stype) {
15932 case 0x4: /* SYNC_WMB */
15933 tcg_mo |= TCG_MO_ST_ST;
15934 break;
15935 case 0x10: /* SYNC_MB */
15936 tcg_mo |= TCG_MO_ALL;
15937 break;
15938 case 0x11: /* SYNC_ACQUIRE */
15939 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
15940 break;
15941 case 0x12: /* SYNC_RELEASE */
15942 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
15943 break;
15944 case 0x13: /* SYNC_RMB */
15945 tcg_mo |= TCG_MO_LD_LD;
15946 break;
15947 default:
15948 tcg_mo |= TCG_MO_ALL;
15949 break;
15952 tcg_gen_mb(tcg_mo);
15955 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
15957 int extension = (ctx->opcode >> 6) & 0x3f;
15958 int minor = (ctx->opcode >> 12) & 0xf;
15959 uint32_t mips32_op;
15961 switch (extension) {
15962 case TEQ:
15963 mips32_op = OPC_TEQ;
15964 goto do_trap;
15965 case TGE:
15966 mips32_op = OPC_TGE;
15967 goto do_trap;
15968 case TGEU:
15969 mips32_op = OPC_TGEU;
15970 goto do_trap;
15971 case TLT:
15972 mips32_op = OPC_TLT;
15973 goto do_trap;
15974 case TLTU:
15975 mips32_op = OPC_TLTU;
15976 goto do_trap;
15977 case TNE:
15978 mips32_op = OPC_TNE;
15979 do_trap:
15980 gen_trap(ctx, mips32_op, rs, rt, -1);
15981 break;
15982 #ifndef CONFIG_USER_ONLY
15983 case MFC0:
15984 case MFC0 + 32:
15985 check_cp0_enabled(ctx);
15986 if (rt == 0) {
15987 /* Treat as NOP. */
15988 break;
15990 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
15991 break;
15992 case MTC0:
15993 case MTC0 + 32:
15994 check_cp0_enabled(ctx);
15996 TCGv t0 = tcg_temp_new();
15998 gen_load_gpr(t0, rt);
15999 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
16000 tcg_temp_free(t0);
16002 break;
16003 #endif
16004 case 0x2a:
16005 switch (minor & 3) {
16006 case MADD_ACC:
16007 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
16008 break;
16009 case MADDU_ACC:
16010 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
16011 break;
16012 case MSUB_ACC:
16013 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
16014 break;
16015 case MSUBU_ACC:
16016 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
16017 break;
16018 default:
16019 goto pool32axf_invalid;
16021 break;
16022 case 0x32:
16023 switch (minor & 3) {
16024 case MULT_ACC:
16025 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
16026 break;
16027 case MULTU_ACC:
16028 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
16029 break;
16030 default:
16031 goto pool32axf_invalid;
16033 break;
16034 case 0x2c:
16035 switch (minor) {
16036 case BITSWAP:
16037 check_insn(ctx, ISA_MIPS_R6);
16038 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
16039 break;
16040 case SEB:
16041 gen_bshfl(ctx, OPC_SEB, rs, rt);
16042 break;
16043 case SEH:
16044 gen_bshfl(ctx, OPC_SEH, rs, rt);
16045 break;
16046 case CLO:
16047 mips32_op = OPC_CLO;
16048 goto do_cl;
16049 case CLZ:
16050 mips32_op = OPC_CLZ;
16051 do_cl:
16052 check_insn(ctx, ISA_MIPS_R1);
16053 gen_cl(ctx, mips32_op, rt, rs);
16054 break;
16055 case RDHWR:
16056 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16057 gen_rdhwr(ctx, rt, rs, 0);
16058 break;
16059 case WSBH:
16060 gen_bshfl(ctx, OPC_WSBH, rs, rt);
16061 break;
16062 case MULT:
16063 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16064 mips32_op = OPC_MULT;
16065 goto do_mul;
16066 case MULTU:
16067 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16068 mips32_op = OPC_MULTU;
16069 goto do_mul;
16070 case DIV:
16071 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16072 mips32_op = OPC_DIV;
16073 goto do_div;
16074 case DIVU:
16075 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16076 mips32_op = OPC_DIVU;
16077 goto do_div;
16078 do_div:
16079 check_insn(ctx, ISA_MIPS_R1);
16080 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16081 break;
16082 case MADD:
16083 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16084 mips32_op = OPC_MADD;
16085 goto do_mul;
16086 case MADDU:
16087 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16088 mips32_op = OPC_MADDU;
16089 goto do_mul;
16090 case MSUB:
16091 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16092 mips32_op = OPC_MSUB;
16093 goto do_mul;
16094 case MSUBU:
16095 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16096 mips32_op = OPC_MSUBU;
16097 do_mul:
16098 check_insn(ctx, ISA_MIPS_R1);
16099 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16100 break;
16101 default:
16102 goto pool32axf_invalid;
16104 break;
16105 case 0x34:
16106 switch (minor) {
16107 case MFC2:
16108 case MTC2:
16109 case MFHC2:
16110 case MTHC2:
16111 case CFC2:
16112 case CTC2:
16113 generate_exception_err(ctx, EXCP_CpU, 2);
16114 break;
16115 default:
16116 goto pool32axf_invalid;
16118 break;
16119 case 0x3c:
16120 switch (minor) {
16121 case JALR: /* JALRC */
16122 case JALR_HB: /* JALRC_HB */
16123 if (ctx->insn_flags & ISA_MIPS_R6) {
16124 /* JALRC, JALRC_HB */
16125 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
16126 } else {
16127 /* JALR, JALR_HB */
16128 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
16129 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16131 break;
16132 case JALRS:
16133 case JALRS_HB:
16134 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16135 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
16136 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16137 break;
16138 default:
16139 goto pool32axf_invalid;
16141 break;
16142 case 0x05:
16143 switch (minor) {
16144 case RDPGPR:
16145 check_cp0_enabled(ctx);
16146 check_insn(ctx, ISA_MIPS_R2);
16147 gen_load_srsgpr(rs, rt);
16148 break;
16149 case WRPGPR:
16150 check_cp0_enabled(ctx);
16151 check_insn(ctx, ISA_MIPS_R2);
16152 gen_store_srsgpr(rs, rt);
16153 break;
16154 default:
16155 goto pool32axf_invalid;
16157 break;
16158 #ifndef CONFIG_USER_ONLY
16159 case 0x0d:
16160 switch (minor) {
16161 case TLBP:
16162 mips32_op = OPC_TLBP;
16163 goto do_cp0;
16164 case TLBR:
16165 mips32_op = OPC_TLBR;
16166 goto do_cp0;
16167 case TLBWI:
16168 mips32_op = OPC_TLBWI;
16169 goto do_cp0;
16170 case TLBWR:
16171 mips32_op = OPC_TLBWR;
16172 goto do_cp0;
16173 case TLBINV:
16174 mips32_op = OPC_TLBINV;
16175 goto do_cp0;
16176 case TLBINVF:
16177 mips32_op = OPC_TLBINVF;
16178 goto do_cp0;
16179 case WAIT:
16180 mips32_op = OPC_WAIT;
16181 goto do_cp0;
16182 case DERET:
16183 mips32_op = OPC_DERET;
16184 goto do_cp0;
16185 case ERET:
16186 mips32_op = OPC_ERET;
16187 do_cp0:
16188 gen_cp0(env, ctx, mips32_op, rt, rs);
16189 break;
16190 default:
16191 goto pool32axf_invalid;
16193 break;
16194 case 0x1d:
16195 switch (minor) {
16196 case DI:
16197 check_cp0_enabled(ctx);
16199 TCGv t0 = tcg_temp_new();
16201 save_cpu_state(ctx, 1);
16202 gen_helper_di(t0, cpu_env);
16203 gen_store_gpr(t0, rs);
16205 * Stop translation as we may have switched the execution
16206 * mode.
16208 ctx->base.is_jmp = DISAS_STOP;
16209 tcg_temp_free(t0);
16211 break;
16212 case EI:
16213 check_cp0_enabled(ctx);
16215 TCGv t0 = tcg_temp_new();
16217 save_cpu_state(ctx, 1);
16218 gen_helper_ei(t0, cpu_env);
16219 gen_store_gpr(t0, rs);
16221 * DISAS_STOP isn't sufficient, we need to ensure we break out
16222 * of translated code to check for pending interrupts.
16224 gen_save_pc(ctx->base.pc_next + 4);
16225 ctx->base.is_jmp = DISAS_EXIT;
16226 tcg_temp_free(t0);
16228 break;
16229 default:
16230 goto pool32axf_invalid;
16232 break;
16233 #endif
16234 case 0x2d:
16235 switch (minor) {
16236 case SYNC:
16237 gen_sync(extract32(ctx->opcode, 16, 5));
16238 break;
16239 case SYSCALL:
16240 generate_exception_end(ctx, EXCP_SYSCALL);
16241 break;
16242 case SDBBP:
16243 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
16244 gen_helper_do_semihosting(cpu_env);
16245 } else {
16246 check_insn(ctx, ISA_MIPS_R1);
16247 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16248 gen_reserved_instruction(ctx);
16249 } else {
16250 generate_exception_end(ctx, EXCP_DBp);
16253 break;
16254 default:
16255 goto pool32axf_invalid;
16257 break;
16258 case 0x01:
16259 switch (minor & 3) {
16260 case MFHI_ACC:
16261 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
16262 break;
16263 case MFLO_ACC:
16264 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
16265 break;
16266 case MTHI_ACC:
16267 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
16268 break;
16269 case MTLO_ACC:
16270 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
16271 break;
16272 default:
16273 goto pool32axf_invalid;
16275 break;
16276 case 0x35:
16277 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16278 switch (minor) {
16279 case MFHI32:
16280 gen_HILO(ctx, OPC_MFHI, 0, rs);
16281 break;
16282 case MFLO32:
16283 gen_HILO(ctx, OPC_MFLO, 0, rs);
16284 break;
16285 case MTHI32:
16286 gen_HILO(ctx, OPC_MTHI, 0, rs);
16287 break;
16288 case MTLO32:
16289 gen_HILO(ctx, OPC_MTLO, 0, rs);
16290 break;
16291 default:
16292 goto pool32axf_invalid;
16294 break;
16295 default:
16296 pool32axf_invalid:
16297 MIPS_INVAL("pool32axf");
16298 gen_reserved_instruction(ctx);
16299 break;
16304 * Values for microMIPS fmt field. Variable-width, depending on which
16305 * formats the instruction supports.
16307 enum {
16308 FMT_SD_S = 0,
16309 FMT_SD_D = 1,
16311 FMT_SDPS_S = 0,
16312 FMT_SDPS_D = 1,
16313 FMT_SDPS_PS = 2,
16315 FMT_SWL_S = 0,
16316 FMT_SWL_W = 1,
16317 FMT_SWL_L = 2,
16319 FMT_DWL_D = 0,
16320 FMT_DWL_W = 1,
16321 FMT_DWL_L = 2
16324 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16326 int extension = (ctx->opcode >> 6) & 0x3ff;
16327 uint32_t mips32_op;
16329 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16330 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16331 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16333 switch (extension) {
16334 case FLOAT_1BIT_FMT(CFC1, 0):
16335 mips32_op = OPC_CFC1;
16336 goto do_cp1;
16337 case FLOAT_1BIT_FMT(CTC1, 0):
16338 mips32_op = OPC_CTC1;
16339 goto do_cp1;
16340 case FLOAT_1BIT_FMT(MFC1, 0):
16341 mips32_op = OPC_MFC1;
16342 goto do_cp1;
16343 case FLOAT_1BIT_FMT(MTC1, 0):
16344 mips32_op = OPC_MTC1;
16345 goto do_cp1;
16346 case FLOAT_1BIT_FMT(MFHC1, 0):
16347 mips32_op = OPC_MFHC1;
16348 goto do_cp1;
16349 case FLOAT_1BIT_FMT(MTHC1, 0):
16350 mips32_op = OPC_MTHC1;
16351 do_cp1:
16352 gen_cp1(ctx, mips32_op, rt, rs);
16353 break;
16355 /* Reciprocal square root */
16356 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16357 mips32_op = OPC_RSQRT_S;
16358 goto do_unaryfp;
16359 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16360 mips32_op = OPC_RSQRT_D;
16361 goto do_unaryfp;
16363 /* Square root */
16364 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16365 mips32_op = OPC_SQRT_S;
16366 goto do_unaryfp;
16367 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16368 mips32_op = OPC_SQRT_D;
16369 goto do_unaryfp;
16371 /* Reciprocal */
16372 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16373 mips32_op = OPC_RECIP_S;
16374 goto do_unaryfp;
16375 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16376 mips32_op = OPC_RECIP_D;
16377 goto do_unaryfp;
16379 /* Floor */
16380 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16381 mips32_op = OPC_FLOOR_L_S;
16382 goto do_unaryfp;
16383 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16384 mips32_op = OPC_FLOOR_L_D;
16385 goto do_unaryfp;
16386 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16387 mips32_op = OPC_FLOOR_W_S;
16388 goto do_unaryfp;
16389 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16390 mips32_op = OPC_FLOOR_W_D;
16391 goto do_unaryfp;
16393 /* Ceiling */
16394 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16395 mips32_op = OPC_CEIL_L_S;
16396 goto do_unaryfp;
16397 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16398 mips32_op = OPC_CEIL_L_D;
16399 goto do_unaryfp;
16400 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16401 mips32_op = OPC_CEIL_W_S;
16402 goto do_unaryfp;
16403 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16404 mips32_op = OPC_CEIL_W_D;
16405 goto do_unaryfp;
16407 /* Truncation */
16408 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16409 mips32_op = OPC_TRUNC_L_S;
16410 goto do_unaryfp;
16411 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16412 mips32_op = OPC_TRUNC_L_D;
16413 goto do_unaryfp;
16414 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16415 mips32_op = OPC_TRUNC_W_S;
16416 goto do_unaryfp;
16417 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16418 mips32_op = OPC_TRUNC_W_D;
16419 goto do_unaryfp;
16421 /* Round */
16422 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16423 mips32_op = OPC_ROUND_L_S;
16424 goto do_unaryfp;
16425 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16426 mips32_op = OPC_ROUND_L_D;
16427 goto do_unaryfp;
16428 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16429 mips32_op = OPC_ROUND_W_S;
16430 goto do_unaryfp;
16431 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16432 mips32_op = OPC_ROUND_W_D;
16433 goto do_unaryfp;
16435 /* Integer to floating-point conversion */
16436 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16437 mips32_op = OPC_CVT_L_S;
16438 goto do_unaryfp;
16439 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16440 mips32_op = OPC_CVT_L_D;
16441 goto do_unaryfp;
16442 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16443 mips32_op = OPC_CVT_W_S;
16444 goto do_unaryfp;
16445 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16446 mips32_op = OPC_CVT_W_D;
16447 goto do_unaryfp;
16449 /* Paired-foo conversions */
16450 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16451 mips32_op = OPC_CVT_S_PL;
16452 goto do_unaryfp;
16453 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16454 mips32_op = OPC_CVT_S_PU;
16455 goto do_unaryfp;
16456 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16457 mips32_op = OPC_CVT_PW_PS;
16458 goto do_unaryfp;
16459 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16460 mips32_op = OPC_CVT_PS_PW;
16461 goto do_unaryfp;
16463 /* Floating-point moves */
16464 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16465 mips32_op = OPC_MOV_S;
16466 goto do_unaryfp;
16467 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16468 mips32_op = OPC_MOV_D;
16469 goto do_unaryfp;
16470 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16471 mips32_op = OPC_MOV_PS;
16472 goto do_unaryfp;
16474 /* Absolute value */
16475 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16476 mips32_op = OPC_ABS_S;
16477 goto do_unaryfp;
16478 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16479 mips32_op = OPC_ABS_D;
16480 goto do_unaryfp;
16481 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16482 mips32_op = OPC_ABS_PS;
16483 goto do_unaryfp;
16485 /* Negation */
16486 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16487 mips32_op = OPC_NEG_S;
16488 goto do_unaryfp;
16489 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16490 mips32_op = OPC_NEG_D;
16491 goto do_unaryfp;
16492 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16493 mips32_op = OPC_NEG_PS;
16494 goto do_unaryfp;
16496 /* Reciprocal square root step */
16497 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16498 mips32_op = OPC_RSQRT1_S;
16499 goto do_unaryfp;
16500 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16501 mips32_op = OPC_RSQRT1_D;
16502 goto do_unaryfp;
16503 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16504 mips32_op = OPC_RSQRT1_PS;
16505 goto do_unaryfp;
16507 /* Reciprocal step */
16508 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16509 mips32_op = OPC_RECIP1_S;
16510 goto do_unaryfp;
16511 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16512 mips32_op = OPC_RECIP1_S;
16513 goto do_unaryfp;
16514 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16515 mips32_op = OPC_RECIP1_PS;
16516 goto do_unaryfp;
16518 /* Conversions from double */
16519 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16520 mips32_op = OPC_CVT_D_S;
16521 goto do_unaryfp;
16522 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16523 mips32_op = OPC_CVT_D_W;
16524 goto do_unaryfp;
16525 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16526 mips32_op = OPC_CVT_D_L;
16527 goto do_unaryfp;
16529 /* Conversions from single */
16530 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16531 mips32_op = OPC_CVT_S_D;
16532 goto do_unaryfp;
16533 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16534 mips32_op = OPC_CVT_S_W;
16535 goto do_unaryfp;
16536 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16537 mips32_op = OPC_CVT_S_L;
16538 do_unaryfp:
16539 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16540 break;
16542 /* Conditional moves on floating-point codes */
16543 case COND_FLOAT_MOV(MOVT, 0):
16544 case COND_FLOAT_MOV(MOVT, 1):
16545 case COND_FLOAT_MOV(MOVT, 2):
16546 case COND_FLOAT_MOV(MOVT, 3):
16547 case COND_FLOAT_MOV(MOVT, 4):
16548 case COND_FLOAT_MOV(MOVT, 5):
16549 case COND_FLOAT_MOV(MOVT, 6):
16550 case COND_FLOAT_MOV(MOVT, 7):
16551 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16552 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16553 break;
16554 case COND_FLOAT_MOV(MOVF, 0):
16555 case COND_FLOAT_MOV(MOVF, 1):
16556 case COND_FLOAT_MOV(MOVF, 2):
16557 case COND_FLOAT_MOV(MOVF, 3):
16558 case COND_FLOAT_MOV(MOVF, 4):
16559 case COND_FLOAT_MOV(MOVF, 5):
16560 case COND_FLOAT_MOV(MOVF, 6):
16561 case COND_FLOAT_MOV(MOVF, 7):
16562 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16563 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16564 break;
16565 default:
16566 MIPS_INVAL("pool32fxf");
16567 gen_reserved_instruction(ctx);
16568 break;
16572 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16574 int32_t offset;
16575 uint16_t insn;
16576 int rt, rs, rd, rr;
16577 int16_t imm;
16578 uint32_t op, minor, minor2, mips32_op;
16579 uint32_t cond, fmt, cc;
16581 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16582 ctx->opcode = (ctx->opcode << 16) | insn;
16584 rt = (ctx->opcode >> 21) & 0x1f;
16585 rs = (ctx->opcode >> 16) & 0x1f;
16586 rd = (ctx->opcode >> 11) & 0x1f;
16587 rr = (ctx->opcode >> 6) & 0x1f;
16588 imm = (int16_t) ctx->opcode;
16590 op = (ctx->opcode >> 26) & 0x3f;
16591 switch (op) {
16592 case POOL32A:
16593 minor = ctx->opcode & 0x3f;
16594 switch (minor) {
16595 case 0x00:
16596 minor = (ctx->opcode >> 6) & 0xf;
16597 switch (minor) {
16598 case SLL32:
16599 mips32_op = OPC_SLL;
16600 goto do_shifti;
16601 case SRA:
16602 mips32_op = OPC_SRA;
16603 goto do_shifti;
16604 case SRL32:
16605 mips32_op = OPC_SRL;
16606 goto do_shifti;
16607 case ROTR:
16608 mips32_op = OPC_ROTR;
16609 do_shifti:
16610 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16611 break;
16612 case SELEQZ:
16613 check_insn(ctx, ISA_MIPS_R6);
16614 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16615 break;
16616 case SELNEZ:
16617 check_insn(ctx, ISA_MIPS_R6);
16618 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16619 break;
16620 case R6_RDHWR:
16621 check_insn(ctx, ISA_MIPS_R6);
16622 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16623 break;
16624 default:
16625 goto pool32a_invalid;
16627 break;
16628 case 0x10:
16629 minor = (ctx->opcode >> 6) & 0xf;
16630 switch (minor) {
16631 /* Arithmetic */
16632 case ADD:
16633 mips32_op = OPC_ADD;
16634 goto do_arith;
16635 case ADDU32:
16636 mips32_op = OPC_ADDU;
16637 goto do_arith;
16638 case SUB:
16639 mips32_op = OPC_SUB;
16640 goto do_arith;
16641 case SUBU32:
16642 mips32_op = OPC_SUBU;
16643 goto do_arith;
16644 case MUL:
16645 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16646 mips32_op = OPC_MUL;
16647 do_arith:
16648 gen_arith(ctx, mips32_op, rd, rs, rt);
16649 break;
16650 /* Shifts */
16651 case SLLV:
16652 mips32_op = OPC_SLLV;
16653 goto do_shift;
16654 case SRLV:
16655 mips32_op = OPC_SRLV;
16656 goto do_shift;
16657 case SRAV:
16658 mips32_op = OPC_SRAV;
16659 goto do_shift;
16660 case ROTRV:
16661 mips32_op = OPC_ROTRV;
16662 do_shift:
16663 gen_shift(ctx, mips32_op, rd, rs, rt);
16664 break;
16665 /* Logical operations */
16666 case AND:
16667 mips32_op = OPC_AND;
16668 goto do_logic;
16669 case OR32:
16670 mips32_op = OPC_OR;
16671 goto do_logic;
16672 case NOR:
16673 mips32_op = OPC_NOR;
16674 goto do_logic;
16675 case XOR32:
16676 mips32_op = OPC_XOR;
16677 do_logic:
16678 gen_logic(ctx, mips32_op, rd, rs, rt);
16679 break;
16680 /* Set less than */
16681 case SLT:
16682 mips32_op = OPC_SLT;
16683 goto do_slt;
16684 case SLTU:
16685 mips32_op = OPC_SLTU;
16686 do_slt:
16687 gen_slt(ctx, mips32_op, rd, rs, rt);
16688 break;
16689 default:
16690 goto pool32a_invalid;
16692 break;
16693 case 0x18:
16694 minor = (ctx->opcode >> 6) & 0xf;
16695 switch (minor) {
16696 /* Conditional moves */
16697 case MOVN: /* MUL */
16698 if (ctx->insn_flags & ISA_MIPS_R6) {
16699 /* MUL */
16700 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16701 } else {
16702 /* MOVN */
16703 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16705 break;
16706 case MOVZ: /* MUH */
16707 if (ctx->insn_flags & ISA_MIPS_R6) {
16708 /* MUH */
16709 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16710 } else {
16711 /* MOVZ */
16712 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16714 break;
16715 case MULU:
16716 check_insn(ctx, ISA_MIPS_R6);
16717 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16718 break;
16719 case MUHU:
16720 check_insn(ctx, ISA_MIPS_R6);
16721 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16722 break;
16723 case LWXS: /* DIV */
16724 if (ctx->insn_flags & ISA_MIPS_R6) {
16725 /* DIV */
16726 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16727 } else {
16728 /* LWXS */
16729 gen_ldxs(ctx, rs, rt, rd);
16731 break;
16732 case MOD:
16733 check_insn(ctx, ISA_MIPS_R6);
16734 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16735 break;
16736 case R6_DIVU:
16737 check_insn(ctx, ISA_MIPS_R6);
16738 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16739 break;
16740 case MODU:
16741 check_insn(ctx, ISA_MIPS_R6);
16742 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16743 break;
16744 default:
16745 goto pool32a_invalid;
16747 break;
16748 case INS:
16749 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16750 return;
16751 case LSA:
16752 check_insn(ctx, ISA_MIPS_R6);
16753 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16754 extract32(ctx->opcode, 9, 2));
16755 break;
16756 case ALIGN:
16757 check_insn(ctx, ISA_MIPS_R6);
16758 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16759 break;
16760 case EXT:
16761 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16762 return;
16763 case POOL32AXF:
16764 gen_pool32axf(env, ctx, rt, rs);
16765 break;
16766 case BREAK32:
16767 generate_exception_end(ctx, EXCP_BREAK);
16768 break;
16769 case SIGRIE:
16770 check_insn(ctx, ISA_MIPS_R6);
16771 gen_reserved_instruction(ctx);
16772 break;
16773 default:
16774 pool32a_invalid:
16775 MIPS_INVAL("pool32a");
16776 gen_reserved_instruction(ctx);
16777 break;
16779 break;
16780 case POOL32B:
16781 minor = (ctx->opcode >> 12) & 0xf;
16782 switch (minor) {
16783 case CACHE:
16784 check_cp0_enabled(ctx);
16785 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16786 gen_cache_operation(ctx, rt, rs, imm);
16788 break;
16789 case LWC2:
16790 case SWC2:
16791 /* COP2: Not implemented. */
16792 generate_exception_err(ctx, EXCP_CpU, 2);
16793 break;
16794 #ifdef TARGET_MIPS64
16795 case LDP:
16796 case SDP:
16797 check_insn(ctx, ISA_MIPS3);
16798 check_mips_64(ctx);
16799 #endif
16800 /* fall through */
16801 case LWP:
16802 case SWP:
16803 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16804 break;
16805 #ifdef TARGET_MIPS64
16806 case LDM:
16807 case SDM:
16808 check_insn(ctx, ISA_MIPS3);
16809 check_mips_64(ctx);
16810 #endif
16811 /* fall through */
16812 case LWM32:
16813 case SWM32:
16814 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16815 break;
16816 default:
16817 MIPS_INVAL("pool32b");
16818 gen_reserved_instruction(ctx);
16819 break;
16821 break;
16822 case POOL32F:
16823 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16824 minor = ctx->opcode & 0x3f;
16825 check_cp1_enabled(ctx);
16826 switch (minor) {
16827 case ALNV_PS:
16828 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16829 mips32_op = OPC_ALNV_PS;
16830 goto do_madd;
16831 case MADD_S:
16832 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16833 mips32_op = OPC_MADD_S;
16834 goto do_madd;
16835 case MADD_D:
16836 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16837 mips32_op = OPC_MADD_D;
16838 goto do_madd;
16839 case MADD_PS:
16840 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16841 mips32_op = OPC_MADD_PS;
16842 goto do_madd;
16843 case MSUB_S:
16844 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16845 mips32_op = OPC_MSUB_S;
16846 goto do_madd;
16847 case MSUB_D:
16848 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16849 mips32_op = OPC_MSUB_D;
16850 goto do_madd;
16851 case MSUB_PS:
16852 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16853 mips32_op = OPC_MSUB_PS;
16854 goto do_madd;
16855 case NMADD_S:
16856 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16857 mips32_op = OPC_NMADD_S;
16858 goto do_madd;
16859 case NMADD_D:
16860 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16861 mips32_op = OPC_NMADD_D;
16862 goto do_madd;
16863 case NMADD_PS:
16864 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16865 mips32_op = OPC_NMADD_PS;
16866 goto do_madd;
16867 case NMSUB_S:
16868 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16869 mips32_op = OPC_NMSUB_S;
16870 goto do_madd;
16871 case NMSUB_D:
16872 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16873 mips32_op = OPC_NMSUB_D;
16874 goto do_madd;
16875 case NMSUB_PS:
16876 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16877 mips32_op = OPC_NMSUB_PS;
16878 do_madd:
16879 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
16880 break;
16881 case CABS_COND_FMT:
16882 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16883 cond = (ctx->opcode >> 6) & 0xf;
16884 cc = (ctx->opcode >> 13) & 0x7;
16885 fmt = (ctx->opcode >> 10) & 0x3;
16886 switch (fmt) {
16887 case 0x0:
16888 gen_cmpabs_s(ctx, cond, rt, rs, cc);
16889 break;
16890 case 0x1:
16891 gen_cmpabs_d(ctx, cond, rt, rs, cc);
16892 break;
16893 case 0x2:
16894 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
16895 break;
16896 default:
16897 goto pool32f_invalid;
16899 break;
16900 case C_COND_FMT:
16901 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16902 cond = (ctx->opcode >> 6) & 0xf;
16903 cc = (ctx->opcode >> 13) & 0x7;
16904 fmt = (ctx->opcode >> 10) & 0x3;
16905 switch (fmt) {
16906 case 0x0:
16907 gen_cmp_s(ctx, cond, rt, rs, cc);
16908 break;
16909 case 0x1:
16910 gen_cmp_d(ctx, cond, rt, rs, cc);
16911 break;
16912 case 0x2:
16913 gen_cmp_ps(ctx, cond, rt, rs, cc);
16914 break;
16915 default:
16916 goto pool32f_invalid;
16918 break;
16919 case CMP_CONDN_S:
16920 check_insn(ctx, ISA_MIPS_R6);
16921 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16922 break;
16923 case CMP_CONDN_D:
16924 check_insn(ctx, ISA_MIPS_R6);
16925 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
16926 break;
16927 case POOL32FXF:
16928 gen_pool32fxf(ctx, rt, rs);
16929 break;
16930 case 0x00:
16931 /* PLL foo */
16932 switch ((ctx->opcode >> 6) & 0x7) {
16933 case PLL_PS:
16934 mips32_op = OPC_PLL_PS;
16935 goto do_ps;
16936 case PLU_PS:
16937 mips32_op = OPC_PLU_PS;
16938 goto do_ps;
16939 case PUL_PS:
16940 mips32_op = OPC_PUL_PS;
16941 goto do_ps;
16942 case PUU_PS:
16943 mips32_op = OPC_PUU_PS;
16944 goto do_ps;
16945 case CVT_PS_S:
16946 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16947 mips32_op = OPC_CVT_PS_S;
16948 do_ps:
16949 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
16950 break;
16951 default:
16952 goto pool32f_invalid;
16954 break;
16955 case MIN_FMT:
16956 check_insn(ctx, ISA_MIPS_R6);
16957 switch ((ctx->opcode >> 9) & 0x3) {
16958 case FMT_SDPS_S:
16959 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
16960 break;
16961 case FMT_SDPS_D:
16962 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
16963 break;
16964 default:
16965 goto pool32f_invalid;
16967 break;
16968 case 0x08:
16969 /* [LS][WDU]XC1 */
16970 switch ((ctx->opcode >> 6) & 0x7) {
16971 case LWXC1:
16972 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16973 mips32_op = OPC_LWXC1;
16974 goto do_ldst_cp1;
16975 case SWXC1:
16976 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16977 mips32_op = OPC_SWXC1;
16978 goto do_ldst_cp1;
16979 case LDXC1:
16980 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16981 mips32_op = OPC_LDXC1;
16982 goto do_ldst_cp1;
16983 case SDXC1:
16984 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16985 mips32_op = OPC_SDXC1;
16986 goto do_ldst_cp1;
16987 case LUXC1:
16988 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16989 mips32_op = OPC_LUXC1;
16990 goto do_ldst_cp1;
16991 case SUXC1:
16992 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16993 mips32_op = OPC_SUXC1;
16994 do_ldst_cp1:
16995 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
16996 break;
16997 default:
16998 goto pool32f_invalid;
17000 break;
17001 case MAX_FMT:
17002 check_insn(ctx, ISA_MIPS_R6);
17003 switch ((ctx->opcode >> 9) & 0x3) {
17004 case FMT_SDPS_S:
17005 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
17006 break;
17007 case FMT_SDPS_D:
17008 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
17009 break;
17010 default:
17011 goto pool32f_invalid;
17013 break;
17014 case 0x18:
17015 /* 3D insns */
17016 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17017 fmt = (ctx->opcode >> 9) & 0x3;
17018 switch ((ctx->opcode >> 6) & 0x7) {
17019 case RSQRT2_FMT:
17020 switch (fmt) {
17021 case FMT_SDPS_S:
17022 mips32_op = OPC_RSQRT2_S;
17023 goto do_3d;
17024 case FMT_SDPS_D:
17025 mips32_op = OPC_RSQRT2_D;
17026 goto do_3d;
17027 case FMT_SDPS_PS:
17028 mips32_op = OPC_RSQRT2_PS;
17029 goto do_3d;
17030 default:
17031 goto pool32f_invalid;
17033 break;
17034 case RECIP2_FMT:
17035 switch (fmt) {
17036 case FMT_SDPS_S:
17037 mips32_op = OPC_RECIP2_S;
17038 goto do_3d;
17039 case FMT_SDPS_D:
17040 mips32_op = OPC_RECIP2_D;
17041 goto do_3d;
17042 case FMT_SDPS_PS:
17043 mips32_op = OPC_RECIP2_PS;
17044 goto do_3d;
17045 default:
17046 goto pool32f_invalid;
17048 break;
17049 case ADDR_PS:
17050 mips32_op = OPC_ADDR_PS;
17051 goto do_3d;
17052 case MULR_PS:
17053 mips32_op = OPC_MULR_PS;
17054 do_3d:
17055 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17056 break;
17057 default:
17058 goto pool32f_invalid;
17060 break;
17061 case 0x20:
17062 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
17063 cc = (ctx->opcode >> 13) & 0x7;
17064 fmt = (ctx->opcode >> 9) & 0x3;
17065 switch ((ctx->opcode >> 6) & 0x7) {
17066 case MOVF_FMT: /* RINT_FMT */
17067 if (ctx->insn_flags & ISA_MIPS_R6) {
17068 /* RINT_FMT */
17069 switch (fmt) {
17070 case FMT_SDPS_S:
17071 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
17072 break;
17073 case FMT_SDPS_D:
17074 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
17075 break;
17076 default:
17077 goto pool32f_invalid;
17079 } else {
17080 /* MOVF_FMT */
17081 switch (fmt) {
17082 case FMT_SDPS_S:
17083 gen_movcf_s(ctx, rs, rt, cc, 0);
17084 break;
17085 case FMT_SDPS_D:
17086 gen_movcf_d(ctx, rs, rt, cc, 0);
17087 break;
17088 case FMT_SDPS_PS:
17089 check_ps(ctx);
17090 gen_movcf_ps(ctx, rs, rt, cc, 0);
17091 break;
17092 default:
17093 goto pool32f_invalid;
17096 break;
17097 case MOVT_FMT: /* CLASS_FMT */
17098 if (ctx->insn_flags & ISA_MIPS_R6) {
17099 /* CLASS_FMT */
17100 switch (fmt) {
17101 case FMT_SDPS_S:
17102 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
17103 break;
17104 case FMT_SDPS_D:
17105 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
17106 break;
17107 default:
17108 goto pool32f_invalid;
17110 } else {
17111 /* MOVT_FMT */
17112 switch (fmt) {
17113 case FMT_SDPS_S:
17114 gen_movcf_s(ctx, rs, rt, cc, 1);
17115 break;
17116 case FMT_SDPS_D:
17117 gen_movcf_d(ctx, rs, rt, cc, 1);
17118 break;
17119 case FMT_SDPS_PS:
17120 check_ps(ctx);
17121 gen_movcf_ps(ctx, rs, rt, cc, 1);
17122 break;
17123 default:
17124 goto pool32f_invalid;
17127 break;
17128 case PREFX:
17129 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17130 break;
17131 default:
17132 goto pool32f_invalid;
17134 break;
17135 #define FINSN_3ARG_SDPS(prfx) \
17136 switch ((ctx->opcode >> 8) & 0x3) { \
17137 case FMT_SDPS_S: \
17138 mips32_op = OPC_##prfx##_S; \
17139 goto do_fpop; \
17140 case FMT_SDPS_D: \
17141 mips32_op = OPC_##prfx##_D; \
17142 goto do_fpop; \
17143 case FMT_SDPS_PS: \
17144 check_ps(ctx); \
17145 mips32_op = OPC_##prfx##_PS; \
17146 goto do_fpop; \
17147 default: \
17148 goto pool32f_invalid; \
17150 case MINA_FMT:
17151 check_insn(ctx, ISA_MIPS_R6);
17152 switch ((ctx->opcode >> 9) & 0x3) {
17153 case FMT_SDPS_S:
17154 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
17155 break;
17156 case FMT_SDPS_D:
17157 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
17158 break;
17159 default:
17160 goto pool32f_invalid;
17162 break;
17163 case MAXA_FMT:
17164 check_insn(ctx, ISA_MIPS_R6);
17165 switch ((ctx->opcode >> 9) & 0x3) {
17166 case FMT_SDPS_S:
17167 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
17168 break;
17169 case FMT_SDPS_D:
17170 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
17171 break;
17172 default:
17173 goto pool32f_invalid;
17175 break;
17176 case 0x30:
17177 /* regular FP ops */
17178 switch ((ctx->opcode >> 6) & 0x3) {
17179 case ADD_FMT:
17180 FINSN_3ARG_SDPS(ADD);
17181 break;
17182 case SUB_FMT:
17183 FINSN_3ARG_SDPS(SUB);
17184 break;
17185 case MUL_FMT:
17186 FINSN_3ARG_SDPS(MUL);
17187 break;
17188 case DIV_FMT:
17189 fmt = (ctx->opcode >> 8) & 0x3;
17190 if (fmt == 1) {
17191 mips32_op = OPC_DIV_D;
17192 } else if (fmt == 0) {
17193 mips32_op = OPC_DIV_S;
17194 } else {
17195 goto pool32f_invalid;
17197 goto do_fpop;
17198 default:
17199 goto pool32f_invalid;
17201 break;
17202 case 0x38:
17203 /* cmovs */
17204 switch ((ctx->opcode >> 6) & 0x7) {
17205 case MOVN_FMT: /* SELEQZ_FMT */
17206 if (ctx->insn_flags & ISA_MIPS_R6) {
17207 /* SELEQZ_FMT */
17208 switch ((ctx->opcode >> 9) & 0x3) {
17209 case FMT_SDPS_S:
17210 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
17211 break;
17212 case FMT_SDPS_D:
17213 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
17214 break;
17215 default:
17216 goto pool32f_invalid;
17218 } else {
17219 /* MOVN_FMT */
17220 FINSN_3ARG_SDPS(MOVN);
17222 break;
17223 case MOVN_FMT_04:
17224 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17225 FINSN_3ARG_SDPS(MOVN);
17226 break;
17227 case MOVZ_FMT: /* SELNEZ_FMT */
17228 if (ctx->insn_flags & ISA_MIPS_R6) {
17229 /* SELNEZ_FMT */
17230 switch ((ctx->opcode >> 9) & 0x3) {
17231 case FMT_SDPS_S:
17232 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
17233 break;
17234 case FMT_SDPS_D:
17235 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
17236 break;
17237 default:
17238 goto pool32f_invalid;
17240 } else {
17241 /* MOVZ_FMT */
17242 FINSN_3ARG_SDPS(MOVZ);
17244 break;
17245 case MOVZ_FMT_05:
17246 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17247 FINSN_3ARG_SDPS(MOVZ);
17248 break;
17249 case SEL_FMT:
17250 check_insn(ctx, ISA_MIPS_R6);
17251 switch ((ctx->opcode >> 9) & 0x3) {
17252 case FMT_SDPS_S:
17253 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
17254 break;
17255 case FMT_SDPS_D:
17256 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
17257 break;
17258 default:
17259 goto pool32f_invalid;
17261 break;
17262 case MADDF_FMT:
17263 check_insn(ctx, ISA_MIPS_R6);
17264 switch ((ctx->opcode >> 9) & 0x3) {
17265 case FMT_SDPS_S:
17266 mips32_op = OPC_MADDF_S;
17267 goto do_fpop;
17268 case FMT_SDPS_D:
17269 mips32_op = OPC_MADDF_D;
17270 goto do_fpop;
17271 default:
17272 goto pool32f_invalid;
17274 break;
17275 case MSUBF_FMT:
17276 check_insn(ctx, ISA_MIPS_R6);
17277 switch ((ctx->opcode >> 9) & 0x3) {
17278 case FMT_SDPS_S:
17279 mips32_op = OPC_MSUBF_S;
17280 goto do_fpop;
17281 case FMT_SDPS_D:
17282 mips32_op = OPC_MSUBF_D;
17283 goto do_fpop;
17284 default:
17285 goto pool32f_invalid;
17287 break;
17288 default:
17289 goto pool32f_invalid;
17291 break;
17292 do_fpop:
17293 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17294 break;
17295 default:
17296 pool32f_invalid:
17297 MIPS_INVAL("pool32f");
17298 gen_reserved_instruction(ctx);
17299 break;
17301 } else {
17302 generate_exception_err(ctx, EXCP_CpU, 1);
17304 break;
17305 case POOL32I:
17306 minor = (ctx->opcode >> 21) & 0x1f;
17307 switch (minor) {
17308 case BLTZ:
17309 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17310 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17311 break;
17312 case BLTZAL:
17313 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17314 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17315 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17316 break;
17317 case BLTZALS:
17318 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17319 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17320 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17321 break;
17322 case BGEZ:
17323 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17324 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17325 break;
17326 case BGEZAL:
17327 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17328 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17329 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17330 break;
17331 case BGEZALS:
17332 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17333 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17334 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17335 break;
17336 case BLEZ:
17337 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17338 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17339 break;
17340 case BGTZ:
17341 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17342 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17343 break;
17345 /* Traps */
17346 case TLTI: /* BC1EQZC */
17347 if (ctx->insn_flags & ISA_MIPS_R6) {
17348 /* BC1EQZC */
17349 check_cp1_enabled(ctx);
17350 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17351 } else {
17352 /* TLTI */
17353 mips32_op = OPC_TLTI;
17354 goto do_trapi;
17356 break;
17357 case TGEI: /* BC1NEZC */
17358 if (ctx->insn_flags & ISA_MIPS_R6) {
17359 /* BC1NEZC */
17360 check_cp1_enabled(ctx);
17361 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17362 } else {
17363 /* TGEI */
17364 mips32_op = OPC_TGEI;
17365 goto do_trapi;
17367 break;
17368 case TLTIU:
17369 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17370 mips32_op = OPC_TLTIU;
17371 goto do_trapi;
17372 case TGEIU:
17373 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17374 mips32_op = OPC_TGEIU;
17375 goto do_trapi;
17376 case TNEI: /* SYNCI */
17377 if (ctx->insn_flags & ISA_MIPS_R6) {
17378 /* SYNCI */
17380 * Break the TB to be able to sync copied instructions
17381 * immediately.
17383 ctx->base.is_jmp = DISAS_STOP;
17384 } else {
17385 /* TNEI */
17386 mips32_op = OPC_TNEI;
17387 goto do_trapi;
17389 break;
17390 case TEQI:
17391 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17392 mips32_op = OPC_TEQI;
17393 do_trapi:
17394 gen_trap(ctx, mips32_op, rs, -1, imm);
17395 break;
17397 case BNEZC:
17398 case BEQZC:
17399 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17400 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17401 4, rs, 0, imm << 1, 0);
17403 * Compact branches don't have a delay slot, so just let
17404 * the normal delay slot handling take us to the branch
17405 * target.
17407 break;
17408 case LUI:
17409 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17410 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17411 break;
17412 case SYNCI:
17413 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17415 * Break the TB to be able to sync copied instructions
17416 * immediately.
17418 ctx->base.is_jmp = DISAS_STOP;
17419 break;
17420 case BC2F:
17421 case BC2T:
17422 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17423 /* COP2: Not implemented. */
17424 generate_exception_err(ctx, EXCP_CpU, 2);
17425 break;
17426 case BC1F:
17427 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17428 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17429 goto do_cp1branch;
17430 case BC1T:
17431 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17432 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17433 goto do_cp1branch;
17434 case BC1ANY4F:
17435 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17436 mips32_op = OPC_BC1FANY4;
17437 goto do_cp1mips3d;
17438 case BC1ANY4T:
17439 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17440 mips32_op = OPC_BC1TANY4;
17441 do_cp1mips3d:
17442 check_cop1x(ctx);
17443 check_insn(ctx, ASE_MIPS3D);
17444 /* Fall through */
17445 do_cp1branch:
17446 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17447 check_cp1_enabled(ctx);
17448 gen_compute_branch1(ctx, mips32_op,
17449 (ctx->opcode >> 18) & 0x7, imm << 1);
17450 } else {
17451 generate_exception_err(ctx, EXCP_CpU, 1);
17453 break;
17454 case BPOSGE64:
17455 case BPOSGE32:
17456 /* MIPS DSP: not implemented */
17457 /* Fall through */
17458 default:
17459 MIPS_INVAL("pool32i");
17460 gen_reserved_instruction(ctx);
17461 break;
17463 break;
17464 case POOL32C:
17465 minor = (ctx->opcode >> 12) & 0xf;
17466 offset = sextract32(ctx->opcode, 0,
17467 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
17468 switch (minor) {
17469 case LWL:
17470 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17471 mips32_op = OPC_LWL;
17472 goto do_ld_lr;
17473 case SWL:
17474 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17475 mips32_op = OPC_SWL;
17476 goto do_st_lr;
17477 case LWR:
17478 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17479 mips32_op = OPC_LWR;
17480 goto do_ld_lr;
17481 case SWR:
17482 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17483 mips32_op = OPC_SWR;
17484 goto do_st_lr;
17485 #if defined(TARGET_MIPS64)
17486 case LDL:
17487 check_insn(ctx, ISA_MIPS3);
17488 check_mips_64(ctx);
17489 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17490 mips32_op = OPC_LDL;
17491 goto do_ld_lr;
17492 case SDL:
17493 check_insn(ctx, ISA_MIPS3);
17494 check_mips_64(ctx);
17495 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17496 mips32_op = OPC_SDL;
17497 goto do_st_lr;
17498 case LDR:
17499 check_insn(ctx, ISA_MIPS3);
17500 check_mips_64(ctx);
17501 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17502 mips32_op = OPC_LDR;
17503 goto do_ld_lr;
17504 case SDR:
17505 check_insn(ctx, ISA_MIPS3);
17506 check_mips_64(ctx);
17507 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17508 mips32_op = OPC_SDR;
17509 goto do_st_lr;
17510 case LWU:
17511 check_insn(ctx, ISA_MIPS3);
17512 check_mips_64(ctx);
17513 mips32_op = OPC_LWU;
17514 goto do_ld_lr;
17515 case LLD:
17516 check_insn(ctx, ISA_MIPS3);
17517 check_mips_64(ctx);
17518 mips32_op = OPC_LLD;
17519 goto do_ld_lr;
17520 #endif
17521 case LL:
17522 mips32_op = OPC_LL;
17523 goto do_ld_lr;
17524 do_ld_lr:
17525 gen_ld(ctx, mips32_op, rt, rs, offset);
17526 break;
17527 do_st_lr:
17528 gen_st(ctx, mips32_op, rt, rs, offset);
17529 break;
17530 case SC:
17531 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17532 break;
17533 #if defined(TARGET_MIPS64)
17534 case SCD:
17535 check_insn(ctx, ISA_MIPS3);
17536 check_mips_64(ctx);
17537 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17538 break;
17539 #endif
17540 case LD_EVA:
17541 if (!ctx->eva) {
17542 MIPS_INVAL("pool32c ld-eva");
17543 gen_reserved_instruction(ctx);
17544 break;
17546 check_cp0_enabled(ctx);
17548 minor2 = (ctx->opcode >> 9) & 0x7;
17549 offset = sextract32(ctx->opcode, 0, 9);
17550 switch (minor2) {
17551 case LBUE:
17552 mips32_op = OPC_LBUE;
17553 goto do_ld_lr;
17554 case LHUE:
17555 mips32_op = OPC_LHUE;
17556 goto do_ld_lr;
17557 case LWLE:
17558 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17559 mips32_op = OPC_LWLE;
17560 goto do_ld_lr;
17561 case LWRE:
17562 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17563 mips32_op = OPC_LWRE;
17564 goto do_ld_lr;
17565 case LBE:
17566 mips32_op = OPC_LBE;
17567 goto do_ld_lr;
17568 case LHE:
17569 mips32_op = OPC_LHE;
17570 goto do_ld_lr;
17571 case LLE:
17572 mips32_op = OPC_LLE;
17573 goto do_ld_lr;
17574 case LWE:
17575 mips32_op = OPC_LWE;
17576 goto do_ld_lr;
17578 break;
17579 case ST_EVA:
17580 if (!ctx->eva) {
17581 MIPS_INVAL("pool32c st-eva");
17582 gen_reserved_instruction(ctx);
17583 break;
17585 check_cp0_enabled(ctx);
17587 minor2 = (ctx->opcode >> 9) & 0x7;
17588 offset = sextract32(ctx->opcode, 0, 9);
17589 switch (minor2) {
17590 case SWLE:
17591 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17592 mips32_op = OPC_SWLE;
17593 goto do_st_lr;
17594 case SWRE:
17595 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17596 mips32_op = OPC_SWRE;
17597 goto do_st_lr;
17598 case PREFE:
17599 /* Treat as no-op */
17600 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17601 /* hint codes 24-31 are reserved and signal RI */
17602 generate_exception(ctx, EXCP_RI);
17604 break;
17605 case CACHEE:
17606 /* Treat as no-op */
17607 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17608 gen_cache_operation(ctx, rt, rs, offset);
17610 break;
17611 case SBE:
17612 mips32_op = OPC_SBE;
17613 goto do_st_lr;
17614 case SHE:
17615 mips32_op = OPC_SHE;
17616 goto do_st_lr;
17617 case SCE:
17618 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17619 break;
17620 case SWE:
17621 mips32_op = OPC_SWE;
17622 goto do_st_lr;
17624 break;
17625 case PREF:
17626 /* Treat as no-op */
17627 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
17628 /* hint codes 24-31 are reserved and signal RI */
17629 generate_exception(ctx, EXCP_RI);
17631 break;
17632 default:
17633 MIPS_INVAL("pool32c");
17634 gen_reserved_instruction(ctx);
17635 break;
17637 break;
17638 case ADDI32: /* AUI, LUI */
17639 if (ctx->insn_flags & ISA_MIPS_R6) {
17640 /* AUI, LUI */
17641 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17642 } else {
17643 /* ADDI32 */
17644 mips32_op = OPC_ADDI;
17645 goto do_addi;
17647 break;
17648 case ADDIU32:
17649 mips32_op = OPC_ADDIU;
17650 do_addi:
17651 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17652 break;
17654 /* Logical operations */
17655 case ORI32:
17656 mips32_op = OPC_ORI;
17657 goto do_logici;
17658 case XORI32:
17659 mips32_op = OPC_XORI;
17660 goto do_logici;
17661 case ANDI32:
17662 mips32_op = OPC_ANDI;
17663 do_logici:
17664 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17665 break;
17667 /* Set less than immediate */
17668 case SLTI32:
17669 mips32_op = OPC_SLTI;
17670 goto do_slti;
17671 case SLTIU32:
17672 mips32_op = OPC_SLTIU;
17673 do_slti:
17674 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17675 break;
17676 case JALX32:
17677 check_insn_opc_removed(ctx, ISA_MIPS_R6);
17678 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17679 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17680 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17681 break;
17682 case JALS32: /* BOVC, BEQC, BEQZALC */
17683 if (ctx->insn_flags & ISA_MIPS_R6) {
17684 if (rs >= rt) {
17685 /* BOVC */
17686 mips32_op = OPC_BOVC;
17687 } else if (rs < rt && rs == 0) {
17688 /* BEQZALC */
17689 mips32_op = OPC_BEQZALC;
17690 } else {
17691 /* BEQC */
17692 mips32_op = OPC_BEQC;
17694 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17695 } else {
17696 /* JALS32 */
17697 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17698 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17699 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17701 break;
17702 case BEQ32: /* BC */
17703 if (ctx->insn_flags & ISA_MIPS_R6) {
17704 /* BC */
17705 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17706 sextract32(ctx->opcode << 1, 0, 27));
17707 } else {
17708 /* BEQ32 */
17709 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17711 break;
17712 case BNE32: /* BALC */
17713 if (ctx->insn_flags & ISA_MIPS_R6) {
17714 /* BALC */
17715 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17716 sextract32(ctx->opcode << 1, 0, 27));
17717 } else {
17718 /* BNE32 */
17719 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17721 break;
17722 case J32: /* BGTZC, BLTZC, BLTC */
17723 if (ctx->insn_flags & ISA_MIPS_R6) {
17724 if (rs == 0 && rt != 0) {
17725 /* BGTZC */
17726 mips32_op = OPC_BGTZC;
17727 } else if (rs != 0 && rt != 0 && rs == rt) {
17728 /* BLTZC */
17729 mips32_op = OPC_BLTZC;
17730 } else {
17731 /* BLTC */
17732 mips32_op = OPC_BLTC;
17734 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17735 } else {
17736 /* J32 */
17737 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17738 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17740 break;
17741 case JAL32: /* BLEZC, BGEZC, BGEC */
17742 if (ctx->insn_flags & ISA_MIPS_R6) {
17743 if (rs == 0 && rt != 0) {
17744 /* BLEZC */
17745 mips32_op = OPC_BLEZC;
17746 } else if (rs != 0 && rt != 0 && rs == rt) {
17747 /* BGEZC */
17748 mips32_op = OPC_BGEZC;
17749 } else {
17750 /* BGEC */
17751 mips32_op = OPC_BGEC;
17753 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17754 } else {
17755 /* JAL32 */
17756 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17757 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17758 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17760 break;
17761 /* Floating point (COP1) */
17762 case LWC132:
17763 mips32_op = OPC_LWC1;
17764 goto do_cop1;
17765 case LDC132:
17766 mips32_op = OPC_LDC1;
17767 goto do_cop1;
17768 case SWC132:
17769 mips32_op = OPC_SWC1;
17770 goto do_cop1;
17771 case SDC132:
17772 mips32_op = OPC_SDC1;
17773 do_cop1:
17774 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17775 break;
17776 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17777 if (ctx->insn_flags & ISA_MIPS_R6) {
17778 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17779 switch ((ctx->opcode >> 16) & 0x1f) {
17780 case ADDIUPC_00:
17781 case ADDIUPC_01:
17782 case ADDIUPC_02:
17783 case ADDIUPC_03:
17784 case ADDIUPC_04:
17785 case ADDIUPC_05:
17786 case ADDIUPC_06:
17787 case ADDIUPC_07:
17788 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17789 break;
17790 case AUIPC:
17791 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17792 break;
17793 case ALUIPC:
17794 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17795 break;
17796 case LWPC_08:
17797 case LWPC_09:
17798 case LWPC_0A:
17799 case LWPC_0B:
17800 case LWPC_0C:
17801 case LWPC_0D:
17802 case LWPC_0E:
17803 case LWPC_0F:
17804 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17805 break;
17806 default:
17807 generate_exception(ctx, EXCP_RI);
17808 break;
17810 } else {
17811 /* ADDIUPC */
17812 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17813 offset = SIMM(ctx->opcode, 0, 23) << 2;
17815 gen_addiupc(ctx, reg, offset, 0, 0);
17817 break;
17818 case BNVC: /* BNEC, BNEZALC */
17819 check_insn(ctx, ISA_MIPS_R6);
17820 if (rs >= rt) {
17821 /* BNVC */
17822 mips32_op = OPC_BNVC;
17823 } else if (rs < rt && rs == 0) {
17824 /* BNEZALC */
17825 mips32_op = OPC_BNEZALC;
17826 } else {
17827 /* BNEC */
17828 mips32_op = OPC_BNEC;
17830 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17831 break;
17832 case R6_BNEZC: /* JIALC */
17833 check_insn(ctx, ISA_MIPS_R6);
17834 if (rt != 0) {
17835 /* BNEZC */
17836 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17837 sextract32(ctx->opcode << 1, 0, 22));
17838 } else {
17839 /* JIALC */
17840 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17842 break;
17843 case R6_BEQZC: /* JIC */
17844 check_insn(ctx, ISA_MIPS_R6);
17845 if (rt != 0) {
17846 /* BEQZC */
17847 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17848 sextract32(ctx->opcode << 1, 0, 22));
17849 } else {
17850 /* JIC */
17851 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17853 break;
17854 case BLEZALC: /* BGEZALC, BGEUC */
17855 check_insn(ctx, ISA_MIPS_R6);
17856 if (rs == 0 && rt != 0) {
17857 /* BLEZALC */
17858 mips32_op = OPC_BLEZALC;
17859 } else if (rs != 0 && rt != 0 && rs == rt) {
17860 /* BGEZALC */
17861 mips32_op = OPC_BGEZALC;
17862 } else {
17863 /* BGEUC */
17864 mips32_op = OPC_BGEUC;
17866 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17867 break;
17868 case BGTZALC: /* BLTZALC, BLTUC */
17869 check_insn(ctx, ISA_MIPS_R6);
17870 if (rs == 0 && rt != 0) {
17871 /* BGTZALC */
17872 mips32_op = OPC_BGTZALC;
17873 } else if (rs != 0 && rt != 0 && rs == rt) {
17874 /* BLTZALC */
17875 mips32_op = OPC_BLTZALC;
17876 } else {
17877 /* BLTUC */
17878 mips32_op = OPC_BLTUC;
17880 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17881 break;
17882 /* Loads and stores */
17883 case LB32:
17884 mips32_op = OPC_LB;
17885 goto do_ld;
17886 case LBU32:
17887 mips32_op = OPC_LBU;
17888 goto do_ld;
17889 case LH32:
17890 mips32_op = OPC_LH;
17891 goto do_ld;
17892 case LHU32:
17893 mips32_op = OPC_LHU;
17894 goto do_ld;
17895 case LW32:
17896 mips32_op = OPC_LW;
17897 goto do_ld;
17898 #ifdef TARGET_MIPS64
17899 case LD32:
17900 check_insn(ctx, ISA_MIPS3);
17901 check_mips_64(ctx);
17902 mips32_op = OPC_LD;
17903 goto do_ld;
17904 case SD32:
17905 check_insn(ctx, ISA_MIPS3);
17906 check_mips_64(ctx);
17907 mips32_op = OPC_SD;
17908 goto do_st;
17909 #endif
17910 case SB32:
17911 mips32_op = OPC_SB;
17912 goto do_st;
17913 case SH32:
17914 mips32_op = OPC_SH;
17915 goto do_st;
17916 case SW32:
17917 mips32_op = OPC_SW;
17918 goto do_st;
17919 do_ld:
17920 gen_ld(ctx, mips32_op, rt, rs, imm);
17921 break;
17922 do_st:
17923 gen_st(ctx, mips32_op, rt, rs, imm);
17924 break;
17925 default:
17926 gen_reserved_instruction(ctx);
17927 break;
17931 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
17933 uint32_t op;
17935 /* make sure instructions are on a halfword boundary */
17936 if (ctx->base.pc_next & 0x1) {
17937 env->CP0_BadVAddr = ctx->base.pc_next;
17938 generate_exception_end(ctx, EXCP_AdEL);
17939 return 2;
17942 op = (ctx->opcode >> 10) & 0x3f;
17943 /* Enforce properly-sized instructions in a delay slot */
17944 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
17945 switch (op & 0x7) { /* MSB-3..MSB-5 */
17946 case 0:
17947 /* POOL32A, POOL32B, POOL32I, POOL32C */
17948 case 4:
17949 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
17950 case 5:
17951 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
17952 case 6:
17953 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
17954 case 7:
17955 /* LB32, LH32, LWC132, LDC132, LW32 */
17956 if (ctx->hflags & MIPS_HFLAG_BDS16) {
17957 gen_reserved_instruction(ctx);
17958 return 2;
17960 break;
17961 case 1:
17962 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
17963 case 2:
17964 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
17965 case 3:
17966 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
17967 if (ctx->hflags & MIPS_HFLAG_BDS32) {
17968 gen_reserved_instruction(ctx);
17969 return 2;
17971 break;
17975 switch (op) {
17976 case POOL16A:
17978 int rd = mmreg(uMIPS_RD(ctx->opcode));
17979 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
17980 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
17981 uint32_t opc = 0;
17983 switch (ctx->opcode & 0x1) {
17984 case ADDU16:
17985 opc = OPC_ADDU;
17986 break;
17987 case SUBU16:
17988 opc = OPC_SUBU;
17989 break;
17991 if (ctx->insn_flags & ISA_MIPS_R6) {
17993 * In the Release 6, the register number location in
17994 * the instruction encoding has changed.
17996 gen_arith(ctx, opc, rs1, rd, rs2);
17997 } else {
17998 gen_arith(ctx, opc, rd, rs1, rs2);
18001 break;
18002 case POOL16B:
18004 int rd = mmreg(uMIPS_RD(ctx->opcode));
18005 int rs = mmreg(uMIPS_RS(ctx->opcode));
18006 int amount = (ctx->opcode >> 1) & 0x7;
18007 uint32_t opc = 0;
18008 amount = amount == 0 ? 8 : amount;
18010 switch (ctx->opcode & 0x1) {
18011 case SLL16:
18012 opc = OPC_SLL;
18013 break;
18014 case SRL16:
18015 opc = OPC_SRL;
18016 break;
18019 gen_shift_imm(ctx, opc, rd, rs, amount);
18021 break;
18022 case POOL16C:
18023 if (ctx->insn_flags & ISA_MIPS_R6) {
18024 gen_pool16c_r6_insn(ctx);
18025 } else {
18026 gen_pool16c_insn(ctx);
18028 break;
18029 case LWGP16:
18031 int rd = mmreg(uMIPS_RD(ctx->opcode));
18032 int rb = 28; /* GP */
18033 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
18035 gen_ld(ctx, OPC_LW, rd, rb, offset);
18037 break;
18038 case POOL16F:
18039 check_insn_opc_removed(ctx, ISA_MIPS_R6);
18040 if (ctx->opcode & 1) {
18041 gen_reserved_instruction(ctx);
18042 } else {
18043 /* MOVEP */
18044 int enc_dest = uMIPS_RD(ctx->opcode);
18045 int enc_rt = uMIPS_RS2(ctx->opcode);
18046 int enc_rs = uMIPS_RS1(ctx->opcode);
18047 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
18049 break;
18050 case LBU16:
18052 int rd = mmreg(uMIPS_RD(ctx->opcode));
18053 int rb = mmreg(uMIPS_RS(ctx->opcode));
18054 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18055 offset = (offset == 0xf ? -1 : offset);
18057 gen_ld(ctx, OPC_LBU, rd, rb, offset);
18059 break;
18060 case LHU16:
18062 int rd = mmreg(uMIPS_RD(ctx->opcode));
18063 int rb = mmreg(uMIPS_RS(ctx->opcode));
18064 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18066 gen_ld(ctx, OPC_LHU, rd, rb, offset);
18068 break;
18069 case LWSP16:
18071 int rd = (ctx->opcode >> 5) & 0x1f;
18072 int rb = 29; /* SP */
18073 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18075 gen_ld(ctx, OPC_LW, rd, rb, offset);
18077 break;
18078 case LW16:
18080 int rd = mmreg(uMIPS_RD(ctx->opcode));
18081 int rb = mmreg(uMIPS_RS(ctx->opcode));
18082 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18084 gen_ld(ctx, OPC_LW, rd, rb, offset);
18086 break;
18087 case SB16:
18089 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18090 int rb = mmreg(uMIPS_RS(ctx->opcode));
18091 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18093 gen_st(ctx, OPC_SB, rd, rb, offset);
18095 break;
18096 case SH16:
18098 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18099 int rb = mmreg(uMIPS_RS(ctx->opcode));
18100 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18102 gen_st(ctx, OPC_SH, rd, rb, offset);
18104 break;
18105 case SWSP16:
18107 int rd = (ctx->opcode >> 5) & 0x1f;
18108 int rb = 29; /* SP */
18109 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18111 gen_st(ctx, OPC_SW, rd, rb, offset);
18113 break;
18114 case SW16:
18116 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18117 int rb = mmreg(uMIPS_RS(ctx->opcode));
18118 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18120 gen_st(ctx, OPC_SW, rd, rb, offset);
18122 break;
18123 case MOVE16:
18125 int rd = uMIPS_RD5(ctx->opcode);
18126 int rs = uMIPS_RS5(ctx->opcode);
18128 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
18130 break;
18131 case ANDI16:
18132 gen_andi16(ctx);
18133 break;
18134 case POOL16D:
18135 switch (ctx->opcode & 0x1) {
18136 case ADDIUS5:
18137 gen_addius5(ctx);
18138 break;
18139 case ADDIUSP:
18140 gen_addiusp(ctx);
18141 break;
18143 break;
18144 case POOL16E:
18145 switch (ctx->opcode & 0x1) {
18146 case ADDIUR2:
18147 gen_addiur2(ctx);
18148 break;
18149 case ADDIUR1SP:
18150 gen_addiur1sp(ctx);
18151 break;
18153 break;
18154 case B16: /* BC16 */
18155 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
18156 sextract32(ctx->opcode, 0, 10) << 1,
18157 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
18158 break;
18159 case BNEZ16: /* BNEZC16 */
18160 case BEQZ16: /* BEQZC16 */
18161 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
18162 mmreg(uMIPS_RD(ctx->opcode)),
18163 0, sextract32(ctx->opcode, 0, 7) << 1,
18164 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
18166 break;
18167 case LI16:
18169 int reg = mmreg(uMIPS_RD(ctx->opcode));
18170 int imm = ZIMM(ctx->opcode, 0, 7);
18172 imm = (imm == 0x7f ? -1 : imm);
18173 tcg_gen_movi_tl(cpu_gpr[reg], imm);
18175 break;
18176 case RES_29:
18177 case RES_31:
18178 case RES_39:
18179 gen_reserved_instruction(ctx);
18180 break;
18181 default:
18182 decode_micromips32_opc(env, ctx);
18183 return 4;
18186 return 2;
18191 * nanoMIPS opcodes
18195 /* MAJOR, P16, and P32 pools opcodes */
18196 enum {
18197 NM_P_ADDIU = 0x00,
18198 NM_ADDIUPC = 0x01,
18199 NM_MOVE_BALC = 0x02,
18200 NM_P16_MV = 0x04,
18201 NM_LW16 = 0x05,
18202 NM_BC16 = 0x06,
18203 NM_P16_SR = 0x07,
18205 NM_POOL32A = 0x08,
18206 NM_P_BAL = 0x0a,
18207 NM_P16_SHIFT = 0x0c,
18208 NM_LWSP16 = 0x0d,
18209 NM_BALC16 = 0x0e,
18210 NM_P16_4X4 = 0x0f,
18212 NM_P_GP_W = 0x10,
18213 NM_P_GP_BH = 0x11,
18214 NM_P_J = 0x12,
18215 NM_P16C = 0x14,
18216 NM_LWGP16 = 0x15,
18217 NM_P16_LB = 0x17,
18219 NM_P48I = 0x18,
18220 NM_P16_A1 = 0x1c,
18221 NM_LW4X4 = 0x1d,
18222 NM_P16_LH = 0x1f,
18224 NM_P_U12 = 0x20,
18225 NM_P_LS_U12 = 0x21,
18226 NM_P_BR1 = 0x22,
18227 NM_P16_A2 = 0x24,
18228 NM_SW16 = 0x25,
18229 NM_BEQZC16 = 0x26,
18231 NM_POOL32F = 0x28,
18232 NM_P_LS_S9 = 0x29,
18233 NM_P_BR2 = 0x2a,
18235 NM_P16_ADDU = 0x2c,
18236 NM_SWSP16 = 0x2d,
18237 NM_BNEZC16 = 0x2e,
18238 NM_MOVEP = 0x2f,
18240 NM_POOL32S = 0x30,
18241 NM_P_BRI = 0x32,
18242 NM_LI16 = 0x34,
18243 NM_SWGP16 = 0x35,
18244 NM_P16_BR = 0x36,
18246 NM_P_LUI = 0x38,
18247 NM_ANDI16 = 0x3c,
18248 NM_SW4X4 = 0x3d,
18249 NM_MOVEPREV = 0x3f,
18252 /* POOL32A instruction pool */
18253 enum {
18254 NM_POOL32A0 = 0x00,
18255 NM_SPECIAL2 = 0x01,
18256 NM_COP2_1 = 0x02,
18257 NM_UDI = 0x03,
18258 NM_POOL32A5 = 0x05,
18259 NM_POOL32A7 = 0x07,
18262 /* P.GP.W instruction pool */
18263 enum {
18264 NM_ADDIUGP_W = 0x00,
18265 NM_LWGP = 0x02,
18266 NM_SWGP = 0x03,
18269 /* P48I instruction pool */
18270 enum {
18271 NM_LI48 = 0x00,
18272 NM_ADDIU48 = 0x01,
18273 NM_ADDIUGP48 = 0x02,
18274 NM_ADDIUPC48 = 0x03,
18275 NM_LWPC48 = 0x0b,
18276 NM_SWPC48 = 0x0f,
18279 /* P.U12 instruction pool */
18280 enum {
18281 NM_ORI = 0x00,
18282 NM_XORI = 0x01,
18283 NM_ANDI = 0x02,
18284 NM_P_SR = 0x03,
18285 NM_SLTI = 0x04,
18286 NM_SLTIU = 0x05,
18287 NM_SEQI = 0x06,
18288 NM_ADDIUNEG = 0x08,
18289 NM_P_SHIFT = 0x0c,
18290 NM_P_ROTX = 0x0d,
18291 NM_P_INS = 0x0e,
18292 NM_P_EXT = 0x0f,
18295 /* POOL32F instruction pool */
18296 enum {
18297 NM_POOL32F_0 = 0x00,
18298 NM_POOL32F_3 = 0x03,
18299 NM_POOL32F_5 = 0x05,
18302 /* POOL32S instruction pool */
18303 enum {
18304 NM_POOL32S_0 = 0x00,
18305 NM_POOL32S_4 = 0x04,
18308 /* P.LUI instruction pool */
18309 enum {
18310 NM_LUI = 0x00,
18311 NM_ALUIPC = 0x01,
18314 /* P.GP.BH instruction pool */
18315 enum {
18316 NM_LBGP = 0x00,
18317 NM_SBGP = 0x01,
18318 NM_LBUGP = 0x02,
18319 NM_ADDIUGP_B = 0x03,
18320 NM_P_GP_LH = 0x04,
18321 NM_P_GP_SH = 0x05,
18322 NM_P_GP_CP1 = 0x06,
18325 /* P.LS.U12 instruction pool */
18326 enum {
18327 NM_LB = 0x00,
18328 NM_SB = 0x01,
18329 NM_LBU = 0x02,
18330 NM_P_PREFU12 = 0x03,
18331 NM_LH = 0x04,
18332 NM_SH = 0x05,
18333 NM_LHU = 0x06,
18334 NM_LWU = 0x07,
18335 NM_LW = 0x08,
18336 NM_SW = 0x09,
18337 NM_LWC1 = 0x0a,
18338 NM_SWC1 = 0x0b,
18339 NM_LDC1 = 0x0e,
18340 NM_SDC1 = 0x0f,
18343 /* P.LS.S9 instruction pool */
18344 enum {
18345 NM_P_LS_S0 = 0x00,
18346 NM_P_LS_S1 = 0x01,
18347 NM_P_LS_E0 = 0x02,
18348 NM_P_LS_WM = 0x04,
18349 NM_P_LS_UAWM = 0x05,
18352 /* P.BAL instruction pool */
18353 enum {
18354 NM_BC = 0x00,
18355 NM_BALC = 0x01,
18358 /* P.J instruction pool */
18359 enum {
18360 NM_JALRC = 0x00,
18361 NM_JALRC_HB = 0x01,
18362 NM_P_BALRSC = 0x08,
18365 /* P.BR1 instruction pool */
18366 enum {
18367 NM_BEQC = 0x00,
18368 NM_P_BR3A = 0x01,
18369 NM_BGEC = 0x02,
18370 NM_BGEUC = 0x03,
18373 /* P.BR2 instruction pool */
18374 enum {
18375 NM_BNEC = 0x00,
18376 NM_BLTC = 0x02,
18377 NM_BLTUC = 0x03,
18380 /* P.BRI instruction pool */
18381 enum {
18382 NM_BEQIC = 0x00,
18383 NM_BBEQZC = 0x01,
18384 NM_BGEIC = 0x02,
18385 NM_BGEIUC = 0x03,
18386 NM_BNEIC = 0x04,
18387 NM_BBNEZC = 0x05,
18388 NM_BLTIC = 0x06,
18389 NM_BLTIUC = 0x07,
18392 /* P16.SHIFT instruction pool */
18393 enum {
18394 NM_SLL16 = 0x00,
18395 NM_SRL16 = 0x01,
18398 /* POOL16C instruction pool */
18399 enum {
18400 NM_POOL16C_0 = 0x00,
18401 NM_LWXS16 = 0x01,
18404 /* P16.A1 instruction pool */
18405 enum {
18406 NM_ADDIUR1SP = 0x01,
18409 /* P16.A2 instruction pool */
18410 enum {
18411 NM_ADDIUR2 = 0x00,
18412 NM_P_ADDIURS5 = 0x01,
18415 /* P16.ADDU instruction pool */
18416 enum {
18417 NM_ADDU16 = 0x00,
18418 NM_SUBU16 = 0x01,
18421 /* P16.SR instruction pool */
18422 enum {
18423 NM_SAVE16 = 0x00,
18424 NM_RESTORE_JRC16 = 0x01,
18427 /* P16.4X4 instruction pool */
18428 enum {
18429 NM_ADDU4X4 = 0x00,
18430 NM_MUL4X4 = 0x01,
18433 /* P16.LB instruction pool */
18434 enum {
18435 NM_LB16 = 0x00,
18436 NM_SB16 = 0x01,
18437 NM_LBU16 = 0x02,
18440 /* P16.LH instruction pool */
18441 enum {
18442 NM_LH16 = 0x00,
18443 NM_SH16 = 0x01,
18444 NM_LHU16 = 0x02,
18447 /* P.RI instruction pool */
18448 enum {
18449 NM_SIGRIE = 0x00,
18450 NM_P_SYSCALL = 0x01,
18451 NM_BREAK = 0x02,
18452 NM_SDBBP = 0x03,
18455 /* POOL32A0 instruction pool */
18456 enum {
18457 NM_P_TRAP = 0x00,
18458 NM_SEB = 0x01,
18459 NM_SLLV = 0x02,
18460 NM_MUL = 0x03,
18461 NM_MFC0 = 0x06,
18462 NM_MFHC0 = 0x07,
18463 NM_SEH = 0x09,
18464 NM_SRLV = 0x0a,
18465 NM_MUH = 0x0b,
18466 NM_MTC0 = 0x0e,
18467 NM_MTHC0 = 0x0f,
18468 NM_SRAV = 0x12,
18469 NM_MULU = 0x13,
18470 NM_ROTRV = 0x1a,
18471 NM_MUHU = 0x1b,
18472 NM_ADD = 0x22,
18473 NM_DIV = 0x23,
18474 NM_ADDU = 0x2a,
18475 NM_MOD = 0x2b,
18476 NM_SUB = 0x32,
18477 NM_DIVU = 0x33,
18478 NM_RDHWR = 0x38,
18479 NM_SUBU = 0x3a,
18480 NM_MODU = 0x3b,
18481 NM_P_CMOVE = 0x42,
18482 NM_FORK = 0x45,
18483 NM_MFTR = 0x46,
18484 NM_MFHTR = 0x47,
18485 NM_AND = 0x4a,
18486 NM_YIELD = 0x4d,
18487 NM_MTTR = 0x4e,
18488 NM_MTHTR = 0x4f,
18489 NM_OR = 0x52,
18490 NM_D_E_MT_VPE = 0x56,
18491 NM_NOR = 0x5a,
18492 NM_XOR = 0x62,
18493 NM_SLT = 0x6a,
18494 NM_P_SLTU = 0x72,
18495 NM_SOV = 0x7a,
18498 /* CRC32 instruction pool */
18499 enum {
18500 NM_CRC32B = 0x00,
18501 NM_CRC32H = 0x01,
18502 NM_CRC32W = 0x02,
18503 NM_CRC32CB = 0x04,
18504 NM_CRC32CH = 0x05,
18505 NM_CRC32CW = 0x06,
18508 /* POOL32A5 instruction pool */
18509 enum {
18510 NM_CMP_EQ_PH = 0x00,
18511 NM_CMP_LT_PH = 0x08,
18512 NM_CMP_LE_PH = 0x10,
18513 NM_CMPGU_EQ_QB = 0x18,
18514 NM_CMPGU_LT_QB = 0x20,
18515 NM_CMPGU_LE_QB = 0x28,
18516 NM_CMPGDU_EQ_QB = 0x30,
18517 NM_CMPGDU_LT_QB = 0x38,
18518 NM_CMPGDU_LE_QB = 0x40,
18519 NM_CMPU_EQ_QB = 0x48,
18520 NM_CMPU_LT_QB = 0x50,
18521 NM_CMPU_LE_QB = 0x58,
18522 NM_ADDQ_S_W = 0x60,
18523 NM_SUBQ_S_W = 0x68,
18524 NM_ADDSC = 0x70,
18525 NM_ADDWC = 0x78,
18527 NM_ADDQ_S_PH = 0x01,
18528 NM_ADDQH_R_PH = 0x09,
18529 NM_ADDQH_R_W = 0x11,
18530 NM_ADDU_S_QB = 0x19,
18531 NM_ADDU_S_PH = 0x21,
18532 NM_ADDUH_R_QB = 0x29,
18533 NM_SHRAV_R_PH = 0x31,
18534 NM_SHRAV_R_QB = 0x39,
18535 NM_SUBQ_S_PH = 0x41,
18536 NM_SUBQH_R_PH = 0x49,
18537 NM_SUBQH_R_W = 0x51,
18538 NM_SUBU_S_QB = 0x59,
18539 NM_SUBU_S_PH = 0x61,
18540 NM_SUBUH_R_QB = 0x69,
18541 NM_SHLLV_S_PH = 0x71,
18542 NM_PRECR_SRA_R_PH_W = 0x79,
18544 NM_MULEU_S_PH_QBL = 0x12,
18545 NM_MULEU_S_PH_QBR = 0x1a,
18546 NM_MULQ_RS_PH = 0x22,
18547 NM_MULQ_S_PH = 0x2a,
18548 NM_MULQ_RS_W = 0x32,
18549 NM_MULQ_S_W = 0x3a,
18550 NM_APPEND = 0x42,
18551 NM_MODSUB = 0x52,
18552 NM_SHRAV_R_W = 0x5a,
18553 NM_SHRLV_PH = 0x62,
18554 NM_SHRLV_QB = 0x6a,
18555 NM_SHLLV_QB = 0x72,
18556 NM_SHLLV_S_W = 0x7a,
18558 NM_SHILO = 0x03,
18560 NM_MULEQ_S_W_PHL = 0x04,
18561 NM_MULEQ_S_W_PHR = 0x0c,
18563 NM_MUL_S_PH = 0x05,
18564 NM_PRECR_QB_PH = 0x0d,
18565 NM_PRECRQ_QB_PH = 0x15,
18566 NM_PRECRQ_PH_W = 0x1d,
18567 NM_PRECRQ_RS_PH_W = 0x25,
18568 NM_PRECRQU_S_QB_PH = 0x2d,
18569 NM_PACKRL_PH = 0x35,
18570 NM_PICK_QB = 0x3d,
18571 NM_PICK_PH = 0x45,
18573 NM_SHRA_R_W = 0x5e,
18574 NM_SHRA_R_PH = 0x66,
18575 NM_SHLL_S_PH = 0x76,
18576 NM_SHLL_S_W = 0x7e,
18578 NM_REPL_PH = 0x07
18581 /* POOL32A7 instruction pool */
18582 enum {
18583 NM_P_LSX = 0x00,
18584 NM_LSA = 0x01,
18585 NM_EXTW = 0x03,
18586 NM_POOL32AXF = 0x07,
18589 /* P.SR instruction pool */
18590 enum {
18591 NM_PP_SR = 0x00,
18592 NM_P_SR_F = 0x01,
18595 /* P.SHIFT instruction pool */
18596 enum {
18597 NM_P_SLL = 0x00,
18598 NM_SRL = 0x02,
18599 NM_SRA = 0x04,
18600 NM_ROTR = 0x06,
18603 /* P.ROTX instruction pool */
18604 enum {
18605 NM_ROTX = 0x00,
18608 /* P.INS instruction pool */
18609 enum {
18610 NM_INS = 0x00,
18613 /* P.EXT instruction pool */
18614 enum {
18615 NM_EXT = 0x00,
18618 /* POOL32F_0 (fmt) instruction pool */
18619 enum {
18620 NM_RINT_S = 0x04,
18621 NM_RINT_D = 0x44,
18622 NM_ADD_S = 0x06,
18623 NM_SELEQZ_S = 0x07,
18624 NM_SELEQZ_D = 0x47,
18625 NM_CLASS_S = 0x0c,
18626 NM_CLASS_D = 0x4c,
18627 NM_SUB_S = 0x0e,
18628 NM_SELNEZ_S = 0x0f,
18629 NM_SELNEZ_D = 0x4f,
18630 NM_MUL_S = 0x16,
18631 NM_SEL_S = 0x17,
18632 NM_SEL_D = 0x57,
18633 NM_DIV_S = 0x1e,
18634 NM_ADD_D = 0x26,
18635 NM_SUB_D = 0x2e,
18636 NM_MUL_D = 0x36,
18637 NM_MADDF_S = 0x37,
18638 NM_MADDF_D = 0x77,
18639 NM_DIV_D = 0x3e,
18640 NM_MSUBF_S = 0x3f,
18641 NM_MSUBF_D = 0x7f,
18644 /* POOL32F_3 instruction pool */
18645 enum {
18646 NM_MIN_FMT = 0x00,
18647 NM_MAX_FMT = 0x01,
18648 NM_MINA_FMT = 0x04,
18649 NM_MAXA_FMT = 0x05,
18650 NM_POOL32FXF = 0x07,
18653 /* POOL32F_5 instruction pool */
18654 enum {
18655 NM_CMP_CONDN_S = 0x00,
18656 NM_CMP_CONDN_D = 0x02,
18659 /* P.GP.LH instruction pool */
18660 enum {
18661 NM_LHGP = 0x00,
18662 NM_LHUGP = 0x01,
18665 /* P.GP.SH instruction pool */
18666 enum {
18667 NM_SHGP = 0x00,
18670 /* P.GP.CP1 instruction pool */
18671 enum {
18672 NM_LWC1GP = 0x00,
18673 NM_SWC1GP = 0x01,
18674 NM_LDC1GP = 0x02,
18675 NM_SDC1GP = 0x03,
18678 /* P.LS.S0 instruction pool */
18679 enum {
18680 NM_LBS9 = 0x00,
18681 NM_LHS9 = 0x04,
18682 NM_LWS9 = 0x08,
18683 NM_LDS9 = 0x0c,
18685 NM_SBS9 = 0x01,
18686 NM_SHS9 = 0x05,
18687 NM_SWS9 = 0x09,
18688 NM_SDS9 = 0x0d,
18690 NM_LBUS9 = 0x02,
18691 NM_LHUS9 = 0x06,
18692 NM_LWC1S9 = 0x0a,
18693 NM_LDC1S9 = 0x0e,
18695 NM_P_PREFS9 = 0x03,
18696 NM_LWUS9 = 0x07,
18697 NM_SWC1S9 = 0x0b,
18698 NM_SDC1S9 = 0x0f,
18701 /* P.LS.S1 instruction pool */
18702 enum {
18703 NM_ASET_ACLR = 0x02,
18704 NM_UALH = 0x04,
18705 NM_UASH = 0x05,
18706 NM_CACHE = 0x07,
18707 NM_P_LL = 0x0a,
18708 NM_P_SC = 0x0b,
18711 /* P.LS.E0 instruction pool */
18712 enum {
18713 NM_LBE = 0x00,
18714 NM_SBE = 0x01,
18715 NM_LBUE = 0x02,
18716 NM_P_PREFE = 0x03,
18717 NM_LHE = 0x04,
18718 NM_SHE = 0x05,
18719 NM_LHUE = 0x06,
18720 NM_CACHEE = 0x07,
18721 NM_LWE = 0x08,
18722 NM_SWE = 0x09,
18723 NM_P_LLE = 0x0a,
18724 NM_P_SCE = 0x0b,
18727 /* P.PREFE instruction pool */
18728 enum {
18729 NM_SYNCIE = 0x00,
18730 NM_PREFE = 0x01,
18733 /* P.LLE instruction pool */
18734 enum {
18735 NM_LLE = 0x00,
18736 NM_LLWPE = 0x01,
18739 /* P.SCE instruction pool */
18740 enum {
18741 NM_SCE = 0x00,
18742 NM_SCWPE = 0x01,
18745 /* P.LS.WM instruction pool */
18746 enum {
18747 NM_LWM = 0x00,
18748 NM_SWM = 0x01,
18751 /* P.LS.UAWM instruction pool */
18752 enum {
18753 NM_UALWM = 0x00,
18754 NM_UASWM = 0x01,
18757 /* P.BR3A instruction pool */
18758 enum {
18759 NM_BC1EQZC = 0x00,
18760 NM_BC1NEZC = 0x01,
18761 NM_BC2EQZC = 0x02,
18762 NM_BC2NEZC = 0x03,
18763 NM_BPOSGE32C = 0x04,
18766 /* P16.RI instruction pool */
18767 enum {
18768 NM_P16_SYSCALL = 0x01,
18769 NM_BREAK16 = 0x02,
18770 NM_SDBBP16 = 0x03,
18773 /* POOL16C_0 instruction pool */
18774 enum {
18775 NM_POOL16C_00 = 0x00,
18778 /* P16.JRC instruction pool */
18779 enum {
18780 NM_JRC = 0x00,
18781 NM_JALRC16 = 0x01,
18784 /* P.SYSCALL instruction pool */
18785 enum {
18786 NM_SYSCALL = 0x00,
18787 NM_HYPCALL = 0x01,
18790 /* P.TRAP instruction pool */
18791 enum {
18792 NM_TEQ = 0x00,
18793 NM_TNE = 0x01,
18796 /* P.CMOVE instruction pool */
18797 enum {
18798 NM_MOVZ = 0x00,
18799 NM_MOVN = 0x01,
18802 /* POOL32Axf instruction pool */
18803 enum {
18804 NM_POOL32AXF_1 = 0x01,
18805 NM_POOL32AXF_2 = 0x02,
18806 NM_POOL32AXF_4 = 0x04,
18807 NM_POOL32AXF_5 = 0x05,
18808 NM_POOL32AXF_7 = 0x07,
18811 /* POOL32Axf_1 instruction pool */
18812 enum {
18813 NM_POOL32AXF_1_0 = 0x00,
18814 NM_POOL32AXF_1_1 = 0x01,
18815 NM_POOL32AXF_1_3 = 0x03,
18816 NM_POOL32AXF_1_4 = 0x04,
18817 NM_POOL32AXF_1_5 = 0x05,
18818 NM_POOL32AXF_1_7 = 0x07,
18821 /* POOL32Axf_2 instruction pool */
18822 enum {
18823 NM_POOL32AXF_2_0_7 = 0x00,
18824 NM_POOL32AXF_2_8_15 = 0x01,
18825 NM_POOL32AXF_2_16_23 = 0x02,
18826 NM_POOL32AXF_2_24_31 = 0x03,
18829 /* POOL32Axf_7 instruction pool */
18830 enum {
18831 NM_SHRA_R_QB = 0x0,
18832 NM_SHRL_PH = 0x1,
18833 NM_REPL_QB = 0x2,
18836 /* POOL32Axf_1_0 instruction pool */
18837 enum {
18838 NM_MFHI = 0x0,
18839 NM_MFLO = 0x1,
18840 NM_MTHI = 0x2,
18841 NM_MTLO = 0x3,
18844 /* POOL32Axf_1_1 instruction pool */
18845 enum {
18846 NM_MTHLIP = 0x0,
18847 NM_SHILOV = 0x1,
18850 /* POOL32Axf_1_3 instruction pool */
18851 enum {
18852 NM_RDDSP = 0x0,
18853 NM_WRDSP = 0x1,
18854 NM_EXTP = 0x2,
18855 NM_EXTPDP = 0x3,
18858 /* POOL32Axf_1_4 instruction pool */
18859 enum {
18860 NM_SHLL_QB = 0x0,
18861 NM_SHRL_QB = 0x1,
18864 /* POOL32Axf_1_5 instruction pool */
18865 enum {
18866 NM_MAQ_S_W_PHR = 0x0,
18867 NM_MAQ_S_W_PHL = 0x1,
18868 NM_MAQ_SA_W_PHR = 0x2,
18869 NM_MAQ_SA_W_PHL = 0x3,
18872 /* POOL32Axf_1_7 instruction pool */
18873 enum {
18874 NM_EXTR_W = 0x0,
18875 NM_EXTR_R_W = 0x1,
18876 NM_EXTR_RS_W = 0x2,
18877 NM_EXTR_S_H = 0x3,
18880 /* POOL32Axf_2_0_7 instruction pool */
18881 enum {
18882 NM_DPA_W_PH = 0x0,
18883 NM_DPAQ_S_W_PH = 0x1,
18884 NM_DPS_W_PH = 0x2,
18885 NM_DPSQ_S_W_PH = 0x3,
18886 NM_BALIGN = 0x4,
18887 NM_MADD = 0x5,
18888 NM_MULT = 0x6,
18889 NM_EXTRV_W = 0x7,
18892 /* POOL32Axf_2_8_15 instruction pool */
18893 enum {
18894 NM_DPAX_W_PH = 0x0,
18895 NM_DPAQ_SA_L_W = 0x1,
18896 NM_DPSX_W_PH = 0x2,
18897 NM_DPSQ_SA_L_W = 0x3,
18898 NM_MADDU = 0x5,
18899 NM_MULTU = 0x6,
18900 NM_EXTRV_R_W = 0x7,
18903 /* POOL32Axf_2_16_23 instruction pool */
18904 enum {
18905 NM_DPAU_H_QBL = 0x0,
18906 NM_DPAQX_S_W_PH = 0x1,
18907 NM_DPSU_H_QBL = 0x2,
18908 NM_DPSQX_S_W_PH = 0x3,
18909 NM_EXTPV = 0x4,
18910 NM_MSUB = 0x5,
18911 NM_MULSA_W_PH = 0x6,
18912 NM_EXTRV_RS_W = 0x7,
18915 /* POOL32Axf_2_24_31 instruction pool */
18916 enum {
18917 NM_DPAU_H_QBR = 0x0,
18918 NM_DPAQX_SA_W_PH = 0x1,
18919 NM_DPSU_H_QBR = 0x2,
18920 NM_DPSQX_SA_W_PH = 0x3,
18921 NM_EXTPDPV = 0x4,
18922 NM_MSUBU = 0x5,
18923 NM_MULSAQ_S_W_PH = 0x6,
18924 NM_EXTRV_S_H = 0x7,
18927 /* POOL32Axf_{4, 5} instruction pool */
18928 enum {
18929 NM_CLO = 0x25,
18930 NM_CLZ = 0x2d,
18932 NM_TLBP = 0x01,
18933 NM_TLBR = 0x09,
18934 NM_TLBWI = 0x11,
18935 NM_TLBWR = 0x19,
18936 NM_TLBINV = 0x03,
18937 NM_TLBINVF = 0x0b,
18938 NM_DI = 0x23,
18939 NM_EI = 0x2b,
18940 NM_RDPGPR = 0x70,
18941 NM_WRPGPR = 0x78,
18942 NM_WAIT = 0x61,
18943 NM_DERET = 0x71,
18944 NM_ERETX = 0x79,
18946 /* nanoMIPS DSP instructions */
18947 NM_ABSQ_S_QB = 0x00,
18948 NM_ABSQ_S_PH = 0x08,
18949 NM_ABSQ_S_W = 0x10,
18950 NM_PRECEQ_W_PHL = 0x28,
18951 NM_PRECEQ_W_PHR = 0x30,
18952 NM_PRECEQU_PH_QBL = 0x38,
18953 NM_PRECEQU_PH_QBR = 0x48,
18954 NM_PRECEU_PH_QBL = 0x58,
18955 NM_PRECEU_PH_QBR = 0x68,
18956 NM_PRECEQU_PH_QBLA = 0x39,
18957 NM_PRECEQU_PH_QBRA = 0x49,
18958 NM_PRECEU_PH_QBLA = 0x59,
18959 NM_PRECEU_PH_QBRA = 0x69,
18960 NM_REPLV_PH = 0x01,
18961 NM_REPLV_QB = 0x09,
18962 NM_BITREV = 0x18,
18963 NM_INSV = 0x20,
18964 NM_RADDU_W_QB = 0x78,
18966 NM_BITSWAP = 0x05,
18967 NM_WSBH = 0x3d,
18970 /* PP.SR instruction pool */
18971 enum {
18972 NM_SAVE = 0x00,
18973 NM_RESTORE = 0x02,
18974 NM_RESTORE_JRC = 0x03,
18977 /* P.SR.F instruction pool */
18978 enum {
18979 NM_SAVEF = 0x00,
18980 NM_RESTOREF = 0x01,
18983 /* P16.SYSCALL instruction pool */
18984 enum {
18985 NM_SYSCALL16 = 0x00,
18986 NM_HYPCALL16 = 0x01,
18989 /* POOL16C_00 instruction pool */
18990 enum {
18991 NM_NOT16 = 0x00,
18992 NM_XOR16 = 0x01,
18993 NM_AND16 = 0x02,
18994 NM_OR16 = 0x03,
18997 /* PP.LSX and PP.LSXS instruction pool */
18998 enum {
18999 NM_LBX = 0x00,
19000 NM_LHX = 0x04,
19001 NM_LWX = 0x08,
19002 NM_LDX = 0x0c,
19004 NM_SBX = 0x01,
19005 NM_SHX = 0x05,
19006 NM_SWX = 0x09,
19007 NM_SDX = 0x0d,
19009 NM_LBUX = 0x02,
19010 NM_LHUX = 0x06,
19011 NM_LWC1X = 0x0a,
19012 NM_LDC1X = 0x0e,
19014 NM_LWUX = 0x07,
19015 NM_SWC1X = 0x0b,
19016 NM_SDC1X = 0x0f,
19018 NM_LHXS = 0x04,
19019 NM_LWXS = 0x08,
19020 NM_LDXS = 0x0c,
19022 NM_SHXS = 0x05,
19023 NM_SWXS = 0x09,
19024 NM_SDXS = 0x0d,
19026 NM_LHUXS = 0x06,
19027 NM_LWC1XS = 0x0a,
19028 NM_LDC1XS = 0x0e,
19030 NM_LWUXS = 0x07,
19031 NM_SWC1XS = 0x0b,
19032 NM_SDC1XS = 0x0f,
19035 /* ERETx instruction pool */
19036 enum {
19037 NM_ERET = 0x00,
19038 NM_ERETNC = 0x01,
19041 /* POOL32FxF_{0, 1} insturction pool */
19042 enum {
19043 NM_CFC1 = 0x40,
19044 NM_CTC1 = 0x60,
19045 NM_MFC1 = 0x80,
19046 NM_MTC1 = 0xa0,
19047 NM_MFHC1 = 0xc0,
19048 NM_MTHC1 = 0xe0,
19050 NM_CVT_S_PL = 0x84,
19051 NM_CVT_S_PU = 0xa4,
19053 NM_CVT_L_S = 0x004,
19054 NM_CVT_L_D = 0x104,
19055 NM_CVT_W_S = 0x024,
19056 NM_CVT_W_D = 0x124,
19058 NM_RSQRT_S = 0x008,
19059 NM_RSQRT_D = 0x108,
19061 NM_SQRT_S = 0x028,
19062 NM_SQRT_D = 0x128,
19064 NM_RECIP_S = 0x048,
19065 NM_RECIP_D = 0x148,
19067 NM_FLOOR_L_S = 0x00c,
19068 NM_FLOOR_L_D = 0x10c,
19070 NM_FLOOR_W_S = 0x02c,
19071 NM_FLOOR_W_D = 0x12c,
19073 NM_CEIL_L_S = 0x04c,
19074 NM_CEIL_L_D = 0x14c,
19075 NM_CEIL_W_S = 0x06c,
19076 NM_CEIL_W_D = 0x16c,
19077 NM_TRUNC_L_S = 0x08c,
19078 NM_TRUNC_L_D = 0x18c,
19079 NM_TRUNC_W_S = 0x0ac,
19080 NM_TRUNC_W_D = 0x1ac,
19081 NM_ROUND_L_S = 0x0cc,
19082 NM_ROUND_L_D = 0x1cc,
19083 NM_ROUND_W_S = 0x0ec,
19084 NM_ROUND_W_D = 0x1ec,
19086 NM_MOV_S = 0x01,
19087 NM_MOV_D = 0x81,
19088 NM_ABS_S = 0x0d,
19089 NM_ABS_D = 0x8d,
19090 NM_NEG_S = 0x2d,
19091 NM_NEG_D = 0xad,
19092 NM_CVT_D_S = 0x04d,
19093 NM_CVT_D_W = 0x0cd,
19094 NM_CVT_D_L = 0x14d,
19095 NM_CVT_S_D = 0x06d,
19096 NM_CVT_S_W = 0x0ed,
19097 NM_CVT_S_L = 0x16d,
19100 /* P.LL instruction pool */
19101 enum {
19102 NM_LL = 0x00,
19103 NM_LLWP = 0x01,
19106 /* P.SC instruction pool */
19107 enum {
19108 NM_SC = 0x00,
19109 NM_SCWP = 0x01,
19112 /* P.DVP instruction pool */
19113 enum {
19114 NM_DVP = 0x00,
19115 NM_EVP = 0x01,
19121 * nanoMIPS decoding engine
19126 /* extraction utilities */
19128 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
19129 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
19130 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
19131 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
19132 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
19134 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
19135 static inline int decode_gpr_gpr3(int r)
19137 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
19139 return map[r & 0x7];
19142 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
19143 static inline int decode_gpr_gpr3_src_store(int r)
19145 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
19147 return map[r & 0x7];
19150 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
19151 static inline int decode_gpr_gpr4(int r)
19153 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
19154 16, 17, 18, 19, 20, 21, 22, 23 };
19156 return map[r & 0xf];
19159 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
19160 static inline int decode_gpr_gpr4_zero(int r)
19162 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
19163 16, 17, 18, 19, 20, 21, 22, 23 };
19165 return map[r & 0xf];
19169 static void gen_adjust_sp(DisasContext *ctx, int u)
19171 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
19174 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
19175 uint8_t gp, uint16_t u)
19177 int counter = 0;
19178 TCGv va = tcg_temp_new();
19179 TCGv t0 = tcg_temp_new();
19181 while (counter != count) {
19182 bool use_gp = gp && (counter == count - 1);
19183 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19184 int this_offset = -((counter + 1) << 2);
19185 gen_base_offset_addr(ctx, va, 29, this_offset);
19186 gen_load_gpr(t0, this_rt);
19187 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
19188 (MO_TEUL | ctx->default_tcg_memop_mask));
19189 counter++;
19192 /* adjust stack pointer */
19193 gen_adjust_sp(ctx, -u);
19195 tcg_temp_free(t0);
19196 tcg_temp_free(va);
19199 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
19200 uint8_t gp, uint16_t u)
19202 int counter = 0;
19203 TCGv va = tcg_temp_new();
19204 TCGv t0 = tcg_temp_new();
19206 while (counter != count) {
19207 bool use_gp = gp && (counter == count - 1);
19208 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19209 int this_offset = u - ((counter + 1) << 2);
19210 gen_base_offset_addr(ctx, va, 29, this_offset);
19211 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
19212 ctx->default_tcg_memop_mask);
19213 tcg_gen_ext32s_tl(t0, t0);
19214 gen_store_gpr(t0, this_rt);
19215 counter++;
19218 /* adjust stack pointer */
19219 gen_adjust_sp(ctx, u);
19221 tcg_temp_free(t0);
19222 tcg_temp_free(va);
19225 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
19227 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
19228 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
19230 switch (extract32(ctx->opcode, 2, 2)) {
19231 case NM_NOT16:
19232 gen_logic(ctx, OPC_NOR, rt, rs, 0);
19233 break;
19234 case NM_AND16:
19235 gen_logic(ctx, OPC_AND, rt, rt, rs);
19236 break;
19237 case NM_XOR16:
19238 gen_logic(ctx, OPC_XOR, rt, rt, rs);
19239 break;
19240 case NM_OR16:
19241 gen_logic(ctx, OPC_OR, rt, rt, rs);
19242 break;
19246 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19248 int rt = extract32(ctx->opcode, 21, 5);
19249 int rs = extract32(ctx->opcode, 16, 5);
19250 int rd = extract32(ctx->opcode, 11, 5);
19252 switch (extract32(ctx->opcode, 3, 7)) {
19253 case NM_P_TRAP:
19254 switch (extract32(ctx->opcode, 10, 1)) {
19255 case NM_TEQ:
19256 check_nms(ctx);
19257 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
19258 break;
19259 case NM_TNE:
19260 check_nms(ctx);
19261 gen_trap(ctx, OPC_TNE, rs, rt, -1);
19262 break;
19264 break;
19265 case NM_RDHWR:
19266 check_nms(ctx);
19267 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
19268 break;
19269 case NM_SEB:
19270 check_nms(ctx);
19271 gen_bshfl(ctx, OPC_SEB, rs, rt);
19272 break;
19273 case NM_SEH:
19274 gen_bshfl(ctx, OPC_SEH, rs, rt);
19275 break;
19276 case NM_SLLV:
19277 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
19278 break;
19279 case NM_SRLV:
19280 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
19281 break;
19282 case NM_SRAV:
19283 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19284 break;
19285 case NM_ROTRV:
19286 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19287 break;
19288 case NM_ADD:
19289 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19290 break;
19291 case NM_ADDU:
19292 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19293 break;
19294 case NM_SUB:
19295 check_nms(ctx);
19296 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19297 break;
19298 case NM_SUBU:
19299 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19300 break;
19301 case NM_P_CMOVE:
19302 switch (extract32(ctx->opcode, 10, 1)) {
19303 case NM_MOVZ:
19304 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19305 break;
19306 case NM_MOVN:
19307 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19308 break;
19310 break;
19311 case NM_AND:
19312 gen_logic(ctx, OPC_AND, rd, rs, rt);
19313 break;
19314 case NM_OR:
19315 gen_logic(ctx, OPC_OR, rd, rs, rt);
19316 break;
19317 case NM_NOR:
19318 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19319 break;
19320 case NM_XOR:
19321 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19322 break;
19323 case NM_SLT:
19324 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19325 break;
19326 case NM_P_SLTU:
19327 if (rd == 0) {
19328 /* P_DVP */
19329 #ifndef CONFIG_USER_ONLY
19330 TCGv t0 = tcg_temp_new();
19331 switch (extract32(ctx->opcode, 10, 1)) {
19332 case NM_DVP:
19333 if (ctx->vp) {
19334 check_cp0_enabled(ctx);
19335 gen_helper_dvp(t0, cpu_env);
19336 gen_store_gpr(t0, rt);
19338 break;
19339 case NM_EVP:
19340 if (ctx->vp) {
19341 check_cp0_enabled(ctx);
19342 gen_helper_evp(t0, cpu_env);
19343 gen_store_gpr(t0, rt);
19345 break;
19347 tcg_temp_free(t0);
19348 #endif
19349 } else {
19350 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19352 break;
19353 case NM_SOV:
19355 TCGv t0 = tcg_temp_new();
19356 TCGv t1 = tcg_temp_new();
19357 TCGv t2 = tcg_temp_new();
19359 gen_load_gpr(t1, rs);
19360 gen_load_gpr(t2, rt);
19361 tcg_gen_add_tl(t0, t1, t2);
19362 tcg_gen_ext32s_tl(t0, t0);
19363 tcg_gen_xor_tl(t1, t1, t2);
19364 tcg_gen_xor_tl(t2, t0, t2);
19365 tcg_gen_andc_tl(t1, t2, t1);
19367 /* operands of same sign, result different sign */
19368 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19369 gen_store_gpr(t0, rd);
19371 tcg_temp_free(t0);
19372 tcg_temp_free(t1);
19373 tcg_temp_free(t2);
19375 break;
19376 case NM_MUL:
19377 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19378 break;
19379 case NM_MUH:
19380 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19381 break;
19382 case NM_MULU:
19383 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19384 break;
19385 case NM_MUHU:
19386 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19387 break;
19388 case NM_DIV:
19389 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19390 break;
19391 case NM_MOD:
19392 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19393 break;
19394 case NM_DIVU:
19395 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19396 break;
19397 case NM_MODU:
19398 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19399 break;
19400 #ifndef CONFIG_USER_ONLY
19401 case NM_MFC0:
19402 check_cp0_enabled(ctx);
19403 if (rt == 0) {
19404 /* Treat as NOP. */
19405 break;
19407 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19408 break;
19409 case NM_MTC0:
19410 check_cp0_enabled(ctx);
19412 TCGv t0 = tcg_temp_new();
19414 gen_load_gpr(t0, rt);
19415 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19416 tcg_temp_free(t0);
19418 break;
19419 case NM_D_E_MT_VPE:
19421 uint8_t sc = extract32(ctx->opcode, 10, 1);
19422 TCGv t0 = tcg_temp_new();
19424 switch (sc) {
19425 case 0:
19426 if (rs == 1) {
19427 /* DMT */
19428 check_cp0_mt(ctx);
19429 gen_helper_dmt(t0);
19430 gen_store_gpr(t0, rt);
19431 } else if (rs == 0) {
19432 /* DVPE */
19433 check_cp0_mt(ctx);
19434 gen_helper_dvpe(t0, cpu_env);
19435 gen_store_gpr(t0, rt);
19436 } else {
19437 gen_reserved_instruction(ctx);
19439 break;
19440 case 1:
19441 if (rs == 1) {
19442 /* EMT */
19443 check_cp0_mt(ctx);
19444 gen_helper_emt(t0);
19445 gen_store_gpr(t0, rt);
19446 } else if (rs == 0) {
19447 /* EVPE */
19448 check_cp0_mt(ctx);
19449 gen_helper_evpe(t0, cpu_env);
19450 gen_store_gpr(t0, rt);
19451 } else {
19452 gen_reserved_instruction(ctx);
19454 break;
19457 tcg_temp_free(t0);
19459 break;
19460 case NM_FORK:
19461 check_mt(ctx);
19463 TCGv t0 = tcg_temp_new();
19464 TCGv t1 = tcg_temp_new();
19466 gen_load_gpr(t0, rt);
19467 gen_load_gpr(t1, rs);
19468 gen_helper_fork(t0, t1);
19469 tcg_temp_free(t0);
19470 tcg_temp_free(t1);
19472 break;
19473 case NM_MFTR:
19474 case NM_MFHTR:
19475 check_cp0_enabled(ctx);
19476 if (rd == 0) {
19477 /* Treat as NOP. */
19478 return;
19480 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19481 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19482 break;
19483 case NM_MTTR:
19484 case NM_MTHTR:
19485 check_cp0_enabled(ctx);
19486 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19487 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19488 break;
19489 case NM_YIELD:
19490 check_mt(ctx);
19492 TCGv t0 = tcg_temp_new();
19494 gen_load_gpr(t0, rs);
19495 gen_helper_yield(t0, cpu_env, t0);
19496 gen_store_gpr(t0, rt);
19497 tcg_temp_free(t0);
19499 break;
19500 #endif
19501 default:
19502 gen_reserved_instruction(ctx);
19503 break;
19507 /* dsp */
19508 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19509 int ret, int v1, int v2)
19511 TCGv_i32 t0;
19512 TCGv v0_t;
19513 TCGv v1_t;
19515 t0 = tcg_temp_new_i32();
19517 v0_t = tcg_temp_new();
19518 v1_t = tcg_temp_new();
19520 tcg_gen_movi_i32(t0, v2 >> 3);
19522 gen_load_gpr(v0_t, ret);
19523 gen_load_gpr(v1_t, v1);
19525 switch (opc) {
19526 case NM_MAQ_S_W_PHR:
19527 check_dsp(ctx);
19528 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19529 break;
19530 case NM_MAQ_S_W_PHL:
19531 check_dsp(ctx);
19532 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19533 break;
19534 case NM_MAQ_SA_W_PHR:
19535 check_dsp(ctx);
19536 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19537 break;
19538 case NM_MAQ_SA_W_PHL:
19539 check_dsp(ctx);
19540 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19541 break;
19542 default:
19543 gen_reserved_instruction(ctx);
19544 break;
19547 tcg_temp_free_i32(t0);
19549 tcg_temp_free(v0_t);
19550 tcg_temp_free(v1_t);
19554 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19555 int ret, int v1, int v2)
19557 int16_t imm;
19558 TCGv t0 = tcg_temp_new();
19559 TCGv t1 = tcg_temp_new();
19560 TCGv v0_t = tcg_temp_new();
19562 gen_load_gpr(v0_t, v1);
19564 switch (opc) {
19565 case NM_POOL32AXF_1_0:
19566 check_dsp(ctx);
19567 switch (extract32(ctx->opcode, 12, 2)) {
19568 case NM_MFHI:
19569 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19570 break;
19571 case NM_MFLO:
19572 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19573 break;
19574 case NM_MTHI:
19575 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19576 break;
19577 case NM_MTLO:
19578 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19579 break;
19581 break;
19582 case NM_POOL32AXF_1_1:
19583 check_dsp(ctx);
19584 switch (extract32(ctx->opcode, 12, 2)) {
19585 case NM_MTHLIP:
19586 tcg_gen_movi_tl(t0, v2);
19587 gen_helper_mthlip(t0, v0_t, cpu_env);
19588 break;
19589 case NM_SHILOV:
19590 tcg_gen_movi_tl(t0, v2 >> 3);
19591 gen_helper_shilo(t0, v0_t, cpu_env);
19592 break;
19593 default:
19594 gen_reserved_instruction(ctx);
19595 break;
19597 break;
19598 case NM_POOL32AXF_1_3:
19599 check_dsp(ctx);
19600 imm = extract32(ctx->opcode, 14, 7);
19601 switch (extract32(ctx->opcode, 12, 2)) {
19602 case NM_RDDSP:
19603 tcg_gen_movi_tl(t0, imm);
19604 gen_helper_rddsp(t0, t0, cpu_env);
19605 gen_store_gpr(t0, ret);
19606 break;
19607 case NM_WRDSP:
19608 gen_load_gpr(t0, ret);
19609 tcg_gen_movi_tl(t1, imm);
19610 gen_helper_wrdsp(t0, t1, cpu_env);
19611 break;
19612 case NM_EXTP:
19613 tcg_gen_movi_tl(t0, v2 >> 3);
19614 tcg_gen_movi_tl(t1, v1);
19615 gen_helper_extp(t0, t0, t1, cpu_env);
19616 gen_store_gpr(t0, ret);
19617 break;
19618 case NM_EXTPDP:
19619 tcg_gen_movi_tl(t0, v2 >> 3);
19620 tcg_gen_movi_tl(t1, v1);
19621 gen_helper_extpdp(t0, t0, t1, cpu_env);
19622 gen_store_gpr(t0, ret);
19623 break;
19625 break;
19626 case NM_POOL32AXF_1_4:
19627 check_dsp(ctx);
19628 tcg_gen_movi_tl(t0, v2 >> 2);
19629 switch (extract32(ctx->opcode, 12, 1)) {
19630 case NM_SHLL_QB:
19631 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19632 gen_store_gpr(t0, ret);
19633 break;
19634 case NM_SHRL_QB:
19635 gen_helper_shrl_qb(t0, t0, v0_t);
19636 gen_store_gpr(t0, ret);
19637 break;
19639 break;
19640 case NM_POOL32AXF_1_5:
19641 opc = extract32(ctx->opcode, 12, 2);
19642 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19643 break;
19644 case NM_POOL32AXF_1_7:
19645 check_dsp(ctx);
19646 tcg_gen_movi_tl(t0, v2 >> 3);
19647 tcg_gen_movi_tl(t1, v1);
19648 switch (extract32(ctx->opcode, 12, 2)) {
19649 case NM_EXTR_W:
19650 gen_helper_extr_w(t0, t0, t1, cpu_env);
19651 gen_store_gpr(t0, ret);
19652 break;
19653 case NM_EXTR_R_W:
19654 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19655 gen_store_gpr(t0, ret);
19656 break;
19657 case NM_EXTR_RS_W:
19658 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19659 gen_store_gpr(t0, ret);
19660 break;
19661 case NM_EXTR_S_H:
19662 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19663 gen_store_gpr(t0, ret);
19664 break;
19666 break;
19667 default:
19668 gen_reserved_instruction(ctx);
19669 break;
19672 tcg_temp_free(t0);
19673 tcg_temp_free(t1);
19674 tcg_temp_free(v0_t);
19677 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19678 TCGv v0, TCGv v1, int rd)
19680 TCGv_i32 t0;
19682 t0 = tcg_temp_new_i32();
19684 tcg_gen_movi_i32(t0, rd >> 3);
19686 switch (opc) {
19687 case NM_POOL32AXF_2_0_7:
19688 switch (extract32(ctx->opcode, 9, 3)) {
19689 case NM_DPA_W_PH:
19690 check_dsp_r2(ctx);
19691 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19692 break;
19693 case NM_DPAQ_S_W_PH:
19694 check_dsp(ctx);
19695 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19696 break;
19697 case NM_DPS_W_PH:
19698 check_dsp_r2(ctx);
19699 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19700 break;
19701 case NM_DPSQ_S_W_PH:
19702 check_dsp(ctx);
19703 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19704 break;
19705 default:
19706 gen_reserved_instruction(ctx);
19707 break;
19709 break;
19710 case NM_POOL32AXF_2_8_15:
19711 switch (extract32(ctx->opcode, 9, 3)) {
19712 case NM_DPAX_W_PH:
19713 check_dsp_r2(ctx);
19714 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19715 break;
19716 case NM_DPAQ_SA_L_W:
19717 check_dsp(ctx);
19718 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19719 break;
19720 case NM_DPSX_W_PH:
19721 check_dsp_r2(ctx);
19722 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19723 break;
19724 case NM_DPSQ_SA_L_W:
19725 check_dsp(ctx);
19726 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19727 break;
19728 default:
19729 gen_reserved_instruction(ctx);
19730 break;
19732 break;
19733 case NM_POOL32AXF_2_16_23:
19734 switch (extract32(ctx->opcode, 9, 3)) {
19735 case NM_DPAU_H_QBL:
19736 check_dsp(ctx);
19737 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19738 break;
19739 case NM_DPAQX_S_W_PH:
19740 check_dsp_r2(ctx);
19741 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19742 break;
19743 case NM_DPSU_H_QBL:
19744 check_dsp(ctx);
19745 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19746 break;
19747 case NM_DPSQX_S_W_PH:
19748 check_dsp_r2(ctx);
19749 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19750 break;
19751 case NM_MULSA_W_PH:
19752 check_dsp_r2(ctx);
19753 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19754 break;
19755 default:
19756 gen_reserved_instruction(ctx);
19757 break;
19759 break;
19760 case NM_POOL32AXF_2_24_31:
19761 switch (extract32(ctx->opcode, 9, 3)) {
19762 case NM_DPAU_H_QBR:
19763 check_dsp(ctx);
19764 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19765 break;
19766 case NM_DPAQX_SA_W_PH:
19767 check_dsp_r2(ctx);
19768 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19769 break;
19770 case NM_DPSU_H_QBR:
19771 check_dsp(ctx);
19772 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19773 break;
19774 case NM_DPSQX_SA_W_PH:
19775 check_dsp_r2(ctx);
19776 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19777 break;
19778 case NM_MULSAQ_S_W_PH:
19779 check_dsp(ctx);
19780 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19781 break;
19782 default:
19783 gen_reserved_instruction(ctx);
19784 break;
19786 break;
19787 default:
19788 gen_reserved_instruction(ctx);
19789 break;
19792 tcg_temp_free_i32(t0);
19795 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19796 int rt, int rs, int rd)
19798 int ret = rt;
19799 TCGv t0 = tcg_temp_new();
19800 TCGv t1 = tcg_temp_new();
19801 TCGv v0_t = tcg_temp_new();
19802 TCGv v1_t = tcg_temp_new();
19804 gen_load_gpr(v0_t, rt);
19805 gen_load_gpr(v1_t, rs);
19807 switch (opc) {
19808 case NM_POOL32AXF_2_0_7:
19809 switch (extract32(ctx->opcode, 9, 3)) {
19810 case NM_DPA_W_PH:
19811 case NM_DPAQ_S_W_PH:
19812 case NM_DPS_W_PH:
19813 case NM_DPSQ_S_W_PH:
19814 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19815 break;
19816 case NM_BALIGN:
19817 check_dsp_r2(ctx);
19818 if (rt != 0) {
19819 gen_load_gpr(t0, rs);
19820 rd &= 3;
19821 if (rd != 0 && rd != 2) {
19822 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19823 tcg_gen_ext32u_tl(t0, t0);
19824 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19825 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19827 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19829 break;
19830 case NM_MADD:
19831 check_dsp(ctx);
19833 int acc = extract32(ctx->opcode, 14, 2);
19834 TCGv_i64 t2 = tcg_temp_new_i64();
19835 TCGv_i64 t3 = tcg_temp_new_i64();
19837 gen_load_gpr(t0, rt);
19838 gen_load_gpr(t1, rs);
19839 tcg_gen_ext_tl_i64(t2, t0);
19840 tcg_gen_ext_tl_i64(t3, t1);
19841 tcg_gen_mul_i64(t2, t2, t3);
19842 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19843 tcg_gen_add_i64(t2, t2, t3);
19844 tcg_temp_free_i64(t3);
19845 gen_move_low32(cpu_LO[acc], t2);
19846 gen_move_high32(cpu_HI[acc], t2);
19847 tcg_temp_free_i64(t2);
19849 break;
19850 case NM_MULT:
19851 check_dsp(ctx);
19853 int acc = extract32(ctx->opcode, 14, 2);
19854 TCGv_i32 t2 = tcg_temp_new_i32();
19855 TCGv_i32 t3 = tcg_temp_new_i32();
19857 gen_load_gpr(t0, rs);
19858 gen_load_gpr(t1, rt);
19859 tcg_gen_trunc_tl_i32(t2, t0);
19860 tcg_gen_trunc_tl_i32(t3, t1);
19861 tcg_gen_muls2_i32(t2, t3, t2, t3);
19862 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19863 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19864 tcg_temp_free_i32(t2);
19865 tcg_temp_free_i32(t3);
19867 break;
19868 case NM_EXTRV_W:
19869 check_dsp(ctx);
19870 gen_load_gpr(v1_t, rs);
19871 tcg_gen_movi_tl(t0, rd >> 3);
19872 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19873 gen_store_gpr(t0, ret);
19874 break;
19876 break;
19877 case NM_POOL32AXF_2_8_15:
19878 switch (extract32(ctx->opcode, 9, 3)) {
19879 case NM_DPAX_W_PH:
19880 case NM_DPAQ_SA_L_W:
19881 case NM_DPSX_W_PH:
19882 case NM_DPSQ_SA_L_W:
19883 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19884 break;
19885 case NM_MADDU:
19886 check_dsp(ctx);
19888 int acc = extract32(ctx->opcode, 14, 2);
19889 TCGv_i64 t2 = tcg_temp_new_i64();
19890 TCGv_i64 t3 = tcg_temp_new_i64();
19892 gen_load_gpr(t0, rs);
19893 gen_load_gpr(t1, rt);
19894 tcg_gen_ext32u_tl(t0, t0);
19895 tcg_gen_ext32u_tl(t1, t1);
19896 tcg_gen_extu_tl_i64(t2, t0);
19897 tcg_gen_extu_tl_i64(t3, t1);
19898 tcg_gen_mul_i64(t2, t2, t3);
19899 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19900 tcg_gen_add_i64(t2, t2, t3);
19901 tcg_temp_free_i64(t3);
19902 gen_move_low32(cpu_LO[acc], t2);
19903 gen_move_high32(cpu_HI[acc], t2);
19904 tcg_temp_free_i64(t2);
19906 break;
19907 case NM_MULTU:
19908 check_dsp(ctx);
19910 int acc = extract32(ctx->opcode, 14, 2);
19911 TCGv_i32 t2 = tcg_temp_new_i32();
19912 TCGv_i32 t3 = tcg_temp_new_i32();
19914 gen_load_gpr(t0, rs);
19915 gen_load_gpr(t1, rt);
19916 tcg_gen_trunc_tl_i32(t2, t0);
19917 tcg_gen_trunc_tl_i32(t3, t1);
19918 tcg_gen_mulu2_i32(t2, t3, t2, t3);
19919 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19920 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19921 tcg_temp_free_i32(t2);
19922 tcg_temp_free_i32(t3);
19924 break;
19925 case NM_EXTRV_R_W:
19926 check_dsp(ctx);
19927 tcg_gen_movi_tl(t0, rd >> 3);
19928 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
19929 gen_store_gpr(t0, ret);
19930 break;
19931 default:
19932 gen_reserved_instruction(ctx);
19933 break;
19935 break;
19936 case NM_POOL32AXF_2_16_23:
19937 switch (extract32(ctx->opcode, 9, 3)) {
19938 case NM_DPAU_H_QBL:
19939 case NM_DPAQX_S_W_PH:
19940 case NM_DPSU_H_QBL:
19941 case NM_DPSQX_S_W_PH:
19942 case NM_MULSA_W_PH:
19943 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19944 break;
19945 case NM_EXTPV:
19946 check_dsp(ctx);
19947 tcg_gen_movi_tl(t0, rd >> 3);
19948 gen_helper_extp(t0, t0, v1_t, cpu_env);
19949 gen_store_gpr(t0, ret);
19950 break;
19951 case NM_MSUB:
19952 check_dsp(ctx);
19954 int acc = extract32(ctx->opcode, 14, 2);
19955 TCGv_i64 t2 = tcg_temp_new_i64();
19956 TCGv_i64 t3 = tcg_temp_new_i64();
19958 gen_load_gpr(t0, rs);
19959 gen_load_gpr(t1, rt);
19960 tcg_gen_ext_tl_i64(t2, t0);
19961 tcg_gen_ext_tl_i64(t3, t1);
19962 tcg_gen_mul_i64(t2, t2, t3);
19963 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19964 tcg_gen_sub_i64(t2, t3, t2);
19965 tcg_temp_free_i64(t3);
19966 gen_move_low32(cpu_LO[acc], t2);
19967 gen_move_high32(cpu_HI[acc], t2);
19968 tcg_temp_free_i64(t2);
19970 break;
19971 case NM_EXTRV_RS_W:
19972 check_dsp(ctx);
19973 tcg_gen_movi_tl(t0, rd >> 3);
19974 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
19975 gen_store_gpr(t0, ret);
19976 break;
19978 break;
19979 case NM_POOL32AXF_2_24_31:
19980 switch (extract32(ctx->opcode, 9, 3)) {
19981 case NM_DPAU_H_QBR:
19982 case NM_DPAQX_SA_W_PH:
19983 case NM_DPSU_H_QBR:
19984 case NM_DPSQX_SA_W_PH:
19985 case NM_MULSAQ_S_W_PH:
19986 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19987 break;
19988 case NM_EXTPDPV:
19989 check_dsp(ctx);
19990 tcg_gen_movi_tl(t0, rd >> 3);
19991 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
19992 gen_store_gpr(t0, ret);
19993 break;
19994 case NM_MSUBU:
19995 check_dsp(ctx);
19997 int acc = extract32(ctx->opcode, 14, 2);
19998 TCGv_i64 t2 = tcg_temp_new_i64();
19999 TCGv_i64 t3 = tcg_temp_new_i64();
20001 gen_load_gpr(t0, rs);
20002 gen_load_gpr(t1, rt);
20003 tcg_gen_ext32u_tl(t0, t0);
20004 tcg_gen_ext32u_tl(t1, t1);
20005 tcg_gen_extu_tl_i64(t2, t0);
20006 tcg_gen_extu_tl_i64(t3, t1);
20007 tcg_gen_mul_i64(t2, t2, t3);
20008 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20009 tcg_gen_sub_i64(t2, t3, t2);
20010 tcg_temp_free_i64(t3);
20011 gen_move_low32(cpu_LO[acc], t2);
20012 gen_move_high32(cpu_HI[acc], t2);
20013 tcg_temp_free_i64(t2);
20015 break;
20016 case NM_EXTRV_S_H:
20017 check_dsp(ctx);
20018 tcg_gen_movi_tl(t0, rd >> 3);
20019 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
20020 gen_store_gpr(t0, ret);
20021 break;
20023 break;
20024 default:
20025 gen_reserved_instruction(ctx);
20026 break;
20029 tcg_temp_free(t0);
20030 tcg_temp_free(t1);
20032 tcg_temp_free(v0_t);
20033 tcg_temp_free(v1_t);
20036 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
20037 int rt, int rs)
20039 int ret = rt;
20040 TCGv t0 = tcg_temp_new();
20041 TCGv v0_t = tcg_temp_new();
20043 gen_load_gpr(v0_t, rs);
20045 switch (opc) {
20046 case NM_ABSQ_S_QB:
20047 check_dsp_r2(ctx);
20048 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
20049 gen_store_gpr(v0_t, ret);
20050 break;
20051 case NM_ABSQ_S_PH:
20052 check_dsp(ctx);
20053 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
20054 gen_store_gpr(v0_t, ret);
20055 break;
20056 case NM_ABSQ_S_W:
20057 check_dsp(ctx);
20058 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
20059 gen_store_gpr(v0_t, ret);
20060 break;
20061 case NM_PRECEQ_W_PHL:
20062 check_dsp(ctx);
20063 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
20064 tcg_gen_ext32s_tl(v0_t, v0_t);
20065 gen_store_gpr(v0_t, ret);
20066 break;
20067 case NM_PRECEQ_W_PHR:
20068 check_dsp(ctx);
20069 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
20070 tcg_gen_shli_tl(v0_t, v0_t, 16);
20071 tcg_gen_ext32s_tl(v0_t, v0_t);
20072 gen_store_gpr(v0_t, ret);
20073 break;
20074 case NM_PRECEQU_PH_QBL:
20075 check_dsp(ctx);
20076 gen_helper_precequ_ph_qbl(v0_t, v0_t);
20077 gen_store_gpr(v0_t, ret);
20078 break;
20079 case NM_PRECEQU_PH_QBR:
20080 check_dsp(ctx);
20081 gen_helper_precequ_ph_qbr(v0_t, v0_t);
20082 gen_store_gpr(v0_t, ret);
20083 break;
20084 case NM_PRECEQU_PH_QBLA:
20085 check_dsp(ctx);
20086 gen_helper_precequ_ph_qbla(v0_t, v0_t);
20087 gen_store_gpr(v0_t, ret);
20088 break;
20089 case NM_PRECEQU_PH_QBRA:
20090 check_dsp(ctx);
20091 gen_helper_precequ_ph_qbra(v0_t, v0_t);
20092 gen_store_gpr(v0_t, ret);
20093 break;
20094 case NM_PRECEU_PH_QBL:
20095 check_dsp(ctx);
20096 gen_helper_preceu_ph_qbl(v0_t, v0_t);
20097 gen_store_gpr(v0_t, ret);
20098 break;
20099 case NM_PRECEU_PH_QBR:
20100 check_dsp(ctx);
20101 gen_helper_preceu_ph_qbr(v0_t, v0_t);
20102 gen_store_gpr(v0_t, ret);
20103 break;
20104 case NM_PRECEU_PH_QBLA:
20105 check_dsp(ctx);
20106 gen_helper_preceu_ph_qbla(v0_t, v0_t);
20107 gen_store_gpr(v0_t, ret);
20108 break;
20109 case NM_PRECEU_PH_QBRA:
20110 check_dsp(ctx);
20111 gen_helper_preceu_ph_qbra(v0_t, v0_t);
20112 gen_store_gpr(v0_t, ret);
20113 break;
20114 case NM_REPLV_PH:
20115 check_dsp(ctx);
20116 tcg_gen_ext16u_tl(v0_t, v0_t);
20117 tcg_gen_shli_tl(t0, v0_t, 16);
20118 tcg_gen_or_tl(v0_t, v0_t, t0);
20119 tcg_gen_ext32s_tl(v0_t, v0_t);
20120 gen_store_gpr(v0_t, ret);
20121 break;
20122 case NM_REPLV_QB:
20123 check_dsp(ctx);
20124 tcg_gen_ext8u_tl(v0_t, v0_t);
20125 tcg_gen_shli_tl(t0, v0_t, 8);
20126 tcg_gen_or_tl(v0_t, v0_t, t0);
20127 tcg_gen_shli_tl(t0, v0_t, 16);
20128 tcg_gen_or_tl(v0_t, v0_t, t0);
20129 tcg_gen_ext32s_tl(v0_t, v0_t);
20130 gen_store_gpr(v0_t, ret);
20131 break;
20132 case NM_BITREV:
20133 check_dsp(ctx);
20134 gen_helper_bitrev(v0_t, v0_t);
20135 gen_store_gpr(v0_t, ret);
20136 break;
20137 case NM_INSV:
20138 check_dsp(ctx);
20140 TCGv tv0 = tcg_temp_new();
20142 gen_load_gpr(tv0, rt);
20143 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
20144 gen_store_gpr(v0_t, ret);
20145 tcg_temp_free(tv0);
20147 break;
20148 case NM_RADDU_W_QB:
20149 check_dsp(ctx);
20150 gen_helper_raddu_w_qb(v0_t, v0_t);
20151 gen_store_gpr(v0_t, ret);
20152 break;
20153 case NM_BITSWAP:
20154 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
20155 break;
20156 case NM_CLO:
20157 check_nms(ctx);
20158 gen_cl(ctx, OPC_CLO, ret, rs);
20159 break;
20160 case NM_CLZ:
20161 check_nms(ctx);
20162 gen_cl(ctx, OPC_CLZ, ret, rs);
20163 break;
20164 case NM_WSBH:
20165 gen_bshfl(ctx, OPC_WSBH, ret, rs);
20166 break;
20167 default:
20168 gen_reserved_instruction(ctx);
20169 break;
20172 tcg_temp_free(v0_t);
20173 tcg_temp_free(t0);
20176 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
20177 int rt, int rs, int rd)
20179 TCGv t0 = tcg_temp_new();
20180 TCGv rs_t = tcg_temp_new();
20182 gen_load_gpr(rs_t, rs);
20184 switch (opc) {
20185 case NM_SHRA_R_QB:
20186 check_dsp_r2(ctx);
20187 tcg_gen_movi_tl(t0, rd >> 2);
20188 switch (extract32(ctx->opcode, 12, 1)) {
20189 case 0:
20190 /* NM_SHRA_QB */
20191 gen_helper_shra_qb(t0, t0, rs_t);
20192 gen_store_gpr(t0, rt);
20193 break;
20194 case 1:
20195 /* NM_SHRA_R_QB */
20196 gen_helper_shra_r_qb(t0, t0, rs_t);
20197 gen_store_gpr(t0, rt);
20198 break;
20200 break;
20201 case NM_SHRL_PH:
20202 check_dsp_r2(ctx);
20203 tcg_gen_movi_tl(t0, rd >> 1);
20204 gen_helper_shrl_ph(t0, t0, rs_t);
20205 gen_store_gpr(t0, rt);
20206 break;
20207 case NM_REPL_QB:
20208 check_dsp(ctx);
20210 int16_t imm;
20211 target_long result;
20212 imm = extract32(ctx->opcode, 13, 8);
20213 result = (uint32_t)imm << 24 |
20214 (uint32_t)imm << 16 |
20215 (uint32_t)imm << 8 |
20216 (uint32_t)imm;
20217 result = (int32_t)result;
20218 tcg_gen_movi_tl(t0, result);
20219 gen_store_gpr(t0, rt);
20221 break;
20222 default:
20223 gen_reserved_instruction(ctx);
20224 break;
20226 tcg_temp_free(t0);
20227 tcg_temp_free(rs_t);
20231 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
20233 int rt = extract32(ctx->opcode, 21, 5);
20234 int rs = extract32(ctx->opcode, 16, 5);
20235 int rd = extract32(ctx->opcode, 11, 5);
20237 switch (extract32(ctx->opcode, 6, 3)) {
20238 case NM_POOL32AXF_1:
20240 int32_t op1 = extract32(ctx->opcode, 9, 3);
20241 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
20243 break;
20244 case NM_POOL32AXF_2:
20246 int32_t op1 = extract32(ctx->opcode, 12, 2);
20247 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
20249 break;
20250 case NM_POOL32AXF_4:
20252 int32_t op1 = extract32(ctx->opcode, 9, 7);
20253 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
20255 break;
20256 case NM_POOL32AXF_5:
20257 switch (extract32(ctx->opcode, 9, 7)) {
20258 #ifndef CONFIG_USER_ONLY
20259 case NM_TLBP:
20260 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
20261 break;
20262 case NM_TLBR:
20263 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
20264 break;
20265 case NM_TLBWI:
20266 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
20267 break;
20268 case NM_TLBWR:
20269 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
20270 break;
20271 case NM_TLBINV:
20272 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
20273 break;
20274 case NM_TLBINVF:
20275 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
20276 break;
20277 case NM_DI:
20278 check_cp0_enabled(ctx);
20280 TCGv t0 = tcg_temp_new();
20282 save_cpu_state(ctx, 1);
20283 gen_helper_di(t0, cpu_env);
20284 gen_store_gpr(t0, rt);
20285 /* Stop translation as we may have switched the execution mode */
20286 ctx->base.is_jmp = DISAS_STOP;
20287 tcg_temp_free(t0);
20289 break;
20290 case NM_EI:
20291 check_cp0_enabled(ctx);
20293 TCGv t0 = tcg_temp_new();
20295 save_cpu_state(ctx, 1);
20296 gen_helper_ei(t0, cpu_env);
20297 gen_store_gpr(t0, rt);
20298 /* Stop translation as we may have switched the execution mode */
20299 ctx->base.is_jmp = DISAS_STOP;
20300 tcg_temp_free(t0);
20302 break;
20303 case NM_RDPGPR:
20304 gen_load_srsgpr(rs, rt);
20305 break;
20306 case NM_WRPGPR:
20307 gen_store_srsgpr(rs, rt);
20308 break;
20309 case NM_WAIT:
20310 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20311 break;
20312 case NM_DERET:
20313 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20314 break;
20315 case NM_ERETX:
20316 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20317 break;
20318 #endif
20319 default:
20320 gen_reserved_instruction(ctx);
20321 break;
20323 break;
20324 case NM_POOL32AXF_7:
20326 int32_t op1 = extract32(ctx->opcode, 9, 3);
20327 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20329 break;
20330 default:
20331 gen_reserved_instruction(ctx);
20332 break;
20336 /* Immediate Value Compact Branches */
20337 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20338 int rt, int32_t imm, int32_t offset)
20340 TCGCond cond = TCG_COND_ALWAYS;
20341 TCGv t0 = tcg_temp_new();
20342 TCGv t1 = tcg_temp_new();
20344 gen_load_gpr(t0, rt);
20345 tcg_gen_movi_tl(t1, imm);
20346 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20348 /* Load needed operands and calculate btarget */
20349 switch (opc) {
20350 case NM_BEQIC:
20351 if (rt == 0 && imm == 0) {
20352 /* Unconditional branch */
20353 } else if (rt == 0 && imm != 0) {
20354 /* Treat as NOP */
20355 goto out;
20356 } else {
20357 cond = TCG_COND_EQ;
20359 break;
20360 case NM_BBEQZC:
20361 case NM_BBNEZC:
20362 check_nms(ctx);
20363 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20364 gen_reserved_instruction(ctx);
20365 goto out;
20366 } else if (rt == 0 && opc == NM_BBEQZC) {
20367 /* Unconditional branch */
20368 } else if (rt == 0 && opc == NM_BBNEZC) {
20369 /* Treat as NOP */
20370 goto out;
20371 } else {
20372 tcg_gen_shri_tl(t0, t0, imm);
20373 tcg_gen_andi_tl(t0, t0, 1);
20374 tcg_gen_movi_tl(t1, 0);
20375 if (opc == NM_BBEQZC) {
20376 cond = TCG_COND_EQ;
20377 } else {
20378 cond = TCG_COND_NE;
20381 break;
20382 case NM_BNEIC:
20383 if (rt == 0 && imm == 0) {
20384 /* Treat as NOP */
20385 goto out;
20386 } else if (rt == 0 && imm != 0) {
20387 /* Unconditional branch */
20388 } else {
20389 cond = TCG_COND_NE;
20391 break;
20392 case NM_BGEIC:
20393 if (rt == 0 && imm == 0) {
20394 /* Unconditional branch */
20395 } else {
20396 cond = TCG_COND_GE;
20398 break;
20399 case NM_BLTIC:
20400 cond = TCG_COND_LT;
20401 break;
20402 case NM_BGEIUC:
20403 if (rt == 0 && imm == 0) {
20404 /* Unconditional branch */
20405 } else {
20406 cond = TCG_COND_GEU;
20408 break;
20409 case NM_BLTIUC:
20410 cond = TCG_COND_LTU;
20411 break;
20412 default:
20413 MIPS_INVAL("Immediate Value Compact branch");
20414 gen_reserved_instruction(ctx);
20415 goto out;
20418 /* branch completion */
20419 clear_branch_hflags(ctx);
20420 ctx->base.is_jmp = DISAS_NORETURN;
20422 if (cond == TCG_COND_ALWAYS) {
20423 /* Uncoditional compact branch */
20424 gen_goto_tb(ctx, 0, ctx->btarget);
20425 } else {
20426 /* Conditional compact branch */
20427 TCGLabel *fs = gen_new_label();
20429 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20431 gen_goto_tb(ctx, 1, ctx->btarget);
20432 gen_set_label(fs);
20434 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20437 out:
20438 tcg_temp_free(t0);
20439 tcg_temp_free(t1);
20442 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20443 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20444 int rt)
20446 TCGv t0 = tcg_temp_new();
20447 TCGv t1 = tcg_temp_new();
20449 /* load rs */
20450 gen_load_gpr(t0, rs);
20452 /* link */
20453 if (rt != 0) {
20454 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20457 /* calculate btarget */
20458 tcg_gen_shli_tl(t0, t0, 1);
20459 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20460 gen_op_addr_add(ctx, btarget, t1, t0);
20462 /* branch completion */
20463 clear_branch_hflags(ctx);
20464 ctx->base.is_jmp = DISAS_NORETURN;
20466 /* unconditional branch to register */
20467 tcg_gen_mov_tl(cpu_PC, btarget);
20468 tcg_gen_lookup_and_goto_ptr();
20470 tcg_temp_free(t0);
20471 tcg_temp_free(t1);
20474 /* nanoMIPS Branches */
20475 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20476 int rs, int rt, int32_t offset)
20478 int bcond_compute = 0;
20479 TCGv t0 = tcg_temp_new();
20480 TCGv t1 = tcg_temp_new();
20482 /* Load needed operands and calculate btarget */
20483 switch (opc) {
20484 /* compact branch */
20485 case OPC_BGEC:
20486 case OPC_BLTC:
20487 gen_load_gpr(t0, rs);
20488 gen_load_gpr(t1, rt);
20489 bcond_compute = 1;
20490 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20491 break;
20492 case OPC_BGEUC:
20493 case OPC_BLTUC:
20494 if (rs == 0 || rs == rt) {
20495 /* OPC_BLEZALC, OPC_BGEZALC */
20496 /* OPC_BGTZALC, OPC_BLTZALC */
20497 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20499 gen_load_gpr(t0, rs);
20500 gen_load_gpr(t1, rt);
20501 bcond_compute = 1;
20502 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20503 break;
20504 case OPC_BC:
20505 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20506 break;
20507 case OPC_BEQZC:
20508 if (rs != 0) {
20509 /* OPC_BEQZC, OPC_BNEZC */
20510 gen_load_gpr(t0, rs);
20511 bcond_compute = 1;
20512 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20513 } else {
20514 /* OPC_JIC, OPC_JIALC */
20515 TCGv tbase = tcg_temp_new();
20516 TCGv toffset = tcg_temp_new();
20518 gen_load_gpr(tbase, rt);
20519 tcg_gen_movi_tl(toffset, offset);
20520 gen_op_addr_add(ctx, btarget, tbase, toffset);
20521 tcg_temp_free(tbase);
20522 tcg_temp_free(toffset);
20524 break;
20525 default:
20526 MIPS_INVAL("Compact branch/jump");
20527 gen_reserved_instruction(ctx);
20528 goto out;
20531 if (bcond_compute == 0) {
20532 /* Uncoditional compact branch */
20533 switch (opc) {
20534 case OPC_BC:
20535 gen_goto_tb(ctx, 0, ctx->btarget);
20536 break;
20537 default:
20538 MIPS_INVAL("Compact branch/jump");
20539 gen_reserved_instruction(ctx);
20540 goto out;
20542 } else {
20543 /* Conditional compact branch */
20544 TCGLabel *fs = gen_new_label();
20546 switch (opc) {
20547 case OPC_BGEUC:
20548 if (rs == 0 && rt != 0) {
20549 /* OPC_BLEZALC */
20550 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20551 } else if (rs != 0 && rt != 0 && rs == rt) {
20552 /* OPC_BGEZALC */
20553 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20554 } else {
20555 /* OPC_BGEUC */
20556 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20558 break;
20559 case OPC_BLTUC:
20560 if (rs == 0 && rt != 0) {
20561 /* OPC_BGTZALC */
20562 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20563 } else if (rs != 0 && rt != 0 && rs == rt) {
20564 /* OPC_BLTZALC */
20565 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20566 } else {
20567 /* OPC_BLTUC */
20568 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20570 break;
20571 case OPC_BGEC:
20572 if (rs == 0 && rt != 0) {
20573 /* OPC_BLEZC */
20574 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20575 } else if (rs != 0 && rt != 0 && rs == rt) {
20576 /* OPC_BGEZC */
20577 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20578 } else {
20579 /* OPC_BGEC */
20580 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20582 break;
20583 case OPC_BLTC:
20584 if (rs == 0 && rt != 0) {
20585 /* OPC_BGTZC */
20586 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20587 } else if (rs != 0 && rt != 0 && rs == rt) {
20588 /* OPC_BLTZC */
20589 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20590 } else {
20591 /* OPC_BLTC */
20592 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20594 break;
20595 case OPC_BEQZC:
20596 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20597 break;
20598 default:
20599 MIPS_INVAL("Compact conditional branch/jump");
20600 gen_reserved_instruction(ctx);
20601 goto out;
20604 /* branch completion */
20605 clear_branch_hflags(ctx);
20606 ctx->base.is_jmp = DISAS_NORETURN;
20608 /* Generating branch here as compact branches don't have delay slot */
20609 gen_goto_tb(ctx, 1, ctx->btarget);
20610 gen_set_label(fs);
20612 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20615 out:
20616 tcg_temp_free(t0);
20617 tcg_temp_free(t1);
20621 /* nanoMIPS CP1 Branches */
20622 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20623 int32_t ft, int32_t offset)
20625 target_ulong btarget;
20626 TCGv_i64 t0 = tcg_temp_new_i64();
20628 gen_load_fpr64(ctx, t0, ft);
20629 tcg_gen_andi_i64(t0, t0, 1);
20631 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20633 switch (op) {
20634 case NM_BC1EQZC:
20635 tcg_gen_xori_i64(t0, t0, 1);
20636 ctx->hflags |= MIPS_HFLAG_BC;
20637 break;
20638 case NM_BC1NEZC:
20639 /* t0 already set */
20640 ctx->hflags |= MIPS_HFLAG_BC;
20641 break;
20642 default:
20643 MIPS_INVAL("cp1 cond branch");
20644 gen_reserved_instruction(ctx);
20645 goto out;
20648 tcg_gen_trunc_i64_tl(bcond, t0);
20650 ctx->btarget = btarget;
20652 out:
20653 tcg_temp_free_i64(t0);
20657 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20659 TCGv t0, t1;
20660 t0 = tcg_temp_new();
20661 t1 = tcg_temp_new();
20663 gen_load_gpr(t0, rs);
20664 gen_load_gpr(t1, rt);
20666 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20667 /* PP.LSXS instructions require shifting */
20668 switch (extract32(ctx->opcode, 7, 4)) {
20669 case NM_SHXS:
20670 check_nms(ctx);
20671 /* fall through */
20672 case NM_LHXS:
20673 case NM_LHUXS:
20674 tcg_gen_shli_tl(t0, t0, 1);
20675 break;
20676 case NM_SWXS:
20677 check_nms(ctx);
20678 /* fall through */
20679 case NM_LWXS:
20680 case NM_LWC1XS:
20681 case NM_SWC1XS:
20682 tcg_gen_shli_tl(t0, t0, 2);
20683 break;
20684 case NM_LDC1XS:
20685 case NM_SDC1XS:
20686 tcg_gen_shli_tl(t0, t0, 3);
20687 break;
20690 gen_op_addr_add(ctx, t0, t0, t1);
20692 switch (extract32(ctx->opcode, 7, 4)) {
20693 case NM_LBX:
20694 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20695 MO_SB);
20696 gen_store_gpr(t0, rd);
20697 break;
20698 case NM_LHX:
20699 /*case NM_LHXS:*/
20700 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20701 MO_TESW);
20702 gen_store_gpr(t0, rd);
20703 break;
20704 case NM_LWX:
20705 /*case NM_LWXS:*/
20706 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20707 MO_TESL);
20708 gen_store_gpr(t0, rd);
20709 break;
20710 case NM_LBUX:
20711 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20712 MO_UB);
20713 gen_store_gpr(t0, rd);
20714 break;
20715 case NM_LHUX:
20716 /*case NM_LHUXS:*/
20717 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20718 MO_TEUW);
20719 gen_store_gpr(t0, rd);
20720 break;
20721 case NM_SBX:
20722 check_nms(ctx);
20723 gen_load_gpr(t1, rd);
20724 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20725 MO_8);
20726 break;
20727 case NM_SHX:
20728 /*case NM_SHXS:*/
20729 check_nms(ctx);
20730 gen_load_gpr(t1, rd);
20731 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20732 MO_TEUW);
20733 break;
20734 case NM_SWX:
20735 /*case NM_SWXS:*/
20736 check_nms(ctx);
20737 gen_load_gpr(t1, rd);
20738 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20739 MO_TEUL);
20740 break;
20741 case NM_LWC1X:
20742 /*case NM_LWC1XS:*/
20743 case NM_LDC1X:
20744 /*case NM_LDC1XS:*/
20745 case NM_SWC1X:
20746 /*case NM_SWC1XS:*/
20747 case NM_SDC1X:
20748 /*case NM_SDC1XS:*/
20749 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20750 check_cp1_enabled(ctx);
20751 switch (extract32(ctx->opcode, 7, 4)) {
20752 case NM_LWC1X:
20753 /*case NM_LWC1XS:*/
20754 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20755 break;
20756 case NM_LDC1X:
20757 /*case NM_LDC1XS:*/
20758 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20759 break;
20760 case NM_SWC1X:
20761 /*case NM_SWC1XS:*/
20762 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20763 break;
20764 case NM_SDC1X:
20765 /*case NM_SDC1XS:*/
20766 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20767 break;
20769 } else {
20770 generate_exception_err(ctx, EXCP_CpU, 1);
20772 break;
20773 default:
20774 gen_reserved_instruction(ctx);
20775 break;
20778 tcg_temp_free(t0);
20779 tcg_temp_free(t1);
20782 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20784 int rt, rs, rd;
20786 rt = extract32(ctx->opcode, 21, 5);
20787 rs = extract32(ctx->opcode, 16, 5);
20788 rd = extract32(ctx->opcode, 11, 5);
20790 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20791 gen_reserved_instruction(ctx);
20792 return;
20794 check_cp1_enabled(ctx);
20795 switch (extract32(ctx->opcode, 0, 3)) {
20796 case NM_POOL32F_0:
20797 switch (extract32(ctx->opcode, 3, 7)) {
20798 case NM_RINT_S:
20799 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20800 break;
20801 case NM_RINT_D:
20802 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20803 break;
20804 case NM_CLASS_S:
20805 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20806 break;
20807 case NM_CLASS_D:
20808 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20809 break;
20810 case NM_ADD_S:
20811 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20812 break;
20813 case NM_ADD_D:
20814 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20815 break;
20816 case NM_SUB_S:
20817 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20818 break;
20819 case NM_SUB_D:
20820 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20821 break;
20822 case NM_MUL_S:
20823 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20824 break;
20825 case NM_MUL_D:
20826 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20827 break;
20828 case NM_DIV_S:
20829 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20830 break;
20831 case NM_DIV_D:
20832 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20833 break;
20834 case NM_SELEQZ_S:
20835 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20836 break;
20837 case NM_SELEQZ_D:
20838 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20839 break;
20840 case NM_SELNEZ_S:
20841 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20842 break;
20843 case NM_SELNEZ_D:
20844 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20845 break;
20846 case NM_SEL_S:
20847 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20848 break;
20849 case NM_SEL_D:
20850 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20851 break;
20852 case NM_MADDF_S:
20853 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20854 break;
20855 case NM_MADDF_D:
20856 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20857 break;
20858 case NM_MSUBF_S:
20859 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20860 break;
20861 case NM_MSUBF_D:
20862 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20863 break;
20864 default:
20865 gen_reserved_instruction(ctx);
20866 break;
20868 break;
20869 case NM_POOL32F_3:
20870 switch (extract32(ctx->opcode, 3, 3)) {
20871 case NM_MIN_FMT:
20872 switch (extract32(ctx->opcode, 9, 1)) {
20873 case FMT_SDPS_S:
20874 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
20875 break;
20876 case FMT_SDPS_D:
20877 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
20878 break;
20880 break;
20881 case NM_MAX_FMT:
20882 switch (extract32(ctx->opcode, 9, 1)) {
20883 case FMT_SDPS_S:
20884 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
20885 break;
20886 case FMT_SDPS_D:
20887 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
20888 break;
20890 break;
20891 case NM_MINA_FMT:
20892 switch (extract32(ctx->opcode, 9, 1)) {
20893 case FMT_SDPS_S:
20894 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
20895 break;
20896 case FMT_SDPS_D:
20897 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
20898 break;
20900 break;
20901 case NM_MAXA_FMT:
20902 switch (extract32(ctx->opcode, 9, 1)) {
20903 case FMT_SDPS_S:
20904 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
20905 break;
20906 case FMT_SDPS_D:
20907 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
20908 break;
20910 break;
20911 case NM_POOL32FXF:
20912 switch (extract32(ctx->opcode, 6, 8)) {
20913 case NM_CFC1:
20914 gen_cp1(ctx, OPC_CFC1, rt, rs);
20915 break;
20916 case NM_CTC1:
20917 gen_cp1(ctx, OPC_CTC1, rt, rs);
20918 break;
20919 case NM_MFC1:
20920 gen_cp1(ctx, OPC_MFC1, rt, rs);
20921 break;
20922 case NM_MTC1:
20923 gen_cp1(ctx, OPC_MTC1, rt, rs);
20924 break;
20925 case NM_MFHC1:
20926 gen_cp1(ctx, OPC_MFHC1, rt, rs);
20927 break;
20928 case NM_MTHC1:
20929 gen_cp1(ctx, OPC_MTHC1, rt, rs);
20930 break;
20931 case NM_CVT_S_PL:
20932 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
20933 break;
20934 case NM_CVT_S_PU:
20935 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
20936 break;
20937 default:
20938 switch (extract32(ctx->opcode, 6, 9)) {
20939 case NM_CVT_L_S:
20940 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
20941 break;
20942 case NM_CVT_L_D:
20943 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
20944 break;
20945 case NM_CVT_W_S:
20946 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
20947 break;
20948 case NM_CVT_W_D:
20949 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
20950 break;
20951 case NM_RSQRT_S:
20952 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
20953 break;
20954 case NM_RSQRT_D:
20955 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
20956 break;
20957 case NM_SQRT_S:
20958 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
20959 break;
20960 case NM_SQRT_D:
20961 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
20962 break;
20963 case NM_RECIP_S:
20964 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
20965 break;
20966 case NM_RECIP_D:
20967 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
20968 break;
20969 case NM_FLOOR_L_S:
20970 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
20971 break;
20972 case NM_FLOOR_L_D:
20973 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
20974 break;
20975 case NM_FLOOR_W_S:
20976 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
20977 break;
20978 case NM_FLOOR_W_D:
20979 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
20980 break;
20981 case NM_CEIL_L_S:
20982 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
20983 break;
20984 case NM_CEIL_L_D:
20985 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
20986 break;
20987 case NM_CEIL_W_S:
20988 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
20989 break;
20990 case NM_CEIL_W_D:
20991 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
20992 break;
20993 case NM_TRUNC_L_S:
20994 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
20995 break;
20996 case NM_TRUNC_L_D:
20997 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
20998 break;
20999 case NM_TRUNC_W_S:
21000 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
21001 break;
21002 case NM_TRUNC_W_D:
21003 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
21004 break;
21005 case NM_ROUND_L_S:
21006 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
21007 break;
21008 case NM_ROUND_L_D:
21009 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
21010 break;
21011 case NM_ROUND_W_S:
21012 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
21013 break;
21014 case NM_ROUND_W_D:
21015 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
21016 break;
21017 case NM_MOV_S:
21018 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
21019 break;
21020 case NM_MOV_D:
21021 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
21022 break;
21023 case NM_ABS_S:
21024 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
21025 break;
21026 case NM_ABS_D:
21027 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
21028 break;
21029 case NM_NEG_S:
21030 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
21031 break;
21032 case NM_NEG_D:
21033 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
21034 break;
21035 case NM_CVT_D_S:
21036 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
21037 break;
21038 case NM_CVT_D_W:
21039 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
21040 break;
21041 case NM_CVT_D_L:
21042 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
21043 break;
21044 case NM_CVT_S_D:
21045 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
21046 break;
21047 case NM_CVT_S_W:
21048 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
21049 break;
21050 case NM_CVT_S_L:
21051 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
21052 break;
21053 default:
21054 gen_reserved_instruction(ctx);
21055 break;
21057 break;
21059 break;
21061 break;
21062 case NM_POOL32F_5:
21063 switch (extract32(ctx->opcode, 3, 3)) {
21064 case NM_CMP_CONDN_S:
21065 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21066 break;
21067 case NM_CMP_CONDN_D:
21068 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21069 break;
21070 default:
21071 gen_reserved_instruction(ctx);
21072 break;
21074 break;
21075 default:
21076 gen_reserved_instruction(ctx);
21077 break;
21081 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
21082 int rd, int rs, int rt)
21084 int ret = rd;
21085 TCGv t0 = tcg_temp_new();
21086 TCGv v1_t = tcg_temp_new();
21087 TCGv v2_t = tcg_temp_new();
21089 gen_load_gpr(v1_t, rs);
21090 gen_load_gpr(v2_t, rt);
21092 switch (opc) {
21093 case NM_CMP_EQ_PH:
21094 check_dsp(ctx);
21095 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21096 break;
21097 case NM_CMP_LT_PH:
21098 check_dsp(ctx);
21099 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21100 break;
21101 case NM_CMP_LE_PH:
21102 check_dsp(ctx);
21103 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21104 break;
21105 case NM_CMPU_EQ_QB:
21106 check_dsp(ctx);
21107 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21108 break;
21109 case NM_CMPU_LT_QB:
21110 check_dsp(ctx);
21111 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21112 break;
21113 case NM_CMPU_LE_QB:
21114 check_dsp(ctx);
21115 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21116 break;
21117 case NM_CMPGU_EQ_QB:
21118 check_dsp(ctx);
21119 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21120 gen_store_gpr(v1_t, ret);
21121 break;
21122 case NM_CMPGU_LT_QB:
21123 check_dsp(ctx);
21124 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21125 gen_store_gpr(v1_t, ret);
21126 break;
21127 case NM_CMPGU_LE_QB:
21128 check_dsp(ctx);
21129 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21130 gen_store_gpr(v1_t, ret);
21131 break;
21132 case NM_CMPGDU_EQ_QB:
21133 check_dsp_r2(ctx);
21134 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21135 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21136 gen_store_gpr(v1_t, ret);
21137 break;
21138 case NM_CMPGDU_LT_QB:
21139 check_dsp_r2(ctx);
21140 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21141 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21142 gen_store_gpr(v1_t, ret);
21143 break;
21144 case NM_CMPGDU_LE_QB:
21145 check_dsp_r2(ctx);
21146 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21147 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21148 gen_store_gpr(v1_t, ret);
21149 break;
21150 case NM_PACKRL_PH:
21151 check_dsp(ctx);
21152 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
21153 gen_store_gpr(v1_t, ret);
21154 break;
21155 case NM_PICK_QB:
21156 check_dsp(ctx);
21157 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
21158 gen_store_gpr(v1_t, ret);
21159 break;
21160 case NM_PICK_PH:
21161 check_dsp(ctx);
21162 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
21163 gen_store_gpr(v1_t, ret);
21164 break;
21165 case NM_ADDQ_S_W:
21166 check_dsp(ctx);
21167 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
21168 gen_store_gpr(v1_t, ret);
21169 break;
21170 case NM_SUBQ_S_W:
21171 check_dsp(ctx);
21172 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
21173 gen_store_gpr(v1_t, ret);
21174 break;
21175 case NM_ADDSC:
21176 check_dsp(ctx);
21177 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
21178 gen_store_gpr(v1_t, ret);
21179 break;
21180 case NM_ADDWC:
21181 check_dsp(ctx);
21182 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
21183 gen_store_gpr(v1_t, ret);
21184 break;
21185 case NM_ADDQ_S_PH:
21186 check_dsp(ctx);
21187 switch (extract32(ctx->opcode, 10, 1)) {
21188 case 0:
21189 /* ADDQ_PH */
21190 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
21191 gen_store_gpr(v1_t, ret);
21192 break;
21193 case 1:
21194 /* ADDQ_S_PH */
21195 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21196 gen_store_gpr(v1_t, ret);
21197 break;
21199 break;
21200 case NM_ADDQH_R_PH:
21201 check_dsp_r2(ctx);
21202 switch (extract32(ctx->opcode, 10, 1)) {
21203 case 0:
21204 /* ADDQH_PH */
21205 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
21206 gen_store_gpr(v1_t, ret);
21207 break;
21208 case 1:
21209 /* ADDQH_R_PH */
21210 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
21211 gen_store_gpr(v1_t, ret);
21212 break;
21214 break;
21215 case NM_ADDQH_R_W:
21216 check_dsp_r2(ctx);
21217 switch (extract32(ctx->opcode, 10, 1)) {
21218 case 0:
21219 /* ADDQH_W */
21220 gen_helper_addqh_w(v1_t, v1_t, v2_t);
21221 gen_store_gpr(v1_t, ret);
21222 break;
21223 case 1:
21224 /* ADDQH_R_W */
21225 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
21226 gen_store_gpr(v1_t, ret);
21227 break;
21229 break;
21230 case NM_ADDU_S_QB:
21231 check_dsp(ctx);
21232 switch (extract32(ctx->opcode, 10, 1)) {
21233 case 0:
21234 /* ADDU_QB */
21235 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
21236 gen_store_gpr(v1_t, ret);
21237 break;
21238 case 1:
21239 /* ADDU_S_QB */
21240 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21241 gen_store_gpr(v1_t, ret);
21242 break;
21244 break;
21245 case NM_ADDU_S_PH:
21246 check_dsp_r2(ctx);
21247 switch (extract32(ctx->opcode, 10, 1)) {
21248 case 0:
21249 /* ADDU_PH */
21250 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
21251 gen_store_gpr(v1_t, ret);
21252 break;
21253 case 1:
21254 /* ADDU_S_PH */
21255 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21256 gen_store_gpr(v1_t, ret);
21257 break;
21259 break;
21260 case NM_ADDUH_R_QB:
21261 check_dsp_r2(ctx);
21262 switch (extract32(ctx->opcode, 10, 1)) {
21263 case 0:
21264 /* ADDUH_QB */
21265 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
21266 gen_store_gpr(v1_t, ret);
21267 break;
21268 case 1:
21269 /* ADDUH_R_QB */
21270 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
21271 gen_store_gpr(v1_t, ret);
21272 break;
21274 break;
21275 case NM_SHRAV_R_PH:
21276 check_dsp(ctx);
21277 switch (extract32(ctx->opcode, 10, 1)) {
21278 case 0:
21279 /* SHRAV_PH */
21280 gen_helper_shra_ph(v1_t, v1_t, v2_t);
21281 gen_store_gpr(v1_t, ret);
21282 break;
21283 case 1:
21284 /* SHRAV_R_PH */
21285 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21286 gen_store_gpr(v1_t, ret);
21287 break;
21289 break;
21290 case NM_SHRAV_R_QB:
21291 check_dsp_r2(ctx);
21292 switch (extract32(ctx->opcode, 10, 1)) {
21293 case 0:
21294 /* SHRAV_QB */
21295 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21296 gen_store_gpr(v1_t, ret);
21297 break;
21298 case 1:
21299 /* SHRAV_R_QB */
21300 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21301 gen_store_gpr(v1_t, ret);
21302 break;
21304 break;
21305 case NM_SUBQ_S_PH:
21306 check_dsp(ctx);
21307 switch (extract32(ctx->opcode, 10, 1)) {
21308 case 0:
21309 /* SUBQ_PH */
21310 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21311 gen_store_gpr(v1_t, ret);
21312 break;
21313 case 1:
21314 /* SUBQ_S_PH */
21315 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21316 gen_store_gpr(v1_t, ret);
21317 break;
21319 break;
21320 case NM_SUBQH_R_PH:
21321 check_dsp_r2(ctx);
21322 switch (extract32(ctx->opcode, 10, 1)) {
21323 case 0:
21324 /* SUBQH_PH */
21325 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21326 gen_store_gpr(v1_t, ret);
21327 break;
21328 case 1:
21329 /* SUBQH_R_PH */
21330 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21331 gen_store_gpr(v1_t, ret);
21332 break;
21334 break;
21335 case NM_SUBQH_R_W:
21336 check_dsp_r2(ctx);
21337 switch (extract32(ctx->opcode, 10, 1)) {
21338 case 0:
21339 /* SUBQH_W */
21340 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21341 gen_store_gpr(v1_t, ret);
21342 break;
21343 case 1:
21344 /* SUBQH_R_W */
21345 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21346 gen_store_gpr(v1_t, ret);
21347 break;
21349 break;
21350 case NM_SUBU_S_QB:
21351 check_dsp(ctx);
21352 switch (extract32(ctx->opcode, 10, 1)) {
21353 case 0:
21354 /* SUBU_QB */
21355 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21356 gen_store_gpr(v1_t, ret);
21357 break;
21358 case 1:
21359 /* SUBU_S_QB */
21360 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21361 gen_store_gpr(v1_t, ret);
21362 break;
21364 break;
21365 case NM_SUBU_S_PH:
21366 check_dsp_r2(ctx);
21367 switch (extract32(ctx->opcode, 10, 1)) {
21368 case 0:
21369 /* SUBU_PH */
21370 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21371 gen_store_gpr(v1_t, ret);
21372 break;
21373 case 1:
21374 /* SUBU_S_PH */
21375 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21376 gen_store_gpr(v1_t, ret);
21377 break;
21379 break;
21380 case NM_SUBUH_R_QB:
21381 check_dsp_r2(ctx);
21382 switch (extract32(ctx->opcode, 10, 1)) {
21383 case 0:
21384 /* SUBUH_QB */
21385 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21386 gen_store_gpr(v1_t, ret);
21387 break;
21388 case 1:
21389 /* SUBUH_R_QB */
21390 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21391 gen_store_gpr(v1_t, ret);
21392 break;
21394 break;
21395 case NM_SHLLV_S_PH:
21396 check_dsp(ctx);
21397 switch (extract32(ctx->opcode, 10, 1)) {
21398 case 0:
21399 /* SHLLV_PH */
21400 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21401 gen_store_gpr(v1_t, ret);
21402 break;
21403 case 1:
21404 /* SHLLV_S_PH */
21405 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21406 gen_store_gpr(v1_t, ret);
21407 break;
21409 break;
21410 case NM_PRECR_SRA_R_PH_W:
21411 check_dsp_r2(ctx);
21412 switch (extract32(ctx->opcode, 10, 1)) {
21413 case 0:
21414 /* PRECR_SRA_PH_W */
21416 TCGv_i32 sa_t = tcg_const_i32(rd);
21417 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21418 cpu_gpr[rt]);
21419 gen_store_gpr(v1_t, rt);
21420 tcg_temp_free_i32(sa_t);
21422 break;
21423 case 1:
21424 /* PRECR_SRA_R_PH_W */
21426 TCGv_i32 sa_t = tcg_const_i32(rd);
21427 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21428 cpu_gpr[rt]);
21429 gen_store_gpr(v1_t, rt);
21430 tcg_temp_free_i32(sa_t);
21432 break;
21434 break;
21435 case NM_MULEU_S_PH_QBL:
21436 check_dsp(ctx);
21437 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21438 gen_store_gpr(v1_t, ret);
21439 break;
21440 case NM_MULEU_S_PH_QBR:
21441 check_dsp(ctx);
21442 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21443 gen_store_gpr(v1_t, ret);
21444 break;
21445 case NM_MULQ_RS_PH:
21446 check_dsp(ctx);
21447 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21448 gen_store_gpr(v1_t, ret);
21449 break;
21450 case NM_MULQ_S_PH:
21451 check_dsp_r2(ctx);
21452 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21453 gen_store_gpr(v1_t, ret);
21454 break;
21455 case NM_MULQ_RS_W:
21456 check_dsp_r2(ctx);
21457 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21458 gen_store_gpr(v1_t, ret);
21459 break;
21460 case NM_MULQ_S_W:
21461 check_dsp_r2(ctx);
21462 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21463 gen_store_gpr(v1_t, ret);
21464 break;
21465 case NM_APPEND:
21466 check_dsp_r2(ctx);
21467 gen_load_gpr(t0, rs);
21468 if (rd != 0) {
21469 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21471 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21472 break;
21473 case NM_MODSUB:
21474 check_dsp(ctx);
21475 gen_helper_modsub(v1_t, v1_t, v2_t);
21476 gen_store_gpr(v1_t, ret);
21477 break;
21478 case NM_SHRAV_R_W:
21479 check_dsp(ctx);
21480 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21481 gen_store_gpr(v1_t, ret);
21482 break;
21483 case NM_SHRLV_PH:
21484 check_dsp_r2(ctx);
21485 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21486 gen_store_gpr(v1_t, ret);
21487 break;
21488 case NM_SHRLV_QB:
21489 check_dsp(ctx);
21490 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21491 gen_store_gpr(v1_t, ret);
21492 break;
21493 case NM_SHLLV_QB:
21494 check_dsp(ctx);
21495 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21496 gen_store_gpr(v1_t, ret);
21497 break;
21498 case NM_SHLLV_S_W:
21499 check_dsp(ctx);
21500 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21501 gen_store_gpr(v1_t, ret);
21502 break;
21503 case NM_SHILO:
21504 check_dsp(ctx);
21506 TCGv tv0 = tcg_temp_new();
21507 TCGv tv1 = tcg_temp_new();
21508 int16_t imm = extract32(ctx->opcode, 16, 7);
21510 tcg_gen_movi_tl(tv0, rd >> 3);
21511 tcg_gen_movi_tl(tv1, imm);
21512 gen_helper_shilo(tv0, tv1, cpu_env);
21514 break;
21515 case NM_MULEQ_S_W_PHL:
21516 check_dsp(ctx);
21517 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21518 gen_store_gpr(v1_t, ret);
21519 break;
21520 case NM_MULEQ_S_W_PHR:
21521 check_dsp(ctx);
21522 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21523 gen_store_gpr(v1_t, ret);
21524 break;
21525 case NM_MUL_S_PH:
21526 check_dsp_r2(ctx);
21527 switch (extract32(ctx->opcode, 10, 1)) {
21528 case 0:
21529 /* MUL_PH */
21530 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21531 gen_store_gpr(v1_t, ret);
21532 break;
21533 case 1:
21534 /* MUL_S_PH */
21535 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21536 gen_store_gpr(v1_t, ret);
21537 break;
21539 break;
21540 case NM_PRECR_QB_PH:
21541 check_dsp_r2(ctx);
21542 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21543 gen_store_gpr(v1_t, ret);
21544 break;
21545 case NM_PRECRQ_QB_PH:
21546 check_dsp(ctx);
21547 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21548 gen_store_gpr(v1_t, ret);
21549 break;
21550 case NM_PRECRQ_PH_W:
21551 check_dsp(ctx);
21552 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21553 gen_store_gpr(v1_t, ret);
21554 break;
21555 case NM_PRECRQ_RS_PH_W:
21556 check_dsp(ctx);
21557 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21558 gen_store_gpr(v1_t, ret);
21559 break;
21560 case NM_PRECRQU_S_QB_PH:
21561 check_dsp(ctx);
21562 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21563 gen_store_gpr(v1_t, ret);
21564 break;
21565 case NM_SHRA_R_W:
21566 check_dsp(ctx);
21567 tcg_gen_movi_tl(t0, rd);
21568 gen_helper_shra_r_w(v1_t, t0, v1_t);
21569 gen_store_gpr(v1_t, rt);
21570 break;
21571 case NM_SHRA_R_PH:
21572 check_dsp(ctx);
21573 tcg_gen_movi_tl(t0, rd >> 1);
21574 switch (extract32(ctx->opcode, 10, 1)) {
21575 case 0:
21576 /* SHRA_PH */
21577 gen_helper_shra_ph(v1_t, t0, v1_t);
21578 gen_store_gpr(v1_t, rt);
21579 break;
21580 case 1:
21581 /* SHRA_R_PH */
21582 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21583 gen_store_gpr(v1_t, rt);
21584 break;
21586 break;
21587 case NM_SHLL_S_PH:
21588 check_dsp(ctx);
21589 tcg_gen_movi_tl(t0, rd >> 1);
21590 switch (extract32(ctx->opcode, 10, 2)) {
21591 case 0:
21592 /* SHLL_PH */
21593 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21594 gen_store_gpr(v1_t, rt);
21595 break;
21596 case 2:
21597 /* SHLL_S_PH */
21598 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21599 gen_store_gpr(v1_t, rt);
21600 break;
21601 default:
21602 gen_reserved_instruction(ctx);
21603 break;
21605 break;
21606 case NM_SHLL_S_W:
21607 check_dsp(ctx);
21608 tcg_gen_movi_tl(t0, rd);
21609 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21610 gen_store_gpr(v1_t, rt);
21611 break;
21612 case NM_REPL_PH:
21613 check_dsp(ctx);
21615 int16_t imm;
21616 imm = sextract32(ctx->opcode, 11, 11);
21617 imm = (int16_t)(imm << 6) >> 6;
21618 if (rt != 0) {
21619 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21622 break;
21623 default:
21624 gen_reserved_instruction(ctx);
21625 break;
21629 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21631 uint16_t insn;
21632 uint32_t op;
21633 int rt, rs, rd;
21634 int offset;
21635 int imm;
21637 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21638 ctx->opcode = (ctx->opcode << 16) | insn;
21640 rt = extract32(ctx->opcode, 21, 5);
21641 rs = extract32(ctx->opcode, 16, 5);
21642 rd = extract32(ctx->opcode, 11, 5);
21644 op = extract32(ctx->opcode, 26, 6);
21645 switch (op) {
21646 case NM_P_ADDIU:
21647 if (rt == 0) {
21648 /* P.RI */
21649 switch (extract32(ctx->opcode, 19, 2)) {
21650 case NM_SIGRIE:
21651 default:
21652 gen_reserved_instruction(ctx);
21653 break;
21654 case NM_P_SYSCALL:
21655 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21656 generate_exception_end(ctx, EXCP_SYSCALL);
21657 } else {
21658 gen_reserved_instruction(ctx);
21660 break;
21661 case NM_BREAK:
21662 generate_exception_end(ctx, EXCP_BREAK);
21663 break;
21664 case NM_SDBBP:
21665 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21666 gen_helper_do_semihosting(cpu_env);
21667 } else {
21668 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21669 gen_reserved_instruction(ctx);
21670 } else {
21671 generate_exception_end(ctx, EXCP_DBp);
21674 break;
21676 } else {
21677 /* NM_ADDIU */
21678 imm = extract32(ctx->opcode, 0, 16);
21679 if (rs != 0) {
21680 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21681 } else {
21682 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21684 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21686 break;
21687 case NM_ADDIUPC:
21688 if (rt != 0) {
21689 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21690 extract32(ctx->opcode, 1, 20) << 1;
21691 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21692 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21694 break;
21695 case NM_POOL32A:
21696 switch (ctx->opcode & 0x07) {
21697 case NM_POOL32A0:
21698 gen_pool32a0_nanomips_insn(env, ctx);
21699 break;
21700 case NM_POOL32A5:
21702 int32_t op1 = extract32(ctx->opcode, 3, 7);
21703 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21705 break;
21706 case NM_POOL32A7:
21707 switch (extract32(ctx->opcode, 3, 3)) {
21708 case NM_P_LSX:
21709 gen_p_lsx(ctx, rd, rs, rt);
21710 break;
21711 case NM_LSA:
21713 * In nanoMIPS, the shift field directly encodes the shift
21714 * amount, meaning that the supported shift values are in
21715 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21717 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21718 extract32(ctx->opcode, 9, 2) - 1);
21719 break;
21720 case NM_EXTW:
21721 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21722 break;
21723 case NM_POOL32AXF:
21724 gen_pool32axf_nanomips_insn(env, ctx);
21725 break;
21726 default:
21727 gen_reserved_instruction(ctx);
21728 break;
21730 break;
21731 default:
21732 gen_reserved_instruction(ctx);
21733 break;
21735 break;
21736 case NM_P_GP_W:
21737 switch (ctx->opcode & 0x03) {
21738 case NM_ADDIUGP_W:
21739 if (rt != 0) {
21740 offset = extract32(ctx->opcode, 0, 21);
21741 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21743 break;
21744 case NM_LWGP:
21745 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21746 break;
21747 case NM_SWGP:
21748 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21749 break;
21750 default:
21751 gen_reserved_instruction(ctx);
21752 break;
21754 break;
21755 case NM_P48I:
21757 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21758 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21759 switch (extract32(ctx->opcode, 16, 5)) {
21760 case NM_LI48:
21761 check_nms(ctx);
21762 if (rt != 0) {
21763 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21765 break;
21766 case NM_ADDIU48:
21767 check_nms(ctx);
21768 if (rt != 0) {
21769 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21770 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21772 break;
21773 case NM_ADDIUGP48:
21774 check_nms(ctx);
21775 if (rt != 0) {
21776 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21778 break;
21779 case NM_ADDIUPC48:
21780 check_nms(ctx);
21781 if (rt != 0) {
21782 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21783 addr_off);
21785 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21787 break;
21788 case NM_LWPC48:
21789 check_nms(ctx);
21790 if (rt != 0) {
21791 TCGv t0;
21792 t0 = tcg_temp_new();
21794 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21795 addr_off);
21797 tcg_gen_movi_tl(t0, addr);
21798 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21799 tcg_temp_free(t0);
21801 break;
21802 case NM_SWPC48:
21803 check_nms(ctx);
21805 TCGv t0, t1;
21806 t0 = tcg_temp_new();
21807 t1 = tcg_temp_new();
21809 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21810 addr_off);
21812 tcg_gen_movi_tl(t0, addr);
21813 gen_load_gpr(t1, rt);
21815 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21817 tcg_temp_free(t0);
21818 tcg_temp_free(t1);
21820 break;
21821 default:
21822 gen_reserved_instruction(ctx);
21823 break;
21825 return 6;
21827 case NM_P_U12:
21828 switch (extract32(ctx->opcode, 12, 4)) {
21829 case NM_ORI:
21830 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21831 break;
21832 case NM_XORI:
21833 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21834 break;
21835 case NM_ANDI:
21836 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21837 break;
21838 case NM_P_SR:
21839 switch (extract32(ctx->opcode, 20, 1)) {
21840 case NM_PP_SR:
21841 switch (ctx->opcode & 3) {
21842 case NM_SAVE:
21843 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21844 extract32(ctx->opcode, 2, 1),
21845 extract32(ctx->opcode, 3, 9) << 3);
21846 break;
21847 case NM_RESTORE:
21848 case NM_RESTORE_JRC:
21849 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21850 extract32(ctx->opcode, 2, 1),
21851 extract32(ctx->opcode, 3, 9) << 3);
21852 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21853 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21855 break;
21856 default:
21857 gen_reserved_instruction(ctx);
21858 break;
21860 break;
21861 case NM_P_SR_F:
21862 gen_reserved_instruction(ctx);
21863 break;
21865 break;
21866 case NM_SLTI:
21867 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21868 break;
21869 case NM_SLTIU:
21870 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21871 break;
21872 case NM_SEQI:
21874 TCGv t0 = tcg_temp_new();
21876 imm = extract32(ctx->opcode, 0, 12);
21877 gen_load_gpr(t0, rs);
21878 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
21879 gen_store_gpr(t0, rt);
21881 tcg_temp_free(t0);
21883 break;
21884 case NM_ADDIUNEG:
21885 imm = (int16_t) extract32(ctx->opcode, 0, 12);
21886 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
21887 break;
21888 case NM_P_SHIFT:
21890 int shift = extract32(ctx->opcode, 0, 5);
21891 switch (extract32(ctx->opcode, 5, 4)) {
21892 case NM_P_SLL:
21893 if (rt == 0 && shift == 0) {
21894 /* NOP */
21895 } else if (rt == 0 && shift == 3) {
21896 /* EHB - treat as NOP */
21897 } else if (rt == 0 && shift == 5) {
21898 /* PAUSE - treat as NOP */
21899 } else if (rt == 0 && shift == 6) {
21900 /* SYNC */
21901 gen_sync(extract32(ctx->opcode, 16, 5));
21902 } else {
21903 /* SLL */
21904 gen_shift_imm(ctx, OPC_SLL, rt, rs,
21905 extract32(ctx->opcode, 0, 5));
21907 break;
21908 case NM_SRL:
21909 gen_shift_imm(ctx, OPC_SRL, rt, rs,
21910 extract32(ctx->opcode, 0, 5));
21911 break;
21912 case NM_SRA:
21913 gen_shift_imm(ctx, OPC_SRA, rt, rs,
21914 extract32(ctx->opcode, 0, 5));
21915 break;
21916 case NM_ROTR:
21917 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
21918 extract32(ctx->opcode, 0, 5));
21919 break;
21922 break;
21923 case NM_P_ROTX:
21924 check_nms(ctx);
21925 if (rt != 0) {
21926 TCGv t0 = tcg_temp_new();
21927 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
21928 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
21929 << 1);
21930 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
21932 gen_load_gpr(t0, rs);
21933 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
21934 tcg_temp_free(t0);
21936 tcg_temp_free_i32(shift);
21937 tcg_temp_free_i32(shiftx);
21938 tcg_temp_free_i32(stripe);
21940 break;
21941 case NM_P_INS:
21942 switch (((ctx->opcode >> 10) & 2) |
21943 (extract32(ctx->opcode, 5, 1))) {
21944 case NM_INS:
21945 check_nms(ctx);
21946 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
21947 extract32(ctx->opcode, 6, 5));
21948 break;
21949 default:
21950 gen_reserved_instruction(ctx);
21951 break;
21953 break;
21954 case NM_P_EXT:
21955 switch (((ctx->opcode >> 10) & 2) |
21956 (extract32(ctx->opcode, 5, 1))) {
21957 case NM_EXT:
21958 check_nms(ctx);
21959 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
21960 extract32(ctx->opcode, 6, 5));
21961 break;
21962 default:
21963 gen_reserved_instruction(ctx);
21964 break;
21966 break;
21967 default:
21968 gen_reserved_instruction(ctx);
21969 break;
21971 break;
21972 case NM_POOL32F:
21973 gen_pool32f_nanomips_insn(ctx);
21974 break;
21975 case NM_POOL32S:
21976 break;
21977 case NM_P_LUI:
21978 switch (extract32(ctx->opcode, 1, 1)) {
21979 case NM_LUI:
21980 if (rt != 0) {
21981 tcg_gen_movi_tl(cpu_gpr[rt],
21982 sextract32(ctx->opcode, 0, 1) << 31 |
21983 extract32(ctx->opcode, 2, 10) << 21 |
21984 extract32(ctx->opcode, 12, 9) << 12);
21986 break;
21987 case NM_ALUIPC:
21988 if (rt != 0) {
21989 offset = sextract32(ctx->opcode, 0, 1) << 31 |
21990 extract32(ctx->opcode, 2, 10) << 21 |
21991 extract32(ctx->opcode, 12, 9) << 12;
21992 target_long addr;
21993 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
21994 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21996 break;
21998 break;
21999 case NM_P_GP_BH:
22001 uint32_t u = extract32(ctx->opcode, 0, 18);
22003 switch (extract32(ctx->opcode, 18, 3)) {
22004 case NM_LBGP:
22005 gen_ld(ctx, OPC_LB, rt, 28, u);
22006 break;
22007 case NM_SBGP:
22008 gen_st(ctx, OPC_SB, rt, 28, u);
22009 break;
22010 case NM_LBUGP:
22011 gen_ld(ctx, OPC_LBU, rt, 28, u);
22012 break;
22013 case NM_ADDIUGP_B:
22014 if (rt != 0) {
22015 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
22017 break;
22018 case NM_P_GP_LH:
22019 u &= ~1;
22020 switch (ctx->opcode & 1) {
22021 case NM_LHGP:
22022 gen_ld(ctx, OPC_LH, rt, 28, u);
22023 break;
22024 case NM_LHUGP:
22025 gen_ld(ctx, OPC_LHU, rt, 28, u);
22026 break;
22028 break;
22029 case NM_P_GP_SH:
22030 u &= ~1;
22031 switch (ctx->opcode & 1) {
22032 case NM_SHGP:
22033 gen_st(ctx, OPC_SH, rt, 28, u);
22034 break;
22035 default:
22036 gen_reserved_instruction(ctx);
22037 break;
22039 break;
22040 case NM_P_GP_CP1:
22041 u &= ~0x3;
22042 switch (ctx->opcode & 0x3) {
22043 case NM_LWC1GP:
22044 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
22045 break;
22046 case NM_LDC1GP:
22047 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
22048 break;
22049 case NM_SWC1GP:
22050 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
22051 break;
22052 case NM_SDC1GP:
22053 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
22054 break;
22056 break;
22057 default:
22058 gen_reserved_instruction(ctx);
22059 break;
22062 break;
22063 case NM_P_LS_U12:
22065 uint32_t u = extract32(ctx->opcode, 0, 12);
22067 switch (extract32(ctx->opcode, 12, 4)) {
22068 case NM_P_PREFU12:
22069 if (rt == 31) {
22070 /* SYNCI */
22072 * Break the TB to be able to sync copied instructions
22073 * immediately.
22075 ctx->base.is_jmp = DISAS_STOP;
22076 } else {
22077 /* PREF */
22078 /* Treat as NOP. */
22080 break;
22081 case NM_LB:
22082 gen_ld(ctx, OPC_LB, rt, rs, u);
22083 break;
22084 case NM_LH:
22085 gen_ld(ctx, OPC_LH, rt, rs, u);
22086 break;
22087 case NM_LW:
22088 gen_ld(ctx, OPC_LW, rt, rs, u);
22089 break;
22090 case NM_LBU:
22091 gen_ld(ctx, OPC_LBU, rt, rs, u);
22092 break;
22093 case NM_LHU:
22094 gen_ld(ctx, OPC_LHU, rt, rs, u);
22095 break;
22096 case NM_SB:
22097 gen_st(ctx, OPC_SB, rt, rs, u);
22098 break;
22099 case NM_SH:
22100 gen_st(ctx, OPC_SH, rt, rs, u);
22101 break;
22102 case NM_SW:
22103 gen_st(ctx, OPC_SW, rt, rs, u);
22104 break;
22105 case NM_LWC1:
22106 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
22107 break;
22108 case NM_LDC1:
22109 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
22110 break;
22111 case NM_SWC1:
22112 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
22113 break;
22114 case NM_SDC1:
22115 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
22116 break;
22117 default:
22118 gen_reserved_instruction(ctx);
22119 break;
22122 break;
22123 case NM_P_LS_S9:
22125 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
22126 extract32(ctx->opcode, 0, 8);
22128 switch (extract32(ctx->opcode, 8, 3)) {
22129 case NM_P_LS_S0:
22130 switch (extract32(ctx->opcode, 11, 4)) {
22131 case NM_LBS9:
22132 gen_ld(ctx, OPC_LB, rt, rs, s);
22133 break;
22134 case NM_LHS9:
22135 gen_ld(ctx, OPC_LH, rt, rs, s);
22136 break;
22137 case NM_LWS9:
22138 gen_ld(ctx, OPC_LW, rt, rs, s);
22139 break;
22140 case NM_LBUS9:
22141 gen_ld(ctx, OPC_LBU, rt, rs, s);
22142 break;
22143 case NM_LHUS9:
22144 gen_ld(ctx, OPC_LHU, rt, rs, s);
22145 break;
22146 case NM_SBS9:
22147 gen_st(ctx, OPC_SB, rt, rs, s);
22148 break;
22149 case NM_SHS9:
22150 gen_st(ctx, OPC_SH, rt, rs, s);
22151 break;
22152 case NM_SWS9:
22153 gen_st(ctx, OPC_SW, rt, rs, s);
22154 break;
22155 case NM_LWC1S9:
22156 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
22157 break;
22158 case NM_LDC1S9:
22159 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
22160 break;
22161 case NM_SWC1S9:
22162 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
22163 break;
22164 case NM_SDC1S9:
22165 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
22166 break;
22167 case NM_P_PREFS9:
22168 if (rt == 31) {
22169 /* SYNCI */
22171 * Break the TB to be able to sync copied instructions
22172 * immediately.
22174 ctx->base.is_jmp = DISAS_STOP;
22175 } else {
22176 /* PREF */
22177 /* Treat as NOP. */
22179 break;
22180 default:
22181 gen_reserved_instruction(ctx);
22182 break;
22184 break;
22185 case NM_P_LS_S1:
22186 switch (extract32(ctx->opcode, 11, 4)) {
22187 case NM_UALH:
22188 case NM_UASH:
22189 check_nms(ctx);
22191 TCGv t0 = tcg_temp_new();
22192 TCGv t1 = tcg_temp_new();
22194 gen_base_offset_addr(ctx, t0, rs, s);
22196 switch (extract32(ctx->opcode, 11, 4)) {
22197 case NM_UALH:
22198 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
22199 MO_UNALN);
22200 gen_store_gpr(t0, rt);
22201 break;
22202 case NM_UASH:
22203 gen_load_gpr(t1, rt);
22204 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
22205 MO_UNALN);
22206 break;
22208 tcg_temp_free(t0);
22209 tcg_temp_free(t1);
22211 break;
22212 case NM_P_LL:
22213 switch (ctx->opcode & 0x03) {
22214 case NM_LL:
22215 gen_ld(ctx, OPC_LL, rt, rs, s);
22216 break;
22217 case NM_LLWP:
22218 check_xnp(ctx);
22219 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22220 break;
22222 break;
22223 case NM_P_SC:
22224 switch (ctx->opcode & 0x03) {
22225 case NM_SC:
22226 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
22227 break;
22228 case NM_SCWP:
22229 check_xnp(ctx);
22230 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22231 false);
22232 break;
22234 break;
22235 case NM_CACHE:
22236 check_cp0_enabled(ctx);
22237 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22238 gen_cache_operation(ctx, rt, rs, s);
22240 break;
22242 break;
22243 case NM_P_LS_E0:
22244 switch (extract32(ctx->opcode, 11, 4)) {
22245 case NM_LBE:
22246 check_eva(ctx);
22247 check_cp0_enabled(ctx);
22248 gen_ld(ctx, OPC_LBE, rt, rs, s);
22249 break;
22250 case NM_SBE:
22251 check_eva(ctx);
22252 check_cp0_enabled(ctx);
22253 gen_st(ctx, OPC_SBE, rt, rs, s);
22254 break;
22255 case NM_LBUE:
22256 check_eva(ctx);
22257 check_cp0_enabled(ctx);
22258 gen_ld(ctx, OPC_LBUE, rt, rs, s);
22259 break;
22260 case NM_P_PREFE:
22261 if (rt == 31) {
22262 /* case NM_SYNCIE */
22263 check_eva(ctx);
22264 check_cp0_enabled(ctx);
22266 * Break the TB to be able to sync copied instructions
22267 * immediately.
22269 ctx->base.is_jmp = DISAS_STOP;
22270 } else {
22271 /* case NM_PREFE */
22272 check_eva(ctx);
22273 check_cp0_enabled(ctx);
22274 /* Treat as NOP. */
22276 break;
22277 case NM_LHE:
22278 check_eva(ctx);
22279 check_cp0_enabled(ctx);
22280 gen_ld(ctx, OPC_LHE, rt, rs, s);
22281 break;
22282 case NM_SHE:
22283 check_eva(ctx);
22284 check_cp0_enabled(ctx);
22285 gen_st(ctx, OPC_SHE, rt, rs, s);
22286 break;
22287 case NM_LHUE:
22288 check_eva(ctx);
22289 check_cp0_enabled(ctx);
22290 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22291 break;
22292 case NM_CACHEE:
22293 check_nms_dl_il_sl_tl_l2c(ctx);
22294 gen_cache_operation(ctx, rt, rs, s);
22295 break;
22296 case NM_LWE:
22297 check_eva(ctx);
22298 check_cp0_enabled(ctx);
22299 gen_ld(ctx, OPC_LWE, rt, rs, s);
22300 break;
22301 case NM_SWE:
22302 check_eva(ctx);
22303 check_cp0_enabled(ctx);
22304 gen_st(ctx, OPC_SWE, rt, rs, s);
22305 break;
22306 case NM_P_LLE:
22307 switch (extract32(ctx->opcode, 2, 2)) {
22308 case NM_LLE:
22309 check_xnp(ctx);
22310 check_eva(ctx);
22311 check_cp0_enabled(ctx);
22312 gen_ld(ctx, OPC_LLE, rt, rs, s);
22313 break;
22314 case NM_LLWPE:
22315 check_xnp(ctx);
22316 check_eva(ctx);
22317 check_cp0_enabled(ctx);
22318 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22319 break;
22320 default:
22321 gen_reserved_instruction(ctx);
22322 break;
22324 break;
22325 case NM_P_SCE:
22326 switch (extract32(ctx->opcode, 2, 2)) {
22327 case NM_SCE:
22328 check_xnp(ctx);
22329 check_eva(ctx);
22330 check_cp0_enabled(ctx);
22331 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22332 break;
22333 case NM_SCWPE:
22334 check_xnp(ctx);
22335 check_eva(ctx);
22336 check_cp0_enabled(ctx);
22337 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22338 true);
22339 break;
22340 default:
22341 gen_reserved_instruction(ctx);
22342 break;
22344 break;
22346 break;
22347 case NM_P_LS_WM:
22348 case NM_P_LS_UAWM:
22349 check_nms(ctx);
22351 int count = extract32(ctx->opcode, 12, 3);
22352 int counter = 0;
22354 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22355 extract32(ctx->opcode, 0, 8);
22356 TCGv va = tcg_temp_new();
22357 TCGv t1 = tcg_temp_new();
22358 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22359 NM_P_LS_UAWM ? MO_UNALN : 0;
22361 count = (count == 0) ? 8 : count;
22362 while (counter != count) {
22363 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22364 int this_offset = offset + (counter << 2);
22366 gen_base_offset_addr(ctx, va, rs, this_offset);
22368 switch (extract32(ctx->opcode, 11, 1)) {
22369 case NM_LWM:
22370 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22371 memop | MO_TESL);
22372 gen_store_gpr(t1, this_rt);
22373 if ((this_rt == rs) &&
22374 (counter != (count - 1))) {
22375 /* UNPREDICTABLE */
22377 break;
22378 case NM_SWM:
22379 this_rt = (rt == 0) ? 0 : this_rt;
22380 gen_load_gpr(t1, this_rt);
22381 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22382 memop | MO_TEUL);
22383 break;
22385 counter++;
22387 tcg_temp_free(va);
22388 tcg_temp_free(t1);
22390 break;
22391 default:
22392 gen_reserved_instruction(ctx);
22393 break;
22396 break;
22397 case NM_MOVE_BALC:
22398 check_nms(ctx);
22400 TCGv t0 = tcg_temp_new();
22401 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22402 extract32(ctx->opcode, 1, 20) << 1;
22403 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22404 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22405 extract32(ctx->opcode, 21, 3));
22406 gen_load_gpr(t0, rt);
22407 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22408 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22409 tcg_temp_free(t0);
22411 break;
22412 case NM_P_BAL:
22414 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22415 extract32(ctx->opcode, 1, 24) << 1;
22417 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22418 /* BC */
22419 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22420 } else {
22421 /* BALC */
22422 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22425 break;
22426 case NM_P_J:
22427 switch (extract32(ctx->opcode, 12, 4)) {
22428 case NM_JALRC:
22429 case NM_JALRC_HB:
22430 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22431 break;
22432 case NM_P_BALRSC:
22433 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22434 break;
22435 default:
22436 gen_reserved_instruction(ctx);
22437 break;
22439 break;
22440 case NM_P_BR1:
22442 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22443 extract32(ctx->opcode, 1, 13) << 1;
22444 switch (extract32(ctx->opcode, 14, 2)) {
22445 case NM_BEQC:
22446 check_nms(ctx);
22447 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22448 break;
22449 case NM_P_BR3A:
22450 s = sextract32(ctx->opcode, 0, 1) << 14 |
22451 extract32(ctx->opcode, 1, 13) << 1;
22452 check_cp1_enabled(ctx);
22453 switch (extract32(ctx->opcode, 16, 5)) {
22454 case NM_BC1EQZC:
22455 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22456 break;
22457 case NM_BC1NEZC:
22458 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22459 break;
22460 case NM_BPOSGE32C:
22461 check_dsp_r3(ctx);
22463 int32_t imm = extract32(ctx->opcode, 1, 13) |
22464 extract32(ctx->opcode, 0, 1) << 13;
22466 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22467 imm);
22469 break;
22470 default:
22471 gen_reserved_instruction(ctx);
22472 break;
22474 break;
22475 case NM_BGEC:
22476 if (rs == rt) {
22477 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22478 } else {
22479 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22481 break;
22482 case NM_BGEUC:
22483 if (rs == rt || rt == 0) {
22484 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22485 } else if (rs == 0) {
22486 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22487 } else {
22488 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22490 break;
22493 break;
22494 case NM_P_BR2:
22496 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22497 extract32(ctx->opcode, 1, 13) << 1;
22498 switch (extract32(ctx->opcode, 14, 2)) {
22499 case NM_BNEC:
22500 check_nms(ctx);
22501 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22502 break;
22503 case NM_BLTC:
22504 if (rs != 0 && rt != 0 && rs == rt) {
22505 /* NOP */
22506 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22507 } else {
22508 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22510 break;
22511 case NM_BLTUC:
22512 if (rs == 0 || rs == rt) {
22513 /* NOP */
22514 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22515 } else {
22516 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22518 break;
22519 default:
22520 gen_reserved_instruction(ctx);
22521 break;
22524 break;
22525 case NM_P_BRI:
22527 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22528 extract32(ctx->opcode, 1, 10) << 1;
22529 uint32_t u = extract32(ctx->opcode, 11, 7);
22531 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22532 rt, u, s);
22534 break;
22535 default:
22536 gen_reserved_instruction(ctx);
22537 break;
22539 return 4;
22542 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22544 uint32_t op;
22545 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22546 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22547 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22548 int offset;
22549 int imm;
22551 /* make sure instructions are on a halfword boundary */
22552 if (ctx->base.pc_next & 0x1) {
22553 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22554 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22555 tcg_temp_free(tmp);
22556 generate_exception_end(ctx, EXCP_AdEL);
22557 return 2;
22560 op = extract32(ctx->opcode, 10, 6);
22561 switch (op) {
22562 case NM_P16_MV:
22563 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22564 if (rt != 0) {
22565 /* MOVE */
22566 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22567 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22568 } else {
22569 /* P16.RI */
22570 switch (extract32(ctx->opcode, 3, 2)) {
22571 case NM_P16_SYSCALL:
22572 if (extract32(ctx->opcode, 2, 1) == 0) {
22573 generate_exception_end(ctx, EXCP_SYSCALL);
22574 } else {
22575 gen_reserved_instruction(ctx);
22577 break;
22578 case NM_BREAK16:
22579 generate_exception_end(ctx, EXCP_BREAK);
22580 break;
22581 case NM_SDBBP16:
22582 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22583 gen_helper_do_semihosting(cpu_env);
22584 } else {
22585 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22586 gen_reserved_instruction(ctx);
22587 } else {
22588 generate_exception_end(ctx, EXCP_DBp);
22591 break;
22592 default:
22593 gen_reserved_instruction(ctx);
22594 break;
22597 break;
22598 case NM_P16_SHIFT:
22600 int shift = extract32(ctx->opcode, 0, 3);
22601 uint32_t opc = 0;
22602 shift = (shift == 0) ? 8 : shift;
22604 switch (extract32(ctx->opcode, 3, 1)) {
22605 case NM_SLL16:
22606 opc = OPC_SLL;
22607 break;
22608 case NM_SRL16:
22609 opc = OPC_SRL;
22610 break;
22612 gen_shift_imm(ctx, opc, rt, rs, shift);
22614 break;
22615 case NM_P16C:
22616 switch (ctx->opcode & 1) {
22617 case NM_POOL16C_0:
22618 gen_pool16c_nanomips_insn(ctx);
22619 break;
22620 case NM_LWXS16:
22621 gen_ldxs(ctx, rt, rs, rd);
22622 break;
22624 break;
22625 case NM_P16_A1:
22626 switch (extract32(ctx->opcode, 6, 1)) {
22627 case NM_ADDIUR1SP:
22628 imm = extract32(ctx->opcode, 0, 6) << 2;
22629 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22630 break;
22631 default:
22632 gen_reserved_instruction(ctx);
22633 break;
22635 break;
22636 case NM_P16_A2:
22637 switch (extract32(ctx->opcode, 3, 1)) {
22638 case NM_ADDIUR2:
22639 imm = extract32(ctx->opcode, 0, 3) << 2;
22640 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22641 break;
22642 case NM_P_ADDIURS5:
22643 rt = extract32(ctx->opcode, 5, 5);
22644 if (rt != 0) {
22645 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22646 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22647 (extract32(ctx->opcode, 0, 3));
22648 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22650 break;
22652 break;
22653 case NM_P16_ADDU:
22654 switch (ctx->opcode & 0x1) {
22655 case NM_ADDU16:
22656 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22657 break;
22658 case NM_SUBU16:
22659 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22660 break;
22662 break;
22663 case NM_P16_4X4:
22664 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22665 extract32(ctx->opcode, 5, 3);
22666 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22667 extract32(ctx->opcode, 0, 3);
22668 rt = decode_gpr_gpr4(rt);
22669 rs = decode_gpr_gpr4(rs);
22670 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22671 (extract32(ctx->opcode, 3, 1))) {
22672 case NM_ADDU4X4:
22673 check_nms(ctx);
22674 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22675 break;
22676 case NM_MUL4X4:
22677 check_nms(ctx);
22678 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22679 break;
22680 default:
22681 gen_reserved_instruction(ctx);
22682 break;
22684 break;
22685 case NM_LI16:
22687 int imm = extract32(ctx->opcode, 0, 7);
22688 imm = (imm == 0x7f ? -1 : imm);
22689 if (rt != 0) {
22690 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22693 break;
22694 case NM_ANDI16:
22696 uint32_t u = extract32(ctx->opcode, 0, 4);
22697 u = (u == 12) ? 0xff :
22698 (u == 13) ? 0xffff : u;
22699 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22701 break;
22702 case NM_P16_LB:
22703 offset = extract32(ctx->opcode, 0, 2);
22704 switch (extract32(ctx->opcode, 2, 2)) {
22705 case NM_LB16:
22706 gen_ld(ctx, OPC_LB, rt, rs, offset);
22707 break;
22708 case NM_SB16:
22709 rt = decode_gpr_gpr3_src_store(
22710 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22711 gen_st(ctx, OPC_SB, rt, rs, offset);
22712 break;
22713 case NM_LBU16:
22714 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22715 break;
22716 default:
22717 gen_reserved_instruction(ctx);
22718 break;
22720 break;
22721 case NM_P16_LH:
22722 offset = extract32(ctx->opcode, 1, 2) << 1;
22723 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22724 case NM_LH16:
22725 gen_ld(ctx, OPC_LH, rt, rs, offset);
22726 break;
22727 case NM_SH16:
22728 rt = decode_gpr_gpr3_src_store(
22729 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22730 gen_st(ctx, OPC_SH, rt, rs, offset);
22731 break;
22732 case NM_LHU16:
22733 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22734 break;
22735 default:
22736 gen_reserved_instruction(ctx);
22737 break;
22739 break;
22740 case NM_LW16:
22741 offset = extract32(ctx->opcode, 0, 4) << 2;
22742 gen_ld(ctx, OPC_LW, rt, rs, offset);
22743 break;
22744 case NM_LWSP16:
22745 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22746 offset = extract32(ctx->opcode, 0, 5) << 2;
22747 gen_ld(ctx, OPC_LW, rt, 29, offset);
22748 break;
22749 case NM_LW4X4:
22750 check_nms(ctx);
22751 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22752 extract32(ctx->opcode, 5, 3);
22753 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22754 extract32(ctx->opcode, 0, 3);
22755 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22756 (extract32(ctx->opcode, 8, 1) << 2);
22757 rt = decode_gpr_gpr4(rt);
22758 rs = decode_gpr_gpr4(rs);
22759 gen_ld(ctx, OPC_LW, rt, rs, offset);
22760 break;
22761 case NM_SW4X4:
22762 check_nms(ctx);
22763 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22764 extract32(ctx->opcode, 5, 3);
22765 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22766 extract32(ctx->opcode, 0, 3);
22767 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22768 (extract32(ctx->opcode, 8, 1) << 2);
22769 rt = decode_gpr_gpr4_zero(rt);
22770 rs = decode_gpr_gpr4(rs);
22771 gen_st(ctx, OPC_SW, rt, rs, offset);
22772 break;
22773 case NM_LWGP16:
22774 offset = extract32(ctx->opcode, 0, 7) << 2;
22775 gen_ld(ctx, OPC_LW, rt, 28, offset);
22776 break;
22777 case NM_SWSP16:
22778 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22779 offset = extract32(ctx->opcode, 0, 5) << 2;
22780 gen_st(ctx, OPC_SW, rt, 29, offset);
22781 break;
22782 case NM_SW16:
22783 rt = decode_gpr_gpr3_src_store(
22784 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22785 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22786 offset = extract32(ctx->opcode, 0, 4) << 2;
22787 gen_st(ctx, OPC_SW, rt, rs, offset);
22788 break;
22789 case NM_SWGP16:
22790 rt = decode_gpr_gpr3_src_store(
22791 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22792 offset = extract32(ctx->opcode, 0, 7) << 2;
22793 gen_st(ctx, OPC_SW, rt, 28, offset);
22794 break;
22795 case NM_BC16:
22796 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22797 (sextract32(ctx->opcode, 0, 1) << 10) |
22798 (extract32(ctx->opcode, 1, 9) << 1));
22799 break;
22800 case NM_BALC16:
22801 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22802 (sextract32(ctx->opcode, 0, 1) << 10) |
22803 (extract32(ctx->opcode, 1, 9) << 1));
22804 break;
22805 case NM_BEQZC16:
22806 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22807 (sextract32(ctx->opcode, 0, 1) << 7) |
22808 (extract32(ctx->opcode, 1, 6) << 1));
22809 break;
22810 case NM_BNEZC16:
22811 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22812 (sextract32(ctx->opcode, 0, 1) << 7) |
22813 (extract32(ctx->opcode, 1, 6) << 1));
22814 break;
22815 case NM_P16_BR:
22816 switch (ctx->opcode & 0xf) {
22817 case 0:
22818 /* P16.JRC */
22819 switch (extract32(ctx->opcode, 4, 1)) {
22820 case NM_JRC:
22821 gen_compute_branch_nm(ctx, OPC_JR, 2,
22822 extract32(ctx->opcode, 5, 5), 0, 0);
22823 break;
22824 case NM_JALRC16:
22825 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22826 extract32(ctx->opcode, 5, 5), 31, 0);
22827 break;
22829 break;
22830 default:
22832 /* P16.BRI */
22833 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22834 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22835 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22836 extract32(ctx->opcode, 0, 4) << 1);
22838 break;
22840 break;
22841 case NM_P16_SR:
22843 int count = extract32(ctx->opcode, 0, 4);
22844 int u = extract32(ctx->opcode, 4, 4) << 4;
22846 rt = 30 + extract32(ctx->opcode, 9, 1);
22847 switch (extract32(ctx->opcode, 8, 1)) {
22848 case NM_SAVE16:
22849 gen_save(ctx, rt, count, 0, u);
22850 break;
22851 case NM_RESTORE_JRC16:
22852 gen_restore(ctx, rt, count, 0, u);
22853 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22854 break;
22857 break;
22858 case NM_MOVEP:
22859 case NM_MOVEPREV:
22860 check_nms(ctx);
22862 static const int gpr2reg1[] = {4, 5, 6, 7};
22863 static const int gpr2reg2[] = {5, 6, 7, 8};
22864 int re;
22865 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22866 extract32(ctx->opcode, 8, 1);
22867 int r1 = gpr2reg1[rd2];
22868 int r2 = gpr2reg2[rd2];
22869 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22870 extract32(ctx->opcode, 0, 3);
22871 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22872 extract32(ctx->opcode, 5, 3);
22873 TCGv t0 = tcg_temp_new();
22874 TCGv t1 = tcg_temp_new();
22875 if (op == NM_MOVEP) {
22876 rd = r1;
22877 re = r2;
22878 rs = decode_gpr_gpr4_zero(r3);
22879 rt = decode_gpr_gpr4_zero(r4);
22880 } else {
22881 rd = decode_gpr_gpr4(r3);
22882 re = decode_gpr_gpr4(r4);
22883 rs = r1;
22884 rt = r2;
22886 gen_load_gpr(t0, rs);
22887 gen_load_gpr(t1, rt);
22888 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22889 tcg_gen_mov_tl(cpu_gpr[re], t1);
22890 tcg_temp_free(t0);
22891 tcg_temp_free(t1);
22893 break;
22894 default:
22895 return decode_nanomips_32_48_opc(env, ctx);
22898 return 2;
22902 /* SmartMIPS extension to MIPS32 */
22904 #if defined(TARGET_MIPS64)
22906 /* MDMX extension to MIPS64 */
22908 #endif
22910 /* MIPSDSP functions. */
22911 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
22912 int rd, int base, int offset)
22914 TCGv t0;
22916 check_dsp(ctx);
22917 t0 = tcg_temp_new();
22919 if (base == 0) {
22920 gen_load_gpr(t0, offset);
22921 } else if (offset == 0) {
22922 gen_load_gpr(t0, base);
22923 } else {
22924 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
22927 switch (opc) {
22928 case OPC_LBUX:
22929 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
22930 gen_store_gpr(t0, rd);
22931 break;
22932 case OPC_LHX:
22933 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
22934 gen_store_gpr(t0, rd);
22935 break;
22936 case OPC_LWX:
22937 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
22938 gen_store_gpr(t0, rd);
22939 break;
22940 #if defined(TARGET_MIPS64)
22941 case OPC_LDX:
22942 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
22943 gen_store_gpr(t0, rd);
22944 break;
22945 #endif
22947 tcg_temp_free(t0);
22950 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
22951 int ret, int v1, int v2)
22953 TCGv v1_t;
22954 TCGv v2_t;
22956 if (ret == 0) {
22957 /* Treat as NOP. */
22958 return;
22961 v1_t = tcg_temp_new();
22962 v2_t = tcg_temp_new();
22964 gen_load_gpr(v1_t, v1);
22965 gen_load_gpr(v2_t, v2);
22967 switch (op1) {
22968 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
22969 case OPC_MULT_G_2E:
22970 check_dsp_r2(ctx);
22971 switch (op2) {
22972 case OPC_ADDUH_QB:
22973 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
22974 break;
22975 case OPC_ADDUH_R_QB:
22976 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22977 break;
22978 case OPC_ADDQH_PH:
22979 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
22980 break;
22981 case OPC_ADDQH_R_PH:
22982 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
22983 break;
22984 case OPC_ADDQH_W:
22985 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
22986 break;
22987 case OPC_ADDQH_R_W:
22988 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
22989 break;
22990 case OPC_SUBUH_QB:
22991 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
22992 break;
22993 case OPC_SUBUH_R_QB:
22994 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
22995 break;
22996 case OPC_SUBQH_PH:
22997 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
22998 break;
22999 case OPC_SUBQH_R_PH:
23000 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23001 break;
23002 case OPC_SUBQH_W:
23003 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
23004 break;
23005 case OPC_SUBQH_R_W:
23006 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23007 break;
23009 break;
23010 case OPC_ABSQ_S_PH_DSP:
23011 switch (op2) {
23012 case OPC_ABSQ_S_QB:
23013 check_dsp_r2(ctx);
23014 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
23015 break;
23016 case OPC_ABSQ_S_PH:
23017 check_dsp(ctx);
23018 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
23019 break;
23020 case OPC_ABSQ_S_W:
23021 check_dsp(ctx);
23022 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
23023 break;
23024 case OPC_PRECEQ_W_PHL:
23025 check_dsp(ctx);
23026 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
23027 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23028 break;
23029 case OPC_PRECEQ_W_PHR:
23030 check_dsp(ctx);
23031 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
23032 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
23033 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23034 break;
23035 case OPC_PRECEQU_PH_QBL:
23036 check_dsp(ctx);
23037 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
23038 break;
23039 case OPC_PRECEQU_PH_QBR:
23040 check_dsp(ctx);
23041 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
23042 break;
23043 case OPC_PRECEQU_PH_QBLA:
23044 check_dsp(ctx);
23045 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
23046 break;
23047 case OPC_PRECEQU_PH_QBRA:
23048 check_dsp(ctx);
23049 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
23050 break;
23051 case OPC_PRECEU_PH_QBL:
23052 check_dsp(ctx);
23053 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
23054 break;
23055 case OPC_PRECEU_PH_QBR:
23056 check_dsp(ctx);
23057 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
23058 break;
23059 case OPC_PRECEU_PH_QBLA:
23060 check_dsp(ctx);
23061 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
23062 break;
23063 case OPC_PRECEU_PH_QBRA:
23064 check_dsp(ctx);
23065 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
23066 break;
23068 break;
23069 case OPC_ADDU_QB_DSP:
23070 switch (op2) {
23071 case OPC_ADDQ_PH:
23072 check_dsp(ctx);
23073 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23074 break;
23075 case OPC_ADDQ_S_PH:
23076 check_dsp(ctx);
23077 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23078 break;
23079 case OPC_ADDQ_S_W:
23080 check_dsp(ctx);
23081 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23082 break;
23083 case OPC_ADDU_QB:
23084 check_dsp(ctx);
23085 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23086 break;
23087 case OPC_ADDU_S_QB:
23088 check_dsp(ctx);
23089 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23090 break;
23091 case OPC_ADDU_PH:
23092 check_dsp_r2(ctx);
23093 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23094 break;
23095 case OPC_ADDU_S_PH:
23096 check_dsp_r2(ctx);
23097 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23098 break;
23099 case OPC_SUBQ_PH:
23100 check_dsp(ctx);
23101 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23102 break;
23103 case OPC_SUBQ_S_PH:
23104 check_dsp(ctx);
23105 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23106 break;
23107 case OPC_SUBQ_S_W:
23108 check_dsp(ctx);
23109 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23110 break;
23111 case OPC_SUBU_QB:
23112 check_dsp(ctx);
23113 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23114 break;
23115 case OPC_SUBU_S_QB:
23116 check_dsp(ctx);
23117 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23118 break;
23119 case OPC_SUBU_PH:
23120 check_dsp_r2(ctx);
23121 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23122 break;
23123 case OPC_SUBU_S_PH:
23124 check_dsp_r2(ctx);
23125 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23126 break;
23127 case OPC_ADDSC:
23128 check_dsp(ctx);
23129 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23130 break;
23131 case OPC_ADDWC:
23132 check_dsp(ctx);
23133 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23134 break;
23135 case OPC_MODSUB:
23136 check_dsp(ctx);
23137 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
23138 break;
23139 case OPC_RADDU_W_QB:
23140 check_dsp(ctx);
23141 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
23142 break;
23144 break;
23145 case OPC_CMPU_EQ_QB_DSP:
23146 switch (op2) {
23147 case OPC_PRECR_QB_PH:
23148 check_dsp_r2(ctx);
23149 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23150 break;
23151 case OPC_PRECRQ_QB_PH:
23152 check_dsp(ctx);
23153 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23154 break;
23155 case OPC_PRECR_SRA_PH_W:
23156 check_dsp_r2(ctx);
23158 TCGv_i32 sa_t = tcg_const_i32(v2);
23159 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
23160 cpu_gpr[ret]);
23161 tcg_temp_free_i32(sa_t);
23162 break;
23164 case OPC_PRECR_SRA_R_PH_W:
23165 check_dsp_r2(ctx);
23167 TCGv_i32 sa_t = tcg_const_i32(v2);
23168 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
23169 cpu_gpr[ret]);
23170 tcg_temp_free_i32(sa_t);
23171 break;
23173 case OPC_PRECRQ_PH_W:
23174 check_dsp(ctx);
23175 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
23176 break;
23177 case OPC_PRECRQ_RS_PH_W:
23178 check_dsp(ctx);
23179 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23180 break;
23181 case OPC_PRECRQU_S_QB_PH:
23182 check_dsp(ctx);
23183 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23184 break;
23186 break;
23187 #ifdef TARGET_MIPS64
23188 case OPC_ABSQ_S_QH_DSP:
23189 switch (op2) {
23190 case OPC_PRECEQ_L_PWL:
23191 check_dsp(ctx);
23192 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
23193 break;
23194 case OPC_PRECEQ_L_PWR:
23195 check_dsp(ctx);
23196 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
23197 break;
23198 case OPC_PRECEQ_PW_QHL:
23199 check_dsp(ctx);
23200 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
23201 break;
23202 case OPC_PRECEQ_PW_QHR:
23203 check_dsp(ctx);
23204 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
23205 break;
23206 case OPC_PRECEQ_PW_QHLA:
23207 check_dsp(ctx);
23208 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
23209 break;
23210 case OPC_PRECEQ_PW_QHRA:
23211 check_dsp(ctx);
23212 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
23213 break;
23214 case OPC_PRECEQU_QH_OBL:
23215 check_dsp(ctx);
23216 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
23217 break;
23218 case OPC_PRECEQU_QH_OBR:
23219 check_dsp(ctx);
23220 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
23221 break;
23222 case OPC_PRECEQU_QH_OBLA:
23223 check_dsp(ctx);
23224 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
23225 break;
23226 case OPC_PRECEQU_QH_OBRA:
23227 check_dsp(ctx);
23228 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
23229 break;
23230 case OPC_PRECEU_QH_OBL:
23231 check_dsp(ctx);
23232 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
23233 break;
23234 case OPC_PRECEU_QH_OBR:
23235 check_dsp(ctx);
23236 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
23237 break;
23238 case OPC_PRECEU_QH_OBLA:
23239 check_dsp(ctx);
23240 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
23241 break;
23242 case OPC_PRECEU_QH_OBRA:
23243 check_dsp(ctx);
23244 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
23245 break;
23246 case OPC_ABSQ_S_OB:
23247 check_dsp_r2(ctx);
23248 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
23249 break;
23250 case OPC_ABSQ_S_PW:
23251 check_dsp(ctx);
23252 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
23253 break;
23254 case OPC_ABSQ_S_QH:
23255 check_dsp(ctx);
23256 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
23257 break;
23259 break;
23260 case OPC_ADDU_OB_DSP:
23261 switch (op2) {
23262 case OPC_RADDU_L_OB:
23263 check_dsp(ctx);
23264 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
23265 break;
23266 case OPC_SUBQ_PW:
23267 check_dsp(ctx);
23268 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23269 break;
23270 case OPC_SUBQ_S_PW:
23271 check_dsp(ctx);
23272 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23273 break;
23274 case OPC_SUBQ_QH:
23275 check_dsp(ctx);
23276 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23277 break;
23278 case OPC_SUBQ_S_QH:
23279 check_dsp(ctx);
23280 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23281 break;
23282 case OPC_SUBU_OB:
23283 check_dsp(ctx);
23284 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23285 break;
23286 case OPC_SUBU_S_OB:
23287 check_dsp(ctx);
23288 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23289 break;
23290 case OPC_SUBU_QH:
23291 check_dsp_r2(ctx);
23292 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23293 break;
23294 case OPC_SUBU_S_QH:
23295 check_dsp_r2(ctx);
23296 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23297 break;
23298 case OPC_SUBUH_OB:
23299 check_dsp_r2(ctx);
23300 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23301 break;
23302 case OPC_SUBUH_R_OB:
23303 check_dsp_r2(ctx);
23304 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23305 break;
23306 case OPC_ADDQ_PW:
23307 check_dsp(ctx);
23308 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23309 break;
23310 case OPC_ADDQ_S_PW:
23311 check_dsp(ctx);
23312 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23313 break;
23314 case OPC_ADDQ_QH:
23315 check_dsp(ctx);
23316 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23317 break;
23318 case OPC_ADDQ_S_QH:
23319 check_dsp(ctx);
23320 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23321 break;
23322 case OPC_ADDU_OB:
23323 check_dsp(ctx);
23324 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23325 break;
23326 case OPC_ADDU_S_OB:
23327 check_dsp(ctx);
23328 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23329 break;
23330 case OPC_ADDU_QH:
23331 check_dsp_r2(ctx);
23332 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23333 break;
23334 case OPC_ADDU_S_QH:
23335 check_dsp_r2(ctx);
23336 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23337 break;
23338 case OPC_ADDUH_OB:
23339 check_dsp_r2(ctx);
23340 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23341 break;
23342 case OPC_ADDUH_R_OB:
23343 check_dsp_r2(ctx);
23344 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23345 break;
23347 break;
23348 case OPC_CMPU_EQ_OB_DSP:
23349 switch (op2) {
23350 case OPC_PRECR_OB_QH:
23351 check_dsp_r2(ctx);
23352 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23353 break;
23354 case OPC_PRECR_SRA_QH_PW:
23355 check_dsp_r2(ctx);
23357 TCGv_i32 ret_t = tcg_const_i32(ret);
23358 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23359 tcg_temp_free_i32(ret_t);
23360 break;
23362 case OPC_PRECR_SRA_R_QH_PW:
23363 check_dsp_r2(ctx);
23365 TCGv_i32 sa_v = tcg_const_i32(ret);
23366 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23367 tcg_temp_free_i32(sa_v);
23368 break;
23370 case OPC_PRECRQ_OB_QH:
23371 check_dsp(ctx);
23372 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23373 break;
23374 case OPC_PRECRQ_PW_L:
23375 check_dsp(ctx);
23376 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23377 break;
23378 case OPC_PRECRQ_QH_PW:
23379 check_dsp(ctx);
23380 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23381 break;
23382 case OPC_PRECRQ_RS_QH_PW:
23383 check_dsp(ctx);
23384 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23385 break;
23386 case OPC_PRECRQU_S_OB_QH:
23387 check_dsp(ctx);
23388 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23389 break;
23391 break;
23392 #endif
23395 tcg_temp_free(v1_t);
23396 tcg_temp_free(v2_t);
23399 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23400 int ret, int v1, int v2)
23402 uint32_t op2;
23403 TCGv t0;
23404 TCGv v1_t;
23405 TCGv v2_t;
23407 if (ret == 0) {
23408 /* Treat as NOP. */
23409 return;
23412 t0 = tcg_temp_new();
23413 v1_t = tcg_temp_new();
23414 v2_t = tcg_temp_new();
23416 tcg_gen_movi_tl(t0, v1);
23417 gen_load_gpr(v1_t, v1);
23418 gen_load_gpr(v2_t, v2);
23420 switch (opc) {
23421 case OPC_SHLL_QB_DSP:
23423 op2 = MASK_SHLL_QB(ctx->opcode);
23424 switch (op2) {
23425 case OPC_SHLL_QB:
23426 check_dsp(ctx);
23427 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23428 break;
23429 case OPC_SHLLV_QB:
23430 check_dsp(ctx);
23431 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23432 break;
23433 case OPC_SHLL_PH:
23434 check_dsp(ctx);
23435 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23436 break;
23437 case OPC_SHLLV_PH:
23438 check_dsp(ctx);
23439 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23440 break;
23441 case OPC_SHLL_S_PH:
23442 check_dsp(ctx);
23443 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23444 break;
23445 case OPC_SHLLV_S_PH:
23446 check_dsp(ctx);
23447 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23448 break;
23449 case OPC_SHLL_S_W:
23450 check_dsp(ctx);
23451 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23452 break;
23453 case OPC_SHLLV_S_W:
23454 check_dsp(ctx);
23455 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23456 break;
23457 case OPC_SHRL_QB:
23458 check_dsp(ctx);
23459 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23460 break;
23461 case OPC_SHRLV_QB:
23462 check_dsp(ctx);
23463 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23464 break;
23465 case OPC_SHRL_PH:
23466 check_dsp_r2(ctx);
23467 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23468 break;
23469 case OPC_SHRLV_PH:
23470 check_dsp_r2(ctx);
23471 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23472 break;
23473 case OPC_SHRA_QB:
23474 check_dsp_r2(ctx);
23475 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23476 break;
23477 case OPC_SHRA_R_QB:
23478 check_dsp_r2(ctx);
23479 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23480 break;
23481 case OPC_SHRAV_QB:
23482 check_dsp_r2(ctx);
23483 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23484 break;
23485 case OPC_SHRAV_R_QB:
23486 check_dsp_r2(ctx);
23487 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23488 break;
23489 case OPC_SHRA_PH:
23490 check_dsp(ctx);
23491 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23492 break;
23493 case OPC_SHRA_R_PH:
23494 check_dsp(ctx);
23495 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23496 break;
23497 case OPC_SHRAV_PH:
23498 check_dsp(ctx);
23499 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23500 break;
23501 case OPC_SHRAV_R_PH:
23502 check_dsp(ctx);
23503 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23504 break;
23505 case OPC_SHRA_R_W:
23506 check_dsp(ctx);
23507 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23508 break;
23509 case OPC_SHRAV_R_W:
23510 check_dsp(ctx);
23511 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23512 break;
23513 default: /* Invalid */
23514 MIPS_INVAL("MASK SHLL.QB");
23515 gen_reserved_instruction(ctx);
23516 break;
23518 break;
23520 #ifdef TARGET_MIPS64
23521 case OPC_SHLL_OB_DSP:
23522 op2 = MASK_SHLL_OB(ctx->opcode);
23523 switch (op2) {
23524 case OPC_SHLL_PW:
23525 check_dsp(ctx);
23526 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23527 break;
23528 case OPC_SHLLV_PW:
23529 check_dsp(ctx);
23530 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23531 break;
23532 case OPC_SHLL_S_PW:
23533 check_dsp(ctx);
23534 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23535 break;
23536 case OPC_SHLLV_S_PW:
23537 check_dsp(ctx);
23538 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23539 break;
23540 case OPC_SHLL_OB:
23541 check_dsp(ctx);
23542 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23543 break;
23544 case OPC_SHLLV_OB:
23545 check_dsp(ctx);
23546 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23547 break;
23548 case OPC_SHLL_QH:
23549 check_dsp(ctx);
23550 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23551 break;
23552 case OPC_SHLLV_QH:
23553 check_dsp(ctx);
23554 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23555 break;
23556 case OPC_SHLL_S_QH:
23557 check_dsp(ctx);
23558 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23559 break;
23560 case OPC_SHLLV_S_QH:
23561 check_dsp(ctx);
23562 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23563 break;
23564 case OPC_SHRA_OB:
23565 check_dsp_r2(ctx);
23566 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23567 break;
23568 case OPC_SHRAV_OB:
23569 check_dsp_r2(ctx);
23570 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23571 break;
23572 case OPC_SHRA_R_OB:
23573 check_dsp_r2(ctx);
23574 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23575 break;
23576 case OPC_SHRAV_R_OB:
23577 check_dsp_r2(ctx);
23578 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23579 break;
23580 case OPC_SHRA_PW:
23581 check_dsp(ctx);
23582 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23583 break;
23584 case OPC_SHRAV_PW:
23585 check_dsp(ctx);
23586 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23587 break;
23588 case OPC_SHRA_R_PW:
23589 check_dsp(ctx);
23590 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23591 break;
23592 case OPC_SHRAV_R_PW:
23593 check_dsp(ctx);
23594 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23595 break;
23596 case OPC_SHRA_QH:
23597 check_dsp(ctx);
23598 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23599 break;
23600 case OPC_SHRAV_QH:
23601 check_dsp(ctx);
23602 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23603 break;
23604 case OPC_SHRA_R_QH:
23605 check_dsp(ctx);
23606 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23607 break;
23608 case OPC_SHRAV_R_QH:
23609 check_dsp(ctx);
23610 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23611 break;
23612 case OPC_SHRL_OB:
23613 check_dsp(ctx);
23614 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23615 break;
23616 case OPC_SHRLV_OB:
23617 check_dsp(ctx);
23618 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23619 break;
23620 case OPC_SHRL_QH:
23621 check_dsp_r2(ctx);
23622 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23623 break;
23624 case OPC_SHRLV_QH:
23625 check_dsp_r2(ctx);
23626 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23627 break;
23628 default: /* Invalid */
23629 MIPS_INVAL("MASK SHLL.OB");
23630 gen_reserved_instruction(ctx);
23631 break;
23633 break;
23634 #endif
23637 tcg_temp_free(t0);
23638 tcg_temp_free(v1_t);
23639 tcg_temp_free(v2_t);
23642 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23643 int ret, int v1, int v2, int check_ret)
23645 TCGv_i32 t0;
23646 TCGv v1_t;
23647 TCGv v2_t;
23649 if ((ret == 0) && (check_ret == 1)) {
23650 /* Treat as NOP. */
23651 return;
23654 t0 = tcg_temp_new_i32();
23655 v1_t = tcg_temp_new();
23656 v2_t = tcg_temp_new();
23658 tcg_gen_movi_i32(t0, ret);
23659 gen_load_gpr(v1_t, v1);
23660 gen_load_gpr(v2_t, v2);
23662 switch (op1) {
23664 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23665 * the same mask and op1.
23667 case OPC_MULT_G_2E:
23668 check_dsp_r2(ctx);
23669 switch (op2) {
23670 case OPC_MUL_PH:
23671 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23672 break;
23673 case OPC_MUL_S_PH:
23674 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23675 break;
23676 case OPC_MULQ_S_W:
23677 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23678 break;
23679 case OPC_MULQ_RS_W:
23680 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23681 break;
23683 break;
23684 case OPC_DPA_W_PH_DSP:
23685 switch (op2) {
23686 case OPC_DPAU_H_QBL:
23687 check_dsp(ctx);
23688 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23689 break;
23690 case OPC_DPAU_H_QBR:
23691 check_dsp(ctx);
23692 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23693 break;
23694 case OPC_DPSU_H_QBL:
23695 check_dsp(ctx);
23696 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23697 break;
23698 case OPC_DPSU_H_QBR:
23699 check_dsp(ctx);
23700 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23701 break;
23702 case OPC_DPA_W_PH:
23703 check_dsp_r2(ctx);
23704 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23705 break;
23706 case OPC_DPAX_W_PH:
23707 check_dsp_r2(ctx);
23708 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23709 break;
23710 case OPC_DPAQ_S_W_PH:
23711 check_dsp(ctx);
23712 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23713 break;
23714 case OPC_DPAQX_S_W_PH:
23715 check_dsp_r2(ctx);
23716 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23717 break;
23718 case OPC_DPAQX_SA_W_PH:
23719 check_dsp_r2(ctx);
23720 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23721 break;
23722 case OPC_DPS_W_PH:
23723 check_dsp_r2(ctx);
23724 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23725 break;
23726 case OPC_DPSX_W_PH:
23727 check_dsp_r2(ctx);
23728 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23729 break;
23730 case OPC_DPSQ_S_W_PH:
23731 check_dsp(ctx);
23732 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23733 break;
23734 case OPC_DPSQX_S_W_PH:
23735 check_dsp_r2(ctx);
23736 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23737 break;
23738 case OPC_DPSQX_SA_W_PH:
23739 check_dsp_r2(ctx);
23740 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23741 break;
23742 case OPC_MULSAQ_S_W_PH:
23743 check_dsp(ctx);
23744 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23745 break;
23746 case OPC_DPAQ_SA_L_W:
23747 check_dsp(ctx);
23748 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23749 break;
23750 case OPC_DPSQ_SA_L_W:
23751 check_dsp(ctx);
23752 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23753 break;
23754 case OPC_MAQ_S_W_PHL:
23755 check_dsp(ctx);
23756 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23757 break;
23758 case OPC_MAQ_S_W_PHR:
23759 check_dsp(ctx);
23760 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23761 break;
23762 case OPC_MAQ_SA_W_PHL:
23763 check_dsp(ctx);
23764 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23765 break;
23766 case OPC_MAQ_SA_W_PHR:
23767 check_dsp(ctx);
23768 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23769 break;
23770 case OPC_MULSA_W_PH:
23771 check_dsp_r2(ctx);
23772 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23773 break;
23775 break;
23776 #ifdef TARGET_MIPS64
23777 case OPC_DPAQ_W_QH_DSP:
23779 int ac = ret & 0x03;
23780 tcg_gen_movi_i32(t0, ac);
23782 switch (op2) {
23783 case OPC_DMADD:
23784 check_dsp(ctx);
23785 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23786 break;
23787 case OPC_DMADDU:
23788 check_dsp(ctx);
23789 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23790 break;
23791 case OPC_DMSUB:
23792 check_dsp(ctx);
23793 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23794 break;
23795 case OPC_DMSUBU:
23796 check_dsp(ctx);
23797 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23798 break;
23799 case OPC_DPA_W_QH:
23800 check_dsp_r2(ctx);
23801 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23802 break;
23803 case OPC_DPAQ_S_W_QH:
23804 check_dsp(ctx);
23805 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23806 break;
23807 case OPC_DPAQ_SA_L_PW:
23808 check_dsp(ctx);
23809 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23810 break;
23811 case OPC_DPAU_H_OBL:
23812 check_dsp(ctx);
23813 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23814 break;
23815 case OPC_DPAU_H_OBR:
23816 check_dsp(ctx);
23817 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23818 break;
23819 case OPC_DPS_W_QH:
23820 check_dsp_r2(ctx);
23821 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23822 break;
23823 case OPC_DPSQ_S_W_QH:
23824 check_dsp(ctx);
23825 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23826 break;
23827 case OPC_DPSQ_SA_L_PW:
23828 check_dsp(ctx);
23829 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23830 break;
23831 case OPC_DPSU_H_OBL:
23832 check_dsp(ctx);
23833 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23834 break;
23835 case OPC_DPSU_H_OBR:
23836 check_dsp(ctx);
23837 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23838 break;
23839 case OPC_MAQ_S_L_PWL:
23840 check_dsp(ctx);
23841 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23842 break;
23843 case OPC_MAQ_S_L_PWR:
23844 check_dsp(ctx);
23845 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23846 break;
23847 case OPC_MAQ_S_W_QHLL:
23848 check_dsp(ctx);
23849 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23850 break;
23851 case OPC_MAQ_SA_W_QHLL:
23852 check_dsp(ctx);
23853 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23854 break;
23855 case OPC_MAQ_S_W_QHLR:
23856 check_dsp(ctx);
23857 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23858 break;
23859 case OPC_MAQ_SA_W_QHLR:
23860 check_dsp(ctx);
23861 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23862 break;
23863 case OPC_MAQ_S_W_QHRL:
23864 check_dsp(ctx);
23865 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23866 break;
23867 case OPC_MAQ_SA_W_QHRL:
23868 check_dsp(ctx);
23869 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23870 break;
23871 case OPC_MAQ_S_W_QHRR:
23872 check_dsp(ctx);
23873 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
23874 break;
23875 case OPC_MAQ_SA_W_QHRR:
23876 check_dsp(ctx);
23877 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
23878 break;
23879 case OPC_MULSAQ_S_L_PW:
23880 check_dsp(ctx);
23881 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
23882 break;
23883 case OPC_MULSAQ_S_W_QH:
23884 check_dsp(ctx);
23885 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23886 break;
23889 break;
23890 #endif
23891 case OPC_ADDU_QB_DSP:
23892 switch (op2) {
23893 case OPC_MULEU_S_PH_QBL:
23894 check_dsp(ctx);
23895 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23896 break;
23897 case OPC_MULEU_S_PH_QBR:
23898 check_dsp(ctx);
23899 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23900 break;
23901 case OPC_MULQ_RS_PH:
23902 check_dsp(ctx);
23903 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23904 break;
23905 case OPC_MULEQ_S_W_PHL:
23906 check_dsp(ctx);
23907 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23908 break;
23909 case OPC_MULEQ_S_W_PHR:
23910 check_dsp(ctx);
23911 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23912 break;
23913 case OPC_MULQ_S_PH:
23914 check_dsp_r2(ctx);
23915 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23916 break;
23918 break;
23919 #ifdef TARGET_MIPS64
23920 case OPC_ADDU_OB_DSP:
23921 switch (op2) {
23922 case OPC_MULEQ_S_PW_QHL:
23923 check_dsp(ctx);
23924 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23925 break;
23926 case OPC_MULEQ_S_PW_QHR:
23927 check_dsp(ctx);
23928 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23929 break;
23930 case OPC_MULEU_S_QH_OBL:
23931 check_dsp(ctx);
23932 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23933 break;
23934 case OPC_MULEU_S_QH_OBR:
23935 check_dsp(ctx);
23936 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23937 break;
23938 case OPC_MULQ_RS_QH:
23939 check_dsp(ctx);
23940 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23941 break;
23943 break;
23944 #endif
23947 tcg_temp_free_i32(t0);
23948 tcg_temp_free(v1_t);
23949 tcg_temp_free(v2_t);
23952 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23953 int ret, int val)
23955 int16_t imm;
23956 TCGv t0;
23957 TCGv val_t;
23959 if (ret == 0) {
23960 /* Treat as NOP. */
23961 return;
23964 t0 = tcg_temp_new();
23965 val_t = tcg_temp_new();
23966 gen_load_gpr(val_t, val);
23968 switch (op1) {
23969 case OPC_ABSQ_S_PH_DSP:
23970 switch (op2) {
23971 case OPC_BITREV:
23972 check_dsp(ctx);
23973 gen_helper_bitrev(cpu_gpr[ret], val_t);
23974 break;
23975 case OPC_REPL_QB:
23976 check_dsp(ctx);
23978 target_long result;
23979 imm = (ctx->opcode >> 16) & 0xFF;
23980 result = (uint32_t)imm << 24 |
23981 (uint32_t)imm << 16 |
23982 (uint32_t)imm << 8 |
23983 (uint32_t)imm;
23984 result = (int32_t)result;
23985 tcg_gen_movi_tl(cpu_gpr[ret], result);
23987 break;
23988 case OPC_REPLV_QB:
23989 check_dsp(ctx);
23990 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
23991 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
23992 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23993 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
23994 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
23995 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23996 break;
23997 case OPC_REPL_PH:
23998 check_dsp(ctx);
24000 imm = (ctx->opcode >> 16) & 0x03FF;
24001 imm = (int16_t)(imm << 6) >> 6;
24002 tcg_gen_movi_tl(cpu_gpr[ret], \
24003 (target_long)((int32_t)imm << 16 | \
24004 (uint16_t)imm));
24006 break;
24007 case OPC_REPLV_PH:
24008 check_dsp(ctx);
24009 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24010 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24011 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24012 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24013 break;
24015 break;
24016 #ifdef TARGET_MIPS64
24017 case OPC_ABSQ_S_QH_DSP:
24018 switch (op2) {
24019 case OPC_REPL_OB:
24020 check_dsp(ctx);
24022 target_long temp;
24024 imm = (ctx->opcode >> 16) & 0xFF;
24025 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
24026 temp = (temp << 16) | temp;
24027 temp = (temp << 32) | temp;
24028 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24029 break;
24031 case OPC_REPL_PW:
24032 check_dsp(ctx);
24034 target_long temp;
24036 imm = (ctx->opcode >> 16) & 0x03FF;
24037 imm = (int16_t)(imm << 6) >> 6;
24038 temp = ((target_long)imm << 32) \
24039 | ((target_long)imm & 0xFFFFFFFF);
24040 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24041 break;
24043 case OPC_REPL_QH:
24044 check_dsp(ctx);
24046 target_long temp;
24048 imm = (ctx->opcode >> 16) & 0x03FF;
24049 imm = (int16_t)(imm << 6) >> 6;
24051 temp = ((uint64_t)(uint16_t)imm << 48) |
24052 ((uint64_t)(uint16_t)imm << 32) |
24053 ((uint64_t)(uint16_t)imm << 16) |
24054 (uint64_t)(uint16_t)imm;
24055 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24056 break;
24058 case OPC_REPLV_OB:
24059 check_dsp(ctx);
24060 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24061 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24062 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24063 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24064 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24065 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24066 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24067 break;
24068 case OPC_REPLV_PW:
24069 check_dsp(ctx);
24070 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
24071 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24072 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24073 break;
24074 case OPC_REPLV_QH:
24075 check_dsp(ctx);
24076 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24077 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24078 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24079 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24080 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24081 break;
24083 break;
24084 #endif
24086 tcg_temp_free(t0);
24087 tcg_temp_free(val_t);
24090 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
24091 uint32_t op1, uint32_t op2,
24092 int ret, int v1, int v2, int check_ret)
24094 TCGv t1;
24095 TCGv v1_t;
24096 TCGv v2_t;
24098 if ((ret == 0) && (check_ret == 1)) {
24099 /* Treat as NOP. */
24100 return;
24103 t1 = tcg_temp_new();
24104 v1_t = tcg_temp_new();
24105 v2_t = tcg_temp_new();
24107 gen_load_gpr(v1_t, v1);
24108 gen_load_gpr(v2_t, v2);
24110 switch (op1) {
24111 case OPC_CMPU_EQ_QB_DSP:
24112 switch (op2) {
24113 case OPC_CMPU_EQ_QB:
24114 check_dsp(ctx);
24115 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
24116 break;
24117 case OPC_CMPU_LT_QB:
24118 check_dsp(ctx);
24119 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
24120 break;
24121 case OPC_CMPU_LE_QB:
24122 check_dsp(ctx);
24123 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
24124 break;
24125 case OPC_CMPGU_EQ_QB:
24126 check_dsp(ctx);
24127 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
24128 break;
24129 case OPC_CMPGU_LT_QB:
24130 check_dsp(ctx);
24131 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
24132 break;
24133 case OPC_CMPGU_LE_QB:
24134 check_dsp(ctx);
24135 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
24136 break;
24137 case OPC_CMPGDU_EQ_QB:
24138 check_dsp_r2(ctx);
24139 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
24140 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24141 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24142 tcg_gen_shli_tl(t1, t1, 24);
24143 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24144 break;
24145 case OPC_CMPGDU_LT_QB:
24146 check_dsp_r2(ctx);
24147 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
24148 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24149 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24150 tcg_gen_shli_tl(t1, t1, 24);
24151 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24152 break;
24153 case OPC_CMPGDU_LE_QB:
24154 check_dsp_r2(ctx);
24155 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
24156 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24157 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24158 tcg_gen_shli_tl(t1, t1, 24);
24159 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24160 break;
24161 case OPC_CMP_EQ_PH:
24162 check_dsp(ctx);
24163 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
24164 break;
24165 case OPC_CMP_LT_PH:
24166 check_dsp(ctx);
24167 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
24168 break;
24169 case OPC_CMP_LE_PH:
24170 check_dsp(ctx);
24171 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
24172 break;
24173 case OPC_PICK_QB:
24174 check_dsp(ctx);
24175 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24176 break;
24177 case OPC_PICK_PH:
24178 check_dsp(ctx);
24179 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24180 break;
24181 case OPC_PACKRL_PH:
24182 check_dsp(ctx);
24183 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
24184 break;
24186 break;
24187 #ifdef TARGET_MIPS64
24188 case OPC_CMPU_EQ_OB_DSP:
24189 switch (op2) {
24190 case OPC_CMP_EQ_PW:
24191 check_dsp(ctx);
24192 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
24193 break;
24194 case OPC_CMP_LT_PW:
24195 check_dsp(ctx);
24196 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
24197 break;
24198 case OPC_CMP_LE_PW:
24199 check_dsp(ctx);
24200 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
24201 break;
24202 case OPC_CMP_EQ_QH:
24203 check_dsp(ctx);
24204 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
24205 break;
24206 case OPC_CMP_LT_QH:
24207 check_dsp(ctx);
24208 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
24209 break;
24210 case OPC_CMP_LE_QH:
24211 check_dsp(ctx);
24212 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
24213 break;
24214 case OPC_CMPGDU_EQ_OB:
24215 check_dsp_r2(ctx);
24216 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24217 break;
24218 case OPC_CMPGDU_LT_OB:
24219 check_dsp_r2(ctx);
24220 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24221 break;
24222 case OPC_CMPGDU_LE_OB:
24223 check_dsp_r2(ctx);
24224 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24225 break;
24226 case OPC_CMPGU_EQ_OB:
24227 check_dsp(ctx);
24228 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
24229 break;
24230 case OPC_CMPGU_LT_OB:
24231 check_dsp(ctx);
24232 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
24233 break;
24234 case OPC_CMPGU_LE_OB:
24235 check_dsp(ctx);
24236 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
24237 break;
24238 case OPC_CMPU_EQ_OB:
24239 check_dsp(ctx);
24240 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
24241 break;
24242 case OPC_CMPU_LT_OB:
24243 check_dsp(ctx);
24244 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
24245 break;
24246 case OPC_CMPU_LE_OB:
24247 check_dsp(ctx);
24248 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
24249 break;
24250 case OPC_PACKRL_PW:
24251 check_dsp(ctx);
24252 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
24253 break;
24254 case OPC_PICK_OB:
24255 check_dsp(ctx);
24256 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24257 break;
24258 case OPC_PICK_PW:
24259 check_dsp(ctx);
24260 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24261 break;
24262 case OPC_PICK_QH:
24263 check_dsp(ctx);
24264 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24265 break;
24267 break;
24268 #endif
24271 tcg_temp_free(t1);
24272 tcg_temp_free(v1_t);
24273 tcg_temp_free(v2_t);
24276 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
24277 uint32_t op1, int rt, int rs, int sa)
24279 TCGv t0;
24281 check_dsp_r2(ctx);
24283 if (rt == 0) {
24284 /* Treat as NOP. */
24285 return;
24288 t0 = tcg_temp_new();
24289 gen_load_gpr(t0, rs);
24291 switch (op1) {
24292 case OPC_APPEND_DSP:
24293 switch (MASK_APPEND(ctx->opcode)) {
24294 case OPC_APPEND:
24295 if (sa != 0) {
24296 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24298 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24299 break;
24300 case OPC_PREPEND:
24301 if (sa != 0) {
24302 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24303 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24304 tcg_gen_shli_tl(t0, t0, 32 - sa);
24305 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24307 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24308 break;
24309 case OPC_BALIGN:
24310 sa &= 3;
24311 if (sa != 0 && sa != 2) {
24312 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24313 tcg_gen_ext32u_tl(t0, t0);
24314 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24315 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24317 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24318 break;
24319 default: /* Invalid */
24320 MIPS_INVAL("MASK APPEND");
24321 gen_reserved_instruction(ctx);
24322 break;
24324 break;
24325 #ifdef TARGET_MIPS64
24326 case OPC_DAPPEND_DSP:
24327 switch (MASK_DAPPEND(ctx->opcode)) {
24328 case OPC_DAPPEND:
24329 if (sa != 0) {
24330 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24332 break;
24333 case OPC_PREPENDD:
24334 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24335 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24336 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24337 break;
24338 case OPC_PREPENDW:
24339 if (sa != 0) {
24340 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24341 tcg_gen_shli_tl(t0, t0, 64 - sa);
24342 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24344 break;
24345 case OPC_DBALIGN:
24346 sa &= 7;
24347 if (sa != 0 && sa != 2 && sa != 4) {
24348 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24349 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24350 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24352 break;
24353 default: /* Invalid */
24354 MIPS_INVAL("MASK DAPPEND");
24355 gen_reserved_instruction(ctx);
24356 break;
24358 break;
24359 #endif
24361 tcg_temp_free(t0);
24364 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24365 int ret, int v1, int v2, int check_ret)
24368 TCGv t0;
24369 TCGv t1;
24370 TCGv v1_t;
24371 TCGv v2_t;
24372 int16_t imm;
24374 if ((ret == 0) && (check_ret == 1)) {
24375 /* Treat as NOP. */
24376 return;
24379 t0 = tcg_temp_new();
24380 t1 = tcg_temp_new();
24381 v1_t = tcg_temp_new();
24382 v2_t = tcg_temp_new();
24384 gen_load_gpr(v1_t, v1);
24385 gen_load_gpr(v2_t, v2);
24387 switch (op1) {
24388 case OPC_EXTR_W_DSP:
24389 check_dsp(ctx);
24390 switch (op2) {
24391 case OPC_EXTR_W:
24392 tcg_gen_movi_tl(t0, v2);
24393 tcg_gen_movi_tl(t1, v1);
24394 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24395 break;
24396 case OPC_EXTR_R_W:
24397 tcg_gen_movi_tl(t0, v2);
24398 tcg_gen_movi_tl(t1, v1);
24399 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24400 break;
24401 case OPC_EXTR_RS_W:
24402 tcg_gen_movi_tl(t0, v2);
24403 tcg_gen_movi_tl(t1, v1);
24404 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24405 break;
24406 case OPC_EXTR_S_H:
24407 tcg_gen_movi_tl(t0, v2);
24408 tcg_gen_movi_tl(t1, v1);
24409 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24410 break;
24411 case OPC_EXTRV_S_H:
24412 tcg_gen_movi_tl(t0, v2);
24413 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24414 break;
24415 case OPC_EXTRV_W:
24416 tcg_gen_movi_tl(t0, v2);
24417 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24418 break;
24419 case OPC_EXTRV_R_W:
24420 tcg_gen_movi_tl(t0, v2);
24421 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24422 break;
24423 case OPC_EXTRV_RS_W:
24424 tcg_gen_movi_tl(t0, v2);
24425 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24426 break;
24427 case OPC_EXTP:
24428 tcg_gen_movi_tl(t0, v2);
24429 tcg_gen_movi_tl(t1, v1);
24430 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24431 break;
24432 case OPC_EXTPV:
24433 tcg_gen_movi_tl(t0, v2);
24434 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24435 break;
24436 case OPC_EXTPDP:
24437 tcg_gen_movi_tl(t0, v2);
24438 tcg_gen_movi_tl(t1, v1);
24439 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24440 break;
24441 case OPC_EXTPDPV:
24442 tcg_gen_movi_tl(t0, v2);
24443 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24444 break;
24445 case OPC_SHILO:
24446 imm = (ctx->opcode >> 20) & 0x3F;
24447 tcg_gen_movi_tl(t0, ret);
24448 tcg_gen_movi_tl(t1, imm);
24449 gen_helper_shilo(t0, t1, cpu_env);
24450 break;
24451 case OPC_SHILOV:
24452 tcg_gen_movi_tl(t0, ret);
24453 gen_helper_shilo(t0, v1_t, cpu_env);
24454 break;
24455 case OPC_MTHLIP:
24456 tcg_gen_movi_tl(t0, ret);
24457 gen_helper_mthlip(t0, v1_t, cpu_env);
24458 break;
24459 case OPC_WRDSP:
24460 imm = (ctx->opcode >> 11) & 0x3FF;
24461 tcg_gen_movi_tl(t0, imm);
24462 gen_helper_wrdsp(v1_t, t0, cpu_env);
24463 break;
24464 case OPC_RDDSP:
24465 imm = (ctx->opcode >> 16) & 0x03FF;
24466 tcg_gen_movi_tl(t0, imm);
24467 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24468 break;
24470 break;
24471 #ifdef TARGET_MIPS64
24472 case OPC_DEXTR_W_DSP:
24473 check_dsp(ctx);
24474 switch (op2) {
24475 case OPC_DMTHLIP:
24476 tcg_gen_movi_tl(t0, ret);
24477 gen_helper_dmthlip(v1_t, t0, cpu_env);
24478 break;
24479 case OPC_DSHILO:
24481 int shift = (ctx->opcode >> 19) & 0x7F;
24482 int ac = (ctx->opcode >> 11) & 0x03;
24483 tcg_gen_movi_tl(t0, shift);
24484 tcg_gen_movi_tl(t1, ac);
24485 gen_helper_dshilo(t0, t1, cpu_env);
24486 break;
24488 case OPC_DSHILOV:
24490 int ac = (ctx->opcode >> 11) & 0x03;
24491 tcg_gen_movi_tl(t0, ac);
24492 gen_helper_dshilo(v1_t, t0, cpu_env);
24493 break;
24495 case OPC_DEXTP:
24496 tcg_gen_movi_tl(t0, v2);
24497 tcg_gen_movi_tl(t1, v1);
24499 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24500 break;
24501 case OPC_DEXTPV:
24502 tcg_gen_movi_tl(t0, v2);
24503 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24504 break;
24505 case OPC_DEXTPDP:
24506 tcg_gen_movi_tl(t0, v2);
24507 tcg_gen_movi_tl(t1, v1);
24508 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24509 break;
24510 case OPC_DEXTPDPV:
24511 tcg_gen_movi_tl(t0, v2);
24512 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24513 break;
24514 case OPC_DEXTR_L:
24515 tcg_gen_movi_tl(t0, v2);
24516 tcg_gen_movi_tl(t1, v1);
24517 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24518 break;
24519 case OPC_DEXTR_R_L:
24520 tcg_gen_movi_tl(t0, v2);
24521 tcg_gen_movi_tl(t1, v1);
24522 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24523 break;
24524 case OPC_DEXTR_RS_L:
24525 tcg_gen_movi_tl(t0, v2);
24526 tcg_gen_movi_tl(t1, v1);
24527 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24528 break;
24529 case OPC_DEXTR_W:
24530 tcg_gen_movi_tl(t0, v2);
24531 tcg_gen_movi_tl(t1, v1);
24532 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24533 break;
24534 case OPC_DEXTR_R_W:
24535 tcg_gen_movi_tl(t0, v2);
24536 tcg_gen_movi_tl(t1, v1);
24537 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24538 break;
24539 case OPC_DEXTR_RS_W:
24540 tcg_gen_movi_tl(t0, v2);
24541 tcg_gen_movi_tl(t1, v1);
24542 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24543 break;
24544 case OPC_DEXTR_S_H:
24545 tcg_gen_movi_tl(t0, v2);
24546 tcg_gen_movi_tl(t1, v1);
24547 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24548 break;
24549 case OPC_DEXTRV_S_H:
24550 tcg_gen_movi_tl(t0, v2);
24551 tcg_gen_movi_tl(t1, v1);
24552 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24553 break;
24554 case OPC_DEXTRV_L:
24555 tcg_gen_movi_tl(t0, v2);
24556 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24557 break;
24558 case OPC_DEXTRV_R_L:
24559 tcg_gen_movi_tl(t0, v2);
24560 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24561 break;
24562 case OPC_DEXTRV_RS_L:
24563 tcg_gen_movi_tl(t0, v2);
24564 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24565 break;
24566 case OPC_DEXTRV_W:
24567 tcg_gen_movi_tl(t0, v2);
24568 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24569 break;
24570 case OPC_DEXTRV_R_W:
24571 tcg_gen_movi_tl(t0, v2);
24572 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24573 break;
24574 case OPC_DEXTRV_RS_W:
24575 tcg_gen_movi_tl(t0, v2);
24576 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24577 break;
24579 break;
24580 #endif
24583 tcg_temp_free(t0);
24584 tcg_temp_free(t1);
24585 tcg_temp_free(v1_t);
24586 tcg_temp_free(v2_t);
24589 /* End MIPSDSP functions. */
24591 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24593 int rs, rt, rd, sa;
24594 uint32_t op1, op2;
24596 rs = (ctx->opcode >> 21) & 0x1f;
24597 rt = (ctx->opcode >> 16) & 0x1f;
24598 rd = (ctx->opcode >> 11) & 0x1f;
24599 sa = (ctx->opcode >> 6) & 0x1f;
24601 op1 = MASK_SPECIAL(ctx->opcode);
24602 switch (op1) {
24603 case OPC_LSA:
24604 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24605 break;
24606 case OPC_MULT:
24607 case OPC_MULTU:
24608 case OPC_DIV:
24609 case OPC_DIVU:
24610 op2 = MASK_R6_MULDIV(ctx->opcode);
24611 switch (op2) {
24612 case R6_OPC_MUL:
24613 case R6_OPC_MUH:
24614 case R6_OPC_MULU:
24615 case R6_OPC_MUHU:
24616 case R6_OPC_DIV:
24617 case R6_OPC_MOD:
24618 case R6_OPC_DIVU:
24619 case R6_OPC_MODU:
24620 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24621 break;
24622 default:
24623 MIPS_INVAL("special_r6 muldiv");
24624 gen_reserved_instruction(ctx);
24625 break;
24627 break;
24628 case OPC_SELEQZ:
24629 case OPC_SELNEZ:
24630 gen_cond_move(ctx, op1, rd, rs, rt);
24631 break;
24632 case R6_OPC_CLO:
24633 case R6_OPC_CLZ:
24634 if (rt == 0 && sa == 1) {
24636 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24637 * We need additionally to check other fields.
24639 gen_cl(ctx, op1, rd, rs);
24640 } else {
24641 gen_reserved_instruction(ctx);
24643 break;
24644 case R6_OPC_SDBBP:
24645 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24646 gen_helper_do_semihosting(cpu_env);
24647 } else {
24648 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24649 gen_reserved_instruction(ctx);
24650 } else {
24651 generate_exception_end(ctx, EXCP_DBp);
24654 break;
24655 #if defined(TARGET_MIPS64)
24656 case OPC_DLSA:
24657 check_mips_64(ctx);
24658 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24659 break;
24660 case R6_OPC_DCLO:
24661 case R6_OPC_DCLZ:
24662 if (rt == 0 && sa == 1) {
24664 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24665 * We need additionally to check other fields.
24667 check_mips_64(ctx);
24668 gen_cl(ctx, op1, rd, rs);
24669 } else {
24670 gen_reserved_instruction(ctx);
24672 break;
24673 case OPC_DMULT:
24674 case OPC_DMULTU:
24675 case OPC_DDIV:
24676 case OPC_DDIVU:
24678 op2 = MASK_R6_MULDIV(ctx->opcode);
24679 switch (op2) {
24680 case R6_OPC_DMUL:
24681 case R6_OPC_DMUH:
24682 case R6_OPC_DMULU:
24683 case R6_OPC_DMUHU:
24684 case R6_OPC_DDIV:
24685 case R6_OPC_DMOD:
24686 case R6_OPC_DDIVU:
24687 case R6_OPC_DMODU:
24688 check_mips_64(ctx);
24689 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24690 break;
24691 default:
24692 MIPS_INVAL("special_r6 muldiv");
24693 gen_reserved_instruction(ctx);
24694 break;
24696 break;
24697 #endif
24698 default: /* Invalid */
24699 MIPS_INVAL("special_r6");
24700 gen_reserved_instruction(ctx);
24701 break;
24705 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24707 int rs = extract32(ctx->opcode, 21, 5);
24708 int rt = extract32(ctx->opcode, 16, 5);
24709 int rd = extract32(ctx->opcode, 11, 5);
24710 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24712 switch (op1) {
24713 case OPC_MOVN: /* Conditional move */
24714 case OPC_MOVZ:
24715 gen_cond_move(ctx, op1, rd, rs, rt);
24716 break;
24717 case OPC_MFHI: /* Move from HI/LO */
24718 case OPC_MFLO:
24719 gen_HILO(ctx, op1, 0, rd);
24720 break;
24721 case OPC_MTHI:
24722 case OPC_MTLO: /* Move to HI/LO */
24723 gen_HILO(ctx, op1, 0, rs);
24724 break;
24725 case OPC_MULT:
24726 case OPC_MULTU:
24727 gen_mul_txx9(ctx, op1, rd, rs, rt);
24728 break;
24729 case OPC_DIV:
24730 case OPC_DIVU:
24731 gen_muldiv(ctx, op1, 0, rs, rt);
24732 break;
24733 #if defined(TARGET_MIPS64)
24734 case OPC_DMULT:
24735 case OPC_DMULTU:
24736 case OPC_DDIV:
24737 case OPC_DDIVU:
24738 check_insn_opc_user_only(ctx, INSN_R5900);
24739 gen_muldiv(ctx, op1, 0, rs, rt);
24740 break;
24741 #endif
24742 case OPC_JR:
24743 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24744 break;
24745 default: /* Invalid */
24746 MIPS_INVAL("special_tx79");
24747 gen_reserved_instruction(ctx);
24748 break;
24752 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24754 int rs, rt, rd, sa;
24755 uint32_t op1;
24757 rs = (ctx->opcode >> 21) & 0x1f;
24758 rt = (ctx->opcode >> 16) & 0x1f;
24759 rd = (ctx->opcode >> 11) & 0x1f;
24760 sa = (ctx->opcode >> 6) & 0x1f;
24762 op1 = MASK_SPECIAL(ctx->opcode);
24763 switch (op1) {
24764 case OPC_MOVN: /* Conditional move */
24765 case OPC_MOVZ:
24766 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
24767 INSN_LOONGSON2E | INSN_LOONGSON2F);
24768 gen_cond_move(ctx, op1, rd, rs, rt);
24769 break;
24770 case OPC_MFHI: /* Move from HI/LO */
24771 case OPC_MFLO:
24772 gen_HILO(ctx, op1, rs & 3, rd);
24773 break;
24774 case OPC_MTHI:
24775 case OPC_MTLO: /* Move to HI/LO */
24776 gen_HILO(ctx, op1, rd & 3, rs);
24777 break;
24778 case OPC_MOVCI:
24779 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
24780 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24781 check_cp1_enabled(ctx);
24782 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24783 (ctx->opcode >> 16) & 1);
24784 } else {
24785 generate_exception_err(ctx, EXCP_CpU, 1);
24787 break;
24788 case OPC_MULT:
24789 case OPC_MULTU:
24790 if (sa) {
24791 check_insn(ctx, INSN_VR54XX);
24792 op1 = MASK_MUL_VR54XX(ctx->opcode);
24793 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24794 } else {
24795 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24797 break;
24798 case OPC_DIV:
24799 case OPC_DIVU:
24800 gen_muldiv(ctx, op1, 0, rs, rt);
24801 break;
24802 #if defined(TARGET_MIPS64)
24803 case OPC_DMULT:
24804 case OPC_DMULTU:
24805 case OPC_DDIV:
24806 case OPC_DDIVU:
24807 check_insn(ctx, ISA_MIPS3);
24808 check_mips_64(ctx);
24809 gen_muldiv(ctx, op1, 0, rs, rt);
24810 break;
24811 #endif
24812 case OPC_JR:
24813 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24814 break;
24815 case OPC_SPIM:
24816 #ifdef MIPS_STRICT_STANDARD
24817 MIPS_INVAL("SPIM");
24818 gen_reserved_instruction(ctx);
24819 #else
24820 /* Implemented as RI exception for now. */
24821 MIPS_INVAL("spim (unofficial)");
24822 gen_reserved_instruction(ctx);
24823 #endif
24824 break;
24825 default: /* Invalid */
24826 MIPS_INVAL("special_legacy");
24827 gen_reserved_instruction(ctx);
24828 break;
24832 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24834 int rs, rt, rd, sa;
24835 uint32_t op1;
24837 rs = (ctx->opcode >> 21) & 0x1f;
24838 rt = (ctx->opcode >> 16) & 0x1f;
24839 rd = (ctx->opcode >> 11) & 0x1f;
24840 sa = (ctx->opcode >> 6) & 0x1f;
24842 op1 = MASK_SPECIAL(ctx->opcode);
24843 switch (op1) {
24844 case OPC_SLL: /* Shift with immediate */
24845 if (sa == 5 && rd == 0 &&
24846 rs == 0 && rt == 0) { /* PAUSE */
24847 if ((ctx->insn_flags & ISA_MIPS_R6) &&
24848 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24849 gen_reserved_instruction(ctx);
24850 break;
24853 /* Fallthrough */
24854 case OPC_SRA:
24855 gen_shift_imm(ctx, op1, rd, rt, sa);
24856 break;
24857 case OPC_SRL:
24858 switch ((ctx->opcode >> 21) & 0x1f) {
24859 case 1:
24860 /* rotr is decoded as srl on non-R2 CPUs */
24861 if (ctx->insn_flags & ISA_MIPS_R2) {
24862 op1 = OPC_ROTR;
24864 /* Fallthrough */
24865 case 0:
24866 gen_shift_imm(ctx, op1, rd, rt, sa);
24867 break;
24868 default:
24869 gen_reserved_instruction(ctx);
24870 break;
24872 break;
24873 case OPC_ADD:
24874 case OPC_ADDU:
24875 case OPC_SUB:
24876 case OPC_SUBU:
24877 gen_arith(ctx, op1, rd, rs, rt);
24878 break;
24879 case OPC_SLLV: /* Shifts */
24880 case OPC_SRAV:
24881 gen_shift(ctx, op1, rd, rs, rt);
24882 break;
24883 case OPC_SRLV:
24884 switch ((ctx->opcode >> 6) & 0x1f) {
24885 case 1:
24886 /* rotrv is decoded as srlv on non-R2 CPUs */
24887 if (ctx->insn_flags & ISA_MIPS_R2) {
24888 op1 = OPC_ROTRV;
24890 /* Fallthrough */
24891 case 0:
24892 gen_shift(ctx, op1, rd, rs, rt);
24893 break;
24894 default:
24895 gen_reserved_instruction(ctx);
24896 break;
24898 break;
24899 case OPC_SLT: /* Set on less than */
24900 case OPC_SLTU:
24901 gen_slt(ctx, op1, rd, rs, rt);
24902 break;
24903 case OPC_AND: /* Logic*/
24904 case OPC_OR:
24905 case OPC_NOR:
24906 case OPC_XOR:
24907 gen_logic(ctx, op1, rd, rs, rt);
24908 break;
24909 case OPC_JALR:
24910 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24911 break;
24912 case OPC_TGE: /* Traps */
24913 case OPC_TGEU:
24914 case OPC_TLT:
24915 case OPC_TLTU:
24916 case OPC_TEQ:
24917 case OPC_TNE:
24918 check_insn(ctx, ISA_MIPS2);
24919 gen_trap(ctx, op1, rs, rt, -1);
24920 break;
24921 case OPC_LSA: /* OPC_PMON */
24922 if ((ctx->insn_flags & ISA_MIPS_R6) || ase_msa_available(env)) {
24923 decode_opc_special_r6(env, ctx);
24924 } else {
24925 /* Pmon entry point, also R4010 selsl */
24926 #ifdef MIPS_STRICT_STANDARD
24927 MIPS_INVAL("PMON / selsl");
24928 gen_reserved_instruction(ctx);
24929 #else
24930 gen_helper_0e0i(pmon, sa);
24931 #endif
24933 break;
24934 case OPC_SYSCALL:
24935 generate_exception_end(ctx, EXCP_SYSCALL);
24936 break;
24937 case OPC_BREAK:
24938 generate_exception_end(ctx, EXCP_BREAK);
24939 break;
24940 case OPC_SYNC:
24941 check_insn(ctx, ISA_MIPS2);
24942 gen_sync(extract32(ctx->opcode, 6, 5));
24943 break;
24945 #if defined(TARGET_MIPS64)
24946 /* MIPS64 specific opcodes */
24947 case OPC_DSLL:
24948 case OPC_DSRA:
24949 case OPC_DSLL32:
24950 case OPC_DSRA32:
24951 check_insn(ctx, ISA_MIPS3);
24952 check_mips_64(ctx);
24953 gen_shift_imm(ctx, op1, rd, rt, sa);
24954 break;
24955 case OPC_DSRL:
24956 switch ((ctx->opcode >> 21) & 0x1f) {
24957 case 1:
24958 /* drotr is decoded as dsrl on non-R2 CPUs */
24959 if (ctx->insn_flags & ISA_MIPS_R2) {
24960 op1 = OPC_DROTR;
24962 /* Fallthrough */
24963 case 0:
24964 check_insn(ctx, ISA_MIPS3);
24965 check_mips_64(ctx);
24966 gen_shift_imm(ctx, op1, rd, rt, sa);
24967 break;
24968 default:
24969 gen_reserved_instruction(ctx);
24970 break;
24972 break;
24973 case OPC_DSRL32:
24974 switch ((ctx->opcode >> 21) & 0x1f) {
24975 case 1:
24976 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
24977 if (ctx->insn_flags & ISA_MIPS_R2) {
24978 op1 = OPC_DROTR32;
24980 /* Fallthrough */
24981 case 0:
24982 check_insn(ctx, ISA_MIPS3);
24983 check_mips_64(ctx);
24984 gen_shift_imm(ctx, op1, rd, rt, sa);
24985 break;
24986 default:
24987 gen_reserved_instruction(ctx);
24988 break;
24990 break;
24991 case OPC_DADD:
24992 case OPC_DADDU:
24993 case OPC_DSUB:
24994 case OPC_DSUBU:
24995 check_insn(ctx, ISA_MIPS3);
24996 check_mips_64(ctx);
24997 gen_arith(ctx, op1, rd, rs, rt);
24998 break;
24999 case OPC_DSLLV:
25000 case OPC_DSRAV:
25001 check_insn(ctx, ISA_MIPS3);
25002 check_mips_64(ctx);
25003 gen_shift(ctx, op1, rd, rs, rt);
25004 break;
25005 case OPC_DSRLV:
25006 switch ((ctx->opcode >> 6) & 0x1f) {
25007 case 1:
25008 /* drotrv is decoded as dsrlv on non-R2 CPUs */
25009 if (ctx->insn_flags & ISA_MIPS_R2) {
25010 op1 = OPC_DROTRV;
25012 /* Fallthrough */
25013 case 0:
25014 check_insn(ctx, ISA_MIPS3);
25015 check_mips_64(ctx);
25016 gen_shift(ctx, op1, rd, rs, rt);
25017 break;
25018 default:
25019 gen_reserved_instruction(ctx);
25020 break;
25022 break;
25023 case OPC_DLSA:
25024 if ((ctx->insn_flags & ISA_MIPS_R6) || ase_msa_available(env)) {
25025 decode_opc_special_r6(env, ctx);
25027 break;
25028 #endif
25029 default:
25030 if (ctx->insn_flags & ISA_MIPS_R6) {
25031 decode_opc_special_r6(env, ctx);
25032 } else if (ctx->insn_flags & INSN_R5900) {
25033 decode_opc_special_tx79(env, ctx);
25034 } else {
25035 decode_opc_special_legacy(env, ctx);
25041 #if defined(TARGET_MIPS64)
25045 * MMI (MultiMedia Interface) ASE instructions
25046 * ===========================================
25050 * MMI instructions category: data communication
25051 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25053 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
25054 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
25055 * PCPYUD PEXEH PEXTLW PPACW
25056 * PEXEW PEXTUB
25057 * PEXTUH
25058 * PEXTUW
25062 * PCPYH rd, rt
25064 * Parallel Copy Halfword
25066 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25067 * +-----------+---------+---------+---------+---------+-----------+
25068 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
25069 * +-----------+---------+---------+---------+---------+-----------+
25071 static void gen_mmi_pcpyh(DisasContext *ctx)
25073 uint32_t pd, rt, rd;
25074 uint32_t opcode;
25076 opcode = ctx->opcode;
25078 pd = extract32(opcode, 21, 5);
25079 rt = extract32(opcode, 16, 5);
25080 rd = extract32(opcode, 11, 5);
25082 if (unlikely(pd != 0)) {
25083 gen_reserved_instruction(ctx);
25084 } else if (rd == 0) {
25085 /* nop */
25086 } else if (rt == 0) {
25087 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25088 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25089 } else {
25090 TCGv_i64 t0 = tcg_temp_new();
25091 TCGv_i64 t1 = tcg_temp_new();
25092 uint64_t mask = (1ULL << 16) - 1;
25094 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
25095 tcg_gen_movi_i64(t1, 0);
25096 tcg_gen_or_i64(t1, t0, t1);
25097 tcg_gen_shli_i64(t0, t0, 16);
25098 tcg_gen_or_i64(t1, t0, t1);
25099 tcg_gen_shli_i64(t0, t0, 16);
25100 tcg_gen_or_i64(t1, t0, t1);
25101 tcg_gen_shli_i64(t0, t0, 16);
25102 tcg_gen_or_i64(t1, t0, t1);
25104 tcg_gen_mov_i64(cpu_gpr[rd], t1);
25106 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
25107 tcg_gen_movi_i64(t1, 0);
25108 tcg_gen_or_i64(t1, t0, t1);
25109 tcg_gen_shli_i64(t0, t0, 16);
25110 tcg_gen_or_i64(t1, t0, t1);
25111 tcg_gen_shli_i64(t0, t0, 16);
25112 tcg_gen_or_i64(t1, t0, t1);
25113 tcg_gen_shli_i64(t0, t0, 16);
25114 tcg_gen_or_i64(t1, t0, t1);
25116 tcg_gen_mov_i64(cpu_mmr[rd], t1);
25118 tcg_temp_free(t0);
25119 tcg_temp_free(t1);
25124 * PCPYLD rd, rs, rt
25126 * Parallel Copy Lower Doubleword
25128 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25129 * +-----------+---------+---------+---------+---------+-----------+
25130 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
25131 * +-----------+---------+---------+---------+---------+-----------+
25133 static void gen_mmi_pcpyld(DisasContext *ctx)
25135 uint32_t rs, rt, rd;
25136 uint32_t opcode;
25138 opcode = ctx->opcode;
25140 rs = extract32(opcode, 21, 5);
25141 rt = extract32(opcode, 16, 5);
25142 rd = extract32(opcode, 11, 5);
25144 if (rd == 0) {
25145 /* nop */
25146 } else {
25147 if (rs == 0) {
25148 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25149 } else {
25150 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
25152 if (rt == 0) {
25153 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25154 } else {
25155 if (rd != rt) {
25156 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
25163 * PCPYUD rd, rs, rt
25165 * Parallel Copy Upper Doubleword
25167 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25168 * +-----------+---------+---------+---------+---------+-----------+
25169 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
25170 * +-----------+---------+---------+---------+---------+-----------+
25172 static void gen_mmi_pcpyud(DisasContext *ctx)
25174 uint32_t rs, rt, rd;
25175 uint32_t opcode;
25177 opcode = ctx->opcode;
25179 rs = extract32(opcode, 21, 5);
25180 rt = extract32(opcode, 16, 5);
25181 rd = extract32(opcode, 11, 5);
25183 if (rd == 0) {
25184 /* nop */
25185 } else {
25186 if (rs == 0) {
25187 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25188 } else {
25189 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
25191 if (rt == 0) {
25192 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25193 } else {
25194 if (rd != rt) {
25195 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
25201 #endif
25204 #if !defined(TARGET_MIPS64)
25206 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
25207 #define MXU_APTN1_A 0
25208 #define MXU_APTN1_S 1
25210 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
25211 #define MXU_APTN2_AA 0
25212 #define MXU_APTN2_AS 1
25213 #define MXU_APTN2_SA 2
25214 #define MXU_APTN2_SS 3
25216 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
25217 #define MXU_EPTN2_AA 0
25218 #define MXU_EPTN2_AS 1
25219 #define MXU_EPTN2_SA 2
25220 #define MXU_EPTN2_SS 3
25222 /* MXU operand getting pattern 'optn2' */
25223 #define MXU_OPTN2_PTN0 0
25224 #define MXU_OPTN2_PTN1 1
25225 #define MXU_OPTN2_PTN2 2
25226 #define MXU_OPTN2_PTN3 3
25227 /* alternative naming scheme for 'optn2' */
25228 #define MXU_OPTN2_WW 0
25229 #define MXU_OPTN2_LW 1
25230 #define MXU_OPTN2_HW 2
25231 #define MXU_OPTN2_XW 3
25233 /* MXU operand getting pattern 'optn3' */
25234 #define MXU_OPTN3_PTN0 0
25235 #define MXU_OPTN3_PTN1 1
25236 #define MXU_OPTN3_PTN2 2
25237 #define MXU_OPTN3_PTN3 3
25238 #define MXU_OPTN3_PTN4 4
25239 #define MXU_OPTN3_PTN5 5
25240 #define MXU_OPTN3_PTN6 6
25241 #define MXU_OPTN3_PTN7 7
25245 * S32I2M XRa, rb - Register move from GRF to XRF
25247 static void gen_mxu_s32i2m(DisasContext *ctx)
25249 TCGv t0;
25250 uint32_t XRa, Rb;
25252 t0 = tcg_temp_new();
25254 XRa = extract32(ctx->opcode, 6, 5);
25255 Rb = extract32(ctx->opcode, 16, 5);
25257 gen_load_gpr(t0, Rb);
25258 if (XRa <= 15) {
25259 gen_store_mxu_gpr(t0, XRa);
25260 } else if (XRa == 16) {
25261 gen_store_mxu_cr(t0);
25264 tcg_temp_free(t0);
25268 * S32M2I XRa, rb - Register move from XRF to GRF
25270 static void gen_mxu_s32m2i(DisasContext *ctx)
25272 TCGv t0;
25273 uint32_t XRa, Rb;
25275 t0 = tcg_temp_new();
25277 XRa = extract32(ctx->opcode, 6, 5);
25278 Rb = extract32(ctx->opcode, 16, 5);
25280 if (XRa <= 15) {
25281 gen_load_mxu_gpr(t0, XRa);
25282 } else if (XRa == 16) {
25283 gen_load_mxu_cr(t0);
25286 gen_store_gpr(t0, Rb);
25288 tcg_temp_free(t0);
25292 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
25294 static void gen_mxu_s8ldd(DisasContext *ctx)
25296 TCGv t0, t1;
25297 uint32_t XRa, Rb, s8, optn3;
25299 t0 = tcg_temp_new();
25300 t1 = tcg_temp_new();
25302 XRa = extract32(ctx->opcode, 6, 4);
25303 s8 = extract32(ctx->opcode, 10, 8);
25304 optn3 = extract32(ctx->opcode, 18, 3);
25305 Rb = extract32(ctx->opcode, 21, 5);
25307 gen_load_gpr(t0, Rb);
25308 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25310 switch (optn3) {
25311 /* XRa[7:0] = tmp8 */
25312 case MXU_OPTN3_PTN0:
25313 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25314 gen_load_mxu_gpr(t0, XRa);
25315 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25316 break;
25317 /* XRa[15:8] = tmp8 */
25318 case MXU_OPTN3_PTN1:
25319 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25320 gen_load_mxu_gpr(t0, XRa);
25321 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25322 break;
25323 /* XRa[23:16] = tmp8 */
25324 case MXU_OPTN3_PTN2:
25325 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25326 gen_load_mxu_gpr(t0, XRa);
25327 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25328 break;
25329 /* XRa[31:24] = tmp8 */
25330 case MXU_OPTN3_PTN3:
25331 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25332 gen_load_mxu_gpr(t0, XRa);
25333 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25334 break;
25335 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25336 case MXU_OPTN3_PTN4:
25337 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25338 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25339 break;
25340 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25341 case MXU_OPTN3_PTN5:
25342 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25343 tcg_gen_shli_tl(t1, t1, 8);
25344 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25345 break;
25346 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25347 case MXU_OPTN3_PTN6:
25348 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25349 tcg_gen_mov_tl(t0, t1);
25350 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25351 tcg_gen_shli_tl(t1, t1, 16);
25352 tcg_gen_or_tl(t0, t0, t1);
25353 break;
25354 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25355 case MXU_OPTN3_PTN7:
25356 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25357 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25358 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25359 break;
25362 gen_store_mxu_gpr(t0, XRa);
25364 tcg_temp_free(t0);
25365 tcg_temp_free(t1);
25369 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25371 static void gen_mxu_d16mul(DisasContext *ctx)
25373 TCGv t0, t1, t2, t3;
25374 uint32_t XRa, XRb, XRc, XRd, optn2;
25376 t0 = tcg_temp_new();
25377 t1 = tcg_temp_new();
25378 t2 = tcg_temp_new();
25379 t3 = tcg_temp_new();
25381 XRa = extract32(ctx->opcode, 6, 4);
25382 XRb = extract32(ctx->opcode, 10, 4);
25383 XRc = extract32(ctx->opcode, 14, 4);
25384 XRd = extract32(ctx->opcode, 18, 4);
25385 optn2 = extract32(ctx->opcode, 22, 2);
25387 gen_load_mxu_gpr(t1, XRb);
25388 tcg_gen_sextract_tl(t0, t1, 0, 16);
25389 tcg_gen_sextract_tl(t1, t1, 16, 16);
25390 gen_load_mxu_gpr(t3, XRc);
25391 tcg_gen_sextract_tl(t2, t3, 0, 16);
25392 tcg_gen_sextract_tl(t3, t3, 16, 16);
25394 switch (optn2) {
25395 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25396 tcg_gen_mul_tl(t3, t1, t3);
25397 tcg_gen_mul_tl(t2, t0, t2);
25398 break;
25399 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25400 tcg_gen_mul_tl(t3, t0, t3);
25401 tcg_gen_mul_tl(t2, t0, t2);
25402 break;
25403 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25404 tcg_gen_mul_tl(t3, t1, t3);
25405 tcg_gen_mul_tl(t2, t1, t2);
25406 break;
25407 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25408 tcg_gen_mul_tl(t3, t0, t3);
25409 tcg_gen_mul_tl(t2, t1, t2);
25410 break;
25412 gen_store_mxu_gpr(t3, XRa);
25413 gen_store_mxu_gpr(t2, XRd);
25415 tcg_temp_free(t0);
25416 tcg_temp_free(t1);
25417 tcg_temp_free(t2);
25418 tcg_temp_free(t3);
25422 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25423 * and accumulate
25425 static void gen_mxu_d16mac(DisasContext *ctx)
25427 TCGv t0, t1, t2, t3;
25428 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25430 t0 = tcg_temp_new();
25431 t1 = tcg_temp_new();
25432 t2 = tcg_temp_new();
25433 t3 = tcg_temp_new();
25435 XRa = extract32(ctx->opcode, 6, 4);
25436 XRb = extract32(ctx->opcode, 10, 4);
25437 XRc = extract32(ctx->opcode, 14, 4);
25438 XRd = extract32(ctx->opcode, 18, 4);
25439 optn2 = extract32(ctx->opcode, 22, 2);
25440 aptn2 = extract32(ctx->opcode, 24, 2);
25442 gen_load_mxu_gpr(t1, XRb);
25443 tcg_gen_sextract_tl(t0, t1, 0, 16);
25444 tcg_gen_sextract_tl(t1, t1, 16, 16);
25446 gen_load_mxu_gpr(t3, XRc);
25447 tcg_gen_sextract_tl(t2, t3, 0, 16);
25448 tcg_gen_sextract_tl(t3, t3, 16, 16);
25450 switch (optn2) {
25451 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25452 tcg_gen_mul_tl(t3, t1, t3);
25453 tcg_gen_mul_tl(t2, t0, t2);
25454 break;
25455 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25456 tcg_gen_mul_tl(t3, t0, t3);
25457 tcg_gen_mul_tl(t2, t0, t2);
25458 break;
25459 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25460 tcg_gen_mul_tl(t3, t1, t3);
25461 tcg_gen_mul_tl(t2, t1, t2);
25462 break;
25463 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25464 tcg_gen_mul_tl(t3, t0, t3);
25465 tcg_gen_mul_tl(t2, t1, t2);
25466 break;
25468 gen_load_mxu_gpr(t0, XRa);
25469 gen_load_mxu_gpr(t1, XRd);
25471 switch (aptn2) {
25472 case MXU_APTN2_AA:
25473 tcg_gen_add_tl(t3, t0, t3);
25474 tcg_gen_add_tl(t2, t1, t2);
25475 break;
25476 case MXU_APTN2_AS:
25477 tcg_gen_add_tl(t3, t0, t3);
25478 tcg_gen_sub_tl(t2, t1, t2);
25479 break;
25480 case MXU_APTN2_SA:
25481 tcg_gen_sub_tl(t3, t0, t3);
25482 tcg_gen_add_tl(t2, t1, t2);
25483 break;
25484 case MXU_APTN2_SS:
25485 tcg_gen_sub_tl(t3, t0, t3);
25486 tcg_gen_sub_tl(t2, t1, t2);
25487 break;
25489 gen_store_mxu_gpr(t3, XRa);
25490 gen_store_mxu_gpr(t2, XRd);
25492 tcg_temp_free(t0);
25493 tcg_temp_free(t1);
25494 tcg_temp_free(t2);
25495 tcg_temp_free(t3);
25499 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25500 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25502 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25504 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25505 uint32_t XRa, XRb, XRc, XRd, sel;
25507 t0 = tcg_temp_new();
25508 t1 = tcg_temp_new();
25509 t2 = tcg_temp_new();
25510 t3 = tcg_temp_new();
25511 t4 = tcg_temp_new();
25512 t5 = tcg_temp_new();
25513 t6 = tcg_temp_new();
25514 t7 = tcg_temp_new();
25516 XRa = extract32(ctx->opcode, 6, 4);
25517 XRb = extract32(ctx->opcode, 10, 4);
25518 XRc = extract32(ctx->opcode, 14, 4);
25519 XRd = extract32(ctx->opcode, 18, 4);
25520 sel = extract32(ctx->opcode, 22, 2);
25522 gen_load_mxu_gpr(t3, XRb);
25523 gen_load_mxu_gpr(t7, XRc);
25525 if (sel == 0x2) {
25526 /* Q8MULSU */
25527 tcg_gen_ext8s_tl(t0, t3);
25528 tcg_gen_shri_tl(t3, t3, 8);
25529 tcg_gen_ext8s_tl(t1, t3);
25530 tcg_gen_shri_tl(t3, t3, 8);
25531 tcg_gen_ext8s_tl(t2, t3);
25532 tcg_gen_shri_tl(t3, t3, 8);
25533 tcg_gen_ext8s_tl(t3, t3);
25534 } else {
25535 /* Q8MUL */
25536 tcg_gen_ext8u_tl(t0, t3);
25537 tcg_gen_shri_tl(t3, t3, 8);
25538 tcg_gen_ext8u_tl(t1, t3);
25539 tcg_gen_shri_tl(t3, t3, 8);
25540 tcg_gen_ext8u_tl(t2, t3);
25541 tcg_gen_shri_tl(t3, t3, 8);
25542 tcg_gen_ext8u_tl(t3, t3);
25545 tcg_gen_ext8u_tl(t4, t7);
25546 tcg_gen_shri_tl(t7, t7, 8);
25547 tcg_gen_ext8u_tl(t5, t7);
25548 tcg_gen_shri_tl(t7, t7, 8);
25549 tcg_gen_ext8u_tl(t6, t7);
25550 tcg_gen_shri_tl(t7, t7, 8);
25551 tcg_gen_ext8u_tl(t7, t7);
25553 tcg_gen_mul_tl(t0, t0, t4);
25554 tcg_gen_mul_tl(t1, t1, t5);
25555 tcg_gen_mul_tl(t2, t2, t6);
25556 tcg_gen_mul_tl(t3, t3, t7);
25558 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25559 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25560 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25561 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25563 tcg_gen_shli_tl(t1, t1, 16);
25564 tcg_gen_shli_tl(t3, t3, 16);
25566 tcg_gen_or_tl(t0, t0, t1);
25567 tcg_gen_or_tl(t1, t2, t3);
25569 gen_store_mxu_gpr(t0, XRd);
25570 gen_store_mxu_gpr(t1, XRa);
25572 tcg_temp_free(t0);
25573 tcg_temp_free(t1);
25574 tcg_temp_free(t2);
25575 tcg_temp_free(t3);
25576 tcg_temp_free(t4);
25577 tcg_temp_free(t5);
25578 tcg_temp_free(t6);
25579 tcg_temp_free(t7);
25583 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25584 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25586 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25588 TCGv t0, t1;
25589 uint32_t XRa, Rb, s12, sel;
25591 t0 = tcg_temp_new();
25592 t1 = tcg_temp_new();
25594 XRa = extract32(ctx->opcode, 6, 4);
25595 s12 = extract32(ctx->opcode, 10, 10);
25596 sel = extract32(ctx->opcode, 20, 1);
25597 Rb = extract32(ctx->opcode, 21, 5);
25599 gen_load_gpr(t0, Rb);
25601 tcg_gen_movi_tl(t1, s12);
25602 tcg_gen_shli_tl(t1, t1, 2);
25603 if (s12 & 0x200) {
25604 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25606 tcg_gen_add_tl(t1, t0, t1);
25607 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25609 if (sel == 1) {
25610 /* S32LDDR */
25611 tcg_gen_bswap32_tl(t1, t1);
25613 gen_store_mxu_gpr(t1, XRa);
25615 tcg_temp_free(t0);
25616 tcg_temp_free(t1);
25621 * MXU instruction category: logic
25622 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25624 * S32NOR S32AND S32OR S32XOR
25628 * S32NOR XRa, XRb, XRc
25629 * Update XRa with the result of logical bitwise 'nor' operation
25630 * applied to the content of XRb and XRc.
25632 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25633 * +-----------+---------+-----+-------+-------+-------+-----------+
25634 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25635 * +-----------+---------+-----+-------+-------+-------+-----------+
25637 static void gen_mxu_S32NOR(DisasContext *ctx)
25639 uint32_t pad, XRc, XRb, XRa;
25641 pad = extract32(ctx->opcode, 21, 5);
25642 XRc = extract32(ctx->opcode, 14, 4);
25643 XRb = extract32(ctx->opcode, 10, 4);
25644 XRa = extract32(ctx->opcode, 6, 4);
25646 if (unlikely(pad != 0)) {
25647 /* opcode padding incorrect -> do nothing */
25648 } else if (unlikely(XRa == 0)) {
25649 /* destination is zero register -> do nothing */
25650 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25651 /* both operands zero registers -> just set destination to all 1s */
25652 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25653 } else if (unlikely(XRb == 0)) {
25654 /* XRb zero register -> just set destination to the negation of XRc */
25655 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25656 } else if (unlikely(XRc == 0)) {
25657 /* XRa zero register -> just set destination to the negation of XRb */
25658 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25659 } else if (unlikely(XRb == XRc)) {
25660 /* both operands same -> just set destination to the negation of XRb */
25661 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25662 } else {
25663 /* the most general case */
25664 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25669 * S32AND XRa, XRb, XRc
25670 * Update XRa with the result of logical bitwise 'and' operation
25671 * applied to the content of XRb and XRc.
25673 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25674 * +-----------+---------+-----+-------+-------+-------+-----------+
25675 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25676 * +-----------+---------+-----+-------+-------+-------+-----------+
25678 static void gen_mxu_S32AND(DisasContext *ctx)
25680 uint32_t pad, XRc, XRb, XRa;
25682 pad = extract32(ctx->opcode, 21, 5);
25683 XRc = extract32(ctx->opcode, 14, 4);
25684 XRb = extract32(ctx->opcode, 10, 4);
25685 XRa = extract32(ctx->opcode, 6, 4);
25687 if (unlikely(pad != 0)) {
25688 /* opcode padding incorrect -> do nothing */
25689 } else if (unlikely(XRa == 0)) {
25690 /* destination is zero register -> do nothing */
25691 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25692 /* one of operands zero register -> just set destination to all 0s */
25693 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25694 } else if (unlikely(XRb == XRc)) {
25695 /* both operands same -> just set destination to one of them */
25696 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25697 } else {
25698 /* the most general case */
25699 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25704 * S32OR XRa, XRb, XRc
25705 * Update XRa with the result of logical bitwise 'or' operation
25706 * applied to the content of XRb and XRc.
25708 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25709 * +-----------+---------+-----+-------+-------+-------+-----------+
25710 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25711 * +-----------+---------+-----+-------+-------+-------+-----------+
25713 static void gen_mxu_S32OR(DisasContext *ctx)
25715 uint32_t pad, XRc, XRb, XRa;
25717 pad = extract32(ctx->opcode, 21, 5);
25718 XRc = extract32(ctx->opcode, 14, 4);
25719 XRb = extract32(ctx->opcode, 10, 4);
25720 XRa = extract32(ctx->opcode, 6, 4);
25722 if (unlikely(pad != 0)) {
25723 /* opcode padding incorrect -> do nothing */
25724 } else if (unlikely(XRa == 0)) {
25725 /* destination is zero register -> do nothing */
25726 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25727 /* both operands zero registers -> just set destination to all 0s */
25728 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25729 } else if (unlikely(XRb == 0)) {
25730 /* XRb zero register -> just set destination to the content of XRc */
25731 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25732 } else if (unlikely(XRc == 0)) {
25733 /* XRc zero register -> just set destination to the content of XRb */
25734 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25735 } else if (unlikely(XRb == XRc)) {
25736 /* both operands same -> just set destination to one of them */
25737 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25738 } else {
25739 /* the most general case */
25740 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25745 * S32XOR XRa, XRb, XRc
25746 * Update XRa with the result of logical bitwise 'xor' operation
25747 * applied to the content of XRb and XRc.
25749 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25750 * +-----------+---------+-----+-------+-------+-------+-----------+
25751 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25752 * +-----------+---------+-----+-------+-------+-------+-----------+
25754 static void gen_mxu_S32XOR(DisasContext *ctx)
25756 uint32_t pad, XRc, XRb, XRa;
25758 pad = extract32(ctx->opcode, 21, 5);
25759 XRc = extract32(ctx->opcode, 14, 4);
25760 XRb = extract32(ctx->opcode, 10, 4);
25761 XRa = extract32(ctx->opcode, 6, 4);
25763 if (unlikely(pad != 0)) {
25764 /* opcode padding incorrect -> do nothing */
25765 } else if (unlikely(XRa == 0)) {
25766 /* destination is zero register -> do nothing */
25767 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25768 /* both operands zero registers -> just set destination to all 0s */
25769 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25770 } else if (unlikely(XRb == 0)) {
25771 /* XRb zero register -> just set destination to the content of XRc */
25772 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25773 } else if (unlikely(XRc == 0)) {
25774 /* XRc zero register -> just set destination to the content of XRb */
25775 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25776 } else if (unlikely(XRb == XRc)) {
25777 /* both operands same -> just set destination to all 0s */
25778 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25779 } else {
25780 /* the most general case */
25781 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25787 * MXU instruction category max/min
25788 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25790 * S32MAX D16MAX Q8MAX
25791 * S32MIN D16MIN Q8MIN
25795 * S32MAX XRa, XRb, XRc
25796 * Update XRa with the maximum of signed 32-bit integers contained
25797 * in XRb and XRc.
25799 * S32MIN XRa, XRb, XRc
25800 * Update XRa with the minimum of signed 32-bit integers contained
25801 * in XRb and XRc.
25803 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25804 * +-----------+---------+-----+-------+-------+-------+-----------+
25805 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25806 * +-----------+---------+-----+-------+-------+-------+-----------+
25808 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25810 uint32_t pad, opc, XRc, XRb, XRa;
25812 pad = extract32(ctx->opcode, 21, 5);
25813 opc = extract32(ctx->opcode, 18, 3);
25814 XRc = extract32(ctx->opcode, 14, 4);
25815 XRb = extract32(ctx->opcode, 10, 4);
25816 XRa = extract32(ctx->opcode, 6, 4);
25818 if (unlikely(pad != 0)) {
25819 /* opcode padding incorrect -> do nothing */
25820 } else if (unlikely(XRa == 0)) {
25821 /* destination is zero register -> do nothing */
25822 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25823 /* both operands zero registers -> just set destination to zero */
25824 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25825 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25826 /* exactly one operand is zero register - find which one is not...*/
25827 uint32_t XRx = XRb ? XRb : XRc;
25828 /* ...and do max/min operation with one operand 0 */
25829 if (opc == OPC_MXU_S32MAX) {
25830 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25831 } else {
25832 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25834 } else if (unlikely(XRb == XRc)) {
25835 /* both operands same -> just set destination to one of them */
25836 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25837 } else {
25838 /* the most general case */
25839 if (opc == OPC_MXU_S32MAX) {
25840 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25841 mxu_gpr[XRc - 1]);
25842 } else {
25843 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25844 mxu_gpr[XRc - 1]);
25850 * D16MAX
25851 * Update XRa with the 16-bit-wise maximums of signed integers
25852 * contained in XRb and XRc.
25854 * D16MIN
25855 * Update XRa with the 16-bit-wise minimums of signed integers
25856 * contained in XRb and XRc.
25858 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25859 * +-----------+---------+-----+-------+-------+-------+-----------+
25860 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25861 * +-----------+---------+-----+-------+-------+-------+-----------+
25863 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25865 uint32_t pad, opc, XRc, XRb, XRa;
25867 pad = extract32(ctx->opcode, 21, 5);
25868 opc = extract32(ctx->opcode, 18, 3);
25869 XRc = extract32(ctx->opcode, 14, 4);
25870 XRb = extract32(ctx->opcode, 10, 4);
25871 XRa = extract32(ctx->opcode, 6, 4);
25873 if (unlikely(pad != 0)) {
25874 /* opcode padding incorrect -> do nothing */
25875 } else if (unlikely(XRc == 0)) {
25876 /* destination is zero register -> do nothing */
25877 } else if (unlikely((XRb == 0) && (XRa == 0))) {
25878 /* both operands zero registers -> just set destination to zero */
25879 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
25880 } else if (unlikely((XRb == 0) || (XRa == 0))) {
25881 /* exactly one operand is zero register - find which one is not...*/
25882 uint32_t XRx = XRb ? XRb : XRc;
25883 /* ...and do half-word-wise max/min with one operand 0 */
25884 TCGv_i32 t0 = tcg_temp_new();
25885 TCGv_i32 t1 = tcg_const_i32(0);
25887 /* the left half-word first */
25888 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
25889 if (opc == OPC_MXU_D16MAX) {
25890 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25891 } else {
25892 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25895 /* the right half-word */
25896 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
25897 /* move half-words to the leftmost position */
25898 tcg_gen_shli_i32(t0, t0, 16);
25899 /* t0 will be max/min of t0 and t1 */
25900 if (opc == OPC_MXU_D16MAX) {
25901 tcg_gen_smax_i32(t0, t0, t1);
25902 } else {
25903 tcg_gen_smin_i32(t0, t0, t1);
25905 /* return resulting half-words to its original position */
25906 tcg_gen_shri_i32(t0, t0, 16);
25907 /* finally update the destination */
25908 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25910 tcg_temp_free(t1);
25911 tcg_temp_free(t0);
25912 } else if (unlikely(XRb == XRc)) {
25913 /* both operands same -> just set destination to one of them */
25914 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25915 } else {
25916 /* the most general case */
25917 TCGv_i32 t0 = tcg_temp_new();
25918 TCGv_i32 t1 = tcg_temp_new();
25920 /* the left half-word first */
25921 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
25922 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
25923 if (opc == OPC_MXU_D16MAX) {
25924 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25925 } else {
25926 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25929 /* the right half-word */
25930 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
25931 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
25932 /* move half-words to the leftmost position */
25933 tcg_gen_shli_i32(t0, t0, 16);
25934 tcg_gen_shli_i32(t1, t1, 16);
25935 /* t0 will be max/min of t0 and t1 */
25936 if (opc == OPC_MXU_D16MAX) {
25937 tcg_gen_smax_i32(t0, t0, t1);
25938 } else {
25939 tcg_gen_smin_i32(t0, t0, t1);
25941 /* return resulting half-words to its original position */
25942 tcg_gen_shri_i32(t0, t0, 16);
25943 /* finally update the destination */
25944 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
25946 tcg_temp_free(t1);
25947 tcg_temp_free(t0);
25952 * Q8MAX
25953 * Update XRa with the 8-bit-wise maximums of signed integers
25954 * contained in XRb and XRc.
25956 * Q8MIN
25957 * Update XRa with the 8-bit-wise minimums of signed integers
25958 * contained in XRb and XRc.
25960 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
25961 * +-----------+---------+-----+-------+-------+-------+-----------+
25962 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25963 * +-----------+---------+-----+-------+-------+-------+-----------+
25965 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
25967 uint32_t pad, opc, XRc, XRb, XRa;
25969 pad = extract32(ctx->opcode, 21, 5);
25970 opc = extract32(ctx->opcode, 18, 3);
25971 XRc = extract32(ctx->opcode, 14, 4);
25972 XRb = extract32(ctx->opcode, 10, 4);
25973 XRa = extract32(ctx->opcode, 6, 4);
25975 if (unlikely(pad != 0)) {
25976 /* opcode padding incorrect -> do nothing */
25977 } else if (unlikely(XRa == 0)) {
25978 /* destination is zero register -> do nothing */
25979 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25980 /* both operands zero registers -> just set destination to zero */
25981 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25982 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25983 /* exactly one operand is zero register - make it be the first...*/
25984 uint32_t XRx = XRb ? XRb : XRc;
25985 /* ...and do byte-wise max/min with one operand 0 */
25986 TCGv_i32 t0 = tcg_temp_new();
25987 TCGv_i32 t1 = tcg_const_i32(0);
25988 int32_t i;
25990 /* the leftmost byte (byte 3) first */
25991 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
25992 if (opc == OPC_MXU_Q8MAX) {
25993 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
25994 } else {
25995 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
25998 /* bytes 2, 1, 0 */
25999 for (i = 2; i >= 0; i--) {
26000 /* extract the byte */
26001 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
26002 /* move the byte to the leftmost position */
26003 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26004 /* t0 will be max/min of t0 and t1 */
26005 if (opc == OPC_MXU_Q8MAX) {
26006 tcg_gen_smax_i32(t0, t0, t1);
26007 } else {
26008 tcg_gen_smin_i32(t0, t0, t1);
26010 /* return resulting byte to its original position */
26011 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26012 /* finally update the destination */
26013 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26016 tcg_temp_free(t1);
26017 tcg_temp_free(t0);
26018 } else if (unlikely(XRb == XRc)) {
26019 /* both operands same -> just set destination to one of them */
26020 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26021 } else {
26022 /* the most general case */
26023 TCGv_i32 t0 = tcg_temp_new();
26024 TCGv_i32 t1 = tcg_temp_new();
26025 int32_t i;
26027 /* the leftmost bytes (bytes 3) first */
26028 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
26029 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26030 if (opc == OPC_MXU_Q8MAX) {
26031 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26032 } else {
26033 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26036 /* bytes 2, 1, 0 */
26037 for (i = 2; i >= 0; i--) {
26038 /* extract corresponding bytes */
26039 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
26040 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
26041 /* move the bytes to the leftmost position */
26042 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26043 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
26044 /* t0 will be max/min of t0 and t1 */
26045 if (opc == OPC_MXU_Q8MAX) {
26046 tcg_gen_smax_i32(t0, t0, t1);
26047 } else {
26048 tcg_gen_smin_i32(t0, t0, t1);
26050 /* return resulting byte to its original position */
26051 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26052 /* finally update the destination */
26053 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26056 tcg_temp_free(t1);
26057 tcg_temp_free(t0);
26063 * MXU instruction category: align
26064 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26066 * S32ALN S32ALNI
26070 * S32ALNI XRc, XRb, XRa, optn3
26071 * Arrange bytes from XRb and XRc according to one of five sets of
26072 * rules determined by optn3, and place the result in XRa.
26074 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26075 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26076 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26077 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26080 static void gen_mxu_S32ALNI(DisasContext *ctx)
26082 uint32_t optn3, pad, XRc, XRb, XRa;
26084 optn3 = extract32(ctx->opcode, 23, 3);
26085 pad = extract32(ctx->opcode, 21, 2);
26086 XRc = extract32(ctx->opcode, 14, 4);
26087 XRb = extract32(ctx->opcode, 10, 4);
26088 XRa = extract32(ctx->opcode, 6, 4);
26090 if (unlikely(pad != 0)) {
26091 /* opcode padding incorrect -> do nothing */
26092 } else if (unlikely(XRa == 0)) {
26093 /* destination is zero register -> do nothing */
26094 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26095 /* both operands zero registers -> just set destination to all 0s */
26096 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26097 } else if (unlikely(XRb == 0)) {
26098 /* XRb zero register -> just appropriatelly shift XRc into XRa */
26099 switch (optn3) {
26100 case MXU_OPTN3_PTN0:
26101 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26102 break;
26103 case MXU_OPTN3_PTN1:
26104 case MXU_OPTN3_PTN2:
26105 case MXU_OPTN3_PTN3:
26106 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
26107 8 * (4 - optn3));
26108 break;
26109 case MXU_OPTN3_PTN4:
26110 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26111 break;
26113 } else if (unlikely(XRc == 0)) {
26114 /* XRc zero register -> just appropriatelly shift XRb into XRa */
26115 switch (optn3) {
26116 case MXU_OPTN3_PTN0:
26117 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26118 break;
26119 case MXU_OPTN3_PTN1:
26120 case MXU_OPTN3_PTN2:
26121 case MXU_OPTN3_PTN3:
26122 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26123 break;
26124 case MXU_OPTN3_PTN4:
26125 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26126 break;
26128 } else if (unlikely(XRb == XRc)) {
26129 /* both operands same -> just rotation or moving from any of them */
26130 switch (optn3) {
26131 case MXU_OPTN3_PTN0:
26132 case MXU_OPTN3_PTN4:
26133 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26134 break;
26135 case MXU_OPTN3_PTN1:
26136 case MXU_OPTN3_PTN2:
26137 case MXU_OPTN3_PTN3:
26138 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26139 break;
26141 } else {
26142 /* the most general case */
26143 switch (optn3) {
26144 case MXU_OPTN3_PTN0:
26146 /* */
26147 /* XRb XRc */
26148 /* +---------------+ */
26149 /* | A B C D | E F G H */
26150 /* +-------+-------+ */
26151 /* | */
26152 /* XRa */
26153 /* */
26155 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26157 break;
26158 case MXU_OPTN3_PTN1:
26160 /* */
26161 /* XRb XRc */
26162 /* +-------------------+ */
26163 /* A | B C D E | F G H */
26164 /* +---------+---------+ */
26165 /* | */
26166 /* XRa */
26167 /* */
26169 TCGv_i32 t0 = tcg_temp_new();
26170 TCGv_i32 t1 = tcg_temp_new();
26172 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
26173 tcg_gen_shli_i32(t0, t0, 8);
26175 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26176 tcg_gen_shri_i32(t1, t1, 24);
26178 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26180 tcg_temp_free(t1);
26181 tcg_temp_free(t0);
26183 break;
26184 case MXU_OPTN3_PTN2:
26186 /* */
26187 /* XRb XRc */
26188 /* +-------------------+ */
26189 /* A B | C D E F | G H */
26190 /* +---------+---------+ */
26191 /* | */
26192 /* XRa */
26193 /* */
26195 TCGv_i32 t0 = tcg_temp_new();
26196 TCGv_i32 t1 = tcg_temp_new();
26198 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26199 tcg_gen_shli_i32(t0, t0, 16);
26201 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26202 tcg_gen_shri_i32(t1, t1, 16);
26204 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26206 tcg_temp_free(t1);
26207 tcg_temp_free(t0);
26209 break;
26210 case MXU_OPTN3_PTN3:
26212 /* */
26213 /* XRb XRc */
26214 /* +-------------------+ */
26215 /* A B C | D E F G | H */
26216 /* +---------+---------+ */
26217 /* | */
26218 /* XRa */
26219 /* */
26221 TCGv_i32 t0 = tcg_temp_new();
26222 TCGv_i32 t1 = tcg_temp_new();
26224 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
26225 tcg_gen_shli_i32(t0, t0, 24);
26227 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
26228 tcg_gen_shri_i32(t1, t1, 8);
26230 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26232 tcg_temp_free(t1);
26233 tcg_temp_free(t0);
26235 break;
26236 case MXU_OPTN3_PTN4:
26238 /* */
26239 /* XRb XRc */
26240 /* +---------------+ */
26241 /* A B C D | E F G H | */
26242 /* +-------+-------+ */
26243 /* | */
26244 /* XRa */
26245 /* */
26247 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26249 break;
26256 * Decoding engine for MXU
26257 * =======================
26262 * Decode MXU pool00
26264 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26265 * +-----------+---------+-----+-------+-------+-------+-----------+
26266 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
26267 * +-----------+---------+-----+-------+-------+-------+-----------+
26270 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
26272 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26274 switch (opcode) {
26275 case OPC_MXU_S32MAX:
26276 case OPC_MXU_S32MIN:
26277 gen_mxu_S32MAX_S32MIN(ctx);
26278 break;
26279 case OPC_MXU_D16MAX:
26280 case OPC_MXU_D16MIN:
26281 gen_mxu_D16MAX_D16MIN(ctx);
26282 break;
26283 case OPC_MXU_Q8MAX:
26284 case OPC_MXU_Q8MIN:
26285 gen_mxu_Q8MAX_Q8MIN(ctx);
26286 break;
26287 case OPC_MXU_Q8SLT:
26288 /* TODO: Implement emulation of Q8SLT instruction. */
26289 MIPS_INVAL("OPC_MXU_Q8SLT");
26290 gen_reserved_instruction(ctx);
26291 break;
26292 case OPC_MXU_Q8SLTU:
26293 /* TODO: Implement emulation of Q8SLTU instruction. */
26294 MIPS_INVAL("OPC_MXU_Q8SLTU");
26295 gen_reserved_instruction(ctx);
26296 break;
26297 default:
26298 MIPS_INVAL("decode_opc_mxu");
26299 gen_reserved_instruction(ctx);
26300 break;
26306 * Decode MXU pool01
26308 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26309 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26310 * +-----------+---------+-----+-------+-------+-------+-----------+
26311 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26312 * +-----------+---------+-----+-------+-------+-------+-----------+
26314 * Q8ADD:
26315 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26316 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26317 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26318 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26321 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26323 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26325 switch (opcode) {
26326 case OPC_MXU_S32SLT:
26327 /* TODO: Implement emulation of S32SLT instruction. */
26328 MIPS_INVAL("OPC_MXU_S32SLT");
26329 gen_reserved_instruction(ctx);
26330 break;
26331 case OPC_MXU_D16SLT:
26332 /* TODO: Implement emulation of D16SLT instruction. */
26333 MIPS_INVAL("OPC_MXU_D16SLT");
26334 gen_reserved_instruction(ctx);
26335 break;
26336 case OPC_MXU_D16AVG:
26337 /* TODO: Implement emulation of D16AVG instruction. */
26338 MIPS_INVAL("OPC_MXU_D16AVG");
26339 gen_reserved_instruction(ctx);
26340 break;
26341 case OPC_MXU_D16AVGR:
26342 /* TODO: Implement emulation of D16AVGR instruction. */
26343 MIPS_INVAL("OPC_MXU_D16AVGR");
26344 gen_reserved_instruction(ctx);
26345 break;
26346 case OPC_MXU_Q8AVG:
26347 /* TODO: Implement emulation of Q8AVG instruction. */
26348 MIPS_INVAL("OPC_MXU_Q8AVG");
26349 gen_reserved_instruction(ctx);
26350 break;
26351 case OPC_MXU_Q8AVGR:
26352 /* TODO: Implement emulation of Q8AVGR instruction. */
26353 MIPS_INVAL("OPC_MXU_Q8AVGR");
26354 gen_reserved_instruction(ctx);
26355 break;
26356 case OPC_MXU_Q8ADD:
26357 /* TODO: Implement emulation of Q8ADD instruction. */
26358 MIPS_INVAL("OPC_MXU_Q8ADD");
26359 gen_reserved_instruction(ctx);
26360 break;
26361 default:
26362 MIPS_INVAL("decode_opc_mxu");
26363 gen_reserved_instruction(ctx);
26364 break;
26370 * Decode MXU pool02
26372 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26373 * +-----------+---------+-----+-------+-------+-------+-----------+
26374 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26375 * +-----------+---------+-----+-------+-------+-------+-----------+
26378 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26380 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26382 switch (opcode) {
26383 case OPC_MXU_S32CPS:
26384 /* TODO: Implement emulation of S32CPS instruction. */
26385 MIPS_INVAL("OPC_MXU_S32CPS");
26386 gen_reserved_instruction(ctx);
26387 break;
26388 case OPC_MXU_D16CPS:
26389 /* TODO: Implement emulation of D16CPS instruction. */
26390 MIPS_INVAL("OPC_MXU_D16CPS");
26391 gen_reserved_instruction(ctx);
26392 break;
26393 case OPC_MXU_Q8ABD:
26394 /* TODO: Implement emulation of Q8ABD instruction. */
26395 MIPS_INVAL("OPC_MXU_Q8ABD");
26396 gen_reserved_instruction(ctx);
26397 break;
26398 case OPC_MXU_Q16SAT:
26399 /* TODO: Implement emulation of Q16SAT instruction. */
26400 MIPS_INVAL("OPC_MXU_Q16SAT");
26401 gen_reserved_instruction(ctx);
26402 break;
26403 default:
26404 MIPS_INVAL("decode_opc_mxu");
26405 gen_reserved_instruction(ctx);
26406 break;
26412 * Decode MXU pool03
26414 * D16MULF:
26415 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26416 * +-----------+---+---+-------+-------+-------+-------+-----------+
26417 * | SPECIAL2 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26418 * +-----------+---+---+-------+-------+-------+-------+-----------+
26420 * D16MULE:
26421 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26422 * +-----------+---+---+-------+-------+-------+-------+-----------+
26423 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26424 * +-----------+---+---+-------+-------+-------+-------+-----------+
26427 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26429 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26431 switch (opcode) {
26432 case OPC_MXU_D16MULF:
26433 /* TODO: Implement emulation of D16MULF instruction. */
26434 MIPS_INVAL("OPC_MXU_D16MULF");
26435 gen_reserved_instruction(ctx);
26436 break;
26437 case OPC_MXU_D16MULE:
26438 /* TODO: Implement emulation of D16MULE instruction. */
26439 MIPS_INVAL("OPC_MXU_D16MULE");
26440 gen_reserved_instruction(ctx);
26441 break;
26442 default:
26443 MIPS_INVAL("decode_opc_mxu");
26444 gen_reserved_instruction(ctx);
26445 break;
26451 * Decode MXU pool04
26453 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26454 * +-----------+---------+-+-------------------+-------+-----------+
26455 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26456 * +-----------+---------+-+-------------------+-------+-----------+
26459 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26461 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26463 switch (opcode) {
26464 case OPC_MXU_S32LDD:
26465 case OPC_MXU_S32LDDR:
26466 gen_mxu_s32ldd_s32lddr(ctx);
26467 break;
26468 default:
26469 MIPS_INVAL("decode_opc_mxu");
26470 gen_reserved_instruction(ctx);
26471 break;
26477 * Decode MXU pool05
26479 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26480 * +-----------+---------+-+-------------------+-------+-----------+
26481 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL05|
26482 * +-----------+---------+-+-------------------+-------+-----------+
26485 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26487 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26489 switch (opcode) {
26490 case OPC_MXU_S32STD:
26491 /* TODO: Implement emulation of S32STD instruction. */
26492 MIPS_INVAL("OPC_MXU_S32STD");
26493 gen_reserved_instruction(ctx);
26494 break;
26495 case OPC_MXU_S32STDR:
26496 /* TODO: Implement emulation of S32STDR instruction. */
26497 MIPS_INVAL("OPC_MXU_S32STDR");
26498 gen_reserved_instruction(ctx);
26499 break;
26500 default:
26501 MIPS_INVAL("decode_opc_mxu");
26502 gen_reserved_instruction(ctx);
26503 break;
26509 * Decode MXU pool06
26511 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26512 * +-----------+---------+---------+---+-------+-------+-----------+
26513 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL06|
26514 * +-----------+---------+---------+---+-------+-------+-----------+
26517 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26519 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26521 switch (opcode) {
26522 case OPC_MXU_S32LDDV:
26523 /* TODO: Implement emulation of S32LDDV instruction. */
26524 MIPS_INVAL("OPC_MXU_S32LDDV");
26525 gen_reserved_instruction(ctx);
26526 break;
26527 case OPC_MXU_S32LDDVR:
26528 /* TODO: Implement emulation of S32LDDVR instruction. */
26529 MIPS_INVAL("OPC_MXU_S32LDDVR");
26530 gen_reserved_instruction(ctx);
26531 break;
26532 default:
26533 MIPS_INVAL("decode_opc_mxu");
26534 gen_reserved_instruction(ctx);
26535 break;
26541 * Decode MXU pool07
26543 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26544 * +-----------+---------+---------+---+-------+-------+-----------+
26545 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL07|
26546 * +-----------+---------+---------+---+-------+-------+-----------+
26549 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26551 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26553 switch (opcode) {
26554 case OPC_MXU_S32STDV:
26555 /* TODO: Implement emulation of S32TDV instruction. */
26556 MIPS_INVAL("OPC_MXU_S32TDV");
26557 gen_reserved_instruction(ctx);
26558 break;
26559 case OPC_MXU_S32STDVR:
26560 /* TODO: Implement emulation of S32TDVR instruction. */
26561 MIPS_INVAL("OPC_MXU_S32TDVR");
26562 gen_reserved_instruction(ctx);
26563 break;
26564 default:
26565 MIPS_INVAL("decode_opc_mxu");
26566 gen_reserved_instruction(ctx);
26567 break;
26573 * Decode MXU pool08
26575 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26576 * +-----------+---------+-+-------------------+-------+-----------+
26577 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL08|
26578 * +-----------+---------+-+-------------------+-------+-----------+
26581 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26583 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26585 switch (opcode) {
26586 case OPC_MXU_S32LDI:
26587 /* TODO: Implement emulation of S32LDI instruction. */
26588 MIPS_INVAL("OPC_MXU_S32LDI");
26589 gen_reserved_instruction(ctx);
26590 break;
26591 case OPC_MXU_S32LDIR:
26592 /* TODO: Implement emulation of S32LDIR instruction. */
26593 MIPS_INVAL("OPC_MXU_S32LDIR");
26594 gen_reserved_instruction(ctx);
26595 break;
26596 default:
26597 MIPS_INVAL("decode_opc_mxu");
26598 gen_reserved_instruction(ctx);
26599 break;
26605 * Decode MXU pool09
26607 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26608 * +-----------+---------+-+-------------------+-------+-----------+
26609 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26610 * +-----------+---------+-+-------------------+-------+-----------+
26613 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26615 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26617 switch (opcode) {
26618 case OPC_MXU_S32SDI:
26619 /* TODO: Implement emulation of S32SDI instruction. */
26620 MIPS_INVAL("OPC_MXU_S32SDI");
26621 gen_reserved_instruction(ctx);
26622 break;
26623 case OPC_MXU_S32SDIR:
26624 /* TODO: Implement emulation of S32SDIR instruction. */
26625 MIPS_INVAL("OPC_MXU_S32SDIR");
26626 gen_reserved_instruction(ctx);
26627 break;
26628 default:
26629 MIPS_INVAL("decode_opc_mxu");
26630 gen_reserved_instruction(ctx);
26631 break;
26637 * Decode MXU pool10
26639 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26640 * +-----------+---------+---------+---+-------+-------+-----------+
26641 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26642 * +-----------+---------+---------+---+-------+-------+-----------+
26645 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26647 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26649 switch (opcode) {
26650 case OPC_MXU_S32LDIV:
26651 /* TODO: Implement emulation of S32LDIV instruction. */
26652 MIPS_INVAL("OPC_MXU_S32LDIV");
26653 gen_reserved_instruction(ctx);
26654 break;
26655 case OPC_MXU_S32LDIVR:
26656 /* TODO: Implement emulation of S32LDIVR instruction. */
26657 MIPS_INVAL("OPC_MXU_S32LDIVR");
26658 gen_reserved_instruction(ctx);
26659 break;
26660 default:
26661 MIPS_INVAL("decode_opc_mxu");
26662 gen_reserved_instruction(ctx);
26663 break;
26669 * Decode MXU pool11
26671 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26672 * +-----------+---------+---------+---+-------+-------+-----------+
26673 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26674 * +-----------+---------+---------+---+-------+-------+-----------+
26677 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26679 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26681 switch (opcode) {
26682 case OPC_MXU_S32SDIV:
26683 /* TODO: Implement emulation of S32SDIV instruction. */
26684 MIPS_INVAL("OPC_MXU_S32SDIV");
26685 gen_reserved_instruction(ctx);
26686 break;
26687 case OPC_MXU_S32SDIVR:
26688 /* TODO: Implement emulation of S32SDIVR instruction. */
26689 MIPS_INVAL("OPC_MXU_S32SDIVR");
26690 gen_reserved_instruction(ctx);
26691 break;
26692 default:
26693 MIPS_INVAL("decode_opc_mxu");
26694 gen_reserved_instruction(ctx);
26695 break;
26701 * Decode MXU pool12
26703 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26704 * +-----------+---+---+-------+-------+-------+-------+-----------+
26705 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26706 * +-----------+---+---+-------+-------+-------+-------+-----------+
26709 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26711 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26713 switch (opcode) {
26714 case OPC_MXU_D32ACC:
26715 /* TODO: Implement emulation of D32ACC instruction. */
26716 MIPS_INVAL("OPC_MXU_D32ACC");
26717 gen_reserved_instruction(ctx);
26718 break;
26719 case OPC_MXU_D32ACCM:
26720 /* TODO: Implement emulation of D32ACCM instruction. */
26721 MIPS_INVAL("OPC_MXU_D32ACCM");
26722 gen_reserved_instruction(ctx);
26723 break;
26724 case OPC_MXU_D32ASUM:
26725 /* TODO: Implement emulation of D32ASUM instruction. */
26726 MIPS_INVAL("OPC_MXU_D32ASUM");
26727 gen_reserved_instruction(ctx);
26728 break;
26729 default:
26730 MIPS_INVAL("decode_opc_mxu");
26731 gen_reserved_instruction(ctx);
26732 break;
26738 * Decode MXU pool13
26740 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26741 * +-----------+---+---+-------+-------+-------+-------+-----------+
26742 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26743 * +-----------+---+---+-------+-------+-------+-------+-----------+
26746 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26748 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26750 switch (opcode) {
26751 case OPC_MXU_Q16ACC:
26752 /* TODO: Implement emulation of Q16ACC instruction. */
26753 MIPS_INVAL("OPC_MXU_Q16ACC");
26754 gen_reserved_instruction(ctx);
26755 break;
26756 case OPC_MXU_Q16ACCM:
26757 /* TODO: Implement emulation of Q16ACCM instruction. */
26758 MIPS_INVAL("OPC_MXU_Q16ACCM");
26759 gen_reserved_instruction(ctx);
26760 break;
26761 case OPC_MXU_Q16ASUM:
26762 /* TODO: Implement emulation of Q16ASUM instruction. */
26763 MIPS_INVAL("OPC_MXU_Q16ASUM");
26764 gen_reserved_instruction(ctx);
26765 break;
26766 default:
26767 MIPS_INVAL("decode_opc_mxu");
26768 gen_reserved_instruction(ctx);
26769 break;
26775 * Decode MXU pool14
26777 * Q8ADDE, Q8ACCE:
26778 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26779 * +-----------+---+---+-------+-------+-------+-------+-----------+
26780 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26781 * +-----------+---+---+-------+-------+-------+-------+-----------+
26783 * D8SUM, D8SUMC:
26784 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26785 * +-----------+---+---+-------+-------+-------+-------+-----------+
26786 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26787 * +-----------+---+---+-------+-------+-------+-------+-----------+
26790 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26792 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26794 switch (opcode) {
26795 case OPC_MXU_Q8ADDE:
26796 /* TODO: Implement emulation of Q8ADDE instruction. */
26797 MIPS_INVAL("OPC_MXU_Q8ADDE");
26798 gen_reserved_instruction(ctx);
26799 break;
26800 case OPC_MXU_D8SUM:
26801 /* TODO: Implement emulation of D8SUM instruction. */
26802 MIPS_INVAL("OPC_MXU_D8SUM");
26803 gen_reserved_instruction(ctx);
26804 break;
26805 case OPC_MXU_D8SUMC:
26806 /* TODO: Implement emulation of D8SUMC instruction. */
26807 MIPS_INVAL("OPC_MXU_D8SUMC");
26808 gen_reserved_instruction(ctx);
26809 break;
26810 default:
26811 MIPS_INVAL("decode_opc_mxu");
26812 gen_reserved_instruction(ctx);
26813 break;
26819 * Decode MXU pool15
26821 * S32MUL, S32MULU, S32EXTRV:
26822 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26823 * +-----------+---------+---------+---+-------+-------+-----------+
26824 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26825 * +-----------+---------+---------+---+-------+-------+-----------+
26827 * S32EXTR:
26828 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26829 * +-----------+---------+---------+---+-------+-------+-----------+
26830 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26831 * +-----------+---------+---------+---+-------+-------+-----------+
26834 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26836 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26838 switch (opcode) {
26839 case OPC_MXU_S32MUL:
26840 /* TODO: Implement emulation of S32MUL instruction. */
26841 MIPS_INVAL("OPC_MXU_S32MUL");
26842 gen_reserved_instruction(ctx);
26843 break;
26844 case OPC_MXU_S32MULU:
26845 /* TODO: Implement emulation of S32MULU instruction. */
26846 MIPS_INVAL("OPC_MXU_S32MULU");
26847 gen_reserved_instruction(ctx);
26848 break;
26849 case OPC_MXU_S32EXTR:
26850 /* TODO: Implement emulation of S32EXTR instruction. */
26851 MIPS_INVAL("OPC_MXU_S32EXTR");
26852 gen_reserved_instruction(ctx);
26853 break;
26854 case OPC_MXU_S32EXTRV:
26855 /* TODO: Implement emulation of S32EXTRV instruction. */
26856 MIPS_INVAL("OPC_MXU_S32EXTRV");
26857 gen_reserved_instruction(ctx);
26858 break;
26859 default:
26860 MIPS_INVAL("decode_opc_mxu");
26861 gen_reserved_instruction(ctx);
26862 break;
26868 * Decode MXU pool16
26870 * D32SARW:
26871 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26872 * +-----------+---------+-----+-------+-------+-------+-----------+
26873 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
26874 * +-----------+---------+-----+-------+-------+-------+-----------+
26876 * S32ALN:
26877 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26878 * +-----------+---------+-----+-------+-------+-------+-----------+
26879 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
26880 * +-----------+---------+-----+-------+-------+-------+-----------+
26882 * S32ALNI:
26883 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26884 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26885 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26886 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26888 * S32LUI:
26889 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26890 * +-----------+-----+---+-----+-------+---------------+-----------+
26891 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
26892 * +-----------+-----+---+-----+-------+---------------+-----------+
26894 * S32NOR, S32AND, S32OR, S32XOR:
26895 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26896 * +-----------+---------+-----+-------+-------+-------+-----------+
26897 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26898 * +-----------+---------+-----+-------+-------+-------+-----------+
26901 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
26903 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26905 switch (opcode) {
26906 case OPC_MXU_D32SARW:
26907 /* TODO: Implement emulation of D32SARW instruction. */
26908 MIPS_INVAL("OPC_MXU_D32SARW");
26909 gen_reserved_instruction(ctx);
26910 break;
26911 case OPC_MXU_S32ALN:
26912 /* TODO: Implement emulation of S32ALN instruction. */
26913 MIPS_INVAL("OPC_MXU_S32ALN");
26914 gen_reserved_instruction(ctx);
26915 break;
26916 case OPC_MXU_S32ALNI:
26917 gen_mxu_S32ALNI(ctx);
26918 break;
26919 case OPC_MXU_S32LUI:
26920 /* TODO: Implement emulation of S32LUI instruction. */
26921 MIPS_INVAL("OPC_MXU_S32LUI");
26922 gen_reserved_instruction(ctx);
26923 break;
26924 case OPC_MXU_S32NOR:
26925 gen_mxu_S32NOR(ctx);
26926 break;
26927 case OPC_MXU_S32AND:
26928 gen_mxu_S32AND(ctx);
26929 break;
26930 case OPC_MXU_S32OR:
26931 gen_mxu_S32OR(ctx);
26932 break;
26933 case OPC_MXU_S32XOR:
26934 gen_mxu_S32XOR(ctx);
26935 break;
26936 default:
26937 MIPS_INVAL("decode_opc_mxu");
26938 gen_reserved_instruction(ctx);
26939 break;
26945 * Decode MXU pool17
26947 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26948 * +-----------+---------+---------+---+---------+-----+-----------+
26949 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
26950 * +-----------+---------+---------+---+---------+-----+-----------+
26953 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
26955 uint32_t opcode = extract32(ctx->opcode, 6, 2);
26957 switch (opcode) {
26958 case OPC_MXU_LXW:
26959 /* TODO: Implement emulation of LXW instruction. */
26960 MIPS_INVAL("OPC_MXU_LXW");
26961 gen_reserved_instruction(ctx);
26962 break;
26963 case OPC_MXU_LXH:
26964 /* TODO: Implement emulation of LXH instruction. */
26965 MIPS_INVAL("OPC_MXU_LXH");
26966 gen_reserved_instruction(ctx);
26967 break;
26968 case OPC_MXU_LXHU:
26969 /* TODO: Implement emulation of LXHU instruction. */
26970 MIPS_INVAL("OPC_MXU_LXHU");
26971 gen_reserved_instruction(ctx);
26972 break;
26973 case OPC_MXU_LXB:
26974 /* TODO: Implement emulation of LXB instruction. */
26975 MIPS_INVAL("OPC_MXU_LXB");
26976 gen_reserved_instruction(ctx);
26977 break;
26978 case OPC_MXU_LXBU:
26979 /* TODO: Implement emulation of LXBU instruction. */
26980 MIPS_INVAL("OPC_MXU_LXBU");
26981 gen_reserved_instruction(ctx);
26982 break;
26983 default:
26984 MIPS_INVAL("decode_opc_mxu");
26985 gen_reserved_instruction(ctx);
26986 break;
26991 * Decode MXU pool18
26993 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
26994 * +-----------+---------+-----+-------+-------+-------+-----------+
26995 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
26996 * +-----------+---------+-----+-------+-------+-------+-----------+
26999 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
27001 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27003 switch (opcode) {
27004 case OPC_MXU_D32SLLV:
27005 /* TODO: Implement emulation of D32SLLV instruction. */
27006 MIPS_INVAL("OPC_MXU_D32SLLV");
27007 gen_reserved_instruction(ctx);
27008 break;
27009 case OPC_MXU_D32SLRV:
27010 /* TODO: Implement emulation of D32SLRV instruction. */
27011 MIPS_INVAL("OPC_MXU_D32SLRV");
27012 gen_reserved_instruction(ctx);
27013 break;
27014 case OPC_MXU_D32SARV:
27015 /* TODO: Implement emulation of D32SARV instruction. */
27016 MIPS_INVAL("OPC_MXU_D32SARV");
27017 gen_reserved_instruction(ctx);
27018 break;
27019 case OPC_MXU_Q16SLLV:
27020 /* TODO: Implement emulation of Q16SLLV instruction. */
27021 MIPS_INVAL("OPC_MXU_Q16SLLV");
27022 gen_reserved_instruction(ctx);
27023 break;
27024 case OPC_MXU_Q16SLRV:
27025 /* TODO: Implement emulation of Q16SLRV instruction. */
27026 MIPS_INVAL("OPC_MXU_Q16SLRV");
27027 gen_reserved_instruction(ctx);
27028 break;
27029 case OPC_MXU_Q16SARV:
27030 /* TODO: Implement emulation of Q16SARV instruction. */
27031 MIPS_INVAL("OPC_MXU_Q16SARV");
27032 gen_reserved_instruction(ctx);
27033 break;
27034 default:
27035 MIPS_INVAL("decode_opc_mxu");
27036 gen_reserved_instruction(ctx);
27037 break;
27043 * Decode MXU pool19
27045 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
27046 * +-----------+---+---+-------+-------+-------+-------+-----------+
27047 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
27048 * +-----------+---+---+-------+-------+-------+-------+-----------+
27051 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
27053 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27055 switch (opcode) {
27056 case OPC_MXU_Q8MUL:
27057 case OPC_MXU_Q8MULSU:
27058 gen_mxu_q8mul_q8mulsu(ctx);
27059 break;
27060 default:
27061 MIPS_INVAL("decode_opc_mxu");
27062 gen_reserved_instruction(ctx);
27063 break;
27069 * Decode MXU pool20
27071 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
27072 * +-----------+---------+-----+-------+-------+-------+-----------+
27073 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
27074 * +-----------+---------+-----+-------+-------+-------+-----------+
27077 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
27079 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27081 switch (opcode) {
27082 case OPC_MXU_Q8MOVZ:
27083 /* TODO: Implement emulation of Q8MOVZ instruction. */
27084 MIPS_INVAL("OPC_MXU_Q8MOVZ");
27085 gen_reserved_instruction(ctx);
27086 break;
27087 case OPC_MXU_Q8MOVN:
27088 /* TODO: Implement emulation of Q8MOVN instruction. */
27089 MIPS_INVAL("OPC_MXU_Q8MOVN");
27090 gen_reserved_instruction(ctx);
27091 break;
27092 case OPC_MXU_D16MOVZ:
27093 /* TODO: Implement emulation of D16MOVZ instruction. */
27094 MIPS_INVAL("OPC_MXU_D16MOVZ");
27095 gen_reserved_instruction(ctx);
27096 break;
27097 case OPC_MXU_D16MOVN:
27098 /* TODO: Implement emulation of D16MOVN instruction. */
27099 MIPS_INVAL("OPC_MXU_D16MOVN");
27100 gen_reserved_instruction(ctx);
27101 break;
27102 case OPC_MXU_S32MOVZ:
27103 /* TODO: Implement emulation of S32MOVZ instruction. */
27104 MIPS_INVAL("OPC_MXU_S32MOVZ");
27105 gen_reserved_instruction(ctx);
27106 break;
27107 case OPC_MXU_S32MOVN:
27108 /* TODO: Implement emulation of S32MOVN instruction. */
27109 MIPS_INVAL("OPC_MXU_S32MOVN");
27110 gen_reserved_instruction(ctx);
27111 break;
27112 default:
27113 MIPS_INVAL("decode_opc_mxu");
27114 gen_reserved_instruction(ctx);
27115 break;
27121 * Decode MXU pool21
27123 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
27124 * +-----------+---+---+-------+-------+-------+-------+-----------+
27125 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
27126 * +-----------+---+---+-------+-------+-------+-------+-----------+
27129 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
27131 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27133 switch (opcode) {
27134 case OPC_MXU_Q8MAC:
27135 /* TODO: Implement emulation of Q8MAC instruction. */
27136 MIPS_INVAL("OPC_MXU_Q8MAC");
27137 gen_reserved_instruction(ctx);
27138 break;
27139 case OPC_MXU_Q8MACSU:
27140 /* TODO: Implement emulation of Q8MACSU instruction. */
27141 MIPS_INVAL("OPC_MXU_Q8MACSU");
27142 gen_reserved_instruction(ctx);
27143 break;
27144 default:
27145 MIPS_INVAL("decode_opc_mxu");
27146 gen_reserved_instruction(ctx);
27147 break;
27153 * Main MXU decoding function
27155 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
27156 * +-----------+---------------------------------------+-----------+
27157 * | SPECIAL2 | |x x x x x x|
27158 * +-----------+---------------------------------------+-----------+
27161 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
27164 * TODO: Investigate necessity of including handling of
27165 * CLZ, CLO, SDBB in this function, as they belong to
27166 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
27168 uint32_t opcode = extract32(ctx->opcode, 0, 6);
27170 if (opcode == OPC__MXU_MUL) {
27171 uint32_t rs, rt, rd, op1;
27173 rs = extract32(ctx->opcode, 21, 5);
27174 rt = extract32(ctx->opcode, 16, 5);
27175 rd = extract32(ctx->opcode, 11, 5);
27176 op1 = MASK_SPECIAL2(ctx->opcode);
27178 gen_arith(ctx, op1, rd, rs, rt);
27180 return;
27183 if (opcode == OPC_MXU_S32M2I) {
27184 gen_mxu_s32m2i(ctx);
27185 return;
27188 if (opcode == OPC_MXU_S32I2M) {
27189 gen_mxu_s32i2m(ctx);
27190 return;
27194 TCGv t_mxu_cr = tcg_temp_new();
27195 TCGLabel *l_exit = gen_new_label();
27197 gen_load_mxu_cr(t_mxu_cr);
27198 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
27199 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
27201 switch (opcode) {
27202 case OPC_MXU_S32MADD:
27203 /* TODO: Implement emulation of S32MADD instruction. */
27204 MIPS_INVAL("OPC_MXU_S32MADD");
27205 gen_reserved_instruction(ctx);
27206 break;
27207 case OPC_MXU_S32MADDU:
27208 /* TODO: Implement emulation of S32MADDU instruction. */
27209 MIPS_INVAL("OPC_MXU_S32MADDU");
27210 gen_reserved_instruction(ctx);
27211 break;
27212 case OPC_MXU__POOL00:
27213 decode_opc_mxu__pool00(env, ctx);
27214 break;
27215 case OPC_MXU_S32MSUB:
27216 /* TODO: Implement emulation of S32MSUB instruction. */
27217 MIPS_INVAL("OPC_MXU_S32MSUB");
27218 gen_reserved_instruction(ctx);
27219 break;
27220 case OPC_MXU_S32MSUBU:
27221 /* TODO: Implement emulation of S32MSUBU instruction. */
27222 MIPS_INVAL("OPC_MXU_S32MSUBU");
27223 gen_reserved_instruction(ctx);
27224 break;
27225 case OPC_MXU__POOL01:
27226 decode_opc_mxu__pool01(env, ctx);
27227 break;
27228 case OPC_MXU__POOL02:
27229 decode_opc_mxu__pool02(env, ctx);
27230 break;
27231 case OPC_MXU_D16MUL:
27232 gen_mxu_d16mul(ctx);
27233 break;
27234 case OPC_MXU__POOL03:
27235 decode_opc_mxu__pool03(env, ctx);
27236 break;
27237 case OPC_MXU_D16MAC:
27238 gen_mxu_d16mac(ctx);
27239 break;
27240 case OPC_MXU_D16MACF:
27241 /* TODO: Implement emulation of D16MACF instruction. */
27242 MIPS_INVAL("OPC_MXU_D16MACF");
27243 gen_reserved_instruction(ctx);
27244 break;
27245 case OPC_MXU_D16MADL:
27246 /* TODO: Implement emulation of D16MADL instruction. */
27247 MIPS_INVAL("OPC_MXU_D16MADL");
27248 gen_reserved_instruction(ctx);
27249 break;
27250 case OPC_MXU_S16MAD:
27251 /* TODO: Implement emulation of S16MAD instruction. */
27252 MIPS_INVAL("OPC_MXU_S16MAD");
27253 gen_reserved_instruction(ctx);
27254 break;
27255 case OPC_MXU_Q16ADD:
27256 /* TODO: Implement emulation of Q16ADD instruction. */
27257 MIPS_INVAL("OPC_MXU_Q16ADD");
27258 gen_reserved_instruction(ctx);
27259 break;
27260 case OPC_MXU_D16MACE:
27261 /* TODO: Implement emulation of D16MACE instruction. */
27262 MIPS_INVAL("OPC_MXU_D16MACE");
27263 gen_reserved_instruction(ctx);
27264 break;
27265 case OPC_MXU__POOL04:
27266 decode_opc_mxu__pool04(env, ctx);
27267 break;
27268 case OPC_MXU__POOL05:
27269 decode_opc_mxu__pool05(env, ctx);
27270 break;
27271 case OPC_MXU__POOL06:
27272 decode_opc_mxu__pool06(env, ctx);
27273 break;
27274 case OPC_MXU__POOL07:
27275 decode_opc_mxu__pool07(env, ctx);
27276 break;
27277 case OPC_MXU__POOL08:
27278 decode_opc_mxu__pool08(env, ctx);
27279 break;
27280 case OPC_MXU__POOL09:
27281 decode_opc_mxu__pool09(env, ctx);
27282 break;
27283 case OPC_MXU__POOL10:
27284 decode_opc_mxu__pool10(env, ctx);
27285 break;
27286 case OPC_MXU__POOL11:
27287 decode_opc_mxu__pool11(env, ctx);
27288 break;
27289 case OPC_MXU_D32ADD:
27290 /* TODO: Implement emulation of D32ADD instruction. */
27291 MIPS_INVAL("OPC_MXU_D32ADD");
27292 gen_reserved_instruction(ctx);
27293 break;
27294 case OPC_MXU__POOL12:
27295 decode_opc_mxu__pool12(env, ctx);
27296 break;
27297 case OPC_MXU__POOL13:
27298 decode_opc_mxu__pool13(env, ctx);
27299 break;
27300 case OPC_MXU__POOL14:
27301 decode_opc_mxu__pool14(env, ctx);
27302 break;
27303 case OPC_MXU_Q8ACCE:
27304 /* TODO: Implement emulation of Q8ACCE instruction. */
27305 MIPS_INVAL("OPC_MXU_Q8ACCE");
27306 gen_reserved_instruction(ctx);
27307 break;
27308 case OPC_MXU_S8LDD:
27309 gen_mxu_s8ldd(ctx);
27310 break;
27311 case OPC_MXU_S8STD:
27312 /* TODO: Implement emulation of S8STD instruction. */
27313 MIPS_INVAL("OPC_MXU_S8STD");
27314 gen_reserved_instruction(ctx);
27315 break;
27316 case OPC_MXU_S8LDI:
27317 /* TODO: Implement emulation of S8LDI instruction. */
27318 MIPS_INVAL("OPC_MXU_S8LDI");
27319 gen_reserved_instruction(ctx);
27320 break;
27321 case OPC_MXU_S8SDI:
27322 /* TODO: Implement emulation of S8SDI instruction. */
27323 MIPS_INVAL("OPC_MXU_S8SDI");
27324 gen_reserved_instruction(ctx);
27325 break;
27326 case OPC_MXU__POOL15:
27327 decode_opc_mxu__pool15(env, ctx);
27328 break;
27329 case OPC_MXU__POOL16:
27330 decode_opc_mxu__pool16(env, ctx);
27331 break;
27332 case OPC_MXU__POOL17:
27333 decode_opc_mxu__pool17(env, ctx);
27334 break;
27335 case OPC_MXU_S16LDD:
27336 /* TODO: Implement emulation of S16LDD instruction. */
27337 MIPS_INVAL("OPC_MXU_S16LDD");
27338 gen_reserved_instruction(ctx);
27339 break;
27340 case OPC_MXU_S16STD:
27341 /* TODO: Implement emulation of S16STD instruction. */
27342 MIPS_INVAL("OPC_MXU_S16STD");
27343 gen_reserved_instruction(ctx);
27344 break;
27345 case OPC_MXU_S16LDI:
27346 /* TODO: Implement emulation of S16LDI instruction. */
27347 MIPS_INVAL("OPC_MXU_S16LDI");
27348 gen_reserved_instruction(ctx);
27349 break;
27350 case OPC_MXU_S16SDI:
27351 /* TODO: Implement emulation of S16SDI instruction. */
27352 MIPS_INVAL("OPC_MXU_S16SDI");
27353 gen_reserved_instruction(ctx);
27354 break;
27355 case OPC_MXU_D32SLL:
27356 /* TODO: Implement emulation of D32SLL instruction. */
27357 MIPS_INVAL("OPC_MXU_D32SLL");
27358 gen_reserved_instruction(ctx);
27359 break;
27360 case OPC_MXU_D32SLR:
27361 /* TODO: Implement emulation of D32SLR instruction. */
27362 MIPS_INVAL("OPC_MXU_D32SLR");
27363 gen_reserved_instruction(ctx);
27364 break;
27365 case OPC_MXU_D32SARL:
27366 /* TODO: Implement emulation of D32SARL instruction. */
27367 MIPS_INVAL("OPC_MXU_D32SARL");
27368 gen_reserved_instruction(ctx);
27369 break;
27370 case OPC_MXU_D32SAR:
27371 /* TODO: Implement emulation of D32SAR instruction. */
27372 MIPS_INVAL("OPC_MXU_D32SAR");
27373 gen_reserved_instruction(ctx);
27374 break;
27375 case OPC_MXU_Q16SLL:
27376 /* TODO: Implement emulation of Q16SLL instruction. */
27377 MIPS_INVAL("OPC_MXU_Q16SLL");
27378 gen_reserved_instruction(ctx);
27379 break;
27380 case OPC_MXU_Q16SLR:
27381 /* TODO: Implement emulation of Q16SLR instruction. */
27382 MIPS_INVAL("OPC_MXU_Q16SLR");
27383 gen_reserved_instruction(ctx);
27384 break;
27385 case OPC_MXU__POOL18:
27386 decode_opc_mxu__pool18(env, ctx);
27387 break;
27388 case OPC_MXU_Q16SAR:
27389 /* TODO: Implement emulation of Q16SAR instruction. */
27390 MIPS_INVAL("OPC_MXU_Q16SAR");
27391 gen_reserved_instruction(ctx);
27392 break;
27393 case OPC_MXU__POOL19:
27394 decode_opc_mxu__pool19(env, ctx);
27395 break;
27396 case OPC_MXU__POOL20:
27397 decode_opc_mxu__pool20(env, ctx);
27398 break;
27399 case OPC_MXU__POOL21:
27400 decode_opc_mxu__pool21(env, ctx);
27401 break;
27402 case OPC_MXU_Q16SCOP:
27403 /* TODO: Implement emulation of Q16SCOP instruction. */
27404 MIPS_INVAL("OPC_MXU_Q16SCOP");
27405 gen_reserved_instruction(ctx);
27406 break;
27407 case OPC_MXU_Q8MADL:
27408 /* TODO: Implement emulation of Q8MADL instruction. */
27409 MIPS_INVAL("OPC_MXU_Q8MADL");
27410 gen_reserved_instruction(ctx);
27411 break;
27412 case OPC_MXU_S32SFL:
27413 /* TODO: Implement emulation of S32SFL instruction. */
27414 MIPS_INVAL("OPC_MXU_S32SFL");
27415 gen_reserved_instruction(ctx);
27416 break;
27417 case OPC_MXU_Q8SAD:
27418 /* TODO: Implement emulation of Q8SAD instruction. */
27419 MIPS_INVAL("OPC_MXU_Q8SAD");
27420 gen_reserved_instruction(ctx);
27421 break;
27422 default:
27423 MIPS_INVAL("decode_opc_mxu");
27424 gen_reserved_instruction(ctx);
27427 gen_set_label(l_exit);
27428 tcg_temp_free(t_mxu_cr);
27432 #endif /* !defined(TARGET_MIPS64) */
27435 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27437 int rs, rt, rd;
27438 uint32_t op1;
27440 check_insn_opc_removed(ctx, ISA_MIPS_R6);
27442 rs = (ctx->opcode >> 21) & 0x1f;
27443 rt = (ctx->opcode >> 16) & 0x1f;
27444 rd = (ctx->opcode >> 11) & 0x1f;
27446 op1 = MASK_SPECIAL2(ctx->opcode);
27447 switch (op1) {
27448 case OPC_MADD: /* Multiply and add/sub */
27449 case OPC_MADDU:
27450 case OPC_MSUB:
27451 case OPC_MSUBU:
27452 check_insn(ctx, ISA_MIPS_R1);
27453 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27454 break;
27455 case OPC_MUL:
27456 gen_arith(ctx, op1, rd, rs, rt);
27457 break;
27458 case OPC_DIV_G_2F:
27459 case OPC_DIVU_G_2F:
27460 case OPC_MULT_G_2F:
27461 case OPC_MULTU_G_2F:
27462 case OPC_MOD_G_2F:
27463 case OPC_MODU_G_2F:
27464 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27465 gen_loongson_integer(ctx, op1, rd, rs, rt);
27466 break;
27467 case OPC_CLO:
27468 case OPC_CLZ:
27469 check_insn(ctx, ISA_MIPS_R1);
27470 gen_cl(ctx, op1, rd, rs);
27471 break;
27472 case OPC_SDBBP:
27473 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27474 gen_helper_do_semihosting(cpu_env);
27475 } else {
27477 * XXX: not clear which exception should be raised
27478 * when in debug mode...
27480 check_insn(ctx, ISA_MIPS_R1);
27481 generate_exception_end(ctx, EXCP_DBp);
27483 break;
27484 #if defined(TARGET_MIPS64)
27485 case OPC_DCLO:
27486 case OPC_DCLZ:
27487 check_insn(ctx, ISA_MIPS_R1);
27488 check_mips_64(ctx);
27489 gen_cl(ctx, op1, rd, rs);
27490 break;
27491 case OPC_DMULT_G_2F:
27492 case OPC_DMULTU_G_2F:
27493 case OPC_DDIV_G_2F:
27494 case OPC_DDIVU_G_2F:
27495 case OPC_DMOD_G_2F:
27496 case OPC_DMODU_G_2F:
27497 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27498 gen_loongson_integer(ctx, op1, rd, rs, rt);
27499 break;
27500 #endif
27501 default: /* Invalid */
27502 MIPS_INVAL("special2_legacy");
27503 gen_reserved_instruction(ctx);
27504 break;
27508 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27510 int rs, rt, rd, sa;
27511 uint32_t op1, op2;
27512 int16_t imm;
27514 rs = (ctx->opcode >> 21) & 0x1f;
27515 rt = (ctx->opcode >> 16) & 0x1f;
27516 rd = (ctx->opcode >> 11) & 0x1f;
27517 sa = (ctx->opcode >> 6) & 0x1f;
27518 imm = (int16_t)ctx->opcode >> 7;
27520 op1 = MASK_SPECIAL3(ctx->opcode);
27521 switch (op1) {
27522 case R6_OPC_PREF:
27523 if (rt >= 24) {
27524 /* hint codes 24-31 are reserved and signal RI */
27525 gen_reserved_instruction(ctx);
27527 /* Treat as NOP. */
27528 break;
27529 case R6_OPC_CACHE:
27530 check_cp0_enabled(ctx);
27531 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27532 gen_cache_operation(ctx, rt, rs, imm);
27534 break;
27535 case R6_OPC_SC:
27536 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27537 break;
27538 case R6_OPC_LL:
27539 gen_ld(ctx, op1, rt, rs, imm);
27540 break;
27541 case OPC_BSHFL:
27543 if (rd == 0) {
27544 /* Treat as NOP. */
27545 break;
27547 op2 = MASK_BSHFL(ctx->opcode);
27548 switch (op2) {
27549 case OPC_ALIGN:
27550 case OPC_ALIGN_1:
27551 case OPC_ALIGN_2:
27552 case OPC_ALIGN_3:
27553 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27554 break;
27555 case OPC_BITSWAP:
27556 gen_bitswap(ctx, op2, rd, rt);
27557 break;
27560 break;
27561 #ifndef CONFIG_USER_ONLY
27562 case OPC_GINV:
27563 if (unlikely(ctx->gi <= 1)) {
27564 gen_reserved_instruction(ctx);
27566 check_cp0_enabled(ctx);
27567 switch ((ctx->opcode >> 6) & 3) {
27568 case 0: /* GINVI */
27569 /* Treat as NOP. */
27570 break;
27571 case 2: /* GINVT */
27572 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27573 break;
27574 default:
27575 gen_reserved_instruction(ctx);
27576 break;
27578 break;
27579 #endif
27580 #if defined(TARGET_MIPS64)
27581 case R6_OPC_SCD:
27582 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27583 break;
27584 case R6_OPC_LLD:
27585 gen_ld(ctx, op1, rt, rs, imm);
27586 break;
27587 case OPC_DBSHFL:
27588 check_mips_64(ctx);
27590 if (rd == 0) {
27591 /* Treat as NOP. */
27592 break;
27594 op2 = MASK_DBSHFL(ctx->opcode);
27595 switch (op2) {
27596 case OPC_DALIGN:
27597 case OPC_DALIGN_1:
27598 case OPC_DALIGN_2:
27599 case OPC_DALIGN_3:
27600 case OPC_DALIGN_4:
27601 case OPC_DALIGN_5:
27602 case OPC_DALIGN_6:
27603 case OPC_DALIGN_7:
27604 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27605 break;
27606 case OPC_DBITSWAP:
27607 gen_bitswap(ctx, op2, rd, rt);
27608 break;
27612 break;
27613 #endif
27614 default: /* Invalid */
27615 MIPS_INVAL("special3_r6");
27616 gen_reserved_instruction(ctx);
27617 break;
27621 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27623 int rs, rt, rd;
27624 uint32_t op1, op2;
27626 rs = (ctx->opcode >> 21) & 0x1f;
27627 rt = (ctx->opcode >> 16) & 0x1f;
27628 rd = (ctx->opcode >> 11) & 0x1f;
27630 op1 = MASK_SPECIAL3(ctx->opcode);
27631 switch (op1) {
27632 case OPC_DIV_G_2E:
27633 case OPC_DIVU_G_2E:
27634 case OPC_MOD_G_2E:
27635 case OPC_MODU_G_2E:
27636 case OPC_MULT_G_2E:
27637 case OPC_MULTU_G_2E:
27639 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27640 * the same mask and op1.
27642 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27643 op2 = MASK_ADDUH_QB(ctx->opcode);
27644 switch (op2) {
27645 case OPC_ADDUH_QB:
27646 case OPC_ADDUH_R_QB:
27647 case OPC_ADDQH_PH:
27648 case OPC_ADDQH_R_PH:
27649 case OPC_ADDQH_W:
27650 case OPC_ADDQH_R_W:
27651 case OPC_SUBUH_QB:
27652 case OPC_SUBUH_R_QB:
27653 case OPC_SUBQH_PH:
27654 case OPC_SUBQH_R_PH:
27655 case OPC_SUBQH_W:
27656 case OPC_SUBQH_R_W:
27657 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27658 break;
27659 case OPC_MUL_PH:
27660 case OPC_MUL_S_PH:
27661 case OPC_MULQ_S_W:
27662 case OPC_MULQ_RS_W:
27663 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27664 break;
27665 default:
27666 MIPS_INVAL("MASK ADDUH.QB");
27667 gen_reserved_instruction(ctx);
27668 break;
27670 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27671 gen_loongson_integer(ctx, op1, rd, rs, rt);
27672 } else {
27673 gen_reserved_instruction(ctx);
27675 break;
27676 case OPC_LX_DSP:
27677 op2 = MASK_LX(ctx->opcode);
27678 switch (op2) {
27679 #if defined(TARGET_MIPS64)
27680 case OPC_LDX:
27681 #endif
27682 case OPC_LBUX:
27683 case OPC_LHX:
27684 case OPC_LWX:
27685 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27686 break;
27687 default: /* Invalid */
27688 MIPS_INVAL("MASK LX");
27689 gen_reserved_instruction(ctx);
27690 break;
27692 break;
27693 case OPC_ABSQ_S_PH_DSP:
27694 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27695 switch (op2) {
27696 case OPC_ABSQ_S_QB:
27697 case OPC_ABSQ_S_PH:
27698 case OPC_ABSQ_S_W:
27699 case OPC_PRECEQ_W_PHL:
27700 case OPC_PRECEQ_W_PHR:
27701 case OPC_PRECEQU_PH_QBL:
27702 case OPC_PRECEQU_PH_QBR:
27703 case OPC_PRECEQU_PH_QBLA:
27704 case OPC_PRECEQU_PH_QBRA:
27705 case OPC_PRECEU_PH_QBL:
27706 case OPC_PRECEU_PH_QBR:
27707 case OPC_PRECEU_PH_QBLA:
27708 case OPC_PRECEU_PH_QBRA:
27709 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27710 break;
27711 case OPC_BITREV:
27712 case OPC_REPL_QB:
27713 case OPC_REPLV_QB:
27714 case OPC_REPL_PH:
27715 case OPC_REPLV_PH:
27716 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27717 break;
27718 default:
27719 MIPS_INVAL("MASK ABSQ_S.PH");
27720 gen_reserved_instruction(ctx);
27721 break;
27723 break;
27724 case OPC_ADDU_QB_DSP:
27725 op2 = MASK_ADDU_QB(ctx->opcode);
27726 switch (op2) {
27727 case OPC_ADDQ_PH:
27728 case OPC_ADDQ_S_PH:
27729 case OPC_ADDQ_S_W:
27730 case OPC_ADDU_QB:
27731 case OPC_ADDU_S_QB:
27732 case OPC_ADDU_PH:
27733 case OPC_ADDU_S_PH:
27734 case OPC_SUBQ_PH:
27735 case OPC_SUBQ_S_PH:
27736 case OPC_SUBQ_S_W:
27737 case OPC_SUBU_QB:
27738 case OPC_SUBU_S_QB:
27739 case OPC_SUBU_PH:
27740 case OPC_SUBU_S_PH:
27741 case OPC_ADDSC:
27742 case OPC_ADDWC:
27743 case OPC_MODSUB:
27744 case OPC_RADDU_W_QB:
27745 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27746 break;
27747 case OPC_MULEU_S_PH_QBL:
27748 case OPC_MULEU_S_PH_QBR:
27749 case OPC_MULQ_RS_PH:
27750 case OPC_MULEQ_S_W_PHL:
27751 case OPC_MULEQ_S_W_PHR:
27752 case OPC_MULQ_S_PH:
27753 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27754 break;
27755 default: /* Invalid */
27756 MIPS_INVAL("MASK ADDU.QB");
27757 gen_reserved_instruction(ctx);
27758 break;
27761 break;
27762 case OPC_CMPU_EQ_QB_DSP:
27763 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27764 switch (op2) {
27765 case OPC_PRECR_SRA_PH_W:
27766 case OPC_PRECR_SRA_R_PH_W:
27767 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27768 break;
27769 case OPC_PRECR_QB_PH:
27770 case OPC_PRECRQ_QB_PH:
27771 case OPC_PRECRQ_PH_W:
27772 case OPC_PRECRQ_RS_PH_W:
27773 case OPC_PRECRQU_S_QB_PH:
27774 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27775 break;
27776 case OPC_CMPU_EQ_QB:
27777 case OPC_CMPU_LT_QB:
27778 case OPC_CMPU_LE_QB:
27779 case OPC_CMP_EQ_PH:
27780 case OPC_CMP_LT_PH:
27781 case OPC_CMP_LE_PH:
27782 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27783 break;
27784 case OPC_CMPGU_EQ_QB:
27785 case OPC_CMPGU_LT_QB:
27786 case OPC_CMPGU_LE_QB:
27787 case OPC_CMPGDU_EQ_QB:
27788 case OPC_CMPGDU_LT_QB:
27789 case OPC_CMPGDU_LE_QB:
27790 case OPC_PICK_QB:
27791 case OPC_PICK_PH:
27792 case OPC_PACKRL_PH:
27793 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27794 break;
27795 default: /* Invalid */
27796 MIPS_INVAL("MASK CMPU.EQ.QB");
27797 gen_reserved_instruction(ctx);
27798 break;
27800 break;
27801 case OPC_SHLL_QB_DSP:
27802 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27803 break;
27804 case OPC_DPA_W_PH_DSP:
27805 op2 = MASK_DPA_W_PH(ctx->opcode);
27806 switch (op2) {
27807 case OPC_DPAU_H_QBL:
27808 case OPC_DPAU_H_QBR:
27809 case OPC_DPSU_H_QBL:
27810 case OPC_DPSU_H_QBR:
27811 case OPC_DPA_W_PH:
27812 case OPC_DPAX_W_PH:
27813 case OPC_DPAQ_S_W_PH:
27814 case OPC_DPAQX_S_W_PH:
27815 case OPC_DPAQX_SA_W_PH:
27816 case OPC_DPS_W_PH:
27817 case OPC_DPSX_W_PH:
27818 case OPC_DPSQ_S_W_PH:
27819 case OPC_DPSQX_S_W_PH:
27820 case OPC_DPSQX_SA_W_PH:
27821 case OPC_MULSAQ_S_W_PH:
27822 case OPC_DPAQ_SA_L_W:
27823 case OPC_DPSQ_SA_L_W:
27824 case OPC_MAQ_S_W_PHL:
27825 case OPC_MAQ_S_W_PHR:
27826 case OPC_MAQ_SA_W_PHL:
27827 case OPC_MAQ_SA_W_PHR:
27828 case OPC_MULSA_W_PH:
27829 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27830 break;
27831 default: /* Invalid */
27832 MIPS_INVAL("MASK DPAW.PH");
27833 gen_reserved_instruction(ctx);
27834 break;
27836 break;
27837 case OPC_INSV_DSP:
27838 op2 = MASK_INSV(ctx->opcode);
27839 switch (op2) {
27840 case OPC_INSV:
27841 check_dsp(ctx);
27843 TCGv t0, t1;
27845 if (rt == 0) {
27846 break;
27849 t0 = tcg_temp_new();
27850 t1 = tcg_temp_new();
27852 gen_load_gpr(t0, rt);
27853 gen_load_gpr(t1, rs);
27855 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27857 tcg_temp_free(t0);
27858 tcg_temp_free(t1);
27859 break;
27861 default: /* Invalid */
27862 MIPS_INVAL("MASK INSV");
27863 gen_reserved_instruction(ctx);
27864 break;
27866 break;
27867 case OPC_APPEND_DSP:
27868 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27869 break;
27870 case OPC_EXTR_W_DSP:
27871 op2 = MASK_EXTR_W(ctx->opcode);
27872 switch (op2) {
27873 case OPC_EXTR_W:
27874 case OPC_EXTR_R_W:
27875 case OPC_EXTR_RS_W:
27876 case OPC_EXTR_S_H:
27877 case OPC_EXTRV_S_H:
27878 case OPC_EXTRV_W:
27879 case OPC_EXTRV_R_W:
27880 case OPC_EXTRV_RS_W:
27881 case OPC_EXTP:
27882 case OPC_EXTPV:
27883 case OPC_EXTPDP:
27884 case OPC_EXTPDPV:
27885 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
27886 break;
27887 case OPC_RDDSP:
27888 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
27889 break;
27890 case OPC_SHILO:
27891 case OPC_SHILOV:
27892 case OPC_MTHLIP:
27893 case OPC_WRDSP:
27894 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
27895 break;
27896 default: /* Invalid */
27897 MIPS_INVAL("MASK EXTR.W");
27898 gen_reserved_instruction(ctx);
27899 break;
27901 break;
27902 #if defined(TARGET_MIPS64)
27903 case OPC_DDIV_G_2E:
27904 case OPC_DDIVU_G_2E:
27905 case OPC_DMULT_G_2E:
27906 case OPC_DMULTU_G_2E:
27907 case OPC_DMOD_G_2E:
27908 case OPC_DMODU_G_2E:
27909 check_insn(ctx, INSN_LOONGSON2E);
27910 gen_loongson_integer(ctx, op1, rd, rs, rt);
27911 break;
27912 case OPC_ABSQ_S_QH_DSP:
27913 op2 = MASK_ABSQ_S_QH(ctx->opcode);
27914 switch (op2) {
27915 case OPC_PRECEQ_L_PWL:
27916 case OPC_PRECEQ_L_PWR:
27917 case OPC_PRECEQ_PW_QHL:
27918 case OPC_PRECEQ_PW_QHR:
27919 case OPC_PRECEQ_PW_QHLA:
27920 case OPC_PRECEQ_PW_QHRA:
27921 case OPC_PRECEQU_QH_OBL:
27922 case OPC_PRECEQU_QH_OBR:
27923 case OPC_PRECEQU_QH_OBLA:
27924 case OPC_PRECEQU_QH_OBRA:
27925 case OPC_PRECEU_QH_OBL:
27926 case OPC_PRECEU_QH_OBR:
27927 case OPC_PRECEU_QH_OBLA:
27928 case OPC_PRECEU_QH_OBRA:
27929 case OPC_ABSQ_S_OB:
27930 case OPC_ABSQ_S_PW:
27931 case OPC_ABSQ_S_QH:
27932 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27933 break;
27934 case OPC_REPL_OB:
27935 case OPC_REPL_PW:
27936 case OPC_REPL_QH:
27937 case OPC_REPLV_OB:
27938 case OPC_REPLV_PW:
27939 case OPC_REPLV_QH:
27940 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27941 break;
27942 default: /* Invalid */
27943 MIPS_INVAL("MASK ABSQ_S.QH");
27944 gen_reserved_instruction(ctx);
27945 break;
27947 break;
27948 case OPC_ADDU_OB_DSP:
27949 op2 = MASK_ADDU_OB(ctx->opcode);
27950 switch (op2) {
27951 case OPC_RADDU_L_OB:
27952 case OPC_SUBQ_PW:
27953 case OPC_SUBQ_S_PW:
27954 case OPC_SUBQ_QH:
27955 case OPC_SUBQ_S_QH:
27956 case OPC_SUBU_OB:
27957 case OPC_SUBU_S_OB:
27958 case OPC_SUBU_QH:
27959 case OPC_SUBU_S_QH:
27960 case OPC_SUBUH_OB:
27961 case OPC_SUBUH_R_OB:
27962 case OPC_ADDQ_PW:
27963 case OPC_ADDQ_S_PW:
27964 case OPC_ADDQ_QH:
27965 case OPC_ADDQ_S_QH:
27966 case OPC_ADDU_OB:
27967 case OPC_ADDU_S_OB:
27968 case OPC_ADDU_QH:
27969 case OPC_ADDU_S_QH:
27970 case OPC_ADDUH_OB:
27971 case OPC_ADDUH_R_OB:
27972 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27973 break;
27974 case OPC_MULEQ_S_PW_QHL:
27975 case OPC_MULEQ_S_PW_QHR:
27976 case OPC_MULEU_S_QH_OBL:
27977 case OPC_MULEU_S_QH_OBR:
27978 case OPC_MULQ_RS_QH:
27979 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27980 break;
27981 default: /* Invalid */
27982 MIPS_INVAL("MASK ADDU.OB");
27983 gen_reserved_instruction(ctx);
27984 break;
27986 break;
27987 case OPC_CMPU_EQ_OB_DSP:
27988 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
27989 switch (op2) {
27990 case OPC_PRECR_SRA_QH_PW:
27991 case OPC_PRECR_SRA_R_QH_PW:
27992 /* Return value is rt. */
27993 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27994 break;
27995 case OPC_PRECR_OB_QH:
27996 case OPC_PRECRQ_OB_QH:
27997 case OPC_PRECRQ_PW_L:
27998 case OPC_PRECRQ_QH_PW:
27999 case OPC_PRECRQ_RS_QH_PW:
28000 case OPC_PRECRQU_S_OB_QH:
28001 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28002 break;
28003 case OPC_CMPU_EQ_OB:
28004 case OPC_CMPU_LT_OB:
28005 case OPC_CMPU_LE_OB:
28006 case OPC_CMP_EQ_QH:
28007 case OPC_CMP_LT_QH:
28008 case OPC_CMP_LE_QH:
28009 case OPC_CMP_EQ_PW:
28010 case OPC_CMP_LT_PW:
28011 case OPC_CMP_LE_PW:
28012 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
28013 break;
28014 case OPC_CMPGDU_EQ_OB:
28015 case OPC_CMPGDU_LT_OB:
28016 case OPC_CMPGDU_LE_OB:
28017 case OPC_CMPGU_EQ_OB:
28018 case OPC_CMPGU_LT_OB:
28019 case OPC_CMPGU_LE_OB:
28020 case OPC_PACKRL_PW:
28021 case OPC_PICK_OB:
28022 case OPC_PICK_PW:
28023 case OPC_PICK_QH:
28024 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
28025 break;
28026 default: /* Invalid */
28027 MIPS_INVAL("MASK CMPU_EQ.OB");
28028 gen_reserved_instruction(ctx);
28029 break;
28031 break;
28032 case OPC_DAPPEND_DSP:
28033 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
28034 break;
28035 case OPC_DEXTR_W_DSP:
28036 op2 = MASK_DEXTR_W(ctx->opcode);
28037 switch (op2) {
28038 case OPC_DEXTP:
28039 case OPC_DEXTPDP:
28040 case OPC_DEXTPDPV:
28041 case OPC_DEXTPV:
28042 case OPC_DEXTR_L:
28043 case OPC_DEXTR_R_L:
28044 case OPC_DEXTR_RS_L:
28045 case OPC_DEXTR_W:
28046 case OPC_DEXTR_R_W:
28047 case OPC_DEXTR_RS_W:
28048 case OPC_DEXTR_S_H:
28049 case OPC_DEXTRV_L:
28050 case OPC_DEXTRV_R_L:
28051 case OPC_DEXTRV_RS_L:
28052 case OPC_DEXTRV_S_H:
28053 case OPC_DEXTRV_W:
28054 case OPC_DEXTRV_R_W:
28055 case OPC_DEXTRV_RS_W:
28056 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28057 break;
28058 case OPC_DMTHLIP:
28059 case OPC_DSHILO:
28060 case OPC_DSHILOV:
28061 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28062 break;
28063 default: /* Invalid */
28064 MIPS_INVAL("MASK EXTR.W");
28065 gen_reserved_instruction(ctx);
28066 break;
28068 break;
28069 case OPC_DPAQ_W_QH_DSP:
28070 op2 = MASK_DPAQ_W_QH(ctx->opcode);
28071 switch (op2) {
28072 case OPC_DPAU_H_OBL:
28073 case OPC_DPAU_H_OBR:
28074 case OPC_DPSU_H_OBL:
28075 case OPC_DPSU_H_OBR:
28076 case OPC_DPA_W_QH:
28077 case OPC_DPAQ_S_W_QH:
28078 case OPC_DPS_W_QH:
28079 case OPC_DPSQ_S_W_QH:
28080 case OPC_MULSAQ_S_W_QH:
28081 case OPC_DPAQ_SA_L_PW:
28082 case OPC_DPSQ_SA_L_PW:
28083 case OPC_MULSAQ_S_L_PW:
28084 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28085 break;
28086 case OPC_MAQ_S_W_QHLL:
28087 case OPC_MAQ_S_W_QHLR:
28088 case OPC_MAQ_S_W_QHRL:
28089 case OPC_MAQ_S_W_QHRR:
28090 case OPC_MAQ_SA_W_QHLL:
28091 case OPC_MAQ_SA_W_QHLR:
28092 case OPC_MAQ_SA_W_QHRL:
28093 case OPC_MAQ_SA_W_QHRR:
28094 case OPC_MAQ_S_L_PWL:
28095 case OPC_MAQ_S_L_PWR:
28096 case OPC_DMADD:
28097 case OPC_DMADDU:
28098 case OPC_DMSUB:
28099 case OPC_DMSUBU:
28100 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28101 break;
28102 default: /* Invalid */
28103 MIPS_INVAL("MASK DPAQ.W.QH");
28104 gen_reserved_instruction(ctx);
28105 break;
28107 break;
28108 case OPC_DINSV_DSP:
28109 op2 = MASK_INSV(ctx->opcode);
28110 switch (op2) {
28111 case OPC_DINSV:
28113 TCGv t0, t1;
28115 if (rt == 0) {
28116 break;
28118 check_dsp(ctx);
28120 t0 = tcg_temp_new();
28121 t1 = tcg_temp_new();
28123 gen_load_gpr(t0, rt);
28124 gen_load_gpr(t1, rs);
28126 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
28128 tcg_temp_free(t0);
28129 tcg_temp_free(t1);
28130 break;
28132 default: /* Invalid */
28133 MIPS_INVAL("MASK DINSV");
28134 gen_reserved_instruction(ctx);
28135 break;
28137 break;
28138 case OPC_SHLL_OB_DSP:
28139 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
28140 break;
28141 #endif
28142 default: /* Invalid */
28143 MIPS_INVAL("special3_legacy");
28144 gen_reserved_instruction(ctx);
28145 break;
28150 #if defined(TARGET_MIPS64)
28152 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
28154 uint32_t opc = MASK_MMI0(ctx->opcode);
28156 switch (opc) {
28157 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
28158 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
28159 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
28160 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
28161 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
28162 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
28163 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
28164 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
28165 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
28166 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
28167 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
28168 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
28169 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
28170 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
28171 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
28172 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
28173 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
28174 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
28175 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
28176 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
28177 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
28178 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
28179 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
28180 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
28181 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
28182 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI0 */
28183 break;
28184 default:
28185 MIPS_INVAL("TX79 MMI class MMI0");
28186 gen_reserved_instruction(ctx);
28187 break;
28191 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
28193 uint32_t opc = MASK_MMI1(ctx->opcode);
28195 switch (opc) {
28196 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
28197 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
28198 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
28199 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
28200 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
28201 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
28202 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
28203 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
28204 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
28205 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
28206 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
28207 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
28208 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
28209 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
28210 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
28211 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
28212 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
28213 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
28214 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI1 */
28215 break;
28216 default:
28217 MIPS_INVAL("TX79 MMI class MMI1");
28218 gen_reserved_instruction(ctx);
28219 break;
28223 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
28225 uint32_t opc = MASK_MMI2(ctx->opcode);
28227 switch (opc) {
28228 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
28229 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
28230 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
28231 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
28232 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
28233 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
28234 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
28235 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
28236 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
28237 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
28238 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
28239 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
28240 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
28241 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
28242 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
28243 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
28244 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
28245 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
28246 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
28247 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
28248 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
28249 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI2 */
28250 break;
28251 case MMI_OPC_2_PCPYLD:
28252 gen_mmi_pcpyld(ctx);
28253 break;
28254 default:
28255 MIPS_INVAL("TX79 MMI class MMI2");
28256 gen_reserved_instruction(ctx);
28257 break;
28261 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
28263 uint32_t opc = MASK_MMI3(ctx->opcode);
28265 switch (opc) {
28266 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
28267 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
28268 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
28269 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
28270 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
28271 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
28272 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
28273 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
28274 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
28275 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
28276 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
28277 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI3 */
28278 break;
28279 case MMI_OPC_3_PCPYH:
28280 gen_mmi_pcpyh(ctx);
28281 break;
28282 case MMI_OPC_3_PCPYUD:
28283 gen_mmi_pcpyud(ctx);
28284 break;
28285 default:
28286 MIPS_INVAL("TX79 MMI class MMI3");
28287 gen_reserved_instruction(ctx);
28288 break;
28292 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
28294 uint32_t opc = MASK_MMI(ctx->opcode);
28295 int rs = extract32(ctx->opcode, 21, 5);
28296 int rt = extract32(ctx->opcode, 16, 5);
28297 int rd = extract32(ctx->opcode, 11, 5);
28299 switch (opc) {
28300 case MMI_OPC_CLASS_MMI0:
28301 decode_mmi0(env, ctx);
28302 break;
28303 case MMI_OPC_CLASS_MMI1:
28304 decode_mmi1(env, ctx);
28305 break;
28306 case MMI_OPC_CLASS_MMI2:
28307 decode_mmi2(env, ctx);
28308 break;
28309 case MMI_OPC_CLASS_MMI3:
28310 decode_mmi3(env, ctx);
28311 break;
28312 case MMI_OPC_MULT1:
28313 case MMI_OPC_MULTU1:
28314 case MMI_OPC_MADD:
28315 case MMI_OPC_MADDU:
28316 case MMI_OPC_MADD1:
28317 case MMI_OPC_MADDU1:
28318 gen_mul_txx9(ctx, opc, rd, rs, rt);
28319 break;
28320 case MMI_OPC_DIV1:
28321 case MMI_OPC_DIVU1:
28322 gen_div1_tx79(ctx, opc, rs, rt);
28323 break;
28324 case MMI_OPC_MTLO1:
28325 case MMI_OPC_MTHI1:
28326 gen_HILO1_tx79(ctx, opc, rs);
28327 break;
28328 case MMI_OPC_MFLO1:
28329 case MMI_OPC_MFHI1:
28330 gen_HILO1_tx79(ctx, opc, rd);
28331 break;
28332 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28333 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28334 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28335 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28336 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28337 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28338 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28339 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28340 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28341 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_CLASS_MMI */
28342 break;
28343 default:
28344 MIPS_INVAL("TX79 MMI class");
28345 gen_reserved_instruction(ctx);
28346 break;
28350 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28352 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
28355 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28357 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
28361 * The TX79-specific instruction Store Quadword
28363 * +--------+-------+-------+------------------------+
28364 * | 011111 | base | rt | offset | SQ
28365 * +--------+-------+-------+------------------------+
28366 * 6 5 5 16
28368 * has the same opcode as the Read Hardware Register instruction
28370 * +--------+-------+-------+-------+-------+--------+
28371 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28372 * +--------+-------+-------+-------+-------+--------+
28373 * 6 5 5 5 5 6
28375 * that is required, trapped and emulated by the Linux kernel. However, all
28376 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28377 * offset is odd. Therefore all valid SQ instructions can execute normally.
28378 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28379 * between SQ and RDHWR, as the Linux kernel does.
28381 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28383 int base = extract32(ctx->opcode, 21, 5);
28384 int rt = extract32(ctx->opcode, 16, 5);
28385 int offset = extract32(ctx->opcode, 0, 16);
28387 #ifdef CONFIG_USER_ONLY
28388 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28389 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28391 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28392 int rd = extract32(ctx->opcode, 11, 5);
28394 gen_rdhwr(ctx, rt, rd, 0);
28395 return;
28397 #endif
28399 gen_mmi_sq(ctx, base, rt, offset);
28402 #endif
28404 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28406 int rs, rt, rd, sa;
28407 uint32_t op1, op2;
28408 int16_t imm;
28410 rs = (ctx->opcode >> 21) & 0x1f;
28411 rt = (ctx->opcode >> 16) & 0x1f;
28412 rd = (ctx->opcode >> 11) & 0x1f;
28413 sa = (ctx->opcode >> 6) & 0x1f;
28414 imm = sextract32(ctx->opcode, 7, 9);
28416 op1 = MASK_SPECIAL3(ctx->opcode);
28419 * EVA loads and stores overlap Loongson 2E instructions decoded by
28420 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28421 * EVA is absent.
28423 if (ctx->eva) {
28424 switch (op1) {
28425 case OPC_LWLE:
28426 case OPC_LWRE:
28427 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28428 /* fall through */
28429 case OPC_LBUE:
28430 case OPC_LHUE:
28431 case OPC_LBE:
28432 case OPC_LHE:
28433 case OPC_LLE:
28434 case OPC_LWE:
28435 check_cp0_enabled(ctx);
28436 gen_ld(ctx, op1, rt, rs, imm);
28437 return;
28438 case OPC_SWLE:
28439 case OPC_SWRE:
28440 check_insn_opc_removed(ctx, ISA_MIPS_R6);
28441 /* fall through */
28442 case OPC_SBE:
28443 case OPC_SHE:
28444 case OPC_SWE:
28445 check_cp0_enabled(ctx);
28446 gen_st(ctx, op1, rt, rs, imm);
28447 return;
28448 case OPC_SCE:
28449 check_cp0_enabled(ctx);
28450 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28451 return;
28452 case OPC_CACHEE:
28453 check_cp0_enabled(ctx);
28454 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28455 gen_cache_operation(ctx, rt, rs, imm);
28457 /* Treat as NOP. */
28458 return;
28459 case OPC_PREFE:
28460 check_cp0_enabled(ctx);
28461 /* Treat as NOP. */
28462 return;
28466 switch (op1) {
28467 case OPC_EXT:
28468 case OPC_INS:
28469 check_insn(ctx, ISA_MIPS_R2);
28470 gen_bitops(ctx, op1, rt, rs, sa, rd);
28471 break;
28472 case OPC_BSHFL:
28473 op2 = MASK_BSHFL(ctx->opcode);
28474 switch (op2) {
28475 case OPC_ALIGN:
28476 case OPC_ALIGN_1:
28477 case OPC_ALIGN_2:
28478 case OPC_ALIGN_3:
28479 case OPC_BITSWAP:
28480 check_insn(ctx, ISA_MIPS_R6);
28481 decode_opc_special3_r6(env, ctx);
28482 break;
28483 default:
28484 check_insn(ctx, ISA_MIPS_R2);
28485 gen_bshfl(ctx, op2, rt, rd);
28486 break;
28488 break;
28489 #if defined(TARGET_MIPS64)
28490 case OPC_DEXTM:
28491 case OPC_DEXTU:
28492 case OPC_DEXT:
28493 case OPC_DINSM:
28494 case OPC_DINSU:
28495 case OPC_DINS:
28496 check_insn(ctx, ISA_MIPS_R2);
28497 check_mips_64(ctx);
28498 gen_bitops(ctx, op1, rt, rs, sa, rd);
28499 break;
28500 case OPC_DBSHFL:
28501 op2 = MASK_DBSHFL(ctx->opcode);
28502 switch (op2) {
28503 case OPC_DALIGN:
28504 case OPC_DALIGN_1:
28505 case OPC_DALIGN_2:
28506 case OPC_DALIGN_3:
28507 case OPC_DALIGN_4:
28508 case OPC_DALIGN_5:
28509 case OPC_DALIGN_6:
28510 case OPC_DALIGN_7:
28511 case OPC_DBITSWAP:
28512 check_insn(ctx, ISA_MIPS_R6);
28513 decode_opc_special3_r6(env, ctx);
28514 break;
28515 default:
28516 check_insn(ctx, ISA_MIPS_R2);
28517 check_mips_64(ctx);
28518 op2 = MASK_DBSHFL(ctx->opcode);
28519 gen_bshfl(ctx, op2, rt, rd);
28520 break;
28522 break;
28523 #endif
28524 case OPC_RDHWR:
28525 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28526 break;
28527 case OPC_FORK:
28528 check_mt(ctx);
28530 TCGv t0 = tcg_temp_new();
28531 TCGv t1 = tcg_temp_new();
28533 gen_load_gpr(t0, rt);
28534 gen_load_gpr(t1, rs);
28535 gen_helper_fork(t0, t1);
28536 tcg_temp_free(t0);
28537 tcg_temp_free(t1);
28539 break;
28540 case OPC_YIELD:
28541 check_mt(ctx);
28543 TCGv t0 = tcg_temp_new();
28545 gen_load_gpr(t0, rs);
28546 gen_helper_yield(t0, cpu_env, t0);
28547 gen_store_gpr(t0, rd);
28548 tcg_temp_free(t0);
28550 break;
28551 default:
28552 if (ctx->insn_flags & ISA_MIPS_R6) {
28553 decode_opc_special3_r6(env, ctx);
28554 } else {
28555 decode_opc_special3_legacy(env, ctx);
28560 /* MIPS SIMD Architecture (MSA) */
28561 static inline int check_msa_access(DisasContext *ctx)
28563 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28564 !(ctx->hflags & MIPS_HFLAG_F64))) {
28565 gen_reserved_instruction(ctx);
28566 return 0;
28569 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28570 if (ctx->insn_flags & ASE_MSA) {
28571 generate_exception_end(ctx, EXCP_MSADIS);
28572 return 0;
28573 } else {
28574 gen_reserved_instruction(ctx);
28575 return 0;
28578 return 1;
28581 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28583 /* generates tcg ops to check if any element is 0 */
28584 /* Note this function only works with MSA_WRLEN = 128 */
28585 uint64_t eval_zero_or_big = 0;
28586 uint64_t eval_big = 0;
28587 TCGv_i64 t0 = tcg_temp_new_i64();
28588 TCGv_i64 t1 = tcg_temp_new_i64();
28589 switch (df) {
28590 case DF_BYTE:
28591 eval_zero_or_big = 0x0101010101010101ULL;
28592 eval_big = 0x8080808080808080ULL;
28593 break;
28594 case DF_HALF:
28595 eval_zero_or_big = 0x0001000100010001ULL;
28596 eval_big = 0x8000800080008000ULL;
28597 break;
28598 case DF_WORD:
28599 eval_zero_or_big = 0x0000000100000001ULL;
28600 eval_big = 0x8000000080000000ULL;
28601 break;
28602 case DF_DOUBLE:
28603 eval_zero_or_big = 0x0000000000000001ULL;
28604 eval_big = 0x8000000000000000ULL;
28605 break;
28607 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28608 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28609 tcg_gen_andi_i64(t0, t0, eval_big);
28610 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28611 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28612 tcg_gen_andi_i64(t1, t1, eval_big);
28613 tcg_gen_or_i64(t0, t0, t1);
28614 /* if all bits are zero then all elements are not zero */
28615 /* if some bit is non-zero then some element is zero */
28616 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28617 tcg_gen_trunc_i64_tl(tresult, t0);
28618 tcg_temp_free_i64(t0);
28619 tcg_temp_free_i64(t1);
28622 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28624 uint8_t df = (ctx->opcode >> 21) & 0x3;
28625 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28626 int64_t s16 = (int16_t)ctx->opcode;
28628 check_msa_access(ctx);
28630 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28631 gen_reserved_instruction(ctx);
28632 return;
28634 switch (op1) {
28635 case OPC_BZ_V:
28636 case OPC_BNZ_V:
28638 TCGv_i64 t0 = tcg_temp_new_i64();
28639 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28640 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28641 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28642 tcg_gen_trunc_i64_tl(bcond, t0);
28643 tcg_temp_free_i64(t0);
28645 break;
28646 case OPC_BZ_B:
28647 case OPC_BZ_H:
28648 case OPC_BZ_W:
28649 case OPC_BZ_D:
28650 gen_check_zero_element(bcond, df, wt);
28651 break;
28652 case OPC_BNZ_B:
28653 case OPC_BNZ_H:
28654 case OPC_BNZ_W:
28655 case OPC_BNZ_D:
28656 gen_check_zero_element(bcond, df, wt);
28657 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28658 break;
28661 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28663 ctx->hflags |= MIPS_HFLAG_BC;
28664 ctx->hflags |= MIPS_HFLAG_BDS32;
28667 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28669 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28670 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28671 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28672 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28674 TCGv_i32 twd = tcg_const_i32(wd);
28675 TCGv_i32 tws = tcg_const_i32(ws);
28676 TCGv_i32 ti8 = tcg_const_i32(i8);
28678 switch (MASK_MSA_I8(ctx->opcode)) {
28679 case OPC_ANDI_B:
28680 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28681 break;
28682 case OPC_ORI_B:
28683 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28684 break;
28685 case OPC_NORI_B:
28686 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28687 break;
28688 case OPC_XORI_B:
28689 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28690 break;
28691 case OPC_BMNZI_B:
28692 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28693 break;
28694 case OPC_BMZI_B:
28695 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28696 break;
28697 case OPC_BSELI_B:
28698 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28699 break;
28700 case OPC_SHF_B:
28701 case OPC_SHF_H:
28702 case OPC_SHF_W:
28704 uint8_t df = (ctx->opcode >> 24) & 0x3;
28705 if (df == DF_DOUBLE) {
28706 gen_reserved_instruction(ctx);
28707 } else {
28708 TCGv_i32 tdf = tcg_const_i32(df);
28709 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28710 tcg_temp_free_i32(tdf);
28713 break;
28714 default:
28715 MIPS_INVAL("MSA instruction");
28716 gen_reserved_instruction(ctx);
28717 break;
28720 tcg_temp_free_i32(twd);
28721 tcg_temp_free_i32(tws);
28722 tcg_temp_free_i32(ti8);
28725 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28727 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28728 uint8_t df = (ctx->opcode >> 21) & 0x3;
28729 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28730 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28731 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28732 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28734 TCGv_i32 tdf = tcg_const_i32(df);
28735 TCGv_i32 twd = tcg_const_i32(wd);
28736 TCGv_i32 tws = tcg_const_i32(ws);
28737 TCGv_i32 timm = tcg_temp_new_i32();
28738 tcg_gen_movi_i32(timm, u5);
28740 switch (MASK_MSA_I5(ctx->opcode)) {
28741 case OPC_ADDVI_df:
28742 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28743 break;
28744 case OPC_SUBVI_df:
28745 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28746 break;
28747 case OPC_MAXI_S_df:
28748 tcg_gen_movi_i32(timm, s5);
28749 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28750 break;
28751 case OPC_MAXI_U_df:
28752 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28753 break;
28754 case OPC_MINI_S_df:
28755 tcg_gen_movi_i32(timm, s5);
28756 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28757 break;
28758 case OPC_MINI_U_df:
28759 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28760 break;
28761 case OPC_CEQI_df:
28762 tcg_gen_movi_i32(timm, s5);
28763 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28764 break;
28765 case OPC_CLTI_S_df:
28766 tcg_gen_movi_i32(timm, s5);
28767 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28768 break;
28769 case OPC_CLTI_U_df:
28770 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28771 break;
28772 case OPC_CLEI_S_df:
28773 tcg_gen_movi_i32(timm, s5);
28774 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28775 break;
28776 case OPC_CLEI_U_df:
28777 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28778 break;
28779 case OPC_LDI_df:
28781 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28782 tcg_gen_movi_i32(timm, s10);
28783 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28785 break;
28786 default:
28787 MIPS_INVAL("MSA instruction");
28788 gen_reserved_instruction(ctx);
28789 break;
28792 tcg_temp_free_i32(tdf);
28793 tcg_temp_free_i32(twd);
28794 tcg_temp_free_i32(tws);
28795 tcg_temp_free_i32(timm);
28798 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28800 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28801 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28802 uint32_t df = 0, m = 0;
28803 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28804 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28806 TCGv_i32 tdf;
28807 TCGv_i32 tm;
28808 TCGv_i32 twd;
28809 TCGv_i32 tws;
28811 if ((dfm & 0x40) == 0x00) {
28812 m = dfm & 0x3f;
28813 df = DF_DOUBLE;
28814 } else if ((dfm & 0x60) == 0x40) {
28815 m = dfm & 0x1f;
28816 df = DF_WORD;
28817 } else if ((dfm & 0x70) == 0x60) {
28818 m = dfm & 0x0f;
28819 df = DF_HALF;
28820 } else if ((dfm & 0x78) == 0x70) {
28821 m = dfm & 0x7;
28822 df = DF_BYTE;
28823 } else {
28824 gen_reserved_instruction(ctx);
28825 return;
28828 tdf = tcg_const_i32(df);
28829 tm = tcg_const_i32(m);
28830 twd = tcg_const_i32(wd);
28831 tws = tcg_const_i32(ws);
28833 switch (MASK_MSA_BIT(ctx->opcode)) {
28834 case OPC_SLLI_df:
28835 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28836 break;
28837 case OPC_SRAI_df:
28838 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28839 break;
28840 case OPC_SRLI_df:
28841 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28842 break;
28843 case OPC_BCLRI_df:
28844 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28845 break;
28846 case OPC_BSETI_df:
28847 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28848 break;
28849 case OPC_BNEGI_df:
28850 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28851 break;
28852 case OPC_BINSLI_df:
28853 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28854 break;
28855 case OPC_BINSRI_df:
28856 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28857 break;
28858 case OPC_SAT_S_df:
28859 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28860 break;
28861 case OPC_SAT_U_df:
28862 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28863 break;
28864 case OPC_SRARI_df:
28865 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28866 break;
28867 case OPC_SRLRI_df:
28868 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28869 break;
28870 default:
28871 MIPS_INVAL("MSA instruction");
28872 gen_reserved_instruction(ctx);
28873 break;
28876 tcg_temp_free_i32(tdf);
28877 tcg_temp_free_i32(tm);
28878 tcg_temp_free_i32(twd);
28879 tcg_temp_free_i32(tws);
28882 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
28884 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28885 uint8_t df = (ctx->opcode >> 21) & 0x3;
28886 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28887 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28888 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28890 TCGv_i32 tdf = tcg_const_i32(df);
28891 TCGv_i32 twd = tcg_const_i32(wd);
28892 TCGv_i32 tws = tcg_const_i32(ws);
28893 TCGv_i32 twt = tcg_const_i32(wt);
28895 switch (MASK_MSA_3R(ctx->opcode)) {
28896 case OPC_BINSL_df:
28897 switch (df) {
28898 case DF_BYTE:
28899 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
28900 break;
28901 case DF_HALF:
28902 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
28903 break;
28904 case DF_WORD:
28905 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
28906 break;
28907 case DF_DOUBLE:
28908 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
28909 break;
28911 break;
28912 case OPC_BINSR_df:
28913 switch (df) {
28914 case DF_BYTE:
28915 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
28916 break;
28917 case DF_HALF:
28918 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
28919 break;
28920 case DF_WORD:
28921 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
28922 break;
28923 case DF_DOUBLE:
28924 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
28925 break;
28927 break;
28928 case OPC_BCLR_df:
28929 switch (df) {
28930 case DF_BYTE:
28931 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
28932 break;
28933 case DF_HALF:
28934 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
28935 break;
28936 case DF_WORD:
28937 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
28938 break;
28939 case DF_DOUBLE:
28940 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
28941 break;
28943 break;
28944 case OPC_BNEG_df:
28945 switch (df) {
28946 case DF_BYTE:
28947 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
28948 break;
28949 case DF_HALF:
28950 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
28951 break;
28952 case DF_WORD:
28953 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
28954 break;
28955 case DF_DOUBLE:
28956 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
28957 break;
28959 break;
28960 case OPC_BSET_df:
28961 switch (df) {
28962 case DF_BYTE:
28963 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
28964 break;
28965 case DF_HALF:
28966 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
28967 break;
28968 case DF_WORD:
28969 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
28970 break;
28971 case DF_DOUBLE:
28972 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
28973 break;
28975 break;
28976 case OPC_ADD_A_df:
28977 switch (df) {
28978 case DF_BYTE:
28979 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
28980 break;
28981 case DF_HALF:
28982 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
28983 break;
28984 case DF_WORD:
28985 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
28986 break;
28987 case DF_DOUBLE:
28988 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
28989 break;
28991 break;
28992 case OPC_ADDS_A_df:
28993 switch (df) {
28994 case DF_BYTE:
28995 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
28996 break;
28997 case DF_HALF:
28998 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
28999 break;
29000 case DF_WORD:
29001 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
29002 break;
29003 case DF_DOUBLE:
29004 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
29005 break;
29007 break;
29008 case OPC_ADDS_S_df:
29009 switch (df) {
29010 case DF_BYTE:
29011 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
29012 break;
29013 case DF_HALF:
29014 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
29015 break;
29016 case DF_WORD:
29017 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
29018 break;
29019 case DF_DOUBLE:
29020 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
29021 break;
29023 break;
29024 case OPC_ADDS_U_df:
29025 switch (df) {
29026 case DF_BYTE:
29027 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
29028 break;
29029 case DF_HALF:
29030 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
29031 break;
29032 case DF_WORD:
29033 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
29034 break;
29035 case DF_DOUBLE:
29036 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
29037 break;
29039 break;
29040 case OPC_ADDV_df:
29041 switch (df) {
29042 case DF_BYTE:
29043 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
29044 break;
29045 case DF_HALF:
29046 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
29047 break;
29048 case DF_WORD:
29049 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
29050 break;
29051 case DF_DOUBLE:
29052 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
29053 break;
29055 break;
29056 case OPC_AVE_S_df:
29057 switch (df) {
29058 case DF_BYTE:
29059 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
29060 break;
29061 case DF_HALF:
29062 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
29063 break;
29064 case DF_WORD:
29065 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
29066 break;
29067 case DF_DOUBLE:
29068 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
29069 break;
29071 break;
29072 case OPC_AVE_U_df:
29073 switch (df) {
29074 case DF_BYTE:
29075 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
29076 break;
29077 case DF_HALF:
29078 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
29079 break;
29080 case DF_WORD:
29081 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
29082 break;
29083 case DF_DOUBLE:
29084 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
29085 break;
29087 break;
29088 case OPC_AVER_S_df:
29089 switch (df) {
29090 case DF_BYTE:
29091 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
29092 break;
29093 case DF_HALF:
29094 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
29095 break;
29096 case DF_WORD:
29097 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
29098 break;
29099 case DF_DOUBLE:
29100 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
29101 break;
29103 break;
29104 case OPC_AVER_U_df:
29105 switch (df) {
29106 case DF_BYTE:
29107 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
29108 break;
29109 case DF_HALF:
29110 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
29111 break;
29112 case DF_WORD:
29113 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
29114 break;
29115 case DF_DOUBLE:
29116 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
29117 break;
29119 break;
29120 case OPC_CEQ_df:
29121 switch (df) {
29122 case DF_BYTE:
29123 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
29124 break;
29125 case DF_HALF:
29126 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
29127 break;
29128 case DF_WORD:
29129 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
29130 break;
29131 case DF_DOUBLE:
29132 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
29133 break;
29135 break;
29136 case OPC_CLE_S_df:
29137 switch (df) {
29138 case DF_BYTE:
29139 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
29140 break;
29141 case DF_HALF:
29142 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
29143 break;
29144 case DF_WORD:
29145 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
29146 break;
29147 case DF_DOUBLE:
29148 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
29149 break;
29151 break;
29152 case OPC_CLE_U_df:
29153 switch (df) {
29154 case DF_BYTE:
29155 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
29156 break;
29157 case DF_HALF:
29158 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
29159 break;
29160 case DF_WORD:
29161 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
29162 break;
29163 case DF_DOUBLE:
29164 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
29165 break;
29167 break;
29168 case OPC_CLT_S_df:
29169 switch (df) {
29170 case DF_BYTE:
29171 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
29172 break;
29173 case DF_HALF:
29174 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
29175 break;
29176 case DF_WORD:
29177 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
29178 break;
29179 case DF_DOUBLE:
29180 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
29181 break;
29183 break;
29184 case OPC_CLT_U_df:
29185 switch (df) {
29186 case DF_BYTE:
29187 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
29188 break;
29189 case DF_HALF:
29190 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
29191 break;
29192 case DF_WORD:
29193 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
29194 break;
29195 case DF_DOUBLE:
29196 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
29197 break;
29199 break;
29200 case OPC_DIV_S_df:
29201 switch (df) {
29202 case DF_BYTE:
29203 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
29204 break;
29205 case DF_HALF:
29206 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
29207 break;
29208 case DF_WORD:
29209 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
29210 break;
29211 case DF_DOUBLE:
29212 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
29213 break;
29215 break;
29216 case OPC_DIV_U_df:
29217 switch (df) {
29218 case DF_BYTE:
29219 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
29220 break;
29221 case DF_HALF:
29222 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
29223 break;
29224 case DF_WORD:
29225 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
29226 break;
29227 case DF_DOUBLE:
29228 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
29229 break;
29231 break;
29232 case OPC_MAX_A_df:
29233 switch (df) {
29234 case DF_BYTE:
29235 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
29236 break;
29237 case DF_HALF:
29238 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
29239 break;
29240 case DF_WORD:
29241 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
29242 break;
29243 case DF_DOUBLE:
29244 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
29245 break;
29247 break;
29248 case OPC_MAX_S_df:
29249 switch (df) {
29250 case DF_BYTE:
29251 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
29252 break;
29253 case DF_HALF:
29254 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
29255 break;
29256 case DF_WORD:
29257 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
29258 break;
29259 case DF_DOUBLE:
29260 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
29261 break;
29263 break;
29264 case OPC_MAX_U_df:
29265 switch (df) {
29266 case DF_BYTE:
29267 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
29268 break;
29269 case DF_HALF:
29270 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
29271 break;
29272 case DF_WORD:
29273 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
29274 break;
29275 case DF_DOUBLE:
29276 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
29277 break;
29279 break;
29280 case OPC_MIN_A_df:
29281 switch (df) {
29282 case DF_BYTE:
29283 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
29284 break;
29285 case DF_HALF:
29286 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
29287 break;
29288 case DF_WORD:
29289 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
29290 break;
29291 case DF_DOUBLE:
29292 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
29293 break;
29295 break;
29296 case OPC_MIN_S_df:
29297 switch (df) {
29298 case DF_BYTE:
29299 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29300 break;
29301 case DF_HALF:
29302 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29303 break;
29304 case DF_WORD:
29305 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29306 break;
29307 case DF_DOUBLE:
29308 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29309 break;
29311 break;
29312 case OPC_MIN_U_df:
29313 switch (df) {
29314 case DF_BYTE:
29315 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29316 break;
29317 case DF_HALF:
29318 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29319 break;
29320 case DF_WORD:
29321 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29322 break;
29323 case DF_DOUBLE:
29324 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29325 break;
29327 break;
29328 case OPC_MOD_S_df:
29329 switch (df) {
29330 case DF_BYTE:
29331 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29332 break;
29333 case DF_HALF:
29334 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29335 break;
29336 case DF_WORD:
29337 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29338 break;
29339 case DF_DOUBLE:
29340 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29341 break;
29343 break;
29344 case OPC_MOD_U_df:
29345 switch (df) {
29346 case DF_BYTE:
29347 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29348 break;
29349 case DF_HALF:
29350 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29351 break;
29352 case DF_WORD:
29353 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29354 break;
29355 case DF_DOUBLE:
29356 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29357 break;
29359 break;
29360 case OPC_MADDV_df:
29361 switch (df) {
29362 case DF_BYTE:
29363 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29364 break;
29365 case DF_HALF:
29366 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29367 break;
29368 case DF_WORD:
29369 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29370 break;
29371 case DF_DOUBLE:
29372 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29373 break;
29375 break;
29376 case OPC_MSUBV_df:
29377 switch (df) {
29378 case DF_BYTE:
29379 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29380 break;
29381 case DF_HALF:
29382 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29383 break;
29384 case DF_WORD:
29385 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29386 break;
29387 case DF_DOUBLE:
29388 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29389 break;
29391 break;
29392 case OPC_ASUB_S_df:
29393 switch (df) {
29394 case DF_BYTE:
29395 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29396 break;
29397 case DF_HALF:
29398 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29399 break;
29400 case DF_WORD:
29401 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29402 break;
29403 case DF_DOUBLE:
29404 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29405 break;
29407 break;
29408 case OPC_ASUB_U_df:
29409 switch (df) {
29410 case DF_BYTE:
29411 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29412 break;
29413 case DF_HALF:
29414 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29415 break;
29416 case DF_WORD:
29417 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29418 break;
29419 case DF_DOUBLE:
29420 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29421 break;
29423 break;
29424 case OPC_ILVEV_df:
29425 switch (df) {
29426 case DF_BYTE:
29427 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29428 break;
29429 case DF_HALF:
29430 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29431 break;
29432 case DF_WORD:
29433 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29434 break;
29435 case DF_DOUBLE:
29436 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29437 break;
29439 break;
29440 case OPC_ILVOD_df:
29441 switch (df) {
29442 case DF_BYTE:
29443 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29444 break;
29445 case DF_HALF:
29446 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29447 break;
29448 case DF_WORD:
29449 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29450 break;
29451 case DF_DOUBLE:
29452 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29453 break;
29455 break;
29456 case OPC_ILVL_df:
29457 switch (df) {
29458 case DF_BYTE:
29459 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29460 break;
29461 case DF_HALF:
29462 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29463 break;
29464 case DF_WORD:
29465 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29466 break;
29467 case DF_DOUBLE:
29468 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29469 break;
29471 break;
29472 case OPC_ILVR_df:
29473 switch (df) {
29474 case DF_BYTE:
29475 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29476 break;
29477 case DF_HALF:
29478 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29479 break;
29480 case DF_WORD:
29481 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29482 break;
29483 case DF_DOUBLE:
29484 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29485 break;
29487 break;
29488 case OPC_PCKEV_df:
29489 switch (df) {
29490 case DF_BYTE:
29491 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29492 break;
29493 case DF_HALF:
29494 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29495 break;
29496 case DF_WORD:
29497 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29498 break;
29499 case DF_DOUBLE:
29500 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29501 break;
29503 break;
29504 case OPC_PCKOD_df:
29505 switch (df) {
29506 case DF_BYTE:
29507 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29508 break;
29509 case DF_HALF:
29510 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29511 break;
29512 case DF_WORD:
29513 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29514 break;
29515 case DF_DOUBLE:
29516 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29517 break;
29519 break;
29520 case OPC_SLL_df:
29521 switch (df) {
29522 case DF_BYTE:
29523 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29524 break;
29525 case DF_HALF:
29526 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29527 break;
29528 case DF_WORD:
29529 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29530 break;
29531 case DF_DOUBLE:
29532 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29533 break;
29535 break;
29536 case OPC_SRA_df:
29537 switch (df) {
29538 case DF_BYTE:
29539 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29540 break;
29541 case DF_HALF:
29542 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29543 break;
29544 case DF_WORD:
29545 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29546 break;
29547 case DF_DOUBLE:
29548 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29549 break;
29551 break;
29552 case OPC_SRAR_df:
29553 switch (df) {
29554 case DF_BYTE:
29555 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29556 break;
29557 case DF_HALF:
29558 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29559 break;
29560 case DF_WORD:
29561 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29562 break;
29563 case DF_DOUBLE:
29564 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29565 break;
29567 break;
29568 case OPC_SRL_df:
29569 switch (df) {
29570 case DF_BYTE:
29571 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29572 break;
29573 case DF_HALF:
29574 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29575 break;
29576 case DF_WORD:
29577 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29578 break;
29579 case DF_DOUBLE:
29580 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29581 break;
29583 break;
29584 case OPC_SRLR_df:
29585 switch (df) {
29586 case DF_BYTE:
29587 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29588 break;
29589 case DF_HALF:
29590 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29591 break;
29592 case DF_WORD:
29593 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29594 break;
29595 case DF_DOUBLE:
29596 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29597 break;
29599 break;
29600 case OPC_SUBS_S_df:
29601 switch (df) {
29602 case DF_BYTE:
29603 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29604 break;
29605 case DF_HALF:
29606 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29607 break;
29608 case DF_WORD:
29609 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29610 break;
29611 case DF_DOUBLE:
29612 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29613 break;
29615 break;
29616 case OPC_MULV_df:
29617 switch (df) {
29618 case DF_BYTE:
29619 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29620 break;
29621 case DF_HALF:
29622 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29623 break;
29624 case DF_WORD:
29625 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29626 break;
29627 case DF_DOUBLE:
29628 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29629 break;
29631 break;
29632 case OPC_SLD_df:
29633 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29634 break;
29635 case OPC_VSHF_df:
29636 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29637 break;
29638 case OPC_SUBV_df:
29639 switch (df) {
29640 case DF_BYTE:
29641 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29642 break;
29643 case DF_HALF:
29644 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29645 break;
29646 case DF_WORD:
29647 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29648 break;
29649 case DF_DOUBLE:
29650 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29651 break;
29653 break;
29654 case OPC_SUBS_U_df:
29655 switch (df) {
29656 case DF_BYTE:
29657 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29658 break;
29659 case DF_HALF:
29660 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29661 break;
29662 case DF_WORD:
29663 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29664 break;
29665 case DF_DOUBLE:
29666 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29667 break;
29669 break;
29670 case OPC_SPLAT_df:
29671 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29672 break;
29673 case OPC_SUBSUS_U_df:
29674 switch (df) {
29675 case DF_BYTE:
29676 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29677 break;
29678 case DF_HALF:
29679 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29680 break;
29681 case DF_WORD:
29682 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29683 break;
29684 case DF_DOUBLE:
29685 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29686 break;
29688 break;
29689 case OPC_SUBSUU_S_df:
29690 switch (df) {
29691 case DF_BYTE:
29692 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29693 break;
29694 case DF_HALF:
29695 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29696 break;
29697 case DF_WORD:
29698 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29699 break;
29700 case DF_DOUBLE:
29701 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29702 break;
29704 break;
29706 case OPC_DOTP_S_df:
29707 case OPC_DOTP_U_df:
29708 case OPC_DPADD_S_df:
29709 case OPC_DPADD_U_df:
29710 case OPC_DPSUB_S_df:
29711 case OPC_HADD_S_df:
29712 case OPC_DPSUB_U_df:
29713 case OPC_HADD_U_df:
29714 case OPC_HSUB_S_df:
29715 case OPC_HSUB_U_df:
29716 if (df == DF_BYTE) {
29717 gen_reserved_instruction(ctx);
29718 break;
29720 switch (MASK_MSA_3R(ctx->opcode)) {
29721 case OPC_HADD_S_df:
29722 switch (df) {
29723 case DF_HALF:
29724 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29725 break;
29726 case DF_WORD:
29727 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29728 break;
29729 case DF_DOUBLE:
29730 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29731 break;
29733 break;
29734 case OPC_HADD_U_df:
29735 switch (df) {
29736 case DF_HALF:
29737 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29738 break;
29739 case DF_WORD:
29740 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29741 break;
29742 case DF_DOUBLE:
29743 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29744 break;
29746 break;
29747 case OPC_HSUB_S_df:
29748 switch (df) {
29749 case DF_HALF:
29750 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29751 break;
29752 case DF_WORD:
29753 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29754 break;
29755 case DF_DOUBLE:
29756 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29757 break;
29759 break;
29760 case OPC_HSUB_U_df:
29761 switch (df) {
29762 case DF_HALF:
29763 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29764 break;
29765 case DF_WORD:
29766 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29767 break;
29768 case DF_DOUBLE:
29769 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29770 break;
29772 break;
29773 case OPC_DOTP_S_df:
29774 switch (df) {
29775 case DF_HALF:
29776 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29777 break;
29778 case DF_WORD:
29779 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29780 break;
29781 case DF_DOUBLE:
29782 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29783 break;
29785 break;
29786 case OPC_DOTP_U_df:
29787 switch (df) {
29788 case DF_HALF:
29789 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29790 break;
29791 case DF_WORD:
29792 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29793 break;
29794 case DF_DOUBLE:
29795 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29796 break;
29798 break;
29799 case OPC_DPADD_S_df:
29800 switch (df) {
29801 case DF_HALF:
29802 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29803 break;
29804 case DF_WORD:
29805 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29806 break;
29807 case DF_DOUBLE:
29808 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29809 break;
29811 break;
29812 case OPC_DPADD_U_df:
29813 switch (df) {
29814 case DF_HALF:
29815 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29816 break;
29817 case DF_WORD:
29818 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29819 break;
29820 case DF_DOUBLE:
29821 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29822 break;
29824 break;
29825 case OPC_DPSUB_S_df:
29826 switch (df) {
29827 case DF_HALF:
29828 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29829 break;
29830 case DF_WORD:
29831 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29832 break;
29833 case DF_DOUBLE:
29834 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29835 break;
29837 break;
29838 case OPC_DPSUB_U_df:
29839 switch (df) {
29840 case DF_HALF:
29841 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29842 break;
29843 case DF_WORD:
29844 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29845 break;
29846 case DF_DOUBLE:
29847 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29848 break;
29850 break;
29852 break;
29853 default:
29854 MIPS_INVAL("MSA instruction");
29855 gen_reserved_instruction(ctx);
29856 break;
29858 tcg_temp_free_i32(twd);
29859 tcg_temp_free_i32(tws);
29860 tcg_temp_free_i32(twt);
29861 tcg_temp_free_i32(tdf);
29864 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29866 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29867 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29868 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29869 TCGv telm = tcg_temp_new();
29870 TCGv_i32 tsr = tcg_const_i32(source);
29871 TCGv_i32 tdt = tcg_const_i32(dest);
29873 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
29874 case OPC_CTCMSA:
29875 gen_load_gpr(telm, source);
29876 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
29877 break;
29878 case OPC_CFCMSA:
29879 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
29880 gen_store_gpr(telm, dest);
29881 break;
29882 case OPC_MOVE_V:
29883 gen_helper_msa_move_v(cpu_env, tdt, tsr);
29884 break;
29885 default:
29886 MIPS_INVAL("MSA instruction");
29887 gen_reserved_instruction(ctx);
29888 break;
29891 tcg_temp_free(telm);
29892 tcg_temp_free_i32(tdt);
29893 tcg_temp_free_i32(tsr);
29896 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
29897 uint32_t n)
29899 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
29900 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29901 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29903 TCGv_i32 tws = tcg_const_i32(ws);
29904 TCGv_i32 twd = tcg_const_i32(wd);
29905 TCGv_i32 tn = tcg_const_i32(n);
29906 TCGv_i32 tdf = tcg_const_i32(df);
29908 switch (MASK_MSA_ELM(ctx->opcode)) {
29909 case OPC_SLDI_df:
29910 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
29911 break;
29912 case OPC_SPLATI_df:
29913 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
29914 break;
29915 case OPC_INSVE_df:
29916 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
29917 break;
29918 case OPC_COPY_S_df:
29919 case OPC_COPY_U_df:
29920 case OPC_INSERT_df:
29921 #if !defined(TARGET_MIPS64)
29922 /* Double format valid only for MIPS64 */
29923 if (df == DF_DOUBLE) {
29924 gen_reserved_instruction(ctx);
29925 break;
29927 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
29928 (df == DF_WORD)) {
29929 gen_reserved_instruction(ctx);
29930 break;
29932 #endif
29933 switch (MASK_MSA_ELM(ctx->opcode)) {
29934 case OPC_COPY_S_df:
29935 if (likely(wd != 0)) {
29936 switch (df) {
29937 case DF_BYTE:
29938 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
29939 break;
29940 case DF_HALF:
29941 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
29942 break;
29943 case DF_WORD:
29944 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
29945 break;
29946 #if defined(TARGET_MIPS64)
29947 case DF_DOUBLE:
29948 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
29949 break;
29950 #endif
29951 default:
29952 assert(0);
29955 break;
29956 case OPC_COPY_U_df:
29957 if (likely(wd != 0)) {
29958 switch (df) {
29959 case DF_BYTE:
29960 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
29961 break;
29962 case DF_HALF:
29963 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
29964 break;
29965 #if defined(TARGET_MIPS64)
29966 case DF_WORD:
29967 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
29968 break;
29969 #endif
29970 default:
29971 assert(0);
29974 break;
29975 case OPC_INSERT_df:
29976 switch (df) {
29977 case DF_BYTE:
29978 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
29979 break;
29980 case DF_HALF:
29981 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
29982 break;
29983 case DF_WORD:
29984 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
29985 break;
29986 #if defined(TARGET_MIPS64)
29987 case DF_DOUBLE:
29988 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
29989 break;
29990 #endif
29991 default:
29992 assert(0);
29994 break;
29996 break;
29997 default:
29998 MIPS_INVAL("MSA instruction");
29999 gen_reserved_instruction(ctx);
30001 tcg_temp_free_i32(twd);
30002 tcg_temp_free_i32(tws);
30003 tcg_temp_free_i32(tn);
30004 tcg_temp_free_i32(tdf);
30007 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
30009 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
30010 uint32_t df = 0, n = 0;
30012 if ((dfn & 0x30) == 0x00) {
30013 n = dfn & 0x0f;
30014 df = DF_BYTE;
30015 } else if ((dfn & 0x38) == 0x20) {
30016 n = dfn & 0x07;
30017 df = DF_HALF;
30018 } else if ((dfn & 0x3c) == 0x30) {
30019 n = dfn & 0x03;
30020 df = DF_WORD;
30021 } else if ((dfn & 0x3e) == 0x38) {
30022 n = dfn & 0x01;
30023 df = DF_DOUBLE;
30024 } else if (dfn == 0x3E) {
30025 /* CTCMSA, CFCMSA, MOVE.V */
30026 gen_msa_elm_3e(env, ctx);
30027 return;
30028 } else {
30029 gen_reserved_instruction(ctx);
30030 return;
30033 gen_msa_elm_df(env, ctx, df, n);
30036 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
30038 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30039 uint8_t df = (ctx->opcode >> 21) & 0x1;
30040 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30041 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30042 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30044 TCGv_i32 twd = tcg_const_i32(wd);
30045 TCGv_i32 tws = tcg_const_i32(ws);
30046 TCGv_i32 twt = tcg_const_i32(wt);
30047 TCGv_i32 tdf = tcg_temp_new_i32();
30049 /* adjust df value for floating-point instruction */
30050 tcg_gen_movi_i32(tdf, df + 2);
30052 switch (MASK_MSA_3RF(ctx->opcode)) {
30053 case OPC_FCAF_df:
30054 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
30055 break;
30056 case OPC_FADD_df:
30057 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
30058 break;
30059 case OPC_FCUN_df:
30060 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
30061 break;
30062 case OPC_FSUB_df:
30063 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
30064 break;
30065 case OPC_FCOR_df:
30066 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
30067 break;
30068 case OPC_FCEQ_df:
30069 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
30070 break;
30071 case OPC_FMUL_df:
30072 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
30073 break;
30074 case OPC_FCUNE_df:
30075 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
30076 break;
30077 case OPC_FCUEQ_df:
30078 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
30079 break;
30080 case OPC_FDIV_df:
30081 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
30082 break;
30083 case OPC_FCNE_df:
30084 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
30085 break;
30086 case OPC_FCLT_df:
30087 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
30088 break;
30089 case OPC_FMADD_df:
30090 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
30091 break;
30092 case OPC_MUL_Q_df:
30093 tcg_gen_movi_i32(tdf, df + 1);
30094 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
30095 break;
30096 case OPC_FCULT_df:
30097 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
30098 break;
30099 case OPC_FMSUB_df:
30100 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
30101 break;
30102 case OPC_MADD_Q_df:
30103 tcg_gen_movi_i32(tdf, df + 1);
30104 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
30105 break;
30106 case OPC_FCLE_df:
30107 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
30108 break;
30109 case OPC_MSUB_Q_df:
30110 tcg_gen_movi_i32(tdf, df + 1);
30111 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
30112 break;
30113 case OPC_FCULE_df:
30114 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
30115 break;
30116 case OPC_FEXP2_df:
30117 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
30118 break;
30119 case OPC_FSAF_df:
30120 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
30121 break;
30122 case OPC_FEXDO_df:
30123 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
30124 break;
30125 case OPC_FSUN_df:
30126 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
30127 break;
30128 case OPC_FSOR_df:
30129 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
30130 break;
30131 case OPC_FSEQ_df:
30132 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
30133 break;
30134 case OPC_FTQ_df:
30135 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
30136 break;
30137 case OPC_FSUNE_df:
30138 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
30139 break;
30140 case OPC_FSUEQ_df:
30141 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
30142 break;
30143 case OPC_FSNE_df:
30144 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
30145 break;
30146 case OPC_FSLT_df:
30147 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
30148 break;
30149 case OPC_FMIN_df:
30150 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
30151 break;
30152 case OPC_MULR_Q_df:
30153 tcg_gen_movi_i32(tdf, df + 1);
30154 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
30155 break;
30156 case OPC_FSULT_df:
30157 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
30158 break;
30159 case OPC_FMIN_A_df:
30160 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
30161 break;
30162 case OPC_MADDR_Q_df:
30163 tcg_gen_movi_i32(tdf, df + 1);
30164 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
30165 break;
30166 case OPC_FSLE_df:
30167 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
30168 break;
30169 case OPC_FMAX_df:
30170 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
30171 break;
30172 case OPC_MSUBR_Q_df:
30173 tcg_gen_movi_i32(tdf, df + 1);
30174 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
30175 break;
30176 case OPC_FSULE_df:
30177 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
30178 break;
30179 case OPC_FMAX_A_df:
30180 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
30181 break;
30182 default:
30183 MIPS_INVAL("MSA instruction");
30184 gen_reserved_instruction(ctx);
30185 break;
30188 tcg_temp_free_i32(twd);
30189 tcg_temp_free_i32(tws);
30190 tcg_temp_free_i32(twt);
30191 tcg_temp_free_i32(tdf);
30194 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
30196 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30197 (op & (0x7 << 18)))
30198 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30199 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30200 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30201 uint8_t df = (ctx->opcode >> 16) & 0x3;
30202 TCGv_i32 twd = tcg_const_i32(wd);
30203 TCGv_i32 tws = tcg_const_i32(ws);
30204 TCGv_i32 twt = tcg_const_i32(wt);
30205 TCGv_i32 tdf = tcg_const_i32(df);
30207 switch (MASK_MSA_2R(ctx->opcode)) {
30208 case OPC_FILL_df:
30209 #if !defined(TARGET_MIPS64)
30210 /* Double format valid only for MIPS64 */
30211 if (df == DF_DOUBLE) {
30212 gen_reserved_instruction(ctx);
30213 break;
30215 #endif
30216 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
30217 break;
30218 case OPC_NLOC_df:
30219 switch (df) {
30220 case DF_BYTE:
30221 gen_helper_msa_nloc_b(cpu_env, twd, tws);
30222 break;
30223 case DF_HALF:
30224 gen_helper_msa_nloc_h(cpu_env, twd, tws);
30225 break;
30226 case DF_WORD:
30227 gen_helper_msa_nloc_w(cpu_env, twd, tws);
30228 break;
30229 case DF_DOUBLE:
30230 gen_helper_msa_nloc_d(cpu_env, twd, tws);
30231 break;
30233 break;
30234 case OPC_NLZC_df:
30235 switch (df) {
30236 case DF_BYTE:
30237 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
30238 break;
30239 case DF_HALF:
30240 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
30241 break;
30242 case DF_WORD:
30243 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
30244 break;
30245 case DF_DOUBLE:
30246 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
30247 break;
30249 break;
30250 case OPC_PCNT_df:
30251 switch (df) {
30252 case DF_BYTE:
30253 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
30254 break;
30255 case DF_HALF:
30256 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
30257 break;
30258 case DF_WORD:
30259 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
30260 break;
30261 case DF_DOUBLE:
30262 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
30263 break;
30265 break;
30266 default:
30267 MIPS_INVAL("MSA instruction");
30268 gen_reserved_instruction(ctx);
30269 break;
30272 tcg_temp_free_i32(twd);
30273 tcg_temp_free_i32(tws);
30274 tcg_temp_free_i32(twt);
30275 tcg_temp_free_i32(tdf);
30278 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
30280 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30281 (op & (0xf << 17)))
30282 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30283 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30284 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30285 uint8_t df = (ctx->opcode >> 16) & 0x1;
30286 TCGv_i32 twd = tcg_const_i32(wd);
30287 TCGv_i32 tws = tcg_const_i32(ws);
30288 TCGv_i32 twt = tcg_const_i32(wt);
30289 /* adjust df value for floating-point instruction */
30290 TCGv_i32 tdf = tcg_const_i32(df + 2);
30292 switch (MASK_MSA_2RF(ctx->opcode)) {
30293 case OPC_FCLASS_df:
30294 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
30295 break;
30296 case OPC_FTRUNC_S_df:
30297 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
30298 break;
30299 case OPC_FTRUNC_U_df:
30300 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
30301 break;
30302 case OPC_FSQRT_df:
30303 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
30304 break;
30305 case OPC_FRSQRT_df:
30306 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30307 break;
30308 case OPC_FRCP_df:
30309 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30310 break;
30311 case OPC_FRINT_df:
30312 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30313 break;
30314 case OPC_FLOG2_df:
30315 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30316 break;
30317 case OPC_FEXUPL_df:
30318 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30319 break;
30320 case OPC_FEXUPR_df:
30321 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30322 break;
30323 case OPC_FFQL_df:
30324 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30325 break;
30326 case OPC_FFQR_df:
30327 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30328 break;
30329 case OPC_FTINT_S_df:
30330 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30331 break;
30332 case OPC_FTINT_U_df:
30333 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30334 break;
30335 case OPC_FFINT_S_df:
30336 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30337 break;
30338 case OPC_FFINT_U_df:
30339 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30340 break;
30343 tcg_temp_free_i32(twd);
30344 tcg_temp_free_i32(tws);
30345 tcg_temp_free_i32(twt);
30346 tcg_temp_free_i32(tdf);
30349 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30351 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
30352 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30353 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30354 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30355 TCGv_i32 twd = tcg_const_i32(wd);
30356 TCGv_i32 tws = tcg_const_i32(ws);
30357 TCGv_i32 twt = tcg_const_i32(wt);
30359 switch (MASK_MSA_VEC(ctx->opcode)) {
30360 case OPC_AND_V:
30361 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30362 break;
30363 case OPC_OR_V:
30364 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30365 break;
30366 case OPC_NOR_V:
30367 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30368 break;
30369 case OPC_XOR_V:
30370 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30371 break;
30372 case OPC_BMNZ_V:
30373 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30374 break;
30375 case OPC_BMZ_V:
30376 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30377 break;
30378 case OPC_BSEL_V:
30379 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30380 break;
30381 default:
30382 MIPS_INVAL("MSA instruction");
30383 gen_reserved_instruction(ctx);
30384 break;
30387 tcg_temp_free_i32(twd);
30388 tcg_temp_free_i32(tws);
30389 tcg_temp_free_i32(twt);
30392 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30394 switch (MASK_MSA_VEC(ctx->opcode)) {
30395 case OPC_AND_V:
30396 case OPC_OR_V:
30397 case OPC_NOR_V:
30398 case OPC_XOR_V:
30399 case OPC_BMNZ_V:
30400 case OPC_BMZ_V:
30401 case OPC_BSEL_V:
30402 gen_msa_vec_v(env, ctx);
30403 break;
30404 case OPC_MSA_2R:
30405 gen_msa_2r(env, ctx);
30406 break;
30407 case OPC_MSA_2RF:
30408 gen_msa_2rf(env, ctx);
30409 break;
30410 default:
30411 MIPS_INVAL("MSA instruction");
30412 gen_reserved_instruction(ctx);
30413 break;
30417 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30419 uint32_t opcode = ctx->opcode;
30420 check_insn(ctx, ASE_MSA);
30421 check_msa_access(ctx);
30423 switch (MASK_MSA_MINOR(opcode)) {
30424 case OPC_MSA_I8_00:
30425 case OPC_MSA_I8_01:
30426 case OPC_MSA_I8_02:
30427 gen_msa_i8(env, ctx);
30428 break;
30429 case OPC_MSA_I5_06:
30430 case OPC_MSA_I5_07:
30431 gen_msa_i5(env, ctx);
30432 break;
30433 case OPC_MSA_BIT_09:
30434 case OPC_MSA_BIT_0A:
30435 gen_msa_bit(env, ctx);
30436 break;
30437 case OPC_MSA_3R_0D:
30438 case OPC_MSA_3R_0E:
30439 case OPC_MSA_3R_0F:
30440 case OPC_MSA_3R_10:
30441 case OPC_MSA_3R_11:
30442 case OPC_MSA_3R_12:
30443 case OPC_MSA_3R_13:
30444 case OPC_MSA_3R_14:
30445 case OPC_MSA_3R_15:
30446 gen_msa_3r(env, ctx);
30447 break;
30448 case OPC_MSA_ELM:
30449 gen_msa_elm(env, ctx);
30450 break;
30451 case OPC_MSA_3RF_1A:
30452 case OPC_MSA_3RF_1B:
30453 case OPC_MSA_3RF_1C:
30454 gen_msa_3rf(env, ctx);
30455 break;
30456 case OPC_MSA_VEC:
30457 gen_msa_vec(env, ctx);
30458 break;
30459 case OPC_LD_B:
30460 case OPC_LD_H:
30461 case OPC_LD_W:
30462 case OPC_LD_D:
30463 case OPC_ST_B:
30464 case OPC_ST_H:
30465 case OPC_ST_W:
30466 case OPC_ST_D:
30468 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30469 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30470 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30471 uint8_t df = (ctx->opcode >> 0) & 0x3;
30473 TCGv_i32 twd = tcg_const_i32(wd);
30474 TCGv taddr = tcg_temp_new();
30475 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
30477 switch (MASK_MSA_MINOR(opcode)) {
30478 case OPC_LD_B:
30479 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30480 break;
30481 case OPC_LD_H:
30482 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30483 break;
30484 case OPC_LD_W:
30485 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30486 break;
30487 case OPC_LD_D:
30488 gen_helper_msa_ld_d(cpu_env, twd, taddr);
30489 break;
30490 case OPC_ST_B:
30491 gen_helper_msa_st_b(cpu_env, twd, taddr);
30492 break;
30493 case OPC_ST_H:
30494 gen_helper_msa_st_h(cpu_env, twd, taddr);
30495 break;
30496 case OPC_ST_W:
30497 gen_helper_msa_st_w(cpu_env, twd, taddr);
30498 break;
30499 case OPC_ST_D:
30500 gen_helper_msa_st_d(cpu_env, twd, taddr);
30501 break;
30504 tcg_temp_free_i32(twd);
30505 tcg_temp_free(taddr);
30507 break;
30508 default:
30509 MIPS_INVAL("MSA instruction");
30510 gen_reserved_instruction(ctx);
30511 break;
30516 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
30518 int32_t offset;
30519 int rs, rt, rd, sa;
30520 uint32_t op, op1;
30521 int16_t imm;
30523 op = MASK_OP_MAJOR(ctx->opcode);
30524 rs = (ctx->opcode >> 21) & 0x1f;
30525 rt = (ctx->opcode >> 16) & 0x1f;
30526 rd = (ctx->opcode >> 11) & 0x1f;
30527 sa = (ctx->opcode >> 6) & 0x1f;
30528 imm = (int16_t)ctx->opcode;
30529 switch (op) {
30530 case OPC_SPECIAL:
30531 decode_opc_special(env, ctx);
30532 break;
30533 case OPC_SPECIAL2:
30534 #if defined(TARGET_MIPS64)
30535 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30536 decode_mmi(env, ctx);
30537 #else
30538 if (ctx->insn_flags & ASE_MXU) {
30539 decode_opc_mxu(env, ctx);
30540 #endif
30541 } else {
30542 decode_opc_special2_legacy(env, ctx);
30544 break;
30545 case OPC_SPECIAL3:
30546 #if defined(TARGET_MIPS64)
30547 if (ctx->insn_flags & INSN_R5900) {
30548 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30549 } else {
30550 decode_opc_special3(env, ctx);
30552 #else
30553 decode_opc_special3(env, ctx);
30554 #endif
30555 break;
30556 case OPC_REGIMM:
30557 op1 = MASK_REGIMM(ctx->opcode);
30558 switch (op1) {
30559 case OPC_BLTZL: /* REGIMM branches */
30560 case OPC_BGEZL:
30561 case OPC_BLTZALL:
30562 case OPC_BGEZALL:
30563 check_insn(ctx, ISA_MIPS2);
30564 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30565 /* Fallthrough */
30566 case OPC_BLTZ:
30567 case OPC_BGEZ:
30568 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30569 break;
30570 case OPC_BLTZAL:
30571 case OPC_BGEZAL:
30572 if (ctx->insn_flags & ISA_MIPS_R6) {
30573 if (rs == 0) {
30574 /* OPC_NAL, OPC_BAL */
30575 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30576 } else {
30577 gen_reserved_instruction(ctx);
30579 } else {
30580 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30582 break;
30583 case OPC_TGEI: /* REGIMM traps */
30584 case OPC_TGEIU:
30585 case OPC_TLTI:
30586 case OPC_TLTIU:
30587 case OPC_TEQI:
30589 case OPC_TNEI:
30590 check_insn(ctx, ISA_MIPS2);
30591 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30592 gen_trap(ctx, op1, rs, -1, imm);
30593 break;
30594 case OPC_SIGRIE:
30595 check_insn(ctx, ISA_MIPS_R6);
30596 gen_reserved_instruction(ctx);
30597 break;
30598 case OPC_SYNCI:
30599 check_insn(ctx, ISA_MIPS_R2);
30601 * Break the TB to be able to sync copied instructions
30602 * immediately.
30604 ctx->base.is_jmp = DISAS_STOP;
30605 break;
30606 case OPC_BPOSGE32: /* MIPS DSP branch */
30607 #if defined(TARGET_MIPS64)
30608 case OPC_BPOSGE64:
30609 #endif
30610 check_dsp(ctx);
30611 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30612 break;
30613 #if defined(TARGET_MIPS64)
30614 case OPC_DAHI:
30615 check_insn(ctx, ISA_MIPS_R6);
30616 check_mips_64(ctx);
30617 if (rs != 0) {
30618 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30620 break;
30621 case OPC_DATI:
30622 check_insn(ctx, ISA_MIPS_R6);
30623 check_mips_64(ctx);
30624 if (rs != 0) {
30625 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30627 break;
30628 #endif
30629 default: /* Invalid */
30630 MIPS_INVAL("regimm");
30631 gen_reserved_instruction(ctx);
30632 break;
30634 break;
30635 case OPC_CP0:
30636 check_cp0_enabled(ctx);
30637 op1 = MASK_CP0(ctx->opcode);
30638 switch (op1) {
30639 case OPC_MFC0:
30640 case OPC_MTC0:
30641 case OPC_MFTR:
30642 case OPC_MTTR:
30643 case OPC_MFHC0:
30644 case OPC_MTHC0:
30645 #if defined(TARGET_MIPS64)
30646 case OPC_DMFC0:
30647 case OPC_DMTC0:
30648 #endif
30649 #ifndef CONFIG_USER_ONLY
30650 gen_cp0(env, ctx, op1, rt, rd);
30651 #endif /* !CONFIG_USER_ONLY */
30652 break;
30653 case OPC_C0:
30654 case OPC_C0_1:
30655 case OPC_C0_2:
30656 case OPC_C0_3:
30657 case OPC_C0_4:
30658 case OPC_C0_5:
30659 case OPC_C0_6:
30660 case OPC_C0_7:
30661 case OPC_C0_8:
30662 case OPC_C0_9:
30663 case OPC_C0_A:
30664 case OPC_C0_B:
30665 case OPC_C0_C:
30666 case OPC_C0_D:
30667 case OPC_C0_E:
30668 case OPC_C0_F:
30669 #ifndef CONFIG_USER_ONLY
30670 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30671 #endif /* !CONFIG_USER_ONLY */
30672 break;
30673 case OPC_MFMC0:
30674 #ifndef CONFIG_USER_ONLY
30676 uint32_t op2;
30677 TCGv t0 = tcg_temp_new();
30679 op2 = MASK_MFMC0(ctx->opcode);
30680 switch (op2) {
30681 case OPC_DMT:
30682 check_cp0_mt(ctx);
30683 gen_helper_dmt(t0);
30684 gen_store_gpr(t0, rt);
30685 break;
30686 case OPC_EMT:
30687 check_cp0_mt(ctx);
30688 gen_helper_emt(t0);
30689 gen_store_gpr(t0, rt);
30690 break;
30691 case OPC_DVPE:
30692 check_cp0_mt(ctx);
30693 gen_helper_dvpe(t0, cpu_env);
30694 gen_store_gpr(t0, rt);
30695 break;
30696 case OPC_EVPE:
30697 check_cp0_mt(ctx);
30698 gen_helper_evpe(t0, cpu_env);
30699 gen_store_gpr(t0, rt);
30700 break;
30701 case OPC_DVP:
30702 check_insn(ctx, ISA_MIPS_R6);
30703 if (ctx->vp) {
30704 gen_helper_dvp(t0, cpu_env);
30705 gen_store_gpr(t0, rt);
30707 break;
30708 case OPC_EVP:
30709 check_insn(ctx, ISA_MIPS_R6);
30710 if (ctx->vp) {
30711 gen_helper_evp(t0, cpu_env);
30712 gen_store_gpr(t0, rt);
30714 break;
30715 case OPC_DI:
30716 check_insn(ctx, ISA_MIPS_R2);
30717 save_cpu_state(ctx, 1);
30718 gen_helper_di(t0, cpu_env);
30719 gen_store_gpr(t0, rt);
30721 * Stop translation as we may have switched
30722 * the execution mode.
30724 ctx->base.is_jmp = DISAS_STOP;
30725 break;
30726 case OPC_EI:
30727 check_insn(ctx, ISA_MIPS_R2);
30728 save_cpu_state(ctx, 1);
30729 gen_helper_ei(t0, cpu_env);
30730 gen_store_gpr(t0, rt);
30732 * DISAS_STOP isn't sufficient, we need to ensure we break
30733 * out of translated code to check for pending interrupts.
30735 gen_save_pc(ctx->base.pc_next + 4);
30736 ctx->base.is_jmp = DISAS_EXIT;
30737 break;
30738 default: /* Invalid */
30739 MIPS_INVAL("mfmc0");
30740 gen_reserved_instruction(ctx);
30741 break;
30743 tcg_temp_free(t0);
30745 #endif /* !CONFIG_USER_ONLY */
30746 break;
30747 case OPC_RDPGPR:
30748 check_insn(ctx, ISA_MIPS_R2);
30749 gen_load_srsgpr(rt, rd);
30750 break;
30751 case OPC_WRPGPR:
30752 check_insn(ctx, ISA_MIPS_R2);
30753 gen_store_srsgpr(rt, rd);
30754 break;
30755 default:
30756 MIPS_INVAL("cp0");
30757 gen_reserved_instruction(ctx);
30758 break;
30760 break;
30761 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30762 if (ctx->insn_flags & ISA_MIPS_R6) {
30763 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30764 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30765 } else {
30766 /* OPC_ADDI */
30767 /* Arithmetic with immediate opcode */
30768 gen_arith_imm(ctx, op, rt, rs, imm);
30770 break;
30771 case OPC_ADDIU:
30772 gen_arith_imm(ctx, op, rt, rs, imm);
30773 break;
30774 case OPC_SLTI: /* Set on less than with immediate opcode */
30775 case OPC_SLTIU:
30776 gen_slt_imm(ctx, op, rt, rs, imm);
30777 break;
30778 case OPC_ANDI: /* Arithmetic with immediate opcode */
30779 case OPC_LUI: /* OPC_AUI */
30780 case OPC_ORI:
30781 case OPC_XORI:
30782 gen_logic_imm(ctx, op, rt, rs, imm);
30783 break;
30784 case OPC_J: /* Jump */
30785 case OPC_JAL:
30786 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30787 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30788 break;
30789 /* Branch */
30790 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30791 if (ctx->insn_flags & ISA_MIPS_R6) {
30792 if (rt == 0) {
30793 gen_reserved_instruction(ctx);
30794 break;
30796 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30797 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30798 } else {
30799 /* OPC_BLEZL */
30800 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30802 break;
30803 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30804 if (ctx->insn_flags & ISA_MIPS_R6) {
30805 if (rt == 0) {
30806 gen_reserved_instruction(ctx);
30807 break;
30809 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30810 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30811 } else {
30812 /* OPC_BGTZL */
30813 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30815 break;
30816 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30817 if (rt == 0) {
30818 /* OPC_BLEZ */
30819 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30820 } else {
30821 check_insn(ctx, ISA_MIPS_R6);
30822 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30823 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30825 break;
30826 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30827 if (rt == 0) {
30828 /* OPC_BGTZ */
30829 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30830 } else {
30831 check_insn(ctx, ISA_MIPS_R6);
30832 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30833 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30835 break;
30836 case OPC_BEQL:
30837 case OPC_BNEL:
30838 check_insn(ctx, ISA_MIPS2);
30839 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30840 /* Fallthrough */
30841 case OPC_BEQ:
30842 case OPC_BNE:
30843 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30844 break;
30845 case OPC_LL: /* Load and stores */
30846 check_insn(ctx, ISA_MIPS2);
30847 if (ctx->insn_flags & INSN_R5900) {
30848 check_insn_opc_user_only(ctx, INSN_R5900);
30850 /* Fallthrough */
30851 case OPC_LWL:
30852 case OPC_LWR:
30853 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30854 /* Fallthrough */
30855 case OPC_LB:
30856 case OPC_LH:
30857 case OPC_LW:
30858 case OPC_LWPC:
30859 case OPC_LBU:
30860 case OPC_LHU:
30861 gen_ld(ctx, op, rt, rs, imm);
30862 break;
30863 case OPC_SWL:
30864 case OPC_SWR:
30865 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30866 /* fall through */
30867 case OPC_SB:
30868 case OPC_SH:
30869 case OPC_SW:
30870 gen_st(ctx, op, rt, rs, imm);
30871 break;
30872 case OPC_SC:
30873 check_insn(ctx, ISA_MIPS2);
30874 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30875 if (ctx->insn_flags & INSN_R5900) {
30876 check_insn_opc_user_only(ctx, INSN_R5900);
30878 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
30879 break;
30880 case OPC_CACHE:
30881 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30882 check_cp0_enabled(ctx);
30883 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
30884 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
30885 gen_cache_operation(ctx, rt, rs, imm);
30887 /* Treat as NOP. */
30888 break;
30889 case OPC_PREF:
30890 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30891 if (ctx->insn_flags & INSN_R5900) {
30892 /* Treat as NOP. */
30893 } else {
30894 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
30895 /* Treat as NOP. */
30897 break;
30899 /* Floating point (COP1). */
30900 case OPC_LWC1:
30901 case OPC_LDC1:
30902 case OPC_SWC1:
30903 case OPC_SDC1:
30904 gen_cop1_ldst(ctx, op, rt, rs, imm);
30905 break;
30907 case OPC_CP1:
30908 op1 = MASK_CP1(ctx->opcode);
30910 switch (op1) {
30911 case OPC_MFHC1:
30912 case OPC_MTHC1:
30913 check_cp1_enabled(ctx);
30914 check_insn(ctx, ISA_MIPS_R2);
30915 /* fall through */
30916 case OPC_MFC1:
30917 case OPC_CFC1:
30918 case OPC_MTC1:
30919 case OPC_CTC1:
30920 check_cp1_enabled(ctx);
30921 gen_cp1(ctx, op1, rt, rd);
30922 break;
30923 #if defined(TARGET_MIPS64)
30924 case OPC_DMFC1:
30925 case OPC_DMTC1:
30926 check_cp1_enabled(ctx);
30927 check_insn(ctx, ISA_MIPS3);
30928 check_mips_64(ctx);
30929 gen_cp1(ctx, op1, rt, rd);
30930 break;
30931 #endif
30932 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
30933 check_cp1_enabled(ctx);
30934 if (ctx->insn_flags & ISA_MIPS_R6) {
30935 /* OPC_BC1EQZ */
30936 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30937 rt, imm << 2, 4);
30938 } else {
30939 /* OPC_BC1ANY2 */
30940 check_cop1x(ctx);
30941 check_insn(ctx, ASE_MIPS3D);
30942 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30943 (rt >> 2) & 0x7, imm << 2);
30945 break;
30946 case OPC_BC1NEZ:
30947 check_cp1_enabled(ctx);
30948 check_insn(ctx, ISA_MIPS_R6);
30949 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
30950 rt, imm << 2, 4);
30951 break;
30952 case OPC_BC1ANY4:
30953 check_cp1_enabled(ctx);
30954 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30955 check_cop1x(ctx);
30956 check_insn(ctx, ASE_MIPS3D);
30957 /* fall through */
30958 case OPC_BC1:
30959 check_cp1_enabled(ctx);
30960 check_insn_opc_removed(ctx, ISA_MIPS_R6);
30961 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
30962 (rt >> 2) & 0x7, imm << 2);
30963 break;
30964 case OPC_PS_FMT:
30965 check_ps(ctx);
30966 /* fall through */
30967 case OPC_S_FMT:
30968 case OPC_D_FMT:
30969 check_cp1_enabled(ctx);
30970 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
30971 (imm >> 8) & 0x7);
30972 break;
30973 case OPC_W_FMT:
30974 case OPC_L_FMT:
30976 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
30977 check_cp1_enabled(ctx);
30978 if (ctx->insn_flags & ISA_MIPS_R6) {
30979 switch (r6_op) {
30980 case R6_OPC_CMP_AF_S:
30981 case R6_OPC_CMP_UN_S:
30982 case R6_OPC_CMP_EQ_S:
30983 case R6_OPC_CMP_UEQ_S:
30984 case R6_OPC_CMP_LT_S:
30985 case R6_OPC_CMP_ULT_S:
30986 case R6_OPC_CMP_LE_S:
30987 case R6_OPC_CMP_ULE_S:
30988 case R6_OPC_CMP_SAF_S:
30989 case R6_OPC_CMP_SUN_S:
30990 case R6_OPC_CMP_SEQ_S:
30991 case R6_OPC_CMP_SEUQ_S:
30992 case R6_OPC_CMP_SLT_S:
30993 case R6_OPC_CMP_SULT_S:
30994 case R6_OPC_CMP_SLE_S:
30995 case R6_OPC_CMP_SULE_S:
30996 case R6_OPC_CMP_OR_S:
30997 case R6_OPC_CMP_UNE_S:
30998 case R6_OPC_CMP_NE_S:
30999 case R6_OPC_CMP_SOR_S:
31000 case R6_OPC_CMP_SUNE_S:
31001 case R6_OPC_CMP_SNE_S:
31002 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31003 break;
31004 case R6_OPC_CMP_AF_D:
31005 case R6_OPC_CMP_UN_D:
31006 case R6_OPC_CMP_EQ_D:
31007 case R6_OPC_CMP_UEQ_D:
31008 case R6_OPC_CMP_LT_D:
31009 case R6_OPC_CMP_ULT_D:
31010 case R6_OPC_CMP_LE_D:
31011 case R6_OPC_CMP_ULE_D:
31012 case R6_OPC_CMP_SAF_D:
31013 case R6_OPC_CMP_SUN_D:
31014 case R6_OPC_CMP_SEQ_D:
31015 case R6_OPC_CMP_SEUQ_D:
31016 case R6_OPC_CMP_SLT_D:
31017 case R6_OPC_CMP_SULT_D:
31018 case R6_OPC_CMP_SLE_D:
31019 case R6_OPC_CMP_SULE_D:
31020 case R6_OPC_CMP_OR_D:
31021 case R6_OPC_CMP_UNE_D:
31022 case R6_OPC_CMP_NE_D:
31023 case R6_OPC_CMP_SOR_D:
31024 case R6_OPC_CMP_SUNE_D:
31025 case R6_OPC_CMP_SNE_D:
31026 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31027 break;
31028 default:
31029 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
31030 rt, rd, sa, (imm >> 8) & 0x7);
31032 break;
31034 } else {
31035 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31036 (imm >> 8) & 0x7);
31038 break;
31040 case OPC_BZ_V:
31041 case OPC_BNZ_V:
31042 case OPC_BZ_B:
31043 case OPC_BZ_H:
31044 case OPC_BZ_W:
31045 case OPC_BZ_D:
31046 case OPC_BNZ_B:
31047 case OPC_BNZ_H:
31048 case OPC_BNZ_W:
31049 case OPC_BNZ_D:
31050 check_insn(ctx, ASE_MSA);
31051 gen_msa_branch(env, ctx, op1);
31052 break;
31053 default:
31054 MIPS_INVAL("cp1");
31055 gen_reserved_instruction(ctx);
31056 break;
31058 break;
31060 /* Compact branches [R6] and COP2 [non-R6] */
31061 case OPC_BC: /* OPC_LWC2 */
31062 case OPC_BALC: /* OPC_SWC2 */
31063 if (ctx->insn_flags & ISA_MIPS_R6) {
31064 /* OPC_BC, OPC_BALC */
31065 gen_compute_compact_branch(ctx, op, 0, 0,
31066 sextract32(ctx->opcode << 2, 0, 28));
31067 } else if (ctx->insn_flags & ASE_LEXT) {
31068 gen_loongson_lswc2(ctx, rt, rs, rd);
31069 } else {
31070 /* OPC_LWC2, OPC_SWC2 */
31071 /* COP2: Not implemented. */
31072 generate_exception_err(ctx, EXCP_CpU, 2);
31074 break;
31075 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
31076 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
31077 if (ctx->insn_flags & ISA_MIPS_R6) {
31078 if (rs != 0) {
31079 /* OPC_BEQZC, OPC_BNEZC */
31080 gen_compute_compact_branch(ctx, op, rs, 0,
31081 sextract32(ctx->opcode << 2, 0, 23));
31082 } else {
31083 /* OPC_JIC, OPC_JIALC */
31084 gen_compute_compact_branch(ctx, op, 0, rt, imm);
31086 } else if (ctx->insn_flags & ASE_LEXT) {
31087 gen_loongson_lsdc2(ctx, rt, rs, rd);
31088 } else {
31089 /* OPC_LWC2, OPC_SWC2 */
31090 /* COP2: Not implemented. */
31091 generate_exception_err(ctx, EXCP_CpU, 2);
31093 break;
31094 case OPC_CP2:
31095 check_insn(ctx, ASE_LMMI);
31096 /* Note that these instructions use different fields. */
31097 gen_loongson_multimedia(ctx, sa, rd, rt);
31098 break;
31100 case OPC_CP3:
31101 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31102 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
31103 check_cp1_enabled(ctx);
31104 op1 = MASK_CP3(ctx->opcode);
31105 switch (op1) {
31106 case OPC_LUXC1:
31107 case OPC_SUXC1:
31108 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
31109 /* Fallthrough */
31110 case OPC_LWXC1:
31111 case OPC_LDXC1:
31112 case OPC_SWXC1:
31113 case OPC_SDXC1:
31114 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31115 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
31116 break;
31117 case OPC_PREFX:
31118 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31119 /* Treat as NOP. */
31120 break;
31121 case OPC_ALNV_PS:
31122 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
31123 /* Fallthrough */
31124 case OPC_MADD_S:
31125 case OPC_MADD_D:
31126 case OPC_MADD_PS:
31127 case OPC_MSUB_S:
31128 case OPC_MSUB_D:
31129 case OPC_MSUB_PS:
31130 case OPC_NMADD_S:
31131 case OPC_NMADD_D:
31132 case OPC_NMADD_PS:
31133 case OPC_NMSUB_S:
31134 case OPC_NMSUB_D:
31135 case OPC_NMSUB_PS:
31136 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
31137 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
31138 break;
31139 default:
31140 MIPS_INVAL("cp3");
31141 gen_reserved_instruction(ctx);
31142 break;
31144 } else {
31145 generate_exception_err(ctx, EXCP_CpU, 1);
31147 break;
31149 #if defined(TARGET_MIPS64)
31150 /* MIPS64 opcodes */
31151 case OPC_LLD:
31152 if (ctx->insn_flags & INSN_R5900) {
31153 check_insn_opc_user_only(ctx, INSN_R5900);
31155 /* fall through */
31156 case OPC_LDL:
31157 case OPC_LDR:
31158 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31159 /* fall through */
31160 case OPC_LWU:
31161 case OPC_LD:
31162 check_insn(ctx, ISA_MIPS3);
31163 check_mips_64(ctx);
31164 gen_ld(ctx, op, rt, rs, imm);
31165 break;
31166 case OPC_SDL:
31167 case OPC_SDR:
31168 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31169 /* fall through */
31170 case OPC_SD:
31171 check_insn(ctx, ISA_MIPS3);
31172 check_mips_64(ctx);
31173 gen_st(ctx, op, rt, rs, imm);
31174 break;
31175 case OPC_SCD:
31176 check_insn_opc_removed(ctx, ISA_MIPS_R6);
31177 check_insn(ctx, ISA_MIPS3);
31178 if (ctx->insn_flags & INSN_R5900) {
31179 check_insn_opc_user_only(ctx, INSN_R5900);
31181 check_mips_64(ctx);
31182 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
31183 break;
31184 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
31185 if (ctx->insn_flags & ISA_MIPS_R6) {
31186 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
31187 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31188 } else {
31189 /* OPC_DADDI */
31190 check_insn(ctx, ISA_MIPS3);
31191 check_mips_64(ctx);
31192 gen_arith_imm(ctx, op, rt, rs, imm);
31194 break;
31195 case OPC_DADDIU:
31196 check_insn(ctx, ISA_MIPS3);
31197 check_mips_64(ctx);
31198 gen_arith_imm(ctx, op, rt, rs, imm);
31199 break;
31200 #else
31201 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
31202 if (ctx->insn_flags & ISA_MIPS_R6) {
31203 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31204 } else {
31205 MIPS_INVAL("major opcode");
31206 gen_reserved_instruction(ctx);
31208 break;
31209 #endif
31210 case OPC_DAUI: /* OPC_JALX */
31211 if (ctx->insn_flags & ISA_MIPS_R6) {
31212 #if defined(TARGET_MIPS64)
31213 /* OPC_DAUI */
31214 check_mips_64(ctx);
31215 if (rs == 0) {
31216 generate_exception(ctx, EXCP_RI);
31217 } else if (rt != 0) {
31218 TCGv t0 = tcg_temp_new();
31219 gen_load_gpr(t0, rs);
31220 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
31221 tcg_temp_free(t0);
31223 #else
31224 gen_reserved_instruction(ctx);
31225 MIPS_INVAL("major opcode");
31226 #endif
31227 } else {
31228 /* OPC_JALX */
31229 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
31230 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
31231 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
31233 break;
31234 case OPC_MSA: /* OPC_MDMX */
31235 if (ctx->insn_flags & INSN_R5900) {
31236 #if defined(TARGET_MIPS64)
31237 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
31238 #endif
31239 } else {
31240 /* MDMX: Not implemented. */
31241 gen_msa(env, ctx);
31243 break;
31244 case OPC_PCREL:
31245 check_insn(ctx, ISA_MIPS_R6);
31246 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
31247 break;
31248 default: /* Invalid */
31249 MIPS_INVAL("major opcode");
31250 return false;
31252 return true;
31255 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
31257 /* make sure instructions are on a word boundary */
31258 if (ctx->base.pc_next & 0x3) {
31259 env->CP0_BadVAddr = ctx->base.pc_next;
31260 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
31261 return;
31264 /* Handle blikely not taken case */
31265 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
31266 TCGLabel *l1 = gen_new_label();
31268 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
31269 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
31270 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
31271 gen_set_label(l1);
31274 if (decode_opc_legacy(env, ctx)) {
31275 return;
31278 gen_reserved_instruction(ctx);
31281 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
31283 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31284 CPUMIPSState *env = cs->env_ptr;
31286 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
31287 ctx->saved_pc = -1;
31288 ctx->insn_flags = env->insn_flags;
31289 ctx->CP0_Config1 = env->CP0_Config1;
31290 ctx->CP0_Config2 = env->CP0_Config2;
31291 ctx->CP0_Config3 = env->CP0_Config3;
31292 ctx->CP0_Config5 = env->CP0_Config5;
31293 ctx->btarget = 0;
31294 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
31295 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
31296 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
31297 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
31298 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
31299 ctx->PAMask = env->PAMask;
31300 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
31301 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
31302 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
31303 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
31304 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
31305 /* Restore delay slot state from the tb context. */
31306 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
31307 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
31308 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
31309 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
31310 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
31311 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
31312 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
31313 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
31314 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
31315 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
31316 restore_cpu_state(env, ctx);
31317 #ifdef CONFIG_USER_ONLY
31318 ctx->mem_idx = MIPS_HFLAG_UM;
31319 #else
31320 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
31321 #endif
31322 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
31323 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
31325 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31326 ctx->hflags);
31329 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31333 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31335 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31337 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31338 ctx->btarget);
31341 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31342 const CPUBreakpoint *bp)
31344 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31346 save_cpu_state(ctx, 1);
31347 ctx->base.is_jmp = DISAS_NORETURN;
31348 gen_helper_raise_exception_debug(cpu_env);
31350 * The address covered by the breakpoint must be included in
31351 * [tb->pc, tb->pc + tb->size) in order to for it to be
31352 * properly cleared -- thus we increment the PC here so that
31353 * the logic setting tb->size below does the right thing.
31355 ctx->base.pc_next += 4;
31356 return true;
31359 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31361 CPUMIPSState *env = cs->env_ptr;
31362 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31363 int insn_bytes;
31364 int is_slot;
31366 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
31367 if (ctx->insn_flags & ISA_NANOMIPS32) {
31368 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31369 insn_bytes = decode_nanomips_opc(env, ctx);
31370 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
31371 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31372 insn_bytes = 4;
31373 decode_opc(env, ctx);
31374 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31375 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31376 insn_bytes = decode_micromips_opc(env, ctx);
31377 } else if (ctx->insn_flags & ASE_MIPS16) {
31378 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31379 insn_bytes = decode_mips16_opc(env, ctx);
31380 } else {
31381 gen_reserved_instruction(ctx);
31382 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31383 return;
31386 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31387 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31388 MIPS_HFLAG_FBNSLOT))) {
31390 * Force to generate branch as there is neither delay nor
31391 * forbidden slot.
31393 is_slot = 1;
31395 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31396 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
31398 * Force to generate branch as microMIPS R6 doesn't restrict
31399 * branches in the forbidden slot.
31401 is_slot = 1;
31404 if (is_slot) {
31405 gen_branch(ctx, insn_bytes);
31407 ctx->base.pc_next += insn_bytes;
31409 if (ctx->base.is_jmp != DISAS_NEXT) {
31410 return;
31413 * Execute a branch and its delay slot as a single instruction.
31414 * This is what GDB expects and is consistent with what the
31415 * hardware does (e.g. if a delay slot instruction faults, the
31416 * reported PC is the PC of the branch).
31418 if (ctx->base.singlestep_enabled &&
31419 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31420 ctx->base.is_jmp = DISAS_TOO_MANY;
31422 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31423 ctx->base.is_jmp = DISAS_TOO_MANY;
31427 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31429 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31431 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31432 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
31433 gen_helper_raise_exception_debug(cpu_env);
31434 } else {
31435 switch (ctx->base.is_jmp) {
31436 case DISAS_STOP:
31437 gen_save_pc(ctx->base.pc_next);
31438 tcg_gen_lookup_and_goto_ptr();
31439 break;
31440 case DISAS_NEXT:
31441 case DISAS_TOO_MANY:
31442 save_cpu_state(ctx, 0);
31443 gen_goto_tb(ctx, 0, ctx->base.pc_next);
31444 break;
31445 case DISAS_EXIT:
31446 tcg_gen_exit_tb(NULL, 0);
31447 break;
31448 case DISAS_NORETURN:
31449 break;
31450 default:
31451 g_assert_not_reached();
31456 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31458 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31459 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31462 static const TranslatorOps mips_tr_ops = {
31463 .init_disas_context = mips_tr_init_disas_context,
31464 .tb_start = mips_tr_tb_start,
31465 .insn_start = mips_tr_insn_start,
31466 .breakpoint_check = mips_tr_breakpoint_check,
31467 .translate_insn = mips_tr_translate_insn,
31468 .tb_stop = mips_tr_tb_stop,
31469 .disas_log = mips_tr_disas_log,
31472 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31474 DisasContext ctx;
31476 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
31479 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
31481 int i;
31482 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
31484 #define printfpr(fp) \
31485 do { \
31486 if (is_fpu64) \
31487 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31488 " fd:%13g fs:%13g psu: %13g\n", \
31489 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31490 (double)(fp)->fd, \
31491 (double)(fp)->fs[FP_ENDIAN_IDX], \
31492 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
31493 else { \
31494 fpr_t tmp; \
31495 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31496 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
31497 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31498 " fd:%13g fs:%13g psu:%13g\n", \
31499 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31500 (double)tmp.fd, \
31501 (double)tmp.fs[FP_ENDIAN_IDX], \
31502 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31504 } while (0)
31507 qemu_fprintf(f,
31508 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31509 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31510 get_float_exception_flags(&env->active_fpu.fp_status));
31511 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31512 qemu_fprintf(f, "%3s: ", fregnames[i]);
31513 printfpr(&env->active_fpu.fpr[i]);
31516 #undef printfpr
31519 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31521 MIPSCPU *cpu = MIPS_CPU(cs);
31522 CPUMIPSState *env = &cpu->env;
31523 int i;
31525 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31526 " LO=0x" TARGET_FMT_lx " ds %04x "
31527 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31528 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31529 env->hflags, env->btarget, env->bcond);
31530 for (i = 0; i < 32; i++) {
31531 if ((i & 3) == 0) {
31532 qemu_fprintf(f, "GPR%02d:", i);
31534 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31535 regnames[i], env->active_tc.gpr[i]);
31536 if ((i & 3) == 3) {
31537 qemu_fprintf(f, "\n");
31541 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31542 TARGET_FMT_lx "\n",
31543 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31544 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31545 PRIx64 "\n",
31546 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31547 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31548 env->CP0_Config2, env->CP0_Config3);
31549 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31550 env->CP0_Config4, env->CP0_Config5);
31551 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31552 fpu_dump_state(env, f, flags);
31556 void mips_tcg_init(void)
31558 int i;
31560 cpu_gpr[0] = NULL;
31561 for (i = 1; i < 32; i++)
31562 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31563 offsetof(CPUMIPSState,
31564 active_tc.gpr[i]),
31565 regnames[i]);
31567 for (i = 0; i < 32; i++) {
31568 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31569 msa_wr_d[i * 2] =
31570 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31572 * The scalar floating-point unit (FPU) registers are mapped on
31573 * the MSA vector registers.
31575 fpu_f64[i] = msa_wr_d[i * 2];
31576 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31577 msa_wr_d[i * 2 + 1] =
31578 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31581 cpu_PC = tcg_global_mem_new(cpu_env,
31582 offsetof(CPUMIPSState, active_tc.PC), "PC");
31583 for (i = 0; i < MIPS_DSP_ACC; i++) {
31584 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31585 offsetof(CPUMIPSState, active_tc.HI[i]),
31586 regnames_HI[i]);
31587 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31588 offsetof(CPUMIPSState, active_tc.LO[i]),
31589 regnames_LO[i]);
31591 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31592 offsetof(CPUMIPSState,
31593 active_tc.DSPControl),
31594 "DSPControl");
31595 bcond = tcg_global_mem_new(cpu_env,
31596 offsetof(CPUMIPSState, bcond), "bcond");
31597 btarget = tcg_global_mem_new(cpu_env,
31598 offsetof(CPUMIPSState, btarget), "btarget");
31599 hflags = tcg_global_mem_new_i32(cpu_env,
31600 offsetof(CPUMIPSState, hflags), "hflags");
31602 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31603 offsetof(CPUMIPSState, active_fpu.fcr0),
31604 "fcr0");
31605 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31606 offsetof(CPUMIPSState, active_fpu.fcr31),
31607 "fcr31");
31608 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31609 "lladdr");
31610 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31611 "llval");
31613 #if defined(TARGET_MIPS64)
31614 cpu_mmr[0] = NULL;
31615 for (i = 1; i < 32; i++) {
31616 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31617 offsetof(CPUMIPSState,
31618 active_tc.mmr[i]),
31619 regnames[i]);
31621 #endif
31623 #if !defined(TARGET_MIPS64)
31624 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31625 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31626 offsetof(CPUMIPSState,
31627 active_tc.mxu_gpr[i]),
31628 mxuregnames[i]);
31631 mxu_CR = tcg_global_mem_new(cpu_env,
31632 offsetof(CPUMIPSState, active_tc.mxu_cr),
31633 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31634 #endif
31637 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31638 target_ulong *data)
31640 env->active_tc.PC = data[0];
31641 env->hflags &= ~MIPS_HFLAG_BMASK;
31642 env->hflags |= data[1];
31643 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31644 case MIPS_HFLAG_BR:
31645 break;
31646 case MIPS_HFLAG_BC:
31647 case MIPS_HFLAG_BL:
31648 case MIPS_HFLAG_B:
31649 env->btarget = data[2];
31650 break;