target/mips/mips-defs: Use ISA_MIPS32R6 definition to check Release 6
[qemu/ar7.git] / target / mips / translate.c
blobfc93b9da8ebc1f1ccdaa2c9f8c7cabb928854369
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"
39 #define MIPS_DEBUG_DISAS 0
41 /* MIPS major opcodes */
42 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
44 enum {
45 /* indirect opcode tables */
46 OPC_SPECIAL = (0x00 << 26),
47 OPC_REGIMM = (0x01 << 26),
48 OPC_CP0 = (0x10 << 26),
49 OPC_CP1 = (0x11 << 26),
50 OPC_CP2 = (0x12 << 26),
51 OPC_CP3 = (0x13 << 26),
52 OPC_SPECIAL2 = (0x1C << 26),
53 OPC_SPECIAL3 = (0x1F << 26),
54 /* arithmetic with immediate */
55 OPC_ADDI = (0x08 << 26),
56 OPC_ADDIU = (0x09 << 26),
57 OPC_SLTI = (0x0A << 26),
58 OPC_SLTIU = (0x0B << 26),
59 /* logic with immediate */
60 OPC_ANDI = (0x0C << 26),
61 OPC_ORI = (0x0D << 26),
62 OPC_XORI = (0x0E << 26),
63 OPC_LUI = (0x0F << 26),
64 /* arithmetic with immediate */
65 OPC_DADDI = (0x18 << 26),
66 OPC_DADDIU = (0x19 << 26),
67 /* Jump and branches */
68 OPC_J = (0x02 << 26),
69 OPC_JAL = (0x03 << 26),
70 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
71 OPC_BEQL = (0x14 << 26),
72 OPC_BNE = (0x05 << 26),
73 OPC_BNEL = (0x15 << 26),
74 OPC_BLEZ = (0x06 << 26),
75 OPC_BLEZL = (0x16 << 26),
76 OPC_BGTZ = (0x07 << 26),
77 OPC_BGTZL = (0x17 << 26),
78 OPC_JALX = (0x1D << 26),
79 OPC_DAUI = (0x1D << 26),
80 /* Load and stores */
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
87 OPC_LWPC = OPC_LW | 0x5,
88 OPC_LBU = (0x24 << 26),
89 OPC_LHU = (0x25 << 26),
90 OPC_LWR = (0x26 << 26),
91 OPC_LWU = (0x27 << 26),
92 OPC_SB = (0x28 << 26),
93 OPC_SH = (0x29 << 26),
94 OPC_SWL = (0x2A << 26),
95 OPC_SW = (0x2B << 26),
96 OPC_SDL = (0x2C << 26),
97 OPC_SDR = (0x2D << 26),
98 OPC_SWR = (0x2E << 26),
99 OPC_LL = (0x30 << 26),
100 OPC_LLD = (0x34 << 26),
101 OPC_LD = (0x37 << 26),
102 OPC_LDPC = OPC_LD | 0x5,
103 OPC_SC = (0x38 << 26),
104 OPC_SCD = (0x3C << 26),
105 OPC_SD = (0x3F << 26),
106 /* Floating point load/store */
107 OPC_LWC1 = (0x31 << 26),
108 OPC_LWC2 = (0x32 << 26),
109 OPC_LDC1 = (0x35 << 26),
110 OPC_LDC2 = (0x36 << 26),
111 OPC_SWC1 = (0x39 << 26),
112 OPC_SWC2 = (0x3A << 26),
113 OPC_SDC1 = (0x3D << 26),
114 OPC_SDC2 = (0x3E << 26),
115 /* Compact Branches */
116 OPC_BLEZALC = (0x06 << 26),
117 OPC_BGEZALC = (0x06 << 26),
118 OPC_BGEUC = (0x06 << 26),
119 OPC_BGTZALC = (0x07 << 26),
120 OPC_BLTZALC = (0x07 << 26),
121 OPC_BLTUC = (0x07 << 26),
122 OPC_BOVC = (0x08 << 26),
123 OPC_BEQZALC = (0x08 << 26),
124 OPC_BEQC = (0x08 << 26),
125 OPC_BLEZC = (0x16 << 26),
126 OPC_BGEZC = (0x16 << 26),
127 OPC_BGEC = (0x16 << 26),
128 OPC_BGTZC = (0x17 << 26),
129 OPC_BLTZC = (0x17 << 26),
130 OPC_BLTC = (0x17 << 26),
131 OPC_BNVC = (0x18 << 26),
132 OPC_BNEZALC = (0x18 << 26),
133 OPC_BNEC = (0x18 << 26),
134 OPC_BC = (0x32 << 26),
135 OPC_BEQZC = (0x36 << 26),
136 OPC_JIC = (0x36 << 26),
137 OPC_BALC = (0x3A << 26),
138 OPC_BNEZC = (0x3E << 26),
139 OPC_JIALC = (0x3E << 26),
140 /* MDMX ASE specific */
141 OPC_MDMX = (0x1E << 26),
142 /* MSA ASE, same as MDMX */
143 OPC_MSA = OPC_MDMX,
144 /* Cache and prefetch */
145 OPC_CACHE = (0x2F << 26),
146 OPC_PREF = (0x33 << 26),
147 /* PC-relative address computation / loads */
148 OPC_PCREL = (0x3B << 26),
151 /* PC-relative address computation / loads */
152 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
153 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
154 enum {
155 /* Instructions determined by bits 19 and 20 */
156 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
157 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
158 OPC_LWUPC = OPC_PCREL | (2 << 19),
160 /* Instructions determined by bits 16 ... 20 */
161 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
162 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
164 /* Other */
165 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
168 /* MIPS special opcodes */
169 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
171 enum {
172 /* Shifts */
173 OPC_SLL = 0x00 | OPC_SPECIAL,
174 /* NOP is SLL r0, r0, 0 */
175 /* SSNOP is SLL r0, r0, 1 */
176 /* EHB is SLL r0, r0, 3 */
177 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
178 OPC_ROTR = OPC_SRL | (1 << 21),
179 OPC_SRA = 0x03 | OPC_SPECIAL,
180 OPC_SLLV = 0x04 | OPC_SPECIAL,
181 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
182 OPC_ROTRV = OPC_SRLV | (1 << 6),
183 OPC_SRAV = 0x07 | OPC_SPECIAL,
184 OPC_DSLLV = 0x14 | OPC_SPECIAL,
185 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
186 OPC_DROTRV = OPC_DSRLV | (1 << 6),
187 OPC_DSRAV = 0x17 | OPC_SPECIAL,
188 OPC_DSLL = 0x38 | OPC_SPECIAL,
189 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
190 OPC_DROTR = OPC_DSRL | (1 << 21),
191 OPC_DSRA = 0x3B | OPC_SPECIAL,
192 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
193 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
194 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
195 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
196 /* Multiplication / division */
197 OPC_MULT = 0x18 | OPC_SPECIAL,
198 OPC_MULTU = 0x19 | OPC_SPECIAL,
199 OPC_DIV = 0x1A | OPC_SPECIAL,
200 OPC_DIVU = 0x1B | OPC_SPECIAL,
201 OPC_DMULT = 0x1C | OPC_SPECIAL,
202 OPC_DMULTU = 0x1D | OPC_SPECIAL,
203 OPC_DDIV = 0x1E | OPC_SPECIAL,
204 OPC_DDIVU = 0x1F | OPC_SPECIAL,
206 /* 2 registers arithmetic / logic */
207 OPC_ADD = 0x20 | OPC_SPECIAL,
208 OPC_ADDU = 0x21 | OPC_SPECIAL,
209 OPC_SUB = 0x22 | OPC_SPECIAL,
210 OPC_SUBU = 0x23 | OPC_SPECIAL,
211 OPC_AND = 0x24 | OPC_SPECIAL,
212 OPC_OR = 0x25 | OPC_SPECIAL,
213 OPC_XOR = 0x26 | OPC_SPECIAL,
214 OPC_NOR = 0x27 | OPC_SPECIAL,
215 OPC_SLT = 0x2A | OPC_SPECIAL,
216 OPC_SLTU = 0x2B | OPC_SPECIAL,
217 OPC_DADD = 0x2C | OPC_SPECIAL,
218 OPC_DADDU = 0x2D | OPC_SPECIAL,
219 OPC_DSUB = 0x2E | OPC_SPECIAL,
220 OPC_DSUBU = 0x2F | OPC_SPECIAL,
221 /* Jumps */
222 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
223 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
224 /* Traps */
225 OPC_TGE = 0x30 | OPC_SPECIAL,
226 OPC_TGEU = 0x31 | OPC_SPECIAL,
227 OPC_TLT = 0x32 | OPC_SPECIAL,
228 OPC_TLTU = 0x33 | OPC_SPECIAL,
229 OPC_TEQ = 0x34 | OPC_SPECIAL,
230 OPC_TNE = 0x36 | OPC_SPECIAL,
231 /* HI / LO registers load & stores */
232 OPC_MFHI = 0x10 | OPC_SPECIAL,
233 OPC_MTHI = 0x11 | OPC_SPECIAL,
234 OPC_MFLO = 0x12 | OPC_SPECIAL,
235 OPC_MTLO = 0x13 | OPC_SPECIAL,
236 /* Conditional moves */
237 OPC_MOVZ = 0x0A | OPC_SPECIAL,
238 OPC_MOVN = 0x0B | OPC_SPECIAL,
240 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
241 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
243 OPC_MOVCI = 0x01 | OPC_SPECIAL,
245 /* Special */
246 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
247 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
248 OPC_BREAK = 0x0D | OPC_SPECIAL,
249 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
250 OPC_SYNC = 0x0F | OPC_SPECIAL,
252 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
253 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
254 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
255 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
259 * R6 Multiply and Divide instructions have the same opcode
260 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
262 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
264 enum {
265 R6_OPC_MUL = OPC_MULT | (2 << 6),
266 R6_OPC_MUH = OPC_MULT | (3 << 6),
267 R6_OPC_MULU = OPC_MULTU | (2 << 6),
268 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
269 R6_OPC_DIV = OPC_DIV | (2 << 6),
270 R6_OPC_MOD = OPC_DIV | (3 << 6),
271 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
272 R6_OPC_MODU = OPC_DIVU | (3 << 6),
274 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
275 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
276 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
277 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
278 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
279 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
280 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
281 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
283 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
284 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
285 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
286 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
287 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
289 OPC_LSA = 0x05 | OPC_SPECIAL,
290 OPC_DLSA = 0x15 | OPC_SPECIAL,
293 /* Multiplication variants of the vr54xx. */
294 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
296 enum {
297 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
298 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
299 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
300 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
301 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
302 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
303 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
304 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
305 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
306 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
307 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
308 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
309 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
310 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
313 /* REGIMM (rt field) opcodes */
314 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
316 enum {
317 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
318 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
319 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
320 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
321 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
322 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
323 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
324 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
325 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
326 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
327 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
328 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
329 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
330 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
331 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
332 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
334 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
335 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
338 /* Special2 opcodes */
339 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
341 enum {
342 /* Multiply & xxx operations */
343 OPC_MADD = 0x00 | OPC_SPECIAL2,
344 OPC_MADDU = 0x01 | OPC_SPECIAL2,
345 OPC_MUL = 0x02 | OPC_SPECIAL2,
346 OPC_MSUB = 0x04 | OPC_SPECIAL2,
347 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
348 /* Loongson 2F */
349 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
350 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
351 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
352 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
353 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
354 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
355 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
356 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
357 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
358 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
359 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
360 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
361 /* Misc */
362 OPC_CLZ = 0x20 | OPC_SPECIAL2,
363 OPC_CLO = 0x21 | OPC_SPECIAL2,
364 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
365 OPC_DCLO = 0x25 | OPC_SPECIAL2,
366 /* Special */
367 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
370 /* Special3 opcodes */
371 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
373 enum {
374 OPC_EXT = 0x00 | OPC_SPECIAL3,
375 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
376 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
377 OPC_DEXT = 0x03 | OPC_SPECIAL3,
378 OPC_INS = 0x04 | OPC_SPECIAL3,
379 OPC_DINSM = 0x05 | OPC_SPECIAL3,
380 OPC_DINSU = 0x06 | OPC_SPECIAL3,
381 OPC_DINS = 0x07 | OPC_SPECIAL3,
382 OPC_FORK = 0x08 | OPC_SPECIAL3,
383 OPC_YIELD = 0x09 | OPC_SPECIAL3,
384 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
385 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
386 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
387 OPC_GINV = 0x3D | OPC_SPECIAL3,
389 /* Loongson 2E */
390 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
391 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
392 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
393 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
394 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
395 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
396 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
397 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
398 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
399 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
400 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
401 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
403 /* MIPS DSP Load */
404 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
405 /* MIPS DSP Arithmetic */
406 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
407 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
408 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
409 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
410 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
411 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
413 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
414 /* MIPS DSP GPR-Based Shift Sub-class */
415 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
416 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
417 /* MIPS DSP Multiply Sub-class insns */
418 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
419 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
420 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
421 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
422 /* DSP Bit/Manipulation Sub-class */
423 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
424 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
425 /* MIPS DSP Append Sub-class */
426 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
427 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
428 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
429 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
430 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
432 /* EVA */
433 OPC_LWLE = 0x19 | OPC_SPECIAL3,
434 OPC_LWRE = 0x1A | OPC_SPECIAL3,
435 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
436 OPC_SBE = 0x1C | OPC_SPECIAL3,
437 OPC_SHE = 0x1D | OPC_SPECIAL3,
438 OPC_SCE = 0x1E | OPC_SPECIAL3,
439 OPC_SWE = 0x1F | OPC_SPECIAL3,
440 OPC_SWLE = 0x21 | OPC_SPECIAL3,
441 OPC_SWRE = 0x22 | OPC_SPECIAL3,
442 OPC_PREFE = 0x23 | OPC_SPECIAL3,
443 OPC_LBUE = 0x28 | OPC_SPECIAL3,
444 OPC_LHUE = 0x29 | OPC_SPECIAL3,
445 OPC_LBE = 0x2C | OPC_SPECIAL3,
446 OPC_LHE = 0x2D | OPC_SPECIAL3,
447 OPC_LLE = 0x2E | OPC_SPECIAL3,
448 OPC_LWE = 0x2F | OPC_SPECIAL3,
450 /* R6 */
451 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
452 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
453 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
454 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
455 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
456 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
459 /* Loongson EXT load/store quad word opcodes */
460 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
461 enum {
462 OPC_GSLQ = 0x0020 | OPC_LWC2,
463 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
464 OPC_GSSHFL = OPC_LWC2,
465 OPC_GSSQ = 0x0020 | OPC_SWC2,
466 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
467 OPC_GSSHFS = OPC_SWC2,
470 /* Loongson EXT shifted load/store opcodes */
471 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
472 enum {
473 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
474 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
475 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
476 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
477 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
478 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
479 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
480 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
483 /* Loongson EXT LDC2/SDC2 opcodes */
484 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
486 enum {
487 OPC_GSLBX = 0x0 | OPC_LDC2,
488 OPC_GSLHX = 0x1 | OPC_LDC2,
489 OPC_GSLWX = 0x2 | OPC_LDC2,
490 OPC_GSLDX = 0x3 | OPC_LDC2,
491 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
492 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
493 OPC_GSSBX = 0x0 | OPC_SDC2,
494 OPC_GSSHX = 0x1 | OPC_SDC2,
495 OPC_GSSWX = 0x2 | OPC_SDC2,
496 OPC_GSSDX = 0x3 | OPC_SDC2,
497 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
498 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
501 /* BSHFL opcodes */
502 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
504 enum {
505 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
506 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
507 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
508 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
509 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
510 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
511 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
512 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
515 /* DBSHFL opcodes */
516 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
518 enum {
519 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
520 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
521 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
522 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
523 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
524 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
525 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
526 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
527 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
528 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
529 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
532 /* MIPS DSP REGIMM opcodes */
533 enum {
534 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
535 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
538 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
539 /* MIPS DSP Load */
540 enum {
541 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
542 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
543 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
544 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
547 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
548 enum {
549 /* MIPS DSP Arithmetic Sub-class */
550 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
551 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
552 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
553 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
554 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
555 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
557 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
558 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
559 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
560 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
561 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
562 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
563 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
564 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
565 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
566 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
567 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
568 /* MIPS DSP Multiply Sub-class insns */
569 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
570 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
571 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
572 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
573 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
574 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
577 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
578 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
579 enum {
580 /* MIPS DSP Arithmetic Sub-class */
581 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
582 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
583 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
584 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
585 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
586 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
587 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
590 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
591 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
592 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
593 /* MIPS DSP Multiply Sub-class insns */
594 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
595 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
596 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
597 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
600 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
601 enum {
602 /* MIPS DSP Arithmetic Sub-class */
603 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
604 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
605 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
606 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
607 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
608 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
616 /* DSP Bit/Manipulation Sub-class */
617 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
618 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
619 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
620 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
621 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
624 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
625 enum {
626 /* MIPS DSP Arithmetic Sub-class */
627 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
628 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
629 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
630 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
631 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
632 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
634 /* DSP Compare-Pick Sub-class */
635 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
639 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
640 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
646 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
647 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
648 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
649 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
652 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
653 enum {
654 /* MIPS DSP GPR-Based Shift Sub-class */
655 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
656 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
657 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
658 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
659 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
660 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
673 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
674 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
675 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
676 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
679 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
680 enum {
681 /* MIPS DSP Multiply Sub-class insns */
682 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
683 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
684 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
685 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
686 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
687 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
696 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
698 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
699 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
700 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
701 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
702 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
703 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
706 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
707 enum {
708 /* DSP Bit/Manipulation Sub-class */
709 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
712 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
713 enum {
714 /* MIPS DSP Append Sub-class */
715 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
716 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
717 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
720 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
721 enum {
722 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
723 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
724 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
725 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
726 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
727 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
728 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
731 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
732 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
733 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
734 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
735 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
736 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
737 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
738 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
739 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
742 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
743 enum {
744 /* MIPS DSP Arithmetic Sub-class */
745 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
746 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
747 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
748 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
749 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
750 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
762 /* DSP Bit/Manipulation Sub-class */
763 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
765 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
766 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
767 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
768 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
771 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
772 enum {
773 /* MIPS DSP Multiply Sub-class insns */
774 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
775 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
776 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
777 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
778 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
779 /* MIPS DSP Arithmetic Sub-class */
780 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
781 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
782 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
783 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
784 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
785 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
787 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
788 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
789 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
790 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
791 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
792 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
793 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
794 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
795 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
797 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
798 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
799 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
800 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
803 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
804 enum {
805 /* DSP Compare-Pick Sub-class */
806 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
807 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
808 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
809 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
810 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
811 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
825 /* MIPS DSP Arithmetic Sub-class */
826 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
829 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
830 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
831 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
832 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
833 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
836 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
837 enum {
838 /* DSP Append Sub-class */
839 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
840 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
841 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
842 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
845 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
846 enum {
847 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
848 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
849 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
850 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
851 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
852 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
853 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
854 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
865 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
866 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
867 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
868 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
871 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
872 enum {
873 /* DSP Bit/Manipulation Sub-class */
874 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
877 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
878 enum {
879 /* MIPS DSP Multiply Sub-class insns */
880 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
881 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
882 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
883 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
884 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
885 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
902 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
903 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
904 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
905 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
908 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
909 enum {
910 /* MIPS DSP GPR-Based Shift Sub-class */
911 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
912 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
913 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
914 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
915 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
916 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
933 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
934 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
935 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
936 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
939 /* Coprocessor 0 (rs field) */
940 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
942 enum {
943 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
944 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
945 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
946 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
947 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
948 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
949 OPC_MFTR = (0x08 << 21) | OPC_CP0,
950 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
951 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
952 OPC_MTTR = (0x0C << 21) | OPC_CP0,
953 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
954 OPC_C0 = (0x10 << 21) | OPC_CP0,
955 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
956 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
957 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
958 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
959 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
960 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
961 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
962 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
963 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
964 OPC_C0_A = (0x1A << 21) | OPC_CP0,
965 OPC_C0_B = (0x1B << 21) | OPC_CP0,
966 OPC_C0_C = (0x1C << 21) | OPC_CP0,
967 OPC_C0_D = (0x1D << 21) | OPC_CP0,
968 OPC_C0_E = (0x1E << 21) | OPC_CP0,
969 OPC_C0_F = (0x1F << 21) | OPC_CP0,
972 /* MFMC0 opcodes */
973 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
975 enum {
976 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
977 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
978 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
979 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
980 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
981 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
982 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
983 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
986 /* Coprocessor 0 (with rs == C0) */
987 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
989 enum {
990 OPC_TLBR = 0x01 | OPC_C0,
991 OPC_TLBWI = 0x02 | OPC_C0,
992 OPC_TLBINV = 0x03 | OPC_C0,
993 OPC_TLBINVF = 0x04 | OPC_C0,
994 OPC_TLBWR = 0x06 | OPC_C0,
995 OPC_TLBP = 0x08 | OPC_C0,
996 OPC_RFE = 0x10 | OPC_C0,
997 OPC_ERET = 0x18 | OPC_C0,
998 OPC_DERET = 0x1F | OPC_C0,
999 OPC_WAIT = 0x20 | OPC_C0,
1002 /* Coprocessor 1 (rs field) */
1003 #define MASK_CP1(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1005 /* Values for the fmt field in FP instructions */
1006 enum {
1007 /* 0 - 15 are reserved */
1008 FMT_S = 16, /* single fp */
1009 FMT_D = 17, /* double fp */
1010 FMT_E = 18, /* extended fp */
1011 FMT_Q = 19, /* quad fp */
1012 FMT_W = 20, /* 32-bit fixed */
1013 FMT_L = 21, /* 64-bit fixed */
1014 FMT_PS = 22, /* paired single fp */
1015 /* 23 - 31 are reserved */
1018 enum {
1019 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
1020 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
1021 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
1022 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
1023 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
1024 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
1025 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
1026 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
1027 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
1028 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
1029 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
1030 OPC_BZ_V = (0x0B << 21) | OPC_CP1,
1031 OPC_BNZ_V = (0x0F << 21) | OPC_CP1,
1032 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
1033 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
1034 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
1035 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
1036 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
1037 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
1038 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
1039 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
1040 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
1041 OPC_BZ_B = (0x18 << 21) | OPC_CP1,
1042 OPC_BZ_H = (0x19 << 21) | OPC_CP1,
1043 OPC_BZ_W = (0x1A << 21) | OPC_CP1,
1044 OPC_BZ_D = (0x1B << 21) | OPC_CP1,
1045 OPC_BNZ_B = (0x1C << 21) | OPC_CP1,
1046 OPC_BNZ_H = (0x1D << 21) | OPC_CP1,
1047 OPC_BNZ_W = (0x1E << 21) | OPC_CP1,
1048 OPC_BNZ_D = (0x1F << 21) | OPC_CP1,
1051 #define MASK_CP1_FUNC(op) (MASK_CP1(op) | (op & 0x3F))
1052 #define MASK_BC1(op) (MASK_CP1(op) | (op & (0x3 << 16)))
1054 enum {
1055 OPC_BC1F = (0x00 << 16) | OPC_BC1,
1056 OPC_BC1T = (0x01 << 16) | OPC_BC1,
1057 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
1058 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
1061 enum {
1062 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
1063 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
1066 enum {
1067 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
1068 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
1071 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1073 enum {
1074 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1075 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1076 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1077 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1078 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1079 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1080 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1081 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1082 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1083 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1084 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1087 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1089 enum {
1090 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1091 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1092 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1093 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1094 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1095 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1096 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1097 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1099 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1100 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1101 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1102 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1103 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1104 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1105 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1106 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1108 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1109 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1110 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1111 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1112 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1113 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1114 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1115 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1117 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1118 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1119 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1120 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1121 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1122 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1123 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1124 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1126 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1127 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1128 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1129 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1130 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1131 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1133 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1134 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1135 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1136 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1137 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1138 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1140 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1141 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1142 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1143 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1144 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1145 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1147 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1148 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1149 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1150 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1151 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1152 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1154 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1155 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1156 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1157 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1158 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1159 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1161 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1162 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1163 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1164 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1165 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1166 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1168 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1169 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1170 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1171 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1172 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1173 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1175 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1176 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1177 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1178 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1179 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1180 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1184 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1186 enum {
1187 OPC_LWXC1 = 0x00 | OPC_CP3,
1188 OPC_LDXC1 = 0x01 | OPC_CP3,
1189 OPC_LUXC1 = 0x05 | OPC_CP3,
1190 OPC_SWXC1 = 0x08 | OPC_CP3,
1191 OPC_SDXC1 = 0x09 | OPC_CP3,
1192 OPC_SUXC1 = 0x0D | OPC_CP3,
1193 OPC_PREFX = 0x0F | OPC_CP3,
1194 OPC_ALNV_PS = 0x1E | OPC_CP3,
1195 OPC_MADD_S = 0x20 | OPC_CP3,
1196 OPC_MADD_D = 0x21 | OPC_CP3,
1197 OPC_MADD_PS = 0x26 | OPC_CP3,
1198 OPC_MSUB_S = 0x28 | OPC_CP3,
1199 OPC_MSUB_D = 0x29 | OPC_CP3,
1200 OPC_MSUB_PS = 0x2E | OPC_CP3,
1201 OPC_NMADD_S = 0x30 | OPC_CP3,
1202 OPC_NMADD_D = 0x31 | OPC_CP3,
1203 OPC_NMADD_PS = 0x36 | OPC_CP3,
1204 OPC_NMSUB_S = 0x38 | OPC_CP3,
1205 OPC_NMSUB_D = 0x39 | OPC_CP3,
1206 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1209 /* MSA Opcodes */
1210 #define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1211 enum {
1212 OPC_MSA_I8_00 = 0x00 | OPC_MSA,
1213 OPC_MSA_I8_01 = 0x01 | OPC_MSA,
1214 OPC_MSA_I8_02 = 0x02 | OPC_MSA,
1215 OPC_MSA_I5_06 = 0x06 | OPC_MSA,
1216 OPC_MSA_I5_07 = 0x07 | OPC_MSA,
1217 OPC_MSA_BIT_09 = 0x09 | OPC_MSA,
1218 OPC_MSA_BIT_0A = 0x0A | OPC_MSA,
1219 OPC_MSA_3R_0D = 0x0D | OPC_MSA,
1220 OPC_MSA_3R_0E = 0x0E | OPC_MSA,
1221 OPC_MSA_3R_0F = 0x0F | OPC_MSA,
1222 OPC_MSA_3R_10 = 0x10 | OPC_MSA,
1223 OPC_MSA_3R_11 = 0x11 | OPC_MSA,
1224 OPC_MSA_3R_12 = 0x12 | OPC_MSA,
1225 OPC_MSA_3R_13 = 0x13 | OPC_MSA,
1226 OPC_MSA_3R_14 = 0x14 | OPC_MSA,
1227 OPC_MSA_3R_15 = 0x15 | OPC_MSA,
1228 OPC_MSA_ELM = 0x19 | OPC_MSA,
1229 OPC_MSA_3RF_1A = 0x1A | OPC_MSA,
1230 OPC_MSA_3RF_1B = 0x1B | OPC_MSA,
1231 OPC_MSA_3RF_1C = 0x1C | OPC_MSA,
1232 OPC_MSA_VEC = 0x1E | OPC_MSA,
1234 /* MI10 instruction */
1235 OPC_LD_B = (0x20) | OPC_MSA,
1236 OPC_LD_H = (0x21) | OPC_MSA,
1237 OPC_LD_W = (0x22) | OPC_MSA,
1238 OPC_LD_D = (0x23) | OPC_MSA,
1239 OPC_ST_B = (0x24) | OPC_MSA,
1240 OPC_ST_H = (0x25) | OPC_MSA,
1241 OPC_ST_W = (0x26) | OPC_MSA,
1242 OPC_ST_D = (0x27) | OPC_MSA,
1245 enum {
1246 /* I5 instruction df(bits 22..21) = _b, _h, _w, _d */
1247 OPC_ADDVI_df = (0x0 << 23) | OPC_MSA_I5_06,
1248 OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07,
1249 OPC_SUBVI_df = (0x1 << 23) | OPC_MSA_I5_06,
1250 OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06,
1251 OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07,
1252 OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06,
1253 OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07,
1254 OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06,
1255 OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07,
1256 OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06,
1257 OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07,
1258 OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07,
1260 /* I8 instruction */
1261 OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00,
1262 OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01,
1263 OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02,
1264 OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00,
1265 OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01,
1266 OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02,
1267 OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00,
1268 OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01,
1269 OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02,
1270 OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00,
1272 /* VEC/2R/2RF instruction */
1273 OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC,
1274 OPC_OR_V = (0x01 << 21) | OPC_MSA_VEC,
1275 OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC,
1276 OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC,
1277 OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC,
1278 OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC,
1279 OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC,
1281 OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC,
1282 OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC,
1284 /* 2R instruction df(bits 17..16) = _b, _h, _w, _d */
1285 OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R,
1286 OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R,
1287 OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R,
1288 OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R,
1290 /* 2RF instruction df(bit 16) = _w, _d */
1291 OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF,
1292 OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF,
1293 OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF,
1294 OPC_FSQRT_df = (0x03 << 17) | OPC_MSA_2RF,
1295 OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF,
1296 OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF,
1297 OPC_FRINT_df = (0x06 << 17) | OPC_MSA_2RF,
1298 OPC_FLOG2_df = (0x07 << 17) | OPC_MSA_2RF,
1299 OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF,
1300 OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF,
1301 OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF,
1302 OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF,
1303 OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF,
1304 OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF,
1305 OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF,
1306 OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF,
1308 /* 3R instruction df(bits 22..21) = _b, _h, _w, d */
1309 OPC_SLL_df = (0x0 << 23) | OPC_MSA_3R_0D,
1310 OPC_ADDV_df = (0x0 << 23) | OPC_MSA_3R_0E,
1311 OPC_CEQ_df = (0x0 << 23) | OPC_MSA_3R_0F,
1312 OPC_ADD_A_df = (0x0 << 23) | OPC_MSA_3R_10,
1313 OPC_SUBS_S_df = (0x0 << 23) | OPC_MSA_3R_11,
1314 OPC_MULV_df = (0x0 << 23) | OPC_MSA_3R_12,
1315 OPC_DOTP_S_df = (0x0 << 23) | OPC_MSA_3R_13,
1316 OPC_SLD_df = (0x0 << 23) | OPC_MSA_3R_14,
1317 OPC_VSHF_df = (0x0 << 23) | OPC_MSA_3R_15,
1318 OPC_SRA_df = (0x1 << 23) | OPC_MSA_3R_0D,
1319 OPC_SUBV_df = (0x1 << 23) | OPC_MSA_3R_0E,
1320 OPC_ADDS_A_df = (0x1 << 23) | OPC_MSA_3R_10,
1321 OPC_SUBS_U_df = (0x1 << 23) | OPC_MSA_3R_11,
1322 OPC_MADDV_df = (0x1 << 23) | OPC_MSA_3R_12,
1323 OPC_DOTP_U_df = (0x1 << 23) | OPC_MSA_3R_13,
1324 OPC_SPLAT_df = (0x1 << 23) | OPC_MSA_3R_14,
1325 OPC_SRAR_df = (0x1 << 23) | OPC_MSA_3R_15,
1326 OPC_SRL_df = (0x2 << 23) | OPC_MSA_3R_0D,
1327 OPC_MAX_S_df = (0x2 << 23) | OPC_MSA_3R_0E,
1328 OPC_CLT_S_df = (0x2 << 23) | OPC_MSA_3R_0F,
1329 OPC_ADDS_S_df = (0x2 << 23) | OPC_MSA_3R_10,
1330 OPC_SUBSUS_U_df = (0x2 << 23) | OPC_MSA_3R_11,
1331 OPC_MSUBV_df = (0x2 << 23) | OPC_MSA_3R_12,
1332 OPC_DPADD_S_df = (0x2 << 23) | OPC_MSA_3R_13,
1333 OPC_PCKEV_df = (0x2 << 23) | OPC_MSA_3R_14,
1334 OPC_SRLR_df = (0x2 << 23) | OPC_MSA_3R_15,
1335 OPC_BCLR_df = (0x3 << 23) | OPC_MSA_3R_0D,
1336 OPC_MAX_U_df = (0x3 << 23) | OPC_MSA_3R_0E,
1337 OPC_CLT_U_df = (0x3 << 23) | OPC_MSA_3R_0F,
1338 OPC_ADDS_U_df = (0x3 << 23) | OPC_MSA_3R_10,
1339 OPC_SUBSUU_S_df = (0x3 << 23) | OPC_MSA_3R_11,
1340 OPC_DPADD_U_df = (0x3 << 23) | OPC_MSA_3R_13,
1341 OPC_PCKOD_df = (0x3 << 23) | OPC_MSA_3R_14,
1342 OPC_BSET_df = (0x4 << 23) | OPC_MSA_3R_0D,
1343 OPC_MIN_S_df = (0x4 << 23) | OPC_MSA_3R_0E,
1344 OPC_CLE_S_df = (0x4 << 23) | OPC_MSA_3R_0F,
1345 OPC_AVE_S_df = (0x4 << 23) | OPC_MSA_3R_10,
1346 OPC_ASUB_S_df = (0x4 << 23) | OPC_MSA_3R_11,
1347 OPC_DIV_S_df = (0x4 << 23) | OPC_MSA_3R_12,
1348 OPC_DPSUB_S_df = (0x4 << 23) | OPC_MSA_3R_13,
1349 OPC_ILVL_df = (0x4 << 23) | OPC_MSA_3R_14,
1350 OPC_HADD_S_df = (0x4 << 23) | OPC_MSA_3R_15,
1351 OPC_BNEG_df = (0x5 << 23) | OPC_MSA_3R_0D,
1352 OPC_MIN_U_df = (0x5 << 23) | OPC_MSA_3R_0E,
1353 OPC_CLE_U_df = (0x5 << 23) | OPC_MSA_3R_0F,
1354 OPC_AVE_U_df = (0x5 << 23) | OPC_MSA_3R_10,
1355 OPC_ASUB_U_df = (0x5 << 23) | OPC_MSA_3R_11,
1356 OPC_DIV_U_df = (0x5 << 23) | OPC_MSA_3R_12,
1357 OPC_DPSUB_U_df = (0x5 << 23) | OPC_MSA_3R_13,
1358 OPC_ILVR_df = (0x5 << 23) | OPC_MSA_3R_14,
1359 OPC_HADD_U_df = (0x5 << 23) | OPC_MSA_3R_15,
1360 OPC_BINSL_df = (0x6 << 23) | OPC_MSA_3R_0D,
1361 OPC_MAX_A_df = (0x6 << 23) | OPC_MSA_3R_0E,
1362 OPC_AVER_S_df = (0x6 << 23) | OPC_MSA_3R_10,
1363 OPC_MOD_S_df = (0x6 << 23) | OPC_MSA_3R_12,
1364 OPC_ILVEV_df = (0x6 << 23) | OPC_MSA_3R_14,
1365 OPC_HSUB_S_df = (0x6 << 23) | OPC_MSA_3R_15,
1366 OPC_BINSR_df = (0x7 << 23) | OPC_MSA_3R_0D,
1367 OPC_MIN_A_df = (0x7 << 23) | OPC_MSA_3R_0E,
1368 OPC_AVER_U_df = (0x7 << 23) | OPC_MSA_3R_10,
1369 OPC_MOD_U_df = (0x7 << 23) | OPC_MSA_3R_12,
1370 OPC_ILVOD_df = (0x7 << 23) | OPC_MSA_3R_14,
1371 OPC_HSUB_U_df = (0x7 << 23) | OPC_MSA_3R_15,
1373 /* ELM instructions df(bits 21..16) = _b, _h, _w, _d */
1374 OPC_SLDI_df = (0x0 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1375 OPC_CTCMSA = (0x0 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1376 OPC_SPLATI_df = (0x1 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1377 OPC_CFCMSA = (0x1 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1378 OPC_COPY_S_df = (0x2 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1379 OPC_MOVE_V = (0x2 << 22) | (0x3E << 16) | OPC_MSA_ELM,
1380 OPC_COPY_U_df = (0x3 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1381 OPC_INSERT_df = (0x4 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1382 OPC_INSVE_df = (0x5 << 22) | (0x00 << 16) | OPC_MSA_ELM,
1384 /* 3RF instruction _df(bit 21) = _w, _d */
1385 OPC_FCAF_df = (0x0 << 22) | OPC_MSA_3RF_1A,
1386 OPC_FADD_df = (0x0 << 22) | OPC_MSA_3RF_1B,
1387 OPC_FCUN_df = (0x1 << 22) | OPC_MSA_3RF_1A,
1388 OPC_FSUB_df = (0x1 << 22) | OPC_MSA_3RF_1B,
1389 OPC_FCOR_df = (0x1 << 22) | OPC_MSA_3RF_1C,
1390 OPC_FCEQ_df = (0x2 << 22) | OPC_MSA_3RF_1A,
1391 OPC_FMUL_df = (0x2 << 22) | OPC_MSA_3RF_1B,
1392 OPC_FCUNE_df = (0x2 << 22) | OPC_MSA_3RF_1C,
1393 OPC_FCUEQ_df = (0x3 << 22) | OPC_MSA_3RF_1A,
1394 OPC_FDIV_df = (0x3 << 22) | OPC_MSA_3RF_1B,
1395 OPC_FCNE_df = (0x3 << 22) | OPC_MSA_3RF_1C,
1396 OPC_FCLT_df = (0x4 << 22) | OPC_MSA_3RF_1A,
1397 OPC_FMADD_df = (0x4 << 22) | OPC_MSA_3RF_1B,
1398 OPC_MUL_Q_df = (0x4 << 22) | OPC_MSA_3RF_1C,
1399 OPC_FCULT_df = (0x5 << 22) | OPC_MSA_3RF_1A,
1400 OPC_FMSUB_df = (0x5 << 22) | OPC_MSA_3RF_1B,
1401 OPC_MADD_Q_df = (0x5 << 22) | OPC_MSA_3RF_1C,
1402 OPC_FCLE_df = (0x6 << 22) | OPC_MSA_3RF_1A,
1403 OPC_MSUB_Q_df = (0x6 << 22) | OPC_MSA_3RF_1C,
1404 OPC_FCULE_df = (0x7 << 22) | OPC_MSA_3RF_1A,
1405 OPC_FEXP2_df = (0x7 << 22) | OPC_MSA_3RF_1B,
1406 OPC_FSAF_df = (0x8 << 22) | OPC_MSA_3RF_1A,
1407 OPC_FEXDO_df = (0x8 << 22) | OPC_MSA_3RF_1B,
1408 OPC_FSUN_df = (0x9 << 22) | OPC_MSA_3RF_1A,
1409 OPC_FSOR_df = (0x9 << 22) | OPC_MSA_3RF_1C,
1410 OPC_FSEQ_df = (0xA << 22) | OPC_MSA_3RF_1A,
1411 OPC_FTQ_df = (0xA << 22) | OPC_MSA_3RF_1B,
1412 OPC_FSUNE_df = (0xA << 22) | OPC_MSA_3RF_1C,
1413 OPC_FSUEQ_df = (0xB << 22) | OPC_MSA_3RF_1A,
1414 OPC_FSNE_df = (0xB << 22) | OPC_MSA_3RF_1C,
1415 OPC_FSLT_df = (0xC << 22) | OPC_MSA_3RF_1A,
1416 OPC_FMIN_df = (0xC << 22) | OPC_MSA_3RF_1B,
1417 OPC_MULR_Q_df = (0xC << 22) | OPC_MSA_3RF_1C,
1418 OPC_FSULT_df = (0xD << 22) | OPC_MSA_3RF_1A,
1419 OPC_FMIN_A_df = (0xD << 22) | OPC_MSA_3RF_1B,
1420 OPC_MADDR_Q_df = (0xD << 22) | OPC_MSA_3RF_1C,
1421 OPC_FSLE_df = (0xE << 22) | OPC_MSA_3RF_1A,
1422 OPC_FMAX_df = (0xE << 22) | OPC_MSA_3RF_1B,
1423 OPC_MSUBR_Q_df = (0xE << 22) | OPC_MSA_3RF_1C,
1424 OPC_FSULE_df = (0xF << 22) | OPC_MSA_3RF_1A,
1425 OPC_FMAX_A_df = (0xF << 22) | OPC_MSA_3RF_1B,
1427 /* BIT instruction df(bits 22..16) = _B _H _W _D */
1428 OPC_SLLI_df = (0x0 << 23) | OPC_MSA_BIT_09,
1429 OPC_SAT_S_df = (0x0 << 23) | OPC_MSA_BIT_0A,
1430 OPC_SRAI_df = (0x1 << 23) | OPC_MSA_BIT_09,
1431 OPC_SAT_U_df = (0x1 << 23) | OPC_MSA_BIT_0A,
1432 OPC_SRLI_df = (0x2 << 23) | OPC_MSA_BIT_09,
1433 OPC_SRARI_df = (0x2 << 23) | OPC_MSA_BIT_0A,
1434 OPC_BCLRI_df = (0x3 << 23) | OPC_MSA_BIT_09,
1435 OPC_SRLRI_df = (0x3 << 23) | OPC_MSA_BIT_0A,
1436 OPC_BSETI_df = (0x4 << 23) | OPC_MSA_BIT_09,
1437 OPC_BNEGI_df = (0x5 << 23) | OPC_MSA_BIT_09,
1438 OPC_BINSLI_df = (0x6 << 23) | OPC_MSA_BIT_09,
1439 OPC_BINSRI_df = (0x7 << 23) | OPC_MSA_BIT_09,
1445 * AN OVERVIEW OF MXU EXTENSION INSTRUCTION SET
1446 * ============================================
1449 * MXU (full name: MIPS eXtension/enhanced Unit) is a SIMD extension of MIPS32
1450 * instructions set. It is designed to fit the needs of signal, graphical and
1451 * video processing applications. MXU instruction set is used in Xburst family
1452 * of microprocessors by Ingenic.
1454 * MXU unit contains 17 registers called X0-X16. X0 is always zero, and X16 is
1455 * the control register.
1458 * The notation used in MXU assembler mnemonics
1459 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1461 * Register operands:
1463 * XRa, XRb, XRc, XRd - MXU registers
1464 * Rb, Rc, Rd, Rs, Rt - general purpose MIPS registers
1466 * Non-register operands:
1468 * aptn1 - 1-bit accumulate add/subtract pattern
1469 * aptn2 - 2-bit accumulate add/subtract pattern
1470 * eptn2 - 2-bit execute add/subtract pattern
1471 * optn2 - 2-bit operand pattern
1472 * optn3 - 3-bit operand pattern
1473 * sft4 - 4-bit shift amount
1474 * strd2 - 2-bit stride amount
1476 * Prefixes:
1478 * Level of parallelism: Operand size:
1479 * S - single operation at a time 32 - word
1480 * D - two operations in parallel 16 - half word
1481 * Q - four operations in parallel 8 - byte
1483 * Operations:
1485 * ADD - Add or subtract
1486 * ADDC - Add with carry-in
1487 * ACC - Accumulate
1488 * ASUM - Sum together then accumulate (add or subtract)
1489 * ASUMC - Sum together then accumulate (add or subtract) with carry-in
1490 * AVG - Average between 2 operands
1491 * ABD - Absolute difference
1492 * ALN - Align data
1493 * AND - Logical bitwise 'and' operation
1494 * CPS - Copy sign
1495 * EXTR - Extract bits
1496 * I2M - Move from GPR register to MXU register
1497 * LDD - Load data from memory to XRF
1498 * LDI - Load data from memory to XRF (and increase the address base)
1499 * LUI - Load unsigned immediate
1500 * MUL - Multiply
1501 * MULU - Unsigned multiply
1502 * MADD - 64-bit operand add 32x32 product
1503 * MSUB - 64-bit operand subtract 32x32 product
1504 * MAC - Multiply and accumulate (add or subtract)
1505 * MAD - Multiply and add or subtract
1506 * MAX - Maximum between 2 operands
1507 * MIN - Minimum between 2 operands
1508 * M2I - Move from MXU register to GPR register
1509 * MOVZ - Move if zero
1510 * MOVN - Move if non-zero
1511 * NOR - Logical bitwise 'nor' operation
1512 * OR - Logical bitwise 'or' operation
1513 * STD - Store data from XRF to memory
1514 * SDI - Store data from XRF to memory (and increase the address base)
1515 * SLT - Set of less than comparison
1516 * SAD - Sum of absolute differences
1517 * SLL - Logical shift left
1518 * SLR - Logical shift right
1519 * SAR - Arithmetic shift right
1520 * SAT - Saturation
1521 * SFL - Shuffle
1522 * SCOP - Calculate x’s scope (-1, means x<0; 0, means x==0; 1, means x>0)
1523 * XOR - Logical bitwise 'exclusive or' operation
1525 * Suffixes:
1527 * E - Expand results
1528 * F - Fixed point multiplication
1529 * L - Low part result
1530 * R - Doing rounding
1531 * V - Variable instead of immediate
1532 * W - Combine above L and V
1535 * The list of MXU instructions grouped by functionality
1536 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1538 * Load/Store instructions Multiplication instructions
1539 * ----------------------- ---------------------------
1541 * S32LDD XRa, Rb, s12 S32MADD XRa, XRd, Rs, Rt
1542 * S32STD XRa, Rb, s12 S32MADDU XRa, XRd, Rs, Rt
1543 * S32LDDV XRa, Rb, rc, strd2 S32MSUB XRa, XRd, Rs, Rt
1544 * S32STDV XRa, Rb, rc, strd2 S32MSUBU XRa, XRd, Rs, Rt
1545 * S32LDI XRa, Rb, s12 S32MUL XRa, XRd, Rs, Rt
1546 * S32SDI XRa, Rb, s12 S32MULU XRa, XRd, Rs, Rt
1547 * S32LDIV XRa, Rb, rc, strd2 D16MUL XRa, XRb, XRc, XRd, optn2
1548 * S32SDIV XRa, Rb, rc, strd2 D16MULE XRa, XRb, XRc, optn2
1549 * S32LDDR XRa, Rb, s12 D16MULF XRa, XRb, XRc, optn2
1550 * S32STDR XRa, Rb, s12 D16MAC XRa, XRb, XRc, XRd, aptn2, optn2
1551 * S32LDDVR XRa, Rb, rc, strd2 D16MACE XRa, XRb, XRc, XRd, aptn2, optn2
1552 * S32STDVR XRa, Rb, rc, strd2 D16MACF XRa, XRb, XRc, XRd, aptn2, optn2
1553 * S32LDIR XRa, Rb, s12 D16MADL XRa, XRb, XRc, XRd, aptn2, optn2
1554 * S32SDIR XRa, Rb, s12 S16MAD XRa, XRb, XRc, XRd, aptn1, optn2
1555 * S32LDIVR XRa, Rb, rc, strd2 Q8MUL XRa, XRb, XRc, XRd
1556 * S32SDIVR XRa, Rb, rc, strd2 Q8MULSU XRa, XRb, XRc, XRd
1557 * S16LDD XRa, Rb, s10, eptn2 Q8MAC XRa, XRb, XRc, XRd, aptn2
1558 * S16STD XRa, Rb, s10, eptn2 Q8MACSU XRa, XRb, XRc, XRd, aptn2
1559 * S16LDI XRa, Rb, s10, eptn2 Q8MADL XRa, XRb, XRc, XRd, aptn2
1560 * S16SDI XRa, Rb, s10, eptn2
1561 * S8LDD XRa, Rb, s8, eptn3
1562 * S8STD XRa, Rb, s8, eptn3 Addition and subtraction instructions
1563 * S8LDI XRa, Rb, s8, eptn3 -------------------------------------
1564 * S8SDI XRa, Rb, s8, eptn3
1565 * LXW Rd, Rs, Rt, strd2 D32ADD XRa, XRb, XRc, XRd, eptn2
1566 * LXH Rd, Rs, Rt, strd2 D32ADDC XRa, XRb, XRc, XRd
1567 * LXHU Rd, Rs, Rt, strd2 D32ACC XRa, XRb, XRc, XRd, eptn2
1568 * LXB Rd, Rs, Rt, strd2 D32ACCM XRa, XRb, XRc, XRd, eptn2
1569 * LXBU Rd, Rs, Rt, strd2 D32ASUM XRa, XRb, XRc, XRd, eptn2
1570 * S32CPS XRa, XRb, XRc
1571 * Q16ADD XRa, XRb, XRc, XRd, eptn2, optn2
1572 * Comparison instructions Q16ACC XRa, XRb, XRc, XRd, eptn2
1573 * ----------------------- Q16ACCM XRa, XRb, XRc, XRd, eptn2
1574 * D16ASUM XRa, XRb, XRc, XRd, eptn2
1575 * S32MAX XRa, XRb, XRc D16CPS XRa, XRb,
1576 * S32MIN XRa, XRb, XRc D16AVG XRa, XRb, XRc
1577 * S32SLT XRa, XRb, XRc D16AVGR XRa, XRb, XRc
1578 * S32MOVZ XRa, XRb, XRc Q8ADD XRa, XRb, XRc, eptn2
1579 * S32MOVN XRa, XRb, XRc Q8ADDE XRa, XRb, XRc, XRd, eptn2
1580 * D16MAX XRa, XRb, XRc Q8ACCE XRa, XRb, XRc, XRd, eptn2
1581 * D16MIN XRa, XRb, XRc Q8ABD XRa, XRb, XRc
1582 * D16SLT XRa, XRb, XRc Q8SAD XRa, XRb, XRc, XRd
1583 * D16MOVZ XRa, XRb, XRc Q8AVG XRa, XRb, XRc
1584 * D16MOVN XRa, XRb, XRc Q8AVGR XRa, XRb, XRc
1585 * Q8MAX XRa, XRb, XRc D8SUM XRa, XRb, XRc, XRd
1586 * Q8MIN XRa, XRb, XRc D8SUMC XRa, XRb, XRc, XRd
1587 * Q8SLT XRa, XRb, XRc
1588 * Q8SLTU XRa, XRb, XRc
1589 * Q8MOVZ XRa, XRb, XRc Shift instructions
1590 * Q8MOVN XRa, XRb, XRc ------------------
1592 * D32SLL XRa, XRb, XRc, XRd, sft4
1593 * Bitwise instructions D32SLR XRa, XRb, XRc, XRd, sft4
1594 * -------------------- D32SAR XRa, XRb, XRc, XRd, sft4
1595 * D32SARL XRa, XRb, XRc, sft4
1596 * S32NOR XRa, XRb, XRc D32SLLV XRa, XRb, Rb
1597 * S32AND XRa, XRb, XRc D32SLRV XRa, XRb, Rb
1598 * S32XOR XRa, XRb, XRc D32SARV XRa, XRb, Rb
1599 * S32OR XRa, XRb, XRc D32SARW XRa, XRb, XRc, Rb
1600 * Q16SLL XRa, XRb, XRc, XRd, sft4
1601 * Q16SLR XRa, XRb, XRc, XRd, sft4
1602 * Miscellaneous instructions Q16SAR XRa, XRb, XRc, XRd, sft4
1603 * ------------------------- Q16SLLV XRa, XRb, Rb
1604 * Q16SLRV XRa, XRb, Rb
1605 * S32SFL XRa, XRb, XRc, XRd, optn2 Q16SARV XRa, XRb, Rb
1606 * S32ALN XRa, XRb, XRc, Rb
1607 * S32ALNI XRa, XRb, XRc, s3
1608 * S32LUI XRa, s8, optn3 Move instructions
1609 * S32EXTR XRa, XRb, Rb, bits5 -----------------
1610 * S32EXTRV XRa, XRb, Rs, Rt
1611 * Q16SCOP XRa, XRb, XRc, XRd S32M2I XRa, Rb
1612 * Q16SAT XRa, XRb, XRc S32I2M XRa, Rb
1615 * The opcode organization of MXU instructions
1616 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1618 * The bits 31..26 of all MXU instructions are equal to 0x1C (also referred
1619 * as opcode SPECIAL2 in the base MIPS ISA). The organization and meaning of
1620 * other bits up to the instruction level is as follows:
1622 * bits
1623 * 05..00
1625 * ┌─ 000000 ─ OPC_MXU_S32MADD
1626 * ├─ 000001 ─ OPC_MXU_S32MADDU
1627 * ├─ 000010 ─ <not assigned> (non-MXU OPC_MUL)
1628 * │
1629 * │ 20..18
1630 * ├─ 000011 ─ OPC_MXU__POOL00 ─┬─ 000 ─ OPC_MXU_S32MAX
1631 * │ ├─ 001 ─ OPC_MXU_S32MIN
1632 * │ ├─ 010 ─ OPC_MXU_D16MAX
1633 * │ ├─ 011 ─ OPC_MXU_D16MIN
1634 * │ ├─ 100 ─ OPC_MXU_Q8MAX
1635 * │ ├─ 101 ─ OPC_MXU_Q8MIN
1636 * │ ├─ 110 ─ OPC_MXU_Q8SLT
1637 * │ └─ 111 ─ OPC_MXU_Q8SLTU
1638 * ├─ 000100 ─ OPC_MXU_S32MSUB
1639 * ├─ 000101 ─ OPC_MXU_S32MSUBU 20..18
1640 * ├─ 000110 ─ OPC_MXU__POOL01 ─┬─ 000 ─ OPC_MXU_S32SLT
1641 * │ ├─ 001 ─ OPC_MXU_D16SLT
1642 * │ ├─ 010 ─ OPC_MXU_D16AVG
1643 * │ ├─ 011 ─ OPC_MXU_D16AVGR
1644 * │ ├─ 100 ─ OPC_MXU_Q8AVG
1645 * │ ├─ 101 ─ OPC_MXU_Q8AVGR
1646 * │ └─ 111 ─ OPC_MXU_Q8ADD
1647 * │
1648 * │ 20..18
1649 * ├─ 000111 ─ OPC_MXU__POOL02 ─┬─ 000 ─ OPC_MXU_S32CPS
1650 * │ ├─ 010 ─ OPC_MXU_D16CPS
1651 * │ ├─ 100 ─ OPC_MXU_Q8ABD
1652 * │ └─ 110 ─ OPC_MXU_Q16SAT
1653 * ├─ 001000 ─ OPC_MXU_D16MUL
1654 * │ 25..24
1655 * ├─ 001001 ─ OPC_MXU__POOL03 ─┬─ 00 ─ OPC_MXU_D16MULF
1656 * │ └─ 01 ─ OPC_MXU_D16MULE
1657 * ├─ 001010 ─ OPC_MXU_D16MAC
1658 * ├─ 001011 ─ OPC_MXU_D16MACF
1659 * ├─ 001100 ─ OPC_MXU_D16MADL
1660 * ├─ 001101 ─ OPC_MXU_S16MAD
1661 * ├─ 001110 ─ OPC_MXU_Q16ADD
1662 * ├─ 001111 ─ OPC_MXU_D16MACE 23
1663 * │ ┌─ 0 ─ OPC_MXU_S32LDD
1664 * ├─ 010000 ─ OPC_MXU__POOL04 ─┴─ 1 ─ OPC_MXU_S32LDDR
1665 * │
1666 * │ 23
1667 * ├─ 010001 ─ OPC_MXU__POOL05 ─┬─ 0 ─ OPC_MXU_S32STD
1668 * │ └─ 1 ─ OPC_MXU_S32STDR
1669 * │
1670 * │ 13..10
1671 * ├─ 010010 ─ OPC_MXU__POOL06 ─┬─ 0000 ─ OPC_MXU_S32LDDV
1672 * │ └─ 0001 ─ OPC_MXU_S32LDDVR
1673 * │
1674 * │ 13..10
1675 * ├─ 010011 ─ OPC_MXU__POOL07 ─┬─ 0000 ─ OPC_MXU_S32STDV
1676 * │ └─ 0001 ─ OPC_MXU_S32STDVR
1677 * │
1678 * │ 23
1679 * ├─ 010100 ─ OPC_MXU__POOL08 ─┬─ 0 ─ OPC_MXU_S32LDI
1680 * │ └─ 1 ─ OPC_MXU_S32LDIR
1681 * │
1682 * │ 23
1683 * ├─ 010101 ─ OPC_MXU__POOL09 ─┬─ 0 ─ OPC_MXU_S32SDI
1684 * │ └─ 1 ─ OPC_MXU_S32SDIR
1685 * │
1686 * │ 13..10
1687 * ├─ 010110 ─ OPC_MXU__POOL10 ─┬─ 0000 ─ OPC_MXU_S32LDIV
1688 * │ └─ 0001 ─ OPC_MXU_S32LDIVR
1689 * │
1690 * │ 13..10
1691 * ├─ 010111 ─ OPC_MXU__POOL11 ─┬─ 0000 ─ OPC_MXU_S32SDIV
1692 * │ └─ 0001 ─ OPC_MXU_S32SDIVR
1693 * ├─ 011000 ─ OPC_MXU_D32ADD
1694 * │ 23..22
1695 * MXU ├─ 011001 ─ OPC_MXU__POOL12 ─┬─ 00 ─ OPC_MXU_D32ACC
1696 * opcodes ─┤ ├─ 01 ─ OPC_MXU_D32ACCM
1697 * │ └─ 10 ─ OPC_MXU_D32ASUM
1698 * ├─ 011010 ─ <not assigned>
1699 * │ 23..22
1700 * ├─ 011011 ─ OPC_MXU__POOL13 ─┬─ 00 ─ OPC_MXU_Q16ACC
1701 * │ ├─ 01 ─ OPC_MXU_Q16ACCM
1702 * │ └─ 10 ─ OPC_MXU_Q16ASUM
1703 * │
1704 * │ 23..22
1705 * ├─ 011100 ─ OPC_MXU__POOL14 ─┬─ 00 ─ OPC_MXU_Q8ADDE
1706 * │ ├─ 01 ─ OPC_MXU_D8SUM
1707 * ├─ 011101 ─ OPC_MXU_Q8ACCE └─ 10 ─ OPC_MXU_D8SUMC
1708 * ├─ 011110 ─ <not assigned>
1709 * ├─ 011111 ─ <not assigned>
1710 * ├─ 100000 ─ <not assigned> (overlaps with CLZ)
1711 * ├─ 100001 ─ <not assigned> (overlaps with CLO)
1712 * ├─ 100010 ─ OPC_MXU_S8LDD
1713 * ├─ 100011 ─ OPC_MXU_S8STD 15..14
1714 * ├─ 100100 ─ OPC_MXU_S8LDI ┌─ 00 ─ OPC_MXU_S32MUL
1715 * ├─ 100101 ─ OPC_MXU_S8SDI ├─ 00 ─ OPC_MXU_S32MULU
1716 * │ ├─ 00 ─ OPC_MXU_S32EXTR
1717 * ├─ 100110 ─ OPC_MXU__POOL15 ─┴─ 00 ─ OPC_MXU_S32EXTRV
1718 * │
1719 * │ 20..18
1720 * ├─ 100111 ─ OPC_MXU__POOL16 ─┬─ 000 ─ OPC_MXU_D32SARW
1721 * │ ├─ 001 ─ OPC_MXU_S32ALN
1722 * │ ├─ 010 ─ OPC_MXU_S32ALNI
1723 * │ ├─ 011 ─ OPC_MXU_S32LUI
1724 * │ ├─ 100 ─ OPC_MXU_S32NOR
1725 * │ ├─ 101 ─ OPC_MXU_S32AND
1726 * │ ├─ 110 ─ OPC_MXU_S32OR
1727 * │ └─ 111 ─ OPC_MXU_S32XOR
1728 * │
1729 * │ 7..5
1730 * ├─ 101000 ─ OPC_MXU__POOL17 ─┬─ 000 ─ OPC_MXU_LXB
1731 * │ ├─ 001 ─ OPC_MXU_LXH
1732 * ├─ 101001 ─ <not assigned> ├─ 011 ─ OPC_MXU_LXW
1733 * ├─ 101010 ─ OPC_MXU_S16LDD ├─ 100 ─ OPC_MXU_LXBU
1734 * ├─ 101011 ─ OPC_MXU_S16STD └─ 101 ─ OPC_MXU_LXHU
1735 * ├─ 101100 ─ OPC_MXU_S16LDI
1736 * ├─ 101101 ─ OPC_MXU_S16SDI
1737 * ├─ 101110 ─ OPC_MXU_S32M2I
1738 * ├─ 101111 ─ OPC_MXU_S32I2M
1739 * ├─ 110000 ─ OPC_MXU_D32SLL
1740 * ├─ 110001 ─ OPC_MXU_D32SLR 20..18
1741 * ├─ 110010 ─ OPC_MXU_D32SARL ┌─ 000 ─ OPC_MXU_D32SLLV
1742 * ├─ 110011 ─ OPC_MXU_D32SAR ├─ 001 ─ OPC_MXU_D32SLRV
1743 * ├─ 110100 ─ OPC_MXU_Q16SLL ├─ 010 ─ OPC_MXU_D32SARV
1744 * ├─ 110101 ─ OPC_MXU_Q16SLR ├─ 011 ─ OPC_MXU_Q16SLLV
1745 * │ ├─ 100 ─ OPC_MXU_Q16SLRV
1746 * ├─ 110110 ─ OPC_MXU__POOL18 ─┴─ 101 ─ OPC_MXU_Q16SARV
1747 * │
1748 * ├─ 110111 ─ OPC_MXU_Q16SAR
1749 * │ 23..22
1750 * ├─ 111000 ─ OPC_MXU__POOL19 ─┬─ 00 ─ OPC_MXU_Q8MUL
1751 * │ └─ 01 ─ OPC_MXU_Q8MULSU
1752 * │
1753 * │ 20..18
1754 * ├─ 111001 ─ OPC_MXU__POOL20 ─┬─ 000 ─ OPC_MXU_Q8MOVZ
1755 * │ ├─ 001 ─ OPC_MXU_Q8MOVN
1756 * │ ├─ 010 ─ OPC_MXU_D16MOVZ
1757 * │ ├─ 011 ─ OPC_MXU_D16MOVN
1758 * │ ├─ 100 ─ OPC_MXU_S32MOVZ
1759 * │ └─ 101 ─ OPC_MXU_S32MOVN
1760 * │
1761 * │ 23..22
1762 * ├─ 111010 ─ OPC_MXU__POOL21 ─┬─ 00 ─ OPC_MXU_Q8MAC
1763 * │ └─ 10 ─ OPC_MXU_Q8MACSU
1764 * ├─ 111011 ─ OPC_MXU_Q16SCOP
1765 * ├─ 111100 ─ OPC_MXU_Q8MADL
1766 * ├─ 111101 ─ OPC_MXU_S32SFL
1767 * ├─ 111110 ─ OPC_MXU_Q8SAD
1768 * └─ 111111 ─ <not assigned> (overlaps with SDBBP)
1771 * Compiled after:
1773 * "XBurst® Instruction Set Architecture MIPS eXtension/enhanced Unit
1774 * Programming Manual", Ingenic Semiconductor Co, Ltd., revision June 2, 2017
1777 enum {
1778 OPC_MXU_S32MADD = 0x00,
1779 OPC_MXU_S32MADDU = 0x01,
1780 OPC__MXU_MUL = 0x02,
1781 OPC_MXU__POOL00 = 0x03,
1782 OPC_MXU_S32MSUB = 0x04,
1783 OPC_MXU_S32MSUBU = 0x05,
1784 OPC_MXU__POOL01 = 0x06,
1785 OPC_MXU__POOL02 = 0x07,
1786 OPC_MXU_D16MUL = 0x08,
1787 OPC_MXU__POOL03 = 0x09,
1788 OPC_MXU_D16MAC = 0x0A,
1789 OPC_MXU_D16MACF = 0x0B,
1790 OPC_MXU_D16MADL = 0x0C,
1791 OPC_MXU_S16MAD = 0x0D,
1792 OPC_MXU_Q16ADD = 0x0E,
1793 OPC_MXU_D16MACE = 0x0F,
1794 OPC_MXU__POOL04 = 0x10,
1795 OPC_MXU__POOL05 = 0x11,
1796 OPC_MXU__POOL06 = 0x12,
1797 OPC_MXU__POOL07 = 0x13,
1798 OPC_MXU__POOL08 = 0x14,
1799 OPC_MXU__POOL09 = 0x15,
1800 OPC_MXU__POOL10 = 0x16,
1801 OPC_MXU__POOL11 = 0x17,
1802 OPC_MXU_D32ADD = 0x18,
1803 OPC_MXU__POOL12 = 0x19,
1804 /* not assigned 0x1A */
1805 OPC_MXU__POOL13 = 0x1B,
1806 OPC_MXU__POOL14 = 0x1C,
1807 OPC_MXU_Q8ACCE = 0x1D,
1808 /* not assigned 0x1E */
1809 /* not assigned 0x1F */
1810 /* not assigned 0x20 */
1811 /* not assigned 0x21 */
1812 OPC_MXU_S8LDD = 0x22,
1813 OPC_MXU_S8STD = 0x23,
1814 OPC_MXU_S8LDI = 0x24,
1815 OPC_MXU_S8SDI = 0x25,
1816 OPC_MXU__POOL15 = 0x26,
1817 OPC_MXU__POOL16 = 0x27,
1818 OPC_MXU__POOL17 = 0x28,
1819 /* not assigned 0x29 */
1820 OPC_MXU_S16LDD = 0x2A,
1821 OPC_MXU_S16STD = 0x2B,
1822 OPC_MXU_S16LDI = 0x2C,
1823 OPC_MXU_S16SDI = 0x2D,
1824 OPC_MXU_S32M2I = 0x2E,
1825 OPC_MXU_S32I2M = 0x2F,
1826 OPC_MXU_D32SLL = 0x30,
1827 OPC_MXU_D32SLR = 0x31,
1828 OPC_MXU_D32SARL = 0x32,
1829 OPC_MXU_D32SAR = 0x33,
1830 OPC_MXU_Q16SLL = 0x34,
1831 OPC_MXU_Q16SLR = 0x35,
1832 OPC_MXU__POOL18 = 0x36,
1833 OPC_MXU_Q16SAR = 0x37,
1834 OPC_MXU__POOL19 = 0x38,
1835 OPC_MXU__POOL20 = 0x39,
1836 OPC_MXU__POOL21 = 0x3A,
1837 OPC_MXU_Q16SCOP = 0x3B,
1838 OPC_MXU_Q8MADL = 0x3C,
1839 OPC_MXU_S32SFL = 0x3D,
1840 OPC_MXU_Q8SAD = 0x3E,
1841 /* not assigned 0x3F */
1846 * MXU pool 00
1848 enum {
1849 OPC_MXU_S32MAX = 0x00,
1850 OPC_MXU_S32MIN = 0x01,
1851 OPC_MXU_D16MAX = 0x02,
1852 OPC_MXU_D16MIN = 0x03,
1853 OPC_MXU_Q8MAX = 0x04,
1854 OPC_MXU_Q8MIN = 0x05,
1855 OPC_MXU_Q8SLT = 0x06,
1856 OPC_MXU_Q8SLTU = 0x07,
1860 * MXU pool 01
1862 enum {
1863 OPC_MXU_S32SLT = 0x00,
1864 OPC_MXU_D16SLT = 0x01,
1865 OPC_MXU_D16AVG = 0x02,
1866 OPC_MXU_D16AVGR = 0x03,
1867 OPC_MXU_Q8AVG = 0x04,
1868 OPC_MXU_Q8AVGR = 0x05,
1869 OPC_MXU_Q8ADD = 0x07,
1873 * MXU pool 02
1875 enum {
1876 OPC_MXU_S32CPS = 0x00,
1877 OPC_MXU_D16CPS = 0x02,
1878 OPC_MXU_Q8ABD = 0x04,
1879 OPC_MXU_Q16SAT = 0x06,
1883 * MXU pool 03
1885 enum {
1886 OPC_MXU_D16MULF = 0x00,
1887 OPC_MXU_D16MULE = 0x01,
1891 * MXU pool 04
1893 enum {
1894 OPC_MXU_S32LDD = 0x00,
1895 OPC_MXU_S32LDDR = 0x01,
1899 * MXU pool 05
1901 enum {
1902 OPC_MXU_S32STD = 0x00,
1903 OPC_MXU_S32STDR = 0x01,
1907 * MXU pool 06
1909 enum {
1910 OPC_MXU_S32LDDV = 0x00,
1911 OPC_MXU_S32LDDVR = 0x01,
1915 * MXU pool 07
1917 enum {
1918 OPC_MXU_S32STDV = 0x00,
1919 OPC_MXU_S32STDVR = 0x01,
1923 * MXU pool 08
1925 enum {
1926 OPC_MXU_S32LDI = 0x00,
1927 OPC_MXU_S32LDIR = 0x01,
1931 * MXU pool 09
1933 enum {
1934 OPC_MXU_S32SDI = 0x00,
1935 OPC_MXU_S32SDIR = 0x01,
1939 * MXU pool 10
1941 enum {
1942 OPC_MXU_S32LDIV = 0x00,
1943 OPC_MXU_S32LDIVR = 0x01,
1947 * MXU pool 11
1949 enum {
1950 OPC_MXU_S32SDIV = 0x00,
1951 OPC_MXU_S32SDIVR = 0x01,
1955 * MXU pool 12
1957 enum {
1958 OPC_MXU_D32ACC = 0x00,
1959 OPC_MXU_D32ACCM = 0x01,
1960 OPC_MXU_D32ASUM = 0x02,
1964 * MXU pool 13
1966 enum {
1967 OPC_MXU_Q16ACC = 0x00,
1968 OPC_MXU_Q16ACCM = 0x01,
1969 OPC_MXU_Q16ASUM = 0x02,
1973 * MXU pool 14
1975 enum {
1976 OPC_MXU_Q8ADDE = 0x00,
1977 OPC_MXU_D8SUM = 0x01,
1978 OPC_MXU_D8SUMC = 0x02,
1982 * MXU pool 15
1984 enum {
1985 OPC_MXU_S32MUL = 0x00,
1986 OPC_MXU_S32MULU = 0x01,
1987 OPC_MXU_S32EXTR = 0x02,
1988 OPC_MXU_S32EXTRV = 0x03,
1992 * MXU pool 16
1994 enum {
1995 OPC_MXU_D32SARW = 0x00,
1996 OPC_MXU_S32ALN = 0x01,
1997 OPC_MXU_S32ALNI = 0x02,
1998 OPC_MXU_S32LUI = 0x03,
1999 OPC_MXU_S32NOR = 0x04,
2000 OPC_MXU_S32AND = 0x05,
2001 OPC_MXU_S32OR = 0x06,
2002 OPC_MXU_S32XOR = 0x07,
2006 * MXU pool 17
2008 enum {
2009 OPC_MXU_LXB = 0x00,
2010 OPC_MXU_LXH = 0x01,
2011 OPC_MXU_LXW = 0x03,
2012 OPC_MXU_LXBU = 0x04,
2013 OPC_MXU_LXHU = 0x05,
2017 * MXU pool 18
2019 enum {
2020 OPC_MXU_D32SLLV = 0x00,
2021 OPC_MXU_D32SLRV = 0x01,
2022 OPC_MXU_D32SARV = 0x03,
2023 OPC_MXU_Q16SLLV = 0x04,
2024 OPC_MXU_Q16SLRV = 0x05,
2025 OPC_MXU_Q16SARV = 0x07,
2029 * MXU pool 19
2031 enum {
2032 OPC_MXU_Q8MUL = 0x00,
2033 OPC_MXU_Q8MULSU = 0x01,
2037 * MXU pool 20
2039 enum {
2040 OPC_MXU_Q8MOVZ = 0x00,
2041 OPC_MXU_Q8MOVN = 0x01,
2042 OPC_MXU_D16MOVZ = 0x02,
2043 OPC_MXU_D16MOVN = 0x03,
2044 OPC_MXU_S32MOVZ = 0x04,
2045 OPC_MXU_S32MOVN = 0x05,
2049 * MXU pool 21
2051 enum {
2052 OPC_MXU_Q8MAC = 0x00,
2053 OPC_MXU_Q8MACSU = 0x01,
2057 * Overview of the TX79-specific instruction set
2058 * =============================================
2060 * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits
2061 * are only used by the specific quadword (128-bit) LQ/SQ load/store
2062 * instructions and certain multimedia instructions (MMIs). These MMIs
2063 * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit
2064 * or sixteen 8-bit paths.
2066 * Reference:
2068 * The Toshiba TX System RISC TX79 Core Architecture manual,
2069 * https://wiki.qemu.org/File:C790.pdf
2071 * Three-Operand Multiply and Multiply-Add (4 instructions)
2072 * --------------------------------------------------------
2073 * MADD [rd,] rs, rt Multiply/Add
2074 * MADDU [rd,] rs, rt Multiply/Add Unsigned
2075 * MULT [rd,] rs, rt Multiply (3-operand)
2076 * MULTU [rd,] rs, rt Multiply Unsigned (3-operand)
2078 * Multiply Instructions for Pipeline 1 (10 instructions)
2079 * ------------------------------------------------------
2080 * MULT1 [rd,] rs, rt Multiply Pipeline 1
2081 * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1
2082 * DIV1 rs, rt Divide Pipeline 1
2083 * DIVU1 rs, rt Divide Unsigned Pipeline 1
2084 * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1
2085 * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1
2086 * MFHI1 rd Move From HI1 Register
2087 * MFLO1 rd Move From LO1 Register
2088 * MTHI1 rs Move To HI1 Register
2089 * MTLO1 rs Move To LO1 Register
2091 * Arithmetic (19 instructions)
2092 * ----------------------------
2093 * PADDB rd, rs, rt Parallel Add Byte
2094 * PSUBB rd, rs, rt Parallel Subtract Byte
2095 * PADDH rd, rs, rt Parallel Add Halfword
2096 * PSUBH rd, rs, rt Parallel Subtract Halfword
2097 * PADDW rd, rs, rt Parallel Add Word
2098 * PSUBW rd, rs, rt Parallel Subtract Word
2099 * PADSBH rd, rs, rt Parallel Add/Subtract Halfword
2100 * PADDSB rd, rs, rt Parallel Add with Signed Saturation Byte
2101 * PSUBSB rd, rs, rt Parallel Subtract with Signed Saturation Byte
2102 * PADDSH rd, rs, rt Parallel Add with Signed Saturation Halfword
2103 * PSUBSH rd, rs, rt Parallel Subtract with Signed Saturation Halfword
2104 * PADDSW rd, rs, rt Parallel Add with Signed Saturation Word
2105 * PSUBSW rd, rs, rt Parallel Subtract with Signed Saturation Word
2106 * PADDUB rd, rs, rt Parallel Add with Unsigned saturation Byte
2107 * PSUBUB rd, rs, rt Parallel Subtract with Unsigned saturation Byte
2108 * PADDUH rd, rs, rt Parallel Add with Unsigned saturation Halfword
2109 * PSUBUH rd, rs, rt Parallel Subtract with Unsigned saturation Halfword
2110 * PADDUW rd, rs, rt Parallel Add with Unsigned saturation Word
2111 * PSUBUW rd, rs, rt Parallel Subtract with Unsigned saturation Word
2113 * Min/Max (4 instructions)
2114 * ------------------------
2115 * PMAXH rd, rs, rt Parallel Maximum Halfword
2116 * PMINH rd, rs, rt Parallel Minimum Halfword
2117 * PMAXW rd, rs, rt Parallel Maximum Word
2118 * PMINW rd, rs, rt Parallel Minimum Word
2120 * Absolute (2 instructions)
2121 * -------------------------
2122 * PABSH rd, rt Parallel Absolute Halfword
2123 * PABSW rd, rt Parallel Absolute Word
2125 * Logical (4 instructions)
2126 * ------------------------
2127 * PAND rd, rs, rt Parallel AND
2128 * POR rd, rs, rt Parallel OR
2129 * PXOR rd, rs, rt Parallel XOR
2130 * PNOR rd, rs, rt Parallel NOR
2132 * Shift (9 instructions)
2133 * ----------------------
2134 * PSLLH rd, rt, sa Parallel Shift Left Logical Halfword
2135 * PSRLH rd, rt, sa Parallel Shift Right Logical Halfword
2136 * PSRAH rd, rt, sa Parallel Shift Right Arithmetic Halfword
2137 * PSLLW rd, rt, sa Parallel Shift Left Logical Word
2138 * PSRLW rd, rt, sa Parallel Shift Right Logical Word
2139 * PSRAW rd, rt, sa Parallel Shift Right Arithmetic Word
2140 * PSLLVW rd, rt, rs Parallel Shift Left Logical Variable Word
2141 * PSRLVW rd, rt, rs Parallel Shift Right Logical Variable Word
2142 * PSRAVW rd, rt, rs Parallel Shift Right Arithmetic Variable Word
2144 * Compare (6 instructions)
2145 * ------------------------
2146 * PCGTB rd, rs, rt Parallel Compare for Greater Than Byte
2147 * PCEQB rd, rs, rt Parallel Compare for Equal Byte
2148 * PCGTH rd, rs, rt Parallel Compare for Greater Than Halfword
2149 * PCEQH rd, rs, rt Parallel Compare for Equal Halfword
2150 * PCGTW rd, rs, rt Parallel Compare for Greater Than Word
2151 * PCEQW rd, rs, rt Parallel Compare for Equal Word
2153 * LZC (1 instruction)
2154 * -------------------
2155 * PLZCW rd, rs Parallel Leading Zero or One Count Word
2157 * Quadword Load and Store (2 instructions)
2158 * ----------------------------------------
2159 * LQ rt, offset(base) Load Quadword
2160 * SQ rt, offset(base) Store Quadword
2162 * Multiply and Divide (19 instructions)
2163 * -------------------------------------
2164 * PMULTW rd, rs, rt Parallel Multiply Word
2165 * PMULTUW rd, rs, rt Parallel Multiply Unsigned Word
2166 * PDIVW rs, rt Parallel Divide Word
2167 * PDIVUW rs, rt Parallel Divide Unsigned Word
2168 * PMADDW rd, rs, rt Parallel Multiply-Add Word
2169 * PMADDUW rd, rs, rt Parallel Multiply-Add Unsigned Word
2170 * PMSUBW rd, rs, rt Parallel Multiply-Subtract Word
2171 * PMULTH rd, rs, rt Parallel Multiply Halfword
2172 * PMADDH rd, rs, rt Parallel Multiply-Add Halfword
2173 * PMSUBH rd, rs, rt Parallel Multiply-Subtract Halfword
2174 * PHMADH rd, rs, rt Parallel Horizontal Multiply-Add Halfword
2175 * PHMSBH rd, rs, rt Parallel Horizontal Multiply-Subtract Halfword
2176 * PDIVBW rs, rt Parallel Divide Broadcast Word
2177 * PMFHI rd Parallel Move From HI Register
2178 * PMFLO rd Parallel Move From LO Register
2179 * PMTHI rs Parallel Move To HI Register
2180 * PMTLO rs Parallel Move To LO Register
2181 * PMFHL rd Parallel Move From HI/LO Register
2182 * PMTHL rs Parallel Move To HI/LO Register
2184 * Pack/Extend (11 instructions)
2185 * -----------------------------
2186 * PPAC5 rd, rt Parallel Pack to 5 bits
2187 * PPACB rd, rs, rt Parallel Pack to Byte
2188 * PPACH rd, rs, rt Parallel Pack to Halfword
2189 * PPACW rd, rs, rt Parallel Pack to Word
2190 * PEXT5 rd, rt Parallel Extend Upper from 5 bits
2191 * PEXTUB rd, rs, rt Parallel Extend Upper from Byte
2192 * PEXTLB rd, rs, rt Parallel Extend Lower from Byte
2193 * PEXTUH rd, rs, rt Parallel Extend Upper from Halfword
2194 * PEXTLH rd, rs, rt Parallel Extend Lower from Halfword
2195 * PEXTUW rd, rs, rt Parallel Extend Upper from Word
2196 * PEXTLW rd, rs, rt Parallel Extend Lower from Word
2198 * Others (16 instructions)
2199 * ------------------------
2200 * PCPYH rd, rt Parallel Copy Halfword
2201 * PCPYLD rd, rs, rt Parallel Copy Lower Doubleword
2202 * PCPYUD rd, rs, rt Parallel Copy Upper Doubleword
2203 * PREVH rd, rt Parallel Reverse Halfword
2204 * PINTH rd, rs, rt Parallel Interleave Halfword
2205 * PINTEH rd, rs, rt Parallel Interleave Even Halfword
2206 * PEXEH rd, rt Parallel Exchange Even Halfword
2207 * PEXCH rd, rt Parallel Exchange Center Halfword
2208 * PEXEW rd, rt Parallel Exchange Even Word
2209 * PEXCW rd, rt Parallel Exchange Center Word
2210 * QFSRV rd, rs, rt Quadword Funnel Shift Right Variable
2211 * MFSA rd Move from Shift Amount Register
2212 * MTSA rs Move to Shift Amount Register
2213 * MTSAB rs, immediate Move Byte Count to Shift Amount Register
2214 * MTSAH rs, immediate Move Halfword Count to Shift Amount Register
2215 * PROT3W rd, rt Parallel Rotate 3 Words
2217 * MMI (MultiMedia Instruction) encodings
2218 * ======================================
2220 * MMI instructions encoding table keys:
2222 * * This code is reserved for future use. An attempt to execute it
2223 * causes a Reserved Instruction exception.
2224 * % This code indicates an instruction class. The instruction word
2225 * must be further decoded by examining additional tables that show
2226 * the values for other instruction fields.
2227 * # This code is reserved for the unsupported instructions DMULT,
2228 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
2229 * to execute it causes a Reserved Instruction exception.
2231 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
2233 * 31 26 0
2234 * +--------+----------------------------------------+
2235 * | opcode | |
2236 * +--------+----------------------------------------+
2238 * opcode bits 28..26
2239 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2240 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2241 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2242 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
2243 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
2244 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
2245 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
2246 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
2247 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
2248 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
2249 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
2252 enum {
2253 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
2254 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
2255 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
2259 * MMI instructions with opcode field = MMI:
2261 * 31 26 5 0
2262 * +--------+-------------------------------+--------+
2263 * | MMI | |function|
2264 * +--------+-------------------------------+--------+
2266 * function bits 2..0
2267 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
2268 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
2269 * -------+-------+-------+-------+-------+-------+-------+-------+-------
2270 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
2271 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
2272 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
2273 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
2274 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
2275 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
2276 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
2277 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
2280 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
2281 enum {
2282 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
2283 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
2284 MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI,
2285 MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI,
2286 MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI,
2287 MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */
2288 MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */
2289 MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */
2290 MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */
2291 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
2292 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
2293 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
2294 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
2295 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
2296 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
2297 MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI,
2298 MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI,
2299 MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI,
2300 MMI_OPC_PMTHL = 0x31 | MMI_OPC_CLASS_MMI,
2301 MMI_OPC_PSLLH = 0x34 | MMI_OPC_CLASS_MMI,
2302 MMI_OPC_PSRLH = 0x36 | MMI_OPC_CLASS_MMI,
2303 MMI_OPC_PSRAH = 0x37 | MMI_OPC_CLASS_MMI,
2304 MMI_OPC_PSLLW = 0x3C | MMI_OPC_CLASS_MMI,
2305 MMI_OPC_PSRLW = 0x3E | MMI_OPC_CLASS_MMI,
2306 MMI_OPC_PSRAW = 0x3F | MMI_OPC_CLASS_MMI,
2310 * MMI instructions with opcode field = MMI and bits 5..0 = MMI0:
2312 * 31 26 10 6 5 0
2313 * +--------+----------------------+--------+--------+
2314 * | MMI | |function| MMI0 |
2315 * +--------+----------------------+--------+--------+
2317 * function bits 7..6
2318 * bits | 0 | 1 | 2 | 3
2319 * 10..8 | 00 | 01 | 10 | 11
2320 * -------+-------+-------+-------+-------
2321 * 0 000 | PADDW | PSUBW | PCGTW | PMAXW
2322 * 1 001 | PADDH | PSUBH | PCGTH | PMAXH
2323 * 2 010 | PADDB | PSUBB | PCGTB | *
2324 * 3 011 | * | * | * | *
2325 * 4 100 | PADDSW| PSUBSW| PEXTLW| PPACW
2326 * 5 101 | PADDSH| PSUBSH| PEXTLH| PPACH
2327 * 6 110 | PADDSB| PSUBSB| PEXTLB| PPACB
2328 * 7 111 | * | * | PEXT5 | PPAC5
2331 #define MASK_MMI0(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2332 enum {
2333 MMI_OPC_0_PADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI0,
2334 MMI_OPC_0_PSUBW = (0x01 << 6) | MMI_OPC_CLASS_MMI0,
2335 MMI_OPC_0_PCGTW = (0x02 << 6) | MMI_OPC_CLASS_MMI0,
2336 MMI_OPC_0_PMAXW = (0x03 << 6) | MMI_OPC_CLASS_MMI0,
2337 MMI_OPC_0_PADDH = (0x04 << 6) | MMI_OPC_CLASS_MMI0,
2338 MMI_OPC_0_PSUBH = (0x05 << 6) | MMI_OPC_CLASS_MMI0,
2339 MMI_OPC_0_PCGTH = (0x06 << 6) | MMI_OPC_CLASS_MMI0,
2340 MMI_OPC_0_PMAXH = (0x07 << 6) | MMI_OPC_CLASS_MMI0,
2341 MMI_OPC_0_PADDB = (0x08 << 6) | MMI_OPC_CLASS_MMI0,
2342 MMI_OPC_0_PSUBB = (0x09 << 6) | MMI_OPC_CLASS_MMI0,
2343 MMI_OPC_0_PCGTB = (0x0A << 6) | MMI_OPC_CLASS_MMI0,
2344 MMI_OPC_0_PADDSW = (0x10 << 6) | MMI_OPC_CLASS_MMI0,
2345 MMI_OPC_0_PSUBSW = (0x11 << 6) | MMI_OPC_CLASS_MMI0,
2346 MMI_OPC_0_PEXTLW = (0x12 << 6) | MMI_OPC_CLASS_MMI0,
2347 MMI_OPC_0_PPACW = (0x13 << 6) | MMI_OPC_CLASS_MMI0,
2348 MMI_OPC_0_PADDSH = (0x14 << 6) | MMI_OPC_CLASS_MMI0,
2349 MMI_OPC_0_PSUBSH = (0x15 << 6) | MMI_OPC_CLASS_MMI0,
2350 MMI_OPC_0_PEXTLH = (0x16 << 6) | MMI_OPC_CLASS_MMI0,
2351 MMI_OPC_0_PPACH = (0x17 << 6) | MMI_OPC_CLASS_MMI0,
2352 MMI_OPC_0_PADDSB = (0x18 << 6) | MMI_OPC_CLASS_MMI0,
2353 MMI_OPC_0_PSUBSB = (0x19 << 6) | MMI_OPC_CLASS_MMI0,
2354 MMI_OPC_0_PEXTLB = (0x1A << 6) | MMI_OPC_CLASS_MMI0,
2355 MMI_OPC_0_PPACB = (0x1B << 6) | MMI_OPC_CLASS_MMI0,
2356 MMI_OPC_0_PEXT5 = (0x1E << 6) | MMI_OPC_CLASS_MMI0,
2357 MMI_OPC_0_PPAC5 = (0x1F << 6) | MMI_OPC_CLASS_MMI0,
2361 * MMI instructions with opcode field = MMI and bits 5..0 = MMI1:
2363 * 31 26 10 6 5 0
2364 * +--------+----------------------+--------+--------+
2365 * | MMI | |function| MMI1 |
2366 * +--------+----------------------+--------+--------+
2368 * function bits 7..6
2369 * bits | 0 | 1 | 2 | 3
2370 * 10..8 | 00 | 01 | 10 | 11
2371 * -------+-------+-------+-------+-------
2372 * 0 000 | * | PABSW | PCEQW | PMINW
2373 * 1 001 | PADSBH| PABSH | PCEQH | PMINH
2374 * 2 010 | * | * | PCEQB | *
2375 * 3 011 | * | * | * | *
2376 * 4 100 | PADDUW| PSUBUW| PEXTUW| *
2377 * 5 101 | PADDUH| PSUBUH| PEXTUH| *
2378 * 6 110 | PADDUB| PSUBUB| PEXTUB| QFSRV
2379 * 7 111 | * | * | * | *
2382 #define MASK_MMI1(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2383 enum {
2384 MMI_OPC_1_PABSW = (0x01 << 6) | MMI_OPC_CLASS_MMI1,
2385 MMI_OPC_1_PCEQW = (0x02 << 6) | MMI_OPC_CLASS_MMI1,
2386 MMI_OPC_1_PMINW = (0x03 << 6) | MMI_OPC_CLASS_MMI1,
2387 MMI_OPC_1_PADSBH = (0x04 << 6) | MMI_OPC_CLASS_MMI1,
2388 MMI_OPC_1_PABSH = (0x05 << 6) | MMI_OPC_CLASS_MMI1,
2389 MMI_OPC_1_PCEQH = (0x06 << 6) | MMI_OPC_CLASS_MMI1,
2390 MMI_OPC_1_PMINH = (0x07 << 6) | MMI_OPC_CLASS_MMI1,
2391 MMI_OPC_1_PCEQB = (0x0A << 6) | MMI_OPC_CLASS_MMI1,
2392 MMI_OPC_1_PADDUW = (0x10 << 6) | MMI_OPC_CLASS_MMI1,
2393 MMI_OPC_1_PSUBUW = (0x11 << 6) | MMI_OPC_CLASS_MMI1,
2394 MMI_OPC_1_PEXTUW = (0x12 << 6) | MMI_OPC_CLASS_MMI1,
2395 MMI_OPC_1_PADDUH = (0x14 << 6) | MMI_OPC_CLASS_MMI1,
2396 MMI_OPC_1_PSUBUH = (0x15 << 6) | MMI_OPC_CLASS_MMI1,
2397 MMI_OPC_1_PEXTUH = (0x16 << 6) | MMI_OPC_CLASS_MMI1,
2398 MMI_OPC_1_PADDUB = (0x18 << 6) | MMI_OPC_CLASS_MMI1,
2399 MMI_OPC_1_PSUBUB = (0x19 << 6) | MMI_OPC_CLASS_MMI1,
2400 MMI_OPC_1_PEXTUB = (0x1A << 6) | MMI_OPC_CLASS_MMI1,
2401 MMI_OPC_1_QFSRV = (0x1B << 6) | MMI_OPC_CLASS_MMI1,
2405 * MMI instructions with opcode field = MMI and bits 5..0 = MMI2:
2407 * 31 26 10 6 5 0
2408 * +--------+----------------------+--------+--------+
2409 * | MMI | |function| MMI2 |
2410 * +--------+----------------------+--------+--------+
2412 * function bits 7..6
2413 * bits | 0 | 1 | 2 | 3
2414 * 10..8 | 00 | 01 | 10 | 11
2415 * -------+-------+-------+-------+-------
2416 * 0 000 | PMADDW| * | PSLLVW| PSRLVW
2417 * 1 001 | PMSUBW| * | * | *
2418 * 2 010 | PMFHI | PMFLO | PINTH | *
2419 * 3 011 | PMULTW| PDIVW | PCPYLD| *
2420 * 4 100 | PMADDH| PHMADH| PAND | PXOR
2421 * 5 101 | PMSUBH| PHMSBH| * | *
2422 * 6 110 | * | * | PEXEH | PREVH
2423 * 7 111 | PMULTH| PDIVBW| PEXEW | PROT3W
2426 #define MASK_MMI2(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2427 enum {
2428 MMI_OPC_2_PMADDW = (0x00 << 6) | MMI_OPC_CLASS_MMI2,
2429 MMI_OPC_2_PSLLVW = (0x02 << 6) | MMI_OPC_CLASS_MMI2,
2430 MMI_OPC_2_PSRLVW = (0x03 << 6) | MMI_OPC_CLASS_MMI2,
2431 MMI_OPC_2_PMSUBW = (0x04 << 6) | MMI_OPC_CLASS_MMI2,
2432 MMI_OPC_2_PMFHI = (0x08 << 6) | MMI_OPC_CLASS_MMI2,
2433 MMI_OPC_2_PMFLO = (0x09 << 6) | MMI_OPC_CLASS_MMI2,
2434 MMI_OPC_2_PINTH = (0x0A << 6) | MMI_OPC_CLASS_MMI2,
2435 MMI_OPC_2_PMULTW = (0x0C << 6) | MMI_OPC_CLASS_MMI2,
2436 MMI_OPC_2_PDIVW = (0x0D << 6) | MMI_OPC_CLASS_MMI2,
2437 MMI_OPC_2_PCPYLD = (0x0E << 6) | MMI_OPC_CLASS_MMI2,
2438 MMI_OPC_2_PMADDH = (0x10 << 6) | MMI_OPC_CLASS_MMI2,
2439 MMI_OPC_2_PHMADH = (0x11 << 6) | MMI_OPC_CLASS_MMI2,
2440 MMI_OPC_2_PAND = (0x12 << 6) | MMI_OPC_CLASS_MMI2,
2441 MMI_OPC_2_PXOR = (0x13 << 6) | MMI_OPC_CLASS_MMI2,
2442 MMI_OPC_2_PMSUBH = (0x14 << 6) | MMI_OPC_CLASS_MMI2,
2443 MMI_OPC_2_PHMSBH = (0x15 << 6) | MMI_OPC_CLASS_MMI2,
2444 MMI_OPC_2_PEXEH = (0x1A << 6) | MMI_OPC_CLASS_MMI2,
2445 MMI_OPC_2_PREVH = (0x1B << 6) | MMI_OPC_CLASS_MMI2,
2446 MMI_OPC_2_PMULTH = (0x1C << 6) | MMI_OPC_CLASS_MMI2,
2447 MMI_OPC_2_PDIVBW = (0x1D << 6) | MMI_OPC_CLASS_MMI2,
2448 MMI_OPC_2_PEXEW = (0x1E << 6) | MMI_OPC_CLASS_MMI2,
2449 MMI_OPC_2_PROT3W = (0x1F << 6) | MMI_OPC_CLASS_MMI2,
2453 * MMI instructions with opcode field = MMI and bits 5..0 = MMI3:
2455 * 31 26 10 6 5 0
2456 * +--------+----------------------+--------+--------+
2457 * | MMI | |function| MMI3 |
2458 * +--------+----------------------+--------+--------+
2460 * function bits 7..6
2461 * bits | 0 | 1 | 2 | 3
2462 * 10..8 | 00 | 01 | 10 | 11
2463 * -------+-------+-------+-------+-------
2464 * 0 000 |PMADDUW| * | * | PSRAVW
2465 * 1 001 | * | * | * | *
2466 * 2 010 | PMTHI | PMTLO | PINTEH| *
2467 * 3 011 |PMULTUW| PDIVUW| PCPYUD| *
2468 * 4 100 | * | * | POR | PNOR
2469 * 5 101 | * | * | * | *
2470 * 6 110 | * | * | PEXCH | PCPYH
2471 * 7 111 | * | * | PEXCW | *
2474 #define MASK_MMI3(op) (MASK_OP_MAJOR(op) | ((op) & 0x7FF))
2475 enum {
2476 MMI_OPC_3_PMADDUW = (0x00 << 6) | MMI_OPC_CLASS_MMI3,
2477 MMI_OPC_3_PSRAVW = (0x03 << 6) | MMI_OPC_CLASS_MMI3,
2478 MMI_OPC_3_PMTHI = (0x08 << 6) | MMI_OPC_CLASS_MMI3,
2479 MMI_OPC_3_PMTLO = (0x09 << 6) | MMI_OPC_CLASS_MMI3,
2480 MMI_OPC_3_PINTEH = (0x0A << 6) | MMI_OPC_CLASS_MMI3,
2481 MMI_OPC_3_PMULTUW = (0x0C << 6) | MMI_OPC_CLASS_MMI3,
2482 MMI_OPC_3_PDIVUW = (0x0D << 6) | MMI_OPC_CLASS_MMI3,
2483 MMI_OPC_3_PCPYUD = (0x0E << 6) | MMI_OPC_CLASS_MMI3,
2484 MMI_OPC_3_POR = (0x12 << 6) | MMI_OPC_CLASS_MMI3,
2485 MMI_OPC_3_PNOR = (0x13 << 6) | MMI_OPC_CLASS_MMI3,
2486 MMI_OPC_3_PEXCH = (0x1A << 6) | MMI_OPC_CLASS_MMI3,
2487 MMI_OPC_3_PCPYH = (0x1B << 6) | MMI_OPC_CLASS_MMI3,
2488 MMI_OPC_3_PEXCW = (0x1E << 6) | MMI_OPC_CLASS_MMI3,
2491 /* global register indices */
2492 static TCGv cpu_gpr[32], cpu_PC;
2493 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
2494 static TCGv cpu_dspctrl, btarget, bcond;
2495 static TCGv cpu_lladdr, cpu_llval;
2496 static TCGv_i32 hflags;
2497 static TCGv_i32 fpu_fcr0, fpu_fcr31;
2498 static TCGv_i64 fpu_f64[32];
2499 static TCGv_i64 msa_wr_d[64];
2501 #if defined(TARGET_MIPS64)
2502 /* Upper halves of R5900's 128-bit registers: MMRs (multimedia registers) */
2503 static TCGv_i64 cpu_mmr[32];
2504 #endif
2506 #if !defined(TARGET_MIPS64)
2507 /* MXU registers */
2508 static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1];
2509 static TCGv mxu_CR;
2510 #endif
2512 #include "exec/gen-icount.h"
2514 #define gen_helper_0e0i(name, arg) do { \
2515 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
2516 gen_helper_##name(cpu_env, helper_tmp); \
2517 tcg_temp_free_i32(helper_tmp); \
2518 } while (0)
2520 #define gen_helper_0e1i(name, arg1, arg2) do { \
2521 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2522 gen_helper_##name(cpu_env, arg1, helper_tmp); \
2523 tcg_temp_free_i32(helper_tmp); \
2524 } while (0)
2526 #define gen_helper_1e0i(name, ret, arg1) do { \
2527 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
2528 gen_helper_##name(ret, cpu_env, helper_tmp); \
2529 tcg_temp_free_i32(helper_tmp); \
2530 } while (0)
2532 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
2533 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
2534 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
2535 tcg_temp_free_i32(helper_tmp); \
2536 } while (0)
2538 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
2539 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2540 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
2541 tcg_temp_free_i32(helper_tmp); \
2542 } while (0)
2544 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
2545 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
2546 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
2547 tcg_temp_free_i32(helper_tmp); \
2548 } while (0)
2550 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
2551 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
2552 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
2553 tcg_temp_free_i32(helper_tmp); \
2554 } while (0)
2556 typedef struct DisasContext {
2557 DisasContextBase base;
2558 target_ulong saved_pc;
2559 target_ulong page_start;
2560 uint32_t opcode;
2561 uint64_t insn_flags;
2562 int32_t CP0_Config1;
2563 int32_t CP0_Config2;
2564 int32_t CP0_Config3;
2565 int32_t CP0_Config5;
2566 /* Routine used to access memory */
2567 int mem_idx;
2568 MemOp default_tcg_memop_mask;
2569 uint32_t hflags, saved_hflags;
2570 target_ulong btarget;
2571 bool ulri;
2572 int kscrexist;
2573 bool rxi;
2574 int ie;
2575 bool bi;
2576 bool bp;
2577 uint64_t PAMask;
2578 bool mvh;
2579 bool eva;
2580 bool sc;
2581 int CP0_LLAddr_shift;
2582 bool ps;
2583 bool vp;
2584 bool cmgcr;
2585 bool mrp;
2586 bool nan2008;
2587 bool abs2008;
2588 bool saar;
2589 bool mi;
2590 int gi;
2591 } DisasContext;
2593 #define DISAS_STOP DISAS_TARGET_0
2594 #define DISAS_EXIT DISAS_TARGET_1
2596 static const char * const regnames[] = {
2597 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
2598 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
2599 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
2600 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
2603 static const char * const regnames_HI[] = {
2604 "HI0", "HI1", "HI2", "HI3",
2607 static const char * const regnames_LO[] = {
2608 "LO0", "LO1", "LO2", "LO3",
2611 static const char * const fregnames[] = {
2612 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
2613 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
2614 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
2615 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
2618 static const char * const msaregnames[] = {
2619 "w0.d0", "w0.d1", "w1.d0", "w1.d1",
2620 "w2.d0", "w2.d1", "w3.d0", "w3.d1",
2621 "w4.d0", "w4.d1", "w5.d0", "w5.d1",
2622 "w6.d0", "w6.d1", "w7.d0", "w7.d1",
2623 "w8.d0", "w8.d1", "w9.d0", "w9.d1",
2624 "w10.d0", "w10.d1", "w11.d0", "w11.d1",
2625 "w12.d0", "w12.d1", "w13.d0", "w13.d1",
2626 "w14.d0", "w14.d1", "w15.d0", "w15.d1",
2627 "w16.d0", "w16.d1", "w17.d0", "w17.d1",
2628 "w18.d0", "w18.d1", "w19.d0", "w19.d1",
2629 "w20.d0", "w20.d1", "w21.d0", "w21.d1",
2630 "w22.d0", "w22.d1", "w23.d0", "w23.d1",
2631 "w24.d0", "w24.d1", "w25.d0", "w25.d1",
2632 "w26.d0", "w26.d1", "w27.d0", "w27.d1",
2633 "w28.d0", "w28.d1", "w29.d0", "w29.d1",
2634 "w30.d0", "w30.d1", "w31.d0", "w31.d1",
2637 #if !defined(TARGET_MIPS64)
2638 static const char * const mxuregnames[] = {
2639 "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8",
2640 "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "MXU_CR",
2642 #endif
2644 #define LOG_DISAS(...) \
2645 do { \
2646 if (MIPS_DEBUG_DISAS) { \
2647 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
2649 } while (0)
2651 #define MIPS_INVAL(op) \
2652 do { \
2653 if (MIPS_DEBUG_DISAS) { \
2654 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
2655 TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
2656 ctx->base.pc_next, ctx->opcode, op, \
2657 ctx->opcode >> 26, ctx->opcode & 0x3F, \
2658 ((ctx->opcode >> 16) & 0x1F)); \
2660 } while (0)
2662 /* General purpose registers moves. */
2663 static inline void gen_load_gpr(TCGv t, int reg)
2665 if (reg == 0) {
2666 tcg_gen_movi_tl(t, 0);
2667 } else {
2668 tcg_gen_mov_tl(t, cpu_gpr[reg]);
2672 static inline void gen_store_gpr(TCGv t, int reg)
2674 if (reg != 0) {
2675 tcg_gen_mov_tl(cpu_gpr[reg], t);
2679 /* Moves to/from shadow registers. */
2680 static inline void gen_load_srsgpr(int from, int to)
2682 TCGv t0 = tcg_temp_new();
2684 if (from == 0) {
2685 tcg_gen_movi_tl(t0, 0);
2686 } else {
2687 TCGv_i32 t2 = tcg_temp_new_i32();
2688 TCGv_ptr addr = tcg_temp_new_ptr();
2690 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2691 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2692 tcg_gen_andi_i32(t2, t2, 0xf);
2693 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2694 tcg_gen_ext_i32_ptr(addr, t2);
2695 tcg_gen_add_ptr(addr, cpu_env, addr);
2697 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
2698 tcg_temp_free_ptr(addr);
2699 tcg_temp_free_i32(t2);
2701 gen_store_gpr(t0, to);
2702 tcg_temp_free(t0);
2705 static inline void gen_store_srsgpr(int from, int to)
2707 if (to != 0) {
2708 TCGv t0 = tcg_temp_new();
2709 TCGv_i32 t2 = tcg_temp_new_i32();
2710 TCGv_ptr addr = tcg_temp_new_ptr();
2712 gen_load_gpr(t0, from);
2713 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
2714 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
2715 tcg_gen_andi_i32(t2, t2, 0xf);
2716 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
2717 tcg_gen_ext_i32_ptr(addr, t2);
2718 tcg_gen_add_ptr(addr, cpu_env, addr);
2720 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
2721 tcg_temp_free_ptr(addr);
2722 tcg_temp_free_i32(t2);
2723 tcg_temp_free(t0);
2727 #if !defined(TARGET_MIPS64)
2728 /* MXU General purpose registers moves. */
2729 static inline void gen_load_mxu_gpr(TCGv t, unsigned int reg)
2731 if (reg == 0) {
2732 tcg_gen_movi_tl(t, 0);
2733 } else if (reg <= 15) {
2734 tcg_gen_mov_tl(t, mxu_gpr[reg - 1]);
2738 static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg)
2740 if (reg > 0 && reg <= 15) {
2741 tcg_gen_mov_tl(mxu_gpr[reg - 1], t);
2745 /* MXU control register moves. */
2746 static inline void gen_load_mxu_cr(TCGv t)
2748 tcg_gen_mov_tl(t, mxu_CR);
2751 static inline void gen_store_mxu_cr(TCGv t)
2753 /* TODO: Add handling of RW rules for MXU_CR. */
2754 tcg_gen_mov_tl(mxu_CR, t);
2756 #endif
2759 /* Tests */
2760 static inline void gen_save_pc(target_ulong pc)
2762 tcg_gen_movi_tl(cpu_PC, pc);
2765 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
2767 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
2768 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
2769 gen_save_pc(ctx->base.pc_next);
2770 ctx->saved_pc = ctx->base.pc_next;
2772 if (ctx->hflags != ctx->saved_hflags) {
2773 tcg_gen_movi_i32(hflags, ctx->hflags);
2774 ctx->saved_hflags = ctx->hflags;
2775 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2776 case MIPS_HFLAG_BR:
2777 break;
2778 case MIPS_HFLAG_BC:
2779 case MIPS_HFLAG_BL:
2780 case MIPS_HFLAG_B:
2781 tcg_gen_movi_tl(btarget, ctx->btarget);
2782 break;
2787 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
2789 ctx->saved_hflags = ctx->hflags;
2790 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
2791 case MIPS_HFLAG_BR:
2792 break;
2793 case MIPS_HFLAG_BC:
2794 case MIPS_HFLAG_BL:
2795 case MIPS_HFLAG_B:
2796 ctx->btarget = env->btarget;
2797 break;
2801 static inline void generate_exception_err(DisasContext *ctx, int excp, int err)
2803 TCGv_i32 texcp = tcg_const_i32(excp);
2804 TCGv_i32 terr = tcg_const_i32(err);
2805 save_cpu_state(ctx, 1);
2806 gen_helper_raise_exception_err(cpu_env, texcp, terr);
2807 tcg_temp_free_i32(terr);
2808 tcg_temp_free_i32(texcp);
2809 ctx->base.is_jmp = DISAS_NORETURN;
2812 static inline void generate_exception(DisasContext *ctx, int excp)
2814 gen_helper_0e0i(raise_exception, excp);
2817 static inline void generate_exception_end(DisasContext *ctx, int excp)
2819 generate_exception_err(ctx, excp, 0);
2822 /* Floating point register moves. */
2823 static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2825 if (ctx->hflags & MIPS_HFLAG_FRE) {
2826 generate_exception(ctx, EXCP_RI);
2828 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
2831 static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
2833 TCGv_i64 t64;
2834 if (ctx->hflags & MIPS_HFLAG_FRE) {
2835 generate_exception(ctx, EXCP_RI);
2837 t64 = tcg_temp_new_i64();
2838 tcg_gen_extu_i32_i64(t64, t);
2839 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
2840 tcg_temp_free_i64(t64);
2843 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2845 if (ctx->hflags & MIPS_HFLAG_F64) {
2846 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
2847 } else {
2848 gen_load_fpr32(ctx, t, reg | 1);
2852 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
2854 if (ctx->hflags & MIPS_HFLAG_F64) {
2855 TCGv_i64 t64 = tcg_temp_new_i64();
2856 tcg_gen_extu_i32_i64(t64, t);
2857 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
2858 tcg_temp_free_i64(t64);
2859 } else {
2860 gen_store_fpr32(ctx, t, reg | 1);
2864 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2866 if (ctx->hflags & MIPS_HFLAG_F64) {
2867 tcg_gen_mov_i64(t, fpu_f64[reg]);
2868 } else {
2869 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
2873 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
2875 if (ctx->hflags & MIPS_HFLAG_F64) {
2876 tcg_gen_mov_i64(fpu_f64[reg], t);
2877 } else {
2878 TCGv_i64 t0;
2879 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
2880 t0 = tcg_temp_new_i64();
2881 tcg_gen_shri_i64(t0, t, 32);
2882 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
2883 tcg_temp_free_i64(t0);
2887 static inline int get_fp_bit(int cc)
2889 if (cc) {
2890 return 24 + cc;
2891 } else {
2892 return 23;
2896 /* Addresses computation */
2897 static inline void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0,
2898 TCGv arg1)
2900 tcg_gen_add_tl(ret, arg0, arg1);
2902 #if defined(TARGET_MIPS64)
2903 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2904 tcg_gen_ext32s_i64(ret, ret);
2906 #endif
2909 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
2910 target_long ofs)
2912 tcg_gen_addi_tl(ret, base, ofs);
2914 #if defined(TARGET_MIPS64)
2915 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2916 tcg_gen_ext32s_i64(ret, ret);
2918 #endif
2921 /* Addresses computation (translation time) */
2922 static target_long addr_add(DisasContext *ctx, target_long base,
2923 target_long offset)
2925 target_long sum = base + offset;
2927 #if defined(TARGET_MIPS64)
2928 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
2929 sum = (int32_t)sum;
2931 #endif
2932 return sum;
2935 /* Sign-extract the low 32-bits to a target_long. */
2936 static inline void gen_move_low32(TCGv ret, TCGv_i64 arg)
2938 #if defined(TARGET_MIPS64)
2939 tcg_gen_ext32s_i64(ret, arg);
2940 #else
2941 tcg_gen_extrl_i64_i32(ret, arg);
2942 #endif
2945 /* Sign-extract the high 32-bits to a target_long. */
2946 static inline void gen_move_high32(TCGv ret, TCGv_i64 arg)
2948 #if defined(TARGET_MIPS64)
2949 tcg_gen_sari_i64(ret, arg, 32);
2950 #else
2951 tcg_gen_extrh_i64_i32(ret, arg);
2952 #endif
2955 static inline void check_cp0_enabled(DisasContext *ctx)
2957 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
2958 generate_exception_err(ctx, EXCP_CpU, 0);
2962 static inline void check_cp1_enabled(DisasContext *ctx)
2964 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
2965 generate_exception_err(ctx, EXCP_CpU, 1);
2970 * Verify that the processor is running with COP1X instructions enabled.
2971 * This is associated with the nabla symbol in the MIPS32 and MIPS64
2972 * opcode tables.
2974 static inline void check_cop1x(DisasContext *ctx)
2976 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
2977 generate_exception_end(ctx, EXCP_RI);
2982 * Verify that the processor is running with 64-bit floating-point
2983 * operations enabled.
2985 static inline void check_cp1_64bitmode(DisasContext *ctx)
2987 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
2988 generate_exception_end(ctx, EXCP_RI);
2993 * Verify if floating point register is valid; an operation is not defined
2994 * if bit 0 of any register specification is set and the FR bit in the
2995 * Status register equals zero, since the register numbers specify an
2996 * even-odd pair of adjacent coprocessor general registers. When the FR bit
2997 * in the Status register equals one, both even and odd register numbers
2998 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
3000 * Multiple 64 bit wide registers can be checked by calling
3001 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
3003 static inline void check_cp1_registers(DisasContext *ctx, int regs)
3005 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
3006 generate_exception_end(ctx, EXCP_RI);
3011 * Verify that the processor is running with DSP instructions enabled.
3012 * This is enabled by CP0 Status register MX(24) bit.
3014 static inline void check_dsp(DisasContext *ctx)
3016 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
3017 if (ctx->insn_flags & ASE_DSP) {
3018 generate_exception_end(ctx, EXCP_DSPDIS);
3019 } else {
3020 generate_exception_end(ctx, EXCP_RI);
3025 static inline void check_dsp_r2(DisasContext *ctx)
3027 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
3028 if (ctx->insn_flags & ASE_DSP) {
3029 generate_exception_end(ctx, EXCP_DSPDIS);
3030 } else {
3031 generate_exception_end(ctx, EXCP_RI);
3036 static inline void check_dsp_r3(DisasContext *ctx)
3038 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
3039 if (ctx->insn_flags & ASE_DSP) {
3040 generate_exception_end(ctx, EXCP_DSPDIS);
3041 } else {
3042 generate_exception_end(ctx, EXCP_RI);
3048 * This code generates a "reserved instruction" exception if the
3049 * CPU does not support the instruction set corresponding to flags.
3051 static inline void check_insn(DisasContext *ctx, uint64_t flags)
3053 if (unlikely(!(ctx->insn_flags & flags))) {
3054 generate_exception_end(ctx, EXCP_RI);
3059 * This code generates a "reserved instruction" exception if the
3060 * CPU has corresponding flag set which indicates that the instruction
3061 * has been removed.
3063 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
3065 if (unlikely(ctx->insn_flags & flags)) {
3066 generate_exception_end(ctx, EXCP_RI);
3071 * The Linux kernel traps certain reserved instruction exceptions to
3072 * emulate the corresponding instructions. QEMU is the kernel in user
3073 * mode, so those traps are emulated by accepting the instructions.
3075 * A reserved instruction exception is generated for flagged CPUs if
3076 * QEMU runs in system mode.
3078 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
3080 #ifndef CONFIG_USER_ONLY
3081 check_insn_opc_removed(ctx, flags);
3082 #endif
3086 * This code generates a "reserved instruction" exception if the
3087 * CPU does not support 64-bit paired-single (PS) floating point data type.
3089 static inline void check_ps(DisasContext *ctx)
3091 if (unlikely(!ctx->ps)) {
3092 generate_exception(ctx, EXCP_RI);
3094 check_cp1_64bitmode(ctx);
3097 #ifdef TARGET_MIPS64
3099 * This code generates a "reserved instruction" exception if 64-bit
3100 * instructions are not enabled.
3102 static inline void check_mips_64(DisasContext *ctx)
3104 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64))) {
3105 generate_exception_end(ctx, EXCP_RI);
3108 #endif
3110 #ifndef CONFIG_USER_ONLY
3111 static inline void check_mvh(DisasContext *ctx)
3113 if (unlikely(!ctx->mvh)) {
3114 generate_exception(ctx, EXCP_RI);
3117 #endif
3120 * This code generates a "reserved instruction" exception if the
3121 * Config5 XNP bit is set.
3123 static inline void check_xnp(DisasContext *ctx)
3125 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
3126 generate_exception_end(ctx, EXCP_RI);
3130 #ifndef CONFIG_USER_ONLY
3132 * This code generates a "reserved instruction" exception if the
3133 * Config3 PW bit is NOT set.
3135 static inline void check_pw(DisasContext *ctx)
3137 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
3138 generate_exception_end(ctx, EXCP_RI);
3141 #endif
3144 * This code generates a "reserved instruction" exception if the
3145 * Config3 MT bit is NOT set.
3147 static inline void check_mt(DisasContext *ctx)
3149 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3150 generate_exception_end(ctx, EXCP_RI);
3154 #ifndef CONFIG_USER_ONLY
3156 * This code generates a "coprocessor unusable" exception if CP0 is not
3157 * available, and, if that is not the case, generates a "reserved instruction"
3158 * exception if the Config5 MT bit is NOT set. This is needed for availability
3159 * control of some of MT ASE instructions.
3161 static inline void check_cp0_mt(DisasContext *ctx)
3163 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
3164 generate_exception_err(ctx, EXCP_CpU, 0);
3165 } else {
3166 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
3167 generate_exception_err(ctx, EXCP_RI, 0);
3171 #endif
3174 * This code generates a "reserved instruction" exception if the
3175 * Config5 NMS bit is set.
3177 static inline void check_nms(DisasContext *ctx)
3179 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
3180 generate_exception_end(ctx, EXCP_RI);
3185 * This code generates a "reserved instruction" exception if the
3186 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
3187 * Config2 TL, and Config5 L2C are unset.
3189 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
3191 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
3192 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
3193 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
3194 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
3195 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
3196 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
3197 generate_exception_end(ctx, EXCP_RI);
3202 * This code generates a "reserved instruction" exception if the
3203 * Config5 EVA bit is NOT set.
3205 static inline void check_eva(DisasContext *ctx)
3207 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
3208 generate_exception_end(ctx, EXCP_RI);
3214 * Define small wrappers for gen_load_fpr* so that we have a uniform
3215 * calling interface for 32 and 64-bit FPRs. No sense in changing
3216 * all callers for gen_load_fpr32 when we need the CTX parameter for
3217 * this one use.
3219 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
3220 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
3221 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
3222 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
3223 int ft, int fs, int cc) \
3225 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
3226 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
3227 switch (ifmt) { \
3228 case FMT_PS: \
3229 check_ps(ctx); \
3230 break; \
3231 case FMT_D: \
3232 if (abs) { \
3233 check_cop1x(ctx); \
3235 check_cp1_registers(ctx, fs | ft); \
3236 break; \
3237 case FMT_S: \
3238 if (abs) { \
3239 check_cop1x(ctx); \
3241 break; \
3243 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
3244 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
3245 switch (n) { \
3246 case 0: \
3247 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
3248 break; \
3249 case 1: \
3250 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
3251 break; \
3252 case 2: \
3253 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
3254 break; \
3255 case 3: \
3256 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
3257 break; \
3258 case 4: \
3259 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
3260 break; \
3261 case 5: \
3262 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
3263 break; \
3264 case 6: \
3265 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
3266 break; \
3267 case 7: \
3268 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
3269 break; \
3270 case 8: \
3271 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
3272 break; \
3273 case 9: \
3274 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
3275 break; \
3276 case 10: \
3277 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
3278 break; \
3279 case 11: \
3280 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
3281 break; \
3282 case 12: \
3283 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
3284 break; \
3285 case 13: \
3286 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
3287 break; \
3288 case 14: \
3289 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
3290 break; \
3291 case 15: \
3292 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
3293 break; \
3294 default: \
3295 abort(); \
3297 tcg_temp_free_i##bits(fp0); \
3298 tcg_temp_free_i##bits(fp1); \
3301 FOP_CONDS(, 0, d, FMT_D, 64)
3302 FOP_CONDS(abs, 1, d, FMT_D, 64)
3303 FOP_CONDS(, 0, s, FMT_S, 32)
3304 FOP_CONDS(abs, 1, s, FMT_S, 32)
3305 FOP_CONDS(, 0, ps, FMT_PS, 64)
3306 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
3307 #undef FOP_CONDS
3309 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
3310 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
3311 int ft, int fs, int fd) \
3313 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
3314 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
3315 if (ifmt == FMT_D) { \
3316 check_cp1_registers(ctx, fs | ft | fd); \
3318 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
3319 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
3320 switch (n) { \
3321 case 0: \
3322 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
3323 break; \
3324 case 1: \
3325 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
3326 break; \
3327 case 2: \
3328 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
3329 break; \
3330 case 3: \
3331 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
3332 break; \
3333 case 4: \
3334 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
3335 break; \
3336 case 5: \
3337 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
3338 break; \
3339 case 6: \
3340 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
3341 break; \
3342 case 7: \
3343 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
3344 break; \
3345 case 8: \
3346 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
3347 break; \
3348 case 9: \
3349 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
3350 break; \
3351 case 10: \
3352 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
3353 break; \
3354 case 11: \
3355 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
3356 break; \
3357 case 12: \
3358 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
3359 break; \
3360 case 13: \
3361 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
3362 break; \
3363 case 14: \
3364 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
3365 break; \
3366 case 15: \
3367 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
3368 break; \
3369 case 17: \
3370 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
3371 break; \
3372 case 18: \
3373 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
3374 break; \
3375 case 19: \
3376 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
3377 break; \
3378 case 25: \
3379 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
3380 break; \
3381 case 26: \
3382 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
3383 break; \
3384 case 27: \
3385 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
3386 break; \
3387 default: \
3388 abort(); \
3390 STORE; \
3391 tcg_temp_free_i ## bits(fp0); \
3392 tcg_temp_free_i ## bits(fp1); \
3395 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
3396 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
3397 #undef FOP_CONDNS
3398 #undef gen_ldcmp_fpr32
3399 #undef gen_ldcmp_fpr64
3401 /* load/store instructions. */
3402 #ifdef CONFIG_USER_ONLY
3403 #define OP_LD_ATOMIC(insn, fname) \
3404 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3405 DisasContext *ctx) \
3407 TCGv t0 = tcg_temp_new(); \
3408 tcg_gen_mov_tl(t0, arg1); \
3409 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
3410 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
3411 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
3412 tcg_temp_free(t0); \
3414 #else
3415 #define OP_LD_ATOMIC(insn, fname) \
3416 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
3417 DisasContext *ctx) \
3419 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
3421 #endif
3422 OP_LD_ATOMIC(ll, ld32s);
3423 #if defined(TARGET_MIPS64)
3424 OP_LD_ATOMIC(lld, ld64);
3425 #endif
3426 #undef OP_LD_ATOMIC
3428 static void gen_base_offset_addr(DisasContext *ctx, TCGv addr,
3429 int base, int offset)
3431 if (base == 0) {
3432 tcg_gen_movi_tl(addr, offset);
3433 } else if (offset == 0) {
3434 gen_load_gpr(addr, base);
3435 } else {
3436 tcg_gen_movi_tl(addr, offset);
3437 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
3441 static target_ulong pc_relative_pc(DisasContext *ctx)
3443 target_ulong pc = ctx->base.pc_next;
3445 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3446 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
3448 pc -= branch_bytes;
3451 pc &= ~(target_ulong)3;
3452 return pc;
3455 /* Load */
3456 static void gen_ld(DisasContext *ctx, uint32_t opc,
3457 int rt, int base, int offset)
3459 TCGv t0, t1, t2;
3460 int mem_idx = ctx->mem_idx;
3462 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
3463 INSN_LOONGSON3A)) {
3465 * Loongson CPU uses a load to zero register for prefetch.
3466 * We emulate it as a NOP. On other CPU we must perform the
3467 * actual memory access.
3469 return;
3472 t0 = tcg_temp_new();
3473 gen_base_offset_addr(ctx, t0, base, offset);
3475 switch (opc) {
3476 #if defined(TARGET_MIPS64)
3477 case OPC_LWU:
3478 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
3479 ctx->default_tcg_memop_mask);
3480 gen_store_gpr(t0, rt);
3481 break;
3482 case OPC_LD:
3483 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
3484 ctx->default_tcg_memop_mask);
3485 gen_store_gpr(t0, rt);
3486 break;
3487 case OPC_LLD:
3488 case R6_OPC_LLD:
3489 op_ld_lld(t0, t0, mem_idx, ctx);
3490 gen_store_gpr(t0, rt);
3491 break;
3492 case OPC_LDL:
3493 t1 = tcg_temp_new();
3495 * Do a byte access to possibly trigger a page
3496 * fault with the unaligned address.
3498 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3499 tcg_gen_andi_tl(t1, t0, 7);
3500 #ifndef TARGET_WORDS_BIGENDIAN
3501 tcg_gen_xori_tl(t1, t1, 7);
3502 #endif
3503 tcg_gen_shli_tl(t1, t1, 3);
3504 tcg_gen_andi_tl(t0, t0, ~7);
3505 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3506 tcg_gen_shl_tl(t0, t0, t1);
3507 t2 = tcg_const_tl(-1);
3508 tcg_gen_shl_tl(t2, t2, t1);
3509 gen_load_gpr(t1, rt);
3510 tcg_gen_andc_tl(t1, t1, t2);
3511 tcg_temp_free(t2);
3512 tcg_gen_or_tl(t0, t0, t1);
3513 tcg_temp_free(t1);
3514 gen_store_gpr(t0, rt);
3515 break;
3516 case OPC_LDR:
3517 t1 = tcg_temp_new();
3519 * Do a byte access to possibly trigger a page
3520 * fault with the unaligned address.
3522 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3523 tcg_gen_andi_tl(t1, t0, 7);
3524 #ifdef TARGET_WORDS_BIGENDIAN
3525 tcg_gen_xori_tl(t1, t1, 7);
3526 #endif
3527 tcg_gen_shli_tl(t1, t1, 3);
3528 tcg_gen_andi_tl(t0, t0, ~7);
3529 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3530 tcg_gen_shr_tl(t0, t0, t1);
3531 tcg_gen_xori_tl(t1, t1, 63);
3532 t2 = tcg_const_tl(0xfffffffffffffffeull);
3533 tcg_gen_shl_tl(t2, t2, t1);
3534 gen_load_gpr(t1, rt);
3535 tcg_gen_and_tl(t1, t1, t2);
3536 tcg_temp_free(t2);
3537 tcg_gen_or_tl(t0, t0, t1);
3538 tcg_temp_free(t1);
3539 gen_store_gpr(t0, rt);
3540 break;
3541 case OPC_LDPC:
3542 t1 = tcg_const_tl(pc_relative_pc(ctx));
3543 gen_op_addr_add(ctx, t0, t0, t1);
3544 tcg_temp_free(t1);
3545 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
3546 gen_store_gpr(t0, rt);
3547 break;
3548 #endif
3549 case OPC_LWPC:
3550 t1 = tcg_const_tl(pc_relative_pc(ctx));
3551 gen_op_addr_add(ctx, t0, t0, t1);
3552 tcg_temp_free(t1);
3553 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
3554 gen_store_gpr(t0, rt);
3555 break;
3556 case OPC_LWE:
3557 mem_idx = MIPS_HFLAG_UM;
3558 /* fall through */
3559 case OPC_LW:
3560 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
3561 ctx->default_tcg_memop_mask);
3562 gen_store_gpr(t0, rt);
3563 break;
3564 case OPC_LHE:
3565 mem_idx = MIPS_HFLAG_UM;
3566 /* fall through */
3567 case OPC_LH:
3568 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
3569 ctx->default_tcg_memop_mask);
3570 gen_store_gpr(t0, rt);
3571 break;
3572 case OPC_LHUE:
3573 mem_idx = MIPS_HFLAG_UM;
3574 /* fall through */
3575 case OPC_LHU:
3576 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
3577 ctx->default_tcg_memop_mask);
3578 gen_store_gpr(t0, rt);
3579 break;
3580 case OPC_LBE:
3581 mem_idx = MIPS_HFLAG_UM;
3582 /* fall through */
3583 case OPC_LB:
3584 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
3585 gen_store_gpr(t0, rt);
3586 break;
3587 case OPC_LBUE:
3588 mem_idx = MIPS_HFLAG_UM;
3589 /* fall through */
3590 case OPC_LBU:
3591 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
3592 gen_store_gpr(t0, rt);
3593 break;
3594 case OPC_LWLE:
3595 mem_idx = MIPS_HFLAG_UM;
3596 /* fall through */
3597 case OPC_LWL:
3598 t1 = tcg_temp_new();
3600 * Do a byte access to possibly trigger a page
3601 * fault with the unaligned address.
3603 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3604 tcg_gen_andi_tl(t1, t0, 3);
3605 #ifndef TARGET_WORDS_BIGENDIAN
3606 tcg_gen_xori_tl(t1, t1, 3);
3607 #endif
3608 tcg_gen_shli_tl(t1, t1, 3);
3609 tcg_gen_andi_tl(t0, t0, ~3);
3610 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3611 tcg_gen_shl_tl(t0, t0, t1);
3612 t2 = tcg_const_tl(-1);
3613 tcg_gen_shl_tl(t2, t2, t1);
3614 gen_load_gpr(t1, rt);
3615 tcg_gen_andc_tl(t1, t1, t2);
3616 tcg_temp_free(t2);
3617 tcg_gen_or_tl(t0, t0, t1);
3618 tcg_temp_free(t1);
3619 tcg_gen_ext32s_tl(t0, t0);
3620 gen_store_gpr(t0, rt);
3621 break;
3622 case OPC_LWRE:
3623 mem_idx = MIPS_HFLAG_UM;
3624 /* fall through */
3625 case OPC_LWR:
3626 t1 = tcg_temp_new();
3628 * Do a byte access to possibly trigger a page
3629 * fault with the unaligned address.
3631 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
3632 tcg_gen_andi_tl(t1, t0, 3);
3633 #ifdef TARGET_WORDS_BIGENDIAN
3634 tcg_gen_xori_tl(t1, t1, 3);
3635 #endif
3636 tcg_gen_shli_tl(t1, t1, 3);
3637 tcg_gen_andi_tl(t0, t0, ~3);
3638 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
3639 tcg_gen_shr_tl(t0, t0, t1);
3640 tcg_gen_xori_tl(t1, t1, 31);
3641 t2 = tcg_const_tl(0xfffffffeull);
3642 tcg_gen_shl_tl(t2, t2, t1);
3643 gen_load_gpr(t1, rt);
3644 tcg_gen_and_tl(t1, t1, t2);
3645 tcg_temp_free(t2);
3646 tcg_gen_or_tl(t0, t0, t1);
3647 tcg_temp_free(t1);
3648 tcg_gen_ext32s_tl(t0, t0);
3649 gen_store_gpr(t0, rt);
3650 break;
3651 case OPC_LLE:
3652 mem_idx = MIPS_HFLAG_UM;
3653 /* fall through */
3654 case OPC_LL:
3655 case R6_OPC_LL:
3656 op_ld_ll(t0, t0, mem_idx, ctx);
3657 gen_store_gpr(t0, rt);
3658 break;
3660 tcg_temp_free(t0);
3663 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
3664 uint32_t reg1, uint32_t reg2)
3666 TCGv taddr = tcg_temp_new();
3667 TCGv_i64 tval = tcg_temp_new_i64();
3668 TCGv tmp1 = tcg_temp_new();
3669 TCGv tmp2 = tcg_temp_new();
3671 gen_base_offset_addr(ctx, taddr, base, offset);
3672 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
3673 #ifdef TARGET_WORDS_BIGENDIAN
3674 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
3675 #else
3676 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
3677 #endif
3678 gen_store_gpr(tmp1, reg1);
3679 tcg_temp_free(tmp1);
3680 gen_store_gpr(tmp2, reg2);
3681 tcg_temp_free(tmp2);
3682 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3683 tcg_temp_free_i64(tval);
3684 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
3685 tcg_temp_free(taddr);
3688 /* Store */
3689 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
3690 int base, int offset)
3692 TCGv t0 = tcg_temp_new();
3693 TCGv t1 = tcg_temp_new();
3694 int mem_idx = ctx->mem_idx;
3696 gen_base_offset_addr(ctx, t0, base, offset);
3697 gen_load_gpr(t1, rt);
3698 switch (opc) {
3699 #if defined(TARGET_MIPS64)
3700 case OPC_SD:
3701 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
3702 ctx->default_tcg_memop_mask);
3703 break;
3704 case OPC_SDL:
3705 gen_helper_0e2i(sdl, t1, t0, mem_idx);
3706 break;
3707 case OPC_SDR:
3708 gen_helper_0e2i(sdr, t1, t0, mem_idx);
3709 break;
3710 #endif
3711 case OPC_SWE:
3712 mem_idx = MIPS_HFLAG_UM;
3713 /* fall through */
3714 case OPC_SW:
3715 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
3716 ctx->default_tcg_memop_mask);
3717 break;
3718 case OPC_SHE:
3719 mem_idx = MIPS_HFLAG_UM;
3720 /* fall through */
3721 case OPC_SH:
3722 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
3723 ctx->default_tcg_memop_mask);
3724 break;
3725 case OPC_SBE:
3726 mem_idx = MIPS_HFLAG_UM;
3727 /* fall through */
3728 case OPC_SB:
3729 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
3730 break;
3731 case OPC_SWLE:
3732 mem_idx = MIPS_HFLAG_UM;
3733 /* fall through */
3734 case OPC_SWL:
3735 gen_helper_0e2i(swl, t1, t0, mem_idx);
3736 break;
3737 case OPC_SWRE:
3738 mem_idx = MIPS_HFLAG_UM;
3739 /* fall through */
3740 case OPC_SWR:
3741 gen_helper_0e2i(swr, t1, t0, mem_idx);
3742 break;
3744 tcg_temp_free(t0);
3745 tcg_temp_free(t1);
3749 /* Store conditional */
3750 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
3751 MemOp tcg_mo, bool eva)
3753 TCGv addr, t0, val;
3754 TCGLabel *l1 = gen_new_label();
3755 TCGLabel *done = gen_new_label();
3757 t0 = tcg_temp_new();
3758 addr = tcg_temp_new();
3759 /* compare the address against that of the preceding LL */
3760 gen_base_offset_addr(ctx, addr, base, offset);
3761 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
3762 tcg_temp_free(addr);
3763 tcg_gen_movi_tl(t0, 0);
3764 gen_store_gpr(t0, rt);
3765 tcg_gen_br(done);
3767 gen_set_label(l1);
3768 /* generate cmpxchg */
3769 val = tcg_temp_new();
3770 gen_load_gpr(val, rt);
3771 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
3772 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
3773 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
3774 gen_store_gpr(t0, rt);
3775 tcg_temp_free(val);
3777 gen_set_label(done);
3778 tcg_temp_free(t0);
3782 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
3783 uint32_t reg1, uint32_t reg2, bool eva)
3785 TCGv taddr = tcg_temp_local_new();
3786 TCGv lladdr = tcg_temp_local_new();
3787 TCGv_i64 tval = tcg_temp_new_i64();
3788 TCGv_i64 llval = tcg_temp_new_i64();
3789 TCGv_i64 val = tcg_temp_new_i64();
3790 TCGv tmp1 = tcg_temp_new();
3791 TCGv tmp2 = tcg_temp_new();
3792 TCGLabel *lab_fail = gen_new_label();
3793 TCGLabel *lab_done = gen_new_label();
3795 gen_base_offset_addr(ctx, taddr, base, offset);
3797 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3798 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
3800 gen_load_gpr(tmp1, reg1);
3801 gen_load_gpr(tmp2, reg2);
3803 #ifdef TARGET_WORDS_BIGENDIAN
3804 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
3805 #else
3806 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
3807 #endif
3809 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
3810 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
3811 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
3812 if (reg1 != 0) {
3813 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
3815 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
3817 gen_set_label(lab_fail);
3819 if (reg1 != 0) {
3820 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
3822 gen_set_label(lab_done);
3823 tcg_gen_movi_tl(lladdr, -1);
3824 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
3827 /* Load and store */
3828 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
3829 TCGv t0)
3832 * Don't do NOP if destination is zero: we must perform the actual
3833 * memory access.
3835 switch (opc) {
3836 case OPC_LWC1:
3838 TCGv_i32 fp0 = tcg_temp_new_i32();
3839 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
3840 ctx->default_tcg_memop_mask);
3841 gen_store_fpr32(ctx, fp0, ft);
3842 tcg_temp_free_i32(fp0);
3844 break;
3845 case OPC_SWC1:
3847 TCGv_i32 fp0 = tcg_temp_new_i32();
3848 gen_load_fpr32(ctx, fp0, ft);
3849 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
3850 ctx->default_tcg_memop_mask);
3851 tcg_temp_free_i32(fp0);
3853 break;
3854 case OPC_LDC1:
3856 TCGv_i64 fp0 = tcg_temp_new_i64();
3857 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3858 ctx->default_tcg_memop_mask);
3859 gen_store_fpr64(ctx, fp0, ft);
3860 tcg_temp_free_i64(fp0);
3862 break;
3863 case OPC_SDC1:
3865 TCGv_i64 fp0 = tcg_temp_new_i64();
3866 gen_load_fpr64(ctx, fp0, ft);
3867 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
3868 ctx->default_tcg_memop_mask);
3869 tcg_temp_free_i64(fp0);
3871 break;
3872 default:
3873 MIPS_INVAL("flt_ldst");
3874 generate_exception_end(ctx, EXCP_RI);
3875 break;
3879 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
3880 int rs, int16_t imm)
3882 TCGv t0 = tcg_temp_new();
3884 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
3885 check_cp1_enabled(ctx);
3886 switch (op) {
3887 case OPC_LDC1:
3888 case OPC_SDC1:
3889 check_insn(ctx, ISA_MIPS2);
3890 /* Fallthrough */
3891 default:
3892 gen_base_offset_addr(ctx, t0, rs, imm);
3893 gen_flt_ldst(ctx, op, rt, t0);
3895 } else {
3896 generate_exception_err(ctx, EXCP_CpU, 1);
3898 tcg_temp_free(t0);
3901 /* Arithmetic with immediate operand */
3902 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
3903 int rt, int rs, int imm)
3905 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
3907 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
3909 * If no destination, treat it as a NOP.
3910 * For addi, we must generate the overflow exception when needed.
3912 return;
3914 switch (opc) {
3915 case OPC_ADDI:
3917 TCGv t0 = tcg_temp_local_new();
3918 TCGv t1 = tcg_temp_new();
3919 TCGv t2 = tcg_temp_new();
3920 TCGLabel *l1 = gen_new_label();
3922 gen_load_gpr(t1, rs);
3923 tcg_gen_addi_tl(t0, t1, uimm);
3924 tcg_gen_ext32s_tl(t0, t0);
3926 tcg_gen_xori_tl(t1, t1, ~uimm);
3927 tcg_gen_xori_tl(t2, t0, uimm);
3928 tcg_gen_and_tl(t1, t1, t2);
3929 tcg_temp_free(t2);
3930 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3931 tcg_temp_free(t1);
3932 /* operands of same sign, result different sign */
3933 generate_exception(ctx, EXCP_OVERFLOW);
3934 gen_set_label(l1);
3935 tcg_gen_ext32s_tl(t0, t0);
3936 gen_store_gpr(t0, rt);
3937 tcg_temp_free(t0);
3939 break;
3940 case OPC_ADDIU:
3941 if (rs != 0) {
3942 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3943 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
3944 } else {
3945 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3947 break;
3948 #if defined(TARGET_MIPS64)
3949 case OPC_DADDI:
3951 TCGv t0 = tcg_temp_local_new();
3952 TCGv t1 = tcg_temp_new();
3953 TCGv t2 = tcg_temp_new();
3954 TCGLabel *l1 = gen_new_label();
3956 gen_load_gpr(t1, rs);
3957 tcg_gen_addi_tl(t0, t1, uimm);
3959 tcg_gen_xori_tl(t1, t1, ~uimm);
3960 tcg_gen_xori_tl(t2, t0, uimm);
3961 tcg_gen_and_tl(t1, t1, t2);
3962 tcg_temp_free(t2);
3963 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
3964 tcg_temp_free(t1);
3965 /* operands of same sign, result different sign */
3966 generate_exception(ctx, EXCP_OVERFLOW);
3967 gen_set_label(l1);
3968 gen_store_gpr(t0, rt);
3969 tcg_temp_free(t0);
3971 break;
3972 case OPC_DADDIU:
3973 if (rs != 0) {
3974 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3975 } else {
3976 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
3978 break;
3979 #endif
3983 /* Logic with immediate operand */
3984 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
3985 int rt, int rs, int16_t imm)
3987 target_ulong uimm;
3989 if (rt == 0) {
3990 /* If no destination, treat it as a NOP. */
3991 return;
3993 uimm = (uint16_t)imm;
3994 switch (opc) {
3995 case OPC_ANDI:
3996 if (likely(rs != 0)) {
3997 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
3998 } else {
3999 tcg_gen_movi_tl(cpu_gpr[rt], 0);
4001 break;
4002 case OPC_ORI:
4003 if (rs != 0) {
4004 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
4005 } else {
4006 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
4008 break;
4009 case OPC_XORI:
4010 if (likely(rs != 0)) {
4011 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
4012 } else {
4013 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
4015 break;
4016 case OPC_LUI:
4017 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
4018 /* OPC_AUI */
4019 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
4020 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
4021 } else {
4022 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
4024 break;
4026 default:
4027 break;
4031 /* Set on less than with immediate operand */
4032 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
4033 int rt, int rs, int16_t imm)
4035 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
4036 TCGv t0;
4038 if (rt == 0) {
4039 /* If no destination, treat it as a NOP. */
4040 return;
4042 t0 = tcg_temp_new();
4043 gen_load_gpr(t0, rs);
4044 switch (opc) {
4045 case OPC_SLTI:
4046 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
4047 break;
4048 case OPC_SLTIU:
4049 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
4050 break;
4052 tcg_temp_free(t0);
4055 /* Shifts with immediate operand */
4056 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
4057 int rt, int rs, int16_t imm)
4059 target_ulong uimm = ((uint16_t)imm) & 0x1f;
4060 TCGv t0;
4062 if (rt == 0) {
4063 /* If no destination, treat it as a NOP. */
4064 return;
4067 t0 = tcg_temp_new();
4068 gen_load_gpr(t0, rs);
4069 switch (opc) {
4070 case OPC_SLL:
4071 tcg_gen_shli_tl(t0, t0, uimm);
4072 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4073 break;
4074 case OPC_SRA:
4075 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4076 break;
4077 case OPC_SRL:
4078 if (uimm != 0) {
4079 tcg_gen_ext32u_tl(t0, t0);
4080 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4081 } else {
4082 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4084 break;
4085 case OPC_ROTR:
4086 if (uimm != 0) {
4087 TCGv_i32 t1 = tcg_temp_new_i32();
4089 tcg_gen_trunc_tl_i32(t1, t0);
4090 tcg_gen_rotri_i32(t1, t1, uimm);
4091 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
4092 tcg_temp_free_i32(t1);
4093 } else {
4094 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
4096 break;
4097 #if defined(TARGET_MIPS64)
4098 case OPC_DSLL:
4099 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
4100 break;
4101 case OPC_DSRA:
4102 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
4103 break;
4104 case OPC_DSRL:
4105 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
4106 break;
4107 case OPC_DROTR:
4108 if (uimm != 0) {
4109 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
4110 } else {
4111 tcg_gen_mov_tl(cpu_gpr[rt], t0);
4113 break;
4114 case OPC_DSLL32:
4115 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
4116 break;
4117 case OPC_DSRA32:
4118 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
4119 break;
4120 case OPC_DSRL32:
4121 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
4122 break;
4123 case OPC_DROTR32:
4124 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
4125 break;
4126 #endif
4128 tcg_temp_free(t0);
4131 /* Arithmetic */
4132 static void gen_arith(DisasContext *ctx, uint32_t opc,
4133 int rd, int rs, int rt)
4135 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
4136 && opc != OPC_DADD && opc != OPC_DSUB) {
4138 * If no destination, treat it as a NOP.
4139 * For add & sub, we must generate the overflow exception when needed.
4141 return;
4144 switch (opc) {
4145 case OPC_ADD:
4147 TCGv t0 = tcg_temp_local_new();
4148 TCGv t1 = tcg_temp_new();
4149 TCGv t2 = tcg_temp_new();
4150 TCGLabel *l1 = gen_new_label();
4152 gen_load_gpr(t1, rs);
4153 gen_load_gpr(t2, rt);
4154 tcg_gen_add_tl(t0, t1, t2);
4155 tcg_gen_ext32s_tl(t0, t0);
4156 tcg_gen_xor_tl(t1, t1, t2);
4157 tcg_gen_xor_tl(t2, t0, t2);
4158 tcg_gen_andc_tl(t1, t2, t1);
4159 tcg_temp_free(t2);
4160 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4161 tcg_temp_free(t1);
4162 /* operands of same sign, result different sign */
4163 generate_exception(ctx, EXCP_OVERFLOW);
4164 gen_set_label(l1);
4165 gen_store_gpr(t0, rd);
4166 tcg_temp_free(t0);
4168 break;
4169 case OPC_ADDU:
4170 if (rs != 0 && rt != 0) {
4171 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4172 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4173 } else if (rs == 0 && rt != 0) {
4174 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4175 } else if (rs != 0 && rt == 0) {
4176 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4177 } else {
4178 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4180 break;
4181 case OPC_SUB:
4183 TCGv t0 = tcg_temp_local_new();
4184 TCGv t1 = tcg_temp_new();
4185 TCGv t2 = tcg_temp_new();
4186 TCGLabel *l1 = gen_new_label();
4188 gen_load_gpr(t1, rs);
4189 gen_load_gpr(t2, rt);
4190 tcg_gen_sub_tl(t0, t1, t2);
4191 tcg_gen_ext32s_tl(t0, t0);
4192 tcg_gen_xor_tl(t2, t1, t2);
4193 tcg_gen_xor_tl(t1, t0, t1);
4194 tcg_gen_and_tl(t1, t1, t2);
4195 tcg_temp_free(t2);
4196 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4197 tcg_temp_free(t1);
4199 * operands of different sign, first operand and the result
4200 * of different sign
4202 generate_exception(ctx, EXCP_OVERFLOW);
4203 gen_set_label(l1);
4204 gen_store_gpr(t0, rd);
4205 tcg_temp_free(t0);
4207 break;
4208 case OPC_SUBU:
4209 if (rs != 0 && rt != 0) {
4210 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4211 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4212 } else if (rs == 0 && rt != 0) {
4213 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4214 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4215 } else if (rs != 0 && rt == 0) {
4216 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4217 } else {
4218 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4220 break;
4221 #if defined(TARGET_MIPS64)
4222 case OPC_DADD:
4224 TCGv t0 = tcg_temp_local_new();
4225 TCGv t1 = tcg_temp_new();
4226 TCGv t2 = tcg_temp_new();
4227 TCGLabel *l1 = gen_new_label();
4229 gen_load_gpr(t1, rs);
4230 gen_load_gpr(t2, rt);
4231 tcg_gen_add_tl(t0, t1, t2);
4232 tcg_gen_xor_tl(t1, t1, t2);
4233 tcg_gen_xor_tl(t2, t0, t2);
4234 tcg_gen_andc_tl(t1, t2, t1);
4235 tcg_temp_free(t2);
4236 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4237 tcg_temp_free(t1);
4238 /* operands of same sign, result different sign */
4239 generate_exception(ctx, EXCP_OVERFLOW);
4240 gen_set_label(l1);
4241 gen_store_gpr(t0, rd);
4242 tcg_temp_free(t0);
4244 break;
4245 case OPC_DADDU:
4246 if (rs != 0 && rt != 0) {
4247 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4248 } else if (rs == 0 && rt != 0) {
4249 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4250 } else if (rs != 0 && rt == 0) {
4251 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4252 } else {
4253 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4255 break;
4256 case OPC_DSUB:
4258 TCGv t0 = tcg_temp_local_new();
4259 TCGv t1 = tcg_temp_new();
4260 TCGv t2 = tcg_temp_new();
4261 TCGLabel *l1 = gen_new_label();
4263 gen_load_gpr(t1, rs);
4264 gen_load_gpr(t2, rt);
4265 tcg_gen_sub_tl(t0, t1, t2);
4266 tcg_gen_xor_tl(t2, t1, t2);
4267 tcg_gen_xor_tl(t1, t0, t1);
4268 tcg_gen_and_tl(t1, t1, t2);
4269 tcg_temp_free(t2);
4270 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
4271 tcg_temp_free(t1);
4273 * Operands of different sign, first operand and result different
4274 * sign.
4276 generate_exception(ctx, EXCP_OVERFLOW);
4277 gen_set_label(l1);
4278 gen_store_gpr(t0, rd);
4279 tcg_temp_free(t0);
4281 break;
4282 case OPC_DSUBU:
4283 if (rs != 0 && rt != 0) {
4284 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4285 } else if (rs == 0 && rt != 0) {
4286 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
4287 } else if (rs != 0 && rt == 0) {
4288 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4289 } else {
4290 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4292 break;
4293 #endif
4294 case OPC_MUL:
4295 if (likely(rs != 0 && rt != 0)) {
4296 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4297 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4298 } else {
4299 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4301 break;
4305 /* Conditional move */
4306 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
4307 int rd, int rs, int rt)
4309 TCGv t0, t1, t2;
4311 if (rd == 0) {
4312 /* If no destination, treat it as a NOP. */
4313 return;
4316 t0 = tcg_temp_new();
4317 gen_load_gpr(t0, rt);
4318 t1 = tcg_const_tl(0);
4319 t2 = tcg_temp_new();
4320 gen_load_gpr(t2, rs);
4321 switch (opc) {
4322 case OPC_MOVN:
4323 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4324 break;
4325 case OPC_MOVZ:
4326 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
4327 break;
4328 case OPC_SELNEZ:
4329 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
4330 break;
4331 case OPC_SELEQZ:
4332 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
4333 break;
4335 tcg_temp_free(t2);
4336 tcg_temp_free(t1);
4337 tcg_temp_free(t0);
4340 /* Logic */
4341 static void gen_logic(DisasContext *ctx, uint32_t opc,
4342 int rd, int rs, int rt)
4344 if (rd == 0) {
4345 /* If no destination, treat it as a NOP. */
4346 return;
4349 switch (opc) {
4350 case OPC_AND:
4351 if (likely(rs != 0 && rt != 0)) {
4352 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4353 } else {
4354 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4356 break;
4357 case OPC_NOR:
4358 if (rs != 0 && rt != 0) {
4359 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4360 } else if (rs == 0 && rt != 0) {
4361 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
4362 } else if (rs != 0 && rt == 0) {
4363 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
4364 } else {
4365 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
4367 break;
4368 case OPC_OR:
4369 if (likely(rs != 0 && rt != 0)) {
4370 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4371 } else if (rs == 0 && rt != 0) {
4372 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4373 } else if (rs != 0 && rt == 0) {
4374 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4375 } else {
4376 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4378 break;
4379 case OPC_XOR:
4380 if (likely(rs != 0 && rt != 0)) {
4381 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
4382 } else if (rs == 0 && rt != 0) {
4383 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
4384 } else if (rs != 0 && rt == 0) {
4385 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
4386 } else {
4387 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4389 break;
4393 /* Set on lower than */
4394 static void gen_slt(DisasContext *ctx, uint32_t opc,
4395 int rd, int rs, int rt)
4397 TCGv t0, t1;
4399 if (rd == 0) {
4400 /* If no destination, treat it as a NOP. */
4401 return;
4404 t0 = tcg_temp_new();
4405 t1 = tcg_temp_new();
4406 gen_load_gpr(t0, rs);
4407 gen_load_gpr(t1, rt);
4408 switch (opc) {
4409 case OPC_SLT:
4410 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
4411 break;
4412 case OPC_SLTU:
4413 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
4414 break;
4416 tcg_temp_free(t0);
4417 tcg_temp_free(t1);
4420 /* Shifts */
4421 static void gen_shift(DisasContext *ctx, uint32_t opc,
4422 int rd, int rs, int rt)
4424 TCGv t0, t1;
4426 if (rd == 0) {
4428 * If no destination, treat it as a NOP.
4429 * For add & sub, we must generate the overflow exception when needed.
4431 return;
4434 t0 = tcg_temp_new();
4435 t1 = tcg_temp_new();
4436 gen_load_gpr(t0, rs);
4437 gen_load_gpr(t1, rt);
4438 switch (opc) {
4439 case OPC_SLLV:
4440 tcg_gen_andi_tl(t0, t0, 0x1f);
4441 tcg_gen_shl_tl(t0, t1, t0);
4442 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4443 break;
4444 case OPC_SRAV:
4445 tcg_gen_andi_tl(t0, t0, 0x1f);
4446 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4447 break;
4448 case OPC_SRLV:
4449 tcg_gen_ext32u_tl(t1, t1);
4450 tcg_gen_andi_tl(t0, t0, 0x1f);
4451 tcg_gen_shr_tl(t0, t1, t0);
4452 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4453 break;
4454 case OPC_ROTRV:
4456 TCGv_i32 t2 = tcg_temp_new_i32();
4457 TCGv_i32 t3 = tcg_temp_new_i32();
4459 tcg_gen_trunc_tl_i32(t2, t0);
4460 tcg_gen_trunc_tl_i32(t3, t1);
4461 tcg_gen_andi_i32(t2, t2, 0x1f);
4462 tcg_gen_rotr_i32(t2, t3, t2);
4463 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4464 tcg_temp_free_i32(t2);
4465 tcg_temp_free_i32(t3);
4467 break;
4468 #if defined(TARGET_MIPS64)
4469 case OPC_DSLLV:
4470 tcg_gen_andi_tl(t0, t0, 0x3f);
4471 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
4472 break;
4473 case OPC_DSRAV:
4474 tcg_gen_andi_tl(t0, t0, 0x3f);
4475 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
4476 break;
4477 case OPC_DSRLV:
4478 tcg_gen_andi_tl(t0, t0, 0x3f);
4479 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
4480 break;
4481 case OPC_DROTRV:
4482 tcg_gen_andi_tl(t0, t0, 0x3f);
4483 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
4484 break;
4485 #endif
4487 tcg_temp_free(t0);
4488 tcg_temp_free(t1);
4491 #if defined(TARGET_MIPS64)
4492 /* Copy GPR to and from TX79 HI1/LO1 register. */
4493 static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg)
4495 if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) {
4496 /* Treat as NOP. */
4497 return;
4500 switch (opc) {
4501 case MMI_OPC_MFHI1:
4502 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]);
4503 break;
4504 case MMI_OPC_MFLO1:
4505 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]);
4506 break;
4507 case MMI_OPC_MTHI1:
4508 if (reg != 0) {
4509 tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]);
4510 } else {
4511 tcg_gen_movi_tl(cpu_HI[1], 0);
4513 break;
4514 case MMI_OPC_MTLO1:
4515 if (reg != 0) {
4516 tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]);
4517 } else {
4518 tcg_gen_movi_tl(cpu_LO[1], 0);
4520 break;
4521 default:
4522 MIPS_INVAL("mfthilo1 TX79");
4523 generate_exception_end(ctx, EXCP_RI);
4524 break;
4527 #endif
4529 /* Arithmetic on HI/LO registers */
4530 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
4532 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
4533 /* Treat as NOP. */
4534 return;
4537 if (acc != 0) {
4538 check_dsp(ctx);
4541 switch (opc) {
4542 case OPC_MFHI:
4543 #if defined(TARGET_MIPS64)
4544 if (acc != 0) {
4545 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
4546 } else
4547 #endif
4549 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
4551 break;
4552 case OPC_MFLO:
4553 #if defined(TARGET_MIPS64)
4554 if (acc != 0) {
4555 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
4556 } else
4557 #endif
4559 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
4561 break;
4562 case OPC_MTHI:
4563 if (reg != 0) {
4564 #if defined(TARGET_MIPS64)
4565 if (acc != 0) {
4566 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
4567 } else
4568 #endif
4570 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
4572 } else {
4573 tcg_gen_movi_tl(cpu_HI[acc], 0);
4575 break;
4576 case OPC_MTLO:
4577 if (reg != 0) {
4578 #if defined(TARGET_MIPS64)
4579 if (acc != 0) {
4580 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
4581 } else
4582 #endif
4584 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
4586 } else {
4587 tcg_gen_movi_tl(cpu_LO[acc], 0);
4589 break;
4593 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
4594 MemOp memop)
4596 TCGv t0 = tcg_const_tl(addr);
4597 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
4598 gen_store_gpr(t0, reg);
4599 tcg_temp_free(t0);
4602 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
4603 int rs)
4605 target_long offset;
4606 target_long addr;
4608 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
4609 case OPC_ADDIUPC:
4610 if (rs != 0) {
4611 offset = sextract32(ctx->opcode << 2, 0, 21);
4612 addr = addr_add(ctx, pc, offset);
4613 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4615 break;
4616 case R6_OPC_LWPC:
4617 offset = sextract32(ctx->opcode << 2, 0, 21);
4618 addr = addr_add(ctx, pc, offset);
4619 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
4620 break;
4621 #if defined(TARGET_MIPS64)
4622 case OPC_LWUPC:
4623 check_mips_64(ctx);
4624 offset = sextract32(ctx->opcode << 2, 0, 21);
4625 addr = addr_add(ctx, pc, offset);
4626 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
4627 break;
4628 #endif
4629 default:
4630 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
4631 case OPC_AUIPC:
4632 if (rs != 0) {
4633 offset = sextract32(ctx->opcode, 0, 16) << 16;
4634 addr = addr_add(ctx, pc, offset);
4635 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4637 break;
4638 case OPC_ALUIPC:
4639 if (rs != 0) {
4640 offset = sextract32(ctx->opcode, 0, 16) << 16;
4641 addr = ~0xFFFF & addr_add(ctx, pc, offset);
4642 tcg_gen_movi_tl(cpu_gpr[rs], addr);
4644 break;
4645 #if defined(TARGET_MIPS64)
4646 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
4647 case R6_OPC_LDPC + (1 << 16):
4648 case R6_OPC_LDPC + (2 << 16):
4649 case R6_OPC_LDPC + (3 << 16):
4650 check_mips_64(ctx);
4651 offset = sextract32(ctx->opcode << 3, 0, 21);
4652 addr = addr_add(ctx, (pc & ~0x7), offset);
4653 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
4654 break;
4655 #endif
4656 default:
4657 MIPS_INVAL("OPC_PCREL");
4658 generate_exception_end(ctx, EXCP_RI);
4659 break;
4661 break;
4665 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
4667 TCGv t0, t1;
4669 if (rd == 0) {
4670 /* Treat as NOP. */
4671 return;
4674 t0 = tcg_temp_new();
4675 t1 = tcg_temp_new();
4677 gen_load_gpr(t0, rs);
4678 gen_load_gpr(t1, rt);
4680 switch (opc) {
4681 case R6_OPC_DIV:
4683 TCGv t2 = tcg_temp_new();
4684 TCGv t3 = tcg_temp_new();
4685 tcg_gen_ext32s_tl(t0, t0);
4686 tcg_gen_ext32s_tl(t1, t1);
4687 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4688 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4689 tcg_gen_and_tl(t2, t2, t3);
4690 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4691 tcg_gen_or_tl(t2, t2, t3);
4692 tcg_gen_movi_tl(t3, 0);
4693 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4694 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4695 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4696 tcg_temp_free(t3);
4697 tcg_temp_free(t2);
4699 break;
4700 case R6_OPC_MOD:
4702 TCGv t2 = tcg_temp_new();
4703 TCGv t3 = tcg_temp_new();
4704 tcg_gen_ext32s_tl(t0, t0);
4705 tcg_gen_ext32s_tl(t1, t1);
4706 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4707 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4708 tcg_gen_and_tl(t2, t2, t3);
4709 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4710 tcg_gen_or_tl(t2, t2, t3);
4711 tcg_gen_movi_tl(t3, 0);
4712 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4713 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4714 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4715 tcg_temp_free(t3);
4716 tcg_temp_free(t2);
4718 break;
4719 case R6_OPC_DIVU:
4721 TCGv t2 = tcg_const_tl(0);
4722 TCGv t3 = tcg_const_tl(1);
4723 tcg_gen_ext32u_tl(t0, t0);
4724 tcg_gen_ext32u_tl(t1, t1);
4725 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4726 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4727 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4728 tcg_temp_free(t3);
4729 tcg_temp_free(t2);
4731 break;
4732 case R6_OPC_MODU:
4734 TCGv t2 = tcg_const_tl(0);
4735 TCGv t3 = tcg_const_tl(1);
4736 tcg_gen_ext32u_tl(t0, t0);
4737 tcg_gen_ext32u_tl(t1, t1);
4738 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4739 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4740 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4741 tcg_temp_free(t3);
4742 tcg_temp_free(t2);
4744 break;
4745 case R6_OPC_MUL:
4747 TCGv_i32 t2 = tcg_temp_new_i32();
4748 TCGv_i32 t3 = tcg_temp_new_i32();
4749 tcg_gen_trunc_tl_i32(t2, t0);
4750 tcg_gen_trunc_tl_i32(t3, t1);
4751 tcg_gen_mul_i32(t2, t2, t3);
4752 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4753 tcg_temp_free_i32(t2);
4754 tcg_temp_free_i32(t3);
4756 break;
4757 case R6_OPC_MUH:
4759 TCGv_i32 t2 = tcg_temp_new_i32();
4760 TCGv_i32 t3 = tcg_temp_new_i32();
4761 tcg_gen_trunc_tl_i32(t2, t0);
4762 tcg_gen_trunc_tl_i32(t3, t1);
4763 tcg_gen_muls2_i32(t2, t3, t2, t3);
4764 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4765 tcg_temp_free_i32(t2);
4766 tcg_temp_free_i32(t3);
4768 break;
4769 case R6_OPC_MULU:
4771 TCGv_i32 t2 = tcg_temp_new_i32();
4772 TCGv_i32 t3 = tcg_temp_new_i32();
4773 tcg_gen_trunc_tl_i32(t2, t0);
4774 tcg_gen_trunc_tl_i32(t3, t1);
4775 tcg_gen_mul_i32(t2, t2, t3);
4776 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
4777 tcg_temp_free_i32(t2);
4778 tcg_temp_free_i32(t3);
4780 break;
4781 case R6_OPC_MUHU:
4783 TCGv_i32 t2 = tcg_temp_new_i32();
4784 TCGv_i32 t3 = tcg_temp_new_i32();
4785 tcg_gen_trunc_tl_i32(t2, t0);
4786 tcg_gen_trunc_tl_i32(t3, t1);
4787 tcg_gen_mulu2_i32(t2, t3, t2, t3);
4788 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
4789 tcg_temp_free_i32(t2);
4790 tcg_temp_free_i32(t3);
4792 break;
4793 #if defined(TARGET_MIPS64)
4794 case R6_OPC_DDIV:
4796 TCGv t2 = tcg_temp_new();
4797 TCGv t3 = tcg_temp_new();
4798 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4799 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4800 tcg_gen_and_tl(t2, t2, t3);
4801 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4802 tcg_gen_or_tl(t2, t2, t3);
4803 tcg_gen_movi_tl(t3, 0);
4804 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4805 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4806 tcg_temp_free(t3);
4807 tcg_temp_free(t2);
4809 break;
4810 case R6_OPC_DMOD:
4812 TCGv t2 = tcg_temp_new();
4813 TCGv t3 = tcg_temp_new();
4814 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
4815 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
4816 tcg_gen_and_tl(t2, t2, t3);
4817 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4818 tcg_gen_or_tl(t2, t2, t3);
4819 tcg_gen_movi_tl(t3, 0);
4820 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4821 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4822 tcg_temp_free(t3);
4823 tcg_temp_free(t2);
4825 break;
4826 case R6_OPC_DDIVU:
4828 TCGv t2 = tcg_const_tl(0);
4829 TCGv t3 = tcg_const_tl(1);
4830 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4831 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
4832 tcg_temp_free(t3);
4833 tcg_temp_free(t2);
4835 break;
4836 case R6_OPC_DMODU:
4838 TCGv t2 = tcg_const_tl(0);
4839 TCGv t3 = tcg_const_tl(1);
4840 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4841 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
4842 tcg_temp_free(t3);
4843 tcg_temp_free(t2);
4845 break;
4846 case R6_OPC_DMUL:
4847 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4848 break;
4849 case R6_OPC_DMUH:
4851 TCGv t2 = tcg_temp_new();
4852 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
4853 tcg_temp_free(t2);
4855 break;
4856 case R6_OPC_DMULU:
4857 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
4858 break;
4859 case R6_OPC_DMUHU:
4861 TCGv t2 = tcg_temp_new();
4862 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
4863 tcg_temp_free(t2);
4865 break;
4866 #endif
4867 default:
4868 MIPS_INVAL("r6 mul/div");
4869 generate_exception_end(ctx, EXCP_RI);
4870 goto out;
4872 out:
4873 tcg_temp_free(t0);
4874 tcg_temp_free(t1);
4877 #if defined(TARGET_MIPS64)
4878 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
4880 TCGv t0, t1;
4882 t0 = tcg_temp_new();
4883 t1 = tcg_temp_new();
4885 gen_load_gpr(t0, rs);
4886 gen_load_gpr(t1, rt);
4888 switch (opc) {
4889 case MMI_OPC_DIV1:
4891 TCGv t2 = tcg_temp_new();
4892 TCGv t3 = tcg_temp_new();
4893 tcg_gen_ext32s_tl(t0, t0);
4894 tcg_gen_ext32s_tl(t1, t1);
4895 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4896 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4897 tcg_gen_and_tl(t2, t2, t3);
4898 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4899 tcg_gen_or_tl(t2, t2, t3);
4900 tcg_gen_movi_tl(t3, 0);
4901 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4902 tcg_gen_div_tl(cpu_LO[1], t0, t1);
4903 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
4904 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4905 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4906 tcg_temp_free(t3);
4907 tcg_temp_free(t2);
4909 break;
4910 case MMI_OPC_DIVU1:
4912 TCGv t2 = tcg_const_tl(0);
4913 TCGv t3 = tcg_const_tl(1);
4914 tcg_gen_ext32u_tl(t0, t0);
4915 tcg_gen_ext32u_tl(t1, t1);
4916 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4917 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
4918 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
4919 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
4920 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
4921 tcg_temp_free(t3);
4922 tcg_temp_free(t2);
4924 break;
4925 default:
4926 MIPS_INVAL("div1 TX79");
4927 generate_exception_end(ctx, EXCP_RI);
4928 goto out;
4930 out:
4931 tcg_temp_free(t0);
4932 tcg_temp_free(t1);
4934 #endif
4936 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
4937 int acc, int rs, int rt)
4939 TCGv t0, t1;
4941 t0 = tcg_temp_new();
4942 t1 = tcg_temp_new();
4944 gen_load_gpr(t0, rs);
4945 gen_load_gpr(t1, rt);
4947 if (acc != 0) {
4948 check_dsp(ctx);
4951 switch (opc) {
4952 case OPC_DIV:
4954 TCGv t2 = tcg_temp_new();
4955 TCGv t3 = tcg_temp_new();
4956 tcg_gen_ext32s_tl(t0, t0);
4957 tcg_gen_ext32s_tl(t1, t1);
4958 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
4959 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
4960 tcg_gen_and_tl(t2, t2, t3);
4961 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
4962 tcg_gen_or_tl(t2, t2, t3);
4963 tcg_gen_movi_tl(t3, 0);
4964 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
4965 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
4966 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
4967 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4968 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4969 tcg_temp_free(t3);
4970 tcg_temp_free(t2);
4972 break;
4973 case OPC_DIVU:
4975 TCGv t2 = tcg_const_tl(0);
4976 TCGv t3 = tcg_const_tl(1);
4977 tcg_gen_ext32u_tl(t0, t0);
4978 tcg_gen_ext32u_tl(t1, t1);
4979 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
4980 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
4981 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
4982 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
4983 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
4984 tcg_temp_free(t3);
4985 tcg_temp_free(t2);
4987 break;
4988 case OPC_MULT:
4990 TCGv_i32 t2 = tcg_temp_new_i32();
4991 TCGv_i32 t3 = tcg_temp_new_i32();
4992 tcg_gen_trunc_tl_i32(t2, t0);
4993 tcg_gen_trunc_tl_i32(t3, t1);
4994 tcg_gen_muls2_i32(t2, t3, t2, t3);
4995 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
4996 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
4997 tcg_temp_free_i32(t2);
4998 tcg_temp_free_i32(t3);
5000 break;
5001 case OPC_MULTU:
5003 TCGv_i32 t2 = tcg_temp_new_i32();
5004 TCGv_i32 t3 = tcg_temp_new_i32();
5005 tcg_gen_trunc_tl_i32(t2, t0);
5006 tcg_gen_trunc_tl_i32(t3, t1);
5007 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5008 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5009 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5010 tcg_temp_free_i32(t2);
5011 tcg_temp_free_i32(t3);
5013 break;
5014 #if defined(TARGET_MIPS64)
5015 case OPC_DDIV:
5017 TCGv t2 = tcg_temp_new();
5018 TCGv t3 = tcg_temp_new();
5019 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
5020 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
5021 tcg_gen_and_tl(t2, t2, t3);
5022 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
5023 tcg_gen_or_tl(t2, t2, t3);
5024 tcg_gen_movi_tl(t3, 0);
5025 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
5026 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
5027 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
5028 tcg_temp_free(t3);
5029 tcg_temp_free(t2);
5031 break;
5032 case OPC_DDIVU:
5034 TCGv t2 = tcg_const_tl(0);
5035 TCGv t3 = tcg_const_tl(1);
5036 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
5037 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
5038 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
5039 tcg_temp_free(t3);
5040 tcg_temp_free(t2);
5042 break;
5043 case OPC_DMULT:
5044 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5045 break;
5046 case OPC_DMULTU:
5047 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
5048 break;
5049 #endif
5050 case OPC_MADD:
5052 TCGv_i64 t2 = tcg_temp_new_i64();
5053 TCGv_i64 t3 = tcg_temp_new_i64();
5055 tcg_gen_ext_tl_i64(t2, t0);
5056 tcg_gen_ext_tl_i64(t3, t1);
5057 tcg_gen_mul_i64(t2, t2, t3);
5058 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5059 tcg_gen_add_i64(t2, t2, t3);
5060 tcg_temp_free_i64(t3);
5061 gen_move_low32(cpu_LO[acc], t2);
5062 gen_move_high32(cpu_HI[acc], t2);
5063 tcg_temp_free_i64(t2);
5065 break;
5066 case OPC_MADDU:
5068 TCGv_i64 t2 = tcg_temp_new_i64();
5069 TCGv_i64 t3 = tcg_temp_new_i64();
5071 tcg_gen_ext32u_tl(t0, t0);
5072 tcg_gen_ext32u_tl(t1, t1);
5073 tcg_gen_extu_tl_i64(t2, t0);
5074 tcg_gen_extu_tl_i64(t3, t1);
5075 tcg_gen_mul_i64(t2, t2, t3);
5076 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5077 tcg_gen_add_i64(t2, t2, t3);
5078 tcg_temp_free_i64(t3);
5079 gen_move_low32(cpu_LO[acc], t2);
5080 gen_move_high32(cpu_HI[acc], t2);
5081 tcg_temp_free_i64(t2);
5083 break;
5084 case OPC_MSUB:
5086 TCGv_i64 t2 = tcg_temp_new_i64();
5087 TCGv_i64 t3 = tcg_temp_new_i64();
5089 tcg_gen_ext_tl_i64(t2, t0);
5090 tcg_gen_ext_tl_i64(t3, t1);
5091 tcg_gen_mul_i64(t2, t2, t3);
5092 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5093 tcg_gen_sub_i64(t2, t3, t2);
5094 tcg_temp_free_i64(t3);
5095 gen_move_low32(cpu_LO[acc], t2);
5096 gen_move_high32(cpu_HI[acc], t2);
5097 tcg_temp_free_i64(t2);
5099 break;
5100 case OPC_MSUBU:
5102 TCGv_i64 t2 = tcg_temp_new_i64();
5103 TCGv_i64 t3 = tcg_temp_new_i64();
5105 tcg_gen_ext32u_tl(t0, t0);
5106 tcg_gen_ext32u_tl(t1, t1);
5107 tcg_gen_extu_tl_i64(t2, t0);
5108 tcg_gen_extu_tl_i64(t3, t1);
5109 tcg_gen_mul_i64(t2, t2, t3);
5110 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5111 tcg_gen_sub_i64(t2, t3, t2);
5112 tcg_temp_free_i64(t3);
5113 gen_move_low32(cpu_LO[acc], t2);
5114 gen_move_high32(cpu_HI[acc], t2);
5115 tcg_temp_free_i64(t2);
5117 break;
5118 default:
5119 MIPS_INVAL("mul/div");
5120 generate_exception_end(ctx, EXCP_RI);
5121 goto out;
5123 out:
5124 tcg_temp_free(t0);
5125 tcg_temp_free(t1);
5129 * These MULT[U] and MADD[U] instructions implemented in for example
5130 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
5131 * architectures are special three-operand variants with the syntax
5133 * MULT[U][1] rd, rs, rt
5135 * such that
5137 * (rd, LO, HI) <- rs * rt
5139 * and
5141 * MADD[U][1] rd, rs, rt
5143 * such that
5145 * (rd, LO, HI) <- (LO, HI) + rs * rt
5147 * where the low-order 32-bits of the result is placed into both the
5148 * GPR rd and the special register LO. The high-order 32-bits of the
5149 * result is placed into the special register HI.
5151 * If the GPR rd is omitted in assembly language, it is taken to be 0,
5152 * which is the zero register that always reads as 0.
5154 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
5155 int rd, int rs, int rt)
5157 TCGv t0 = tcg_temp_new();
5158 TCGv t1 = tcg_temp_new();
5159 int acc = 0;
5161 gen_load_gpr(t0, rs);
5162 gen_load_gpr(t1, rt);
5164 switch (opc) {
5165 case MMI_OPC_MULT1:
5166 acc = 1;
5167 /* Fall through */
5168 case OPC_MULT:
5170 TCGv_i32 t2 = tcg_temp_new_i32();
5171 TCGv_i32 t3 = tcg_temp_new_i32();
5172 tcg_gen_trunc_tl_i32(t2, t0);
5173 tcg_gen_trunc_tl_i32(t3, t1);
5174 tcg_gen_muls2_i32(t2, t3, t2, t3);
5175 if (rd) {
5176 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5178 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5179 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5180 tcg_temp_free_i32(t2);
5181 tcg_temp_free_i32(t3);
5183 break;
5184 case MMI_OPC_MULTU1:
5185 acc = 1;
5186 /* Fall through */
5187 case OPC_MULTU:
5189 TCGv_i32 t2 = tcg_temp_new_i32();
5190 TCGv_i32 t3 = tcg_temp_new_i32();
5191 tcg_gen_trunc_tl_i32(t2, t0);
5192 tcg_gen_trunc_tl_i32(t3, t1);
5193 tcg_gen_mulu2_i32(t2, t3, t2, t3);
5194 if (rd) {
5195 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
5197 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
5198 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
5199 tcg_temp_free_i32(t2);
5200 tcg_temp_free_i32(t3);
5202 break;
5203 case MMI_OPC_MADD1:
5204 acc = 1;
5205 /* Fall through */
5206 case MMI_OPC_MADD:
5208 TCGv_i64 t2 = tcg_temp_new_i64();
5209 TCGv_i64 t3 = tcg_temp_new_i64();
5211 tcg_gen_ext_tl_i64(t2, t0);
5212 tcg_gen_ext_tl_i64(t3, t1);
5213 tcg_gen_mul_i64(t2, t2, t3);
5214 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5215 tcg_gen_add_i64(t2, t2, t3);
5216 tcg_temp_free_i64(t3);
5217 gen_move_low32(cpu_LO[acc], t2);
5218 gen_move_high32(cpu_HI[acc], t2);
5219 if (rd) {
5220 gen_move_low32(cpu_gpr[rd], t2);
5222 tcg_temp_free_i64(t2);
5224 break;
5225 case MMI_OPC_MADDU1:
5226 acc = 1;
5227 /* Fall through */
5228 case MMI_OPC_MADDU:
5230 TCGv_i64 t2 = tcg_temp_new_i64();
5231 TCGv_i64 t3 = tcg_temp_new_i64();
5233 tcg_gen_ext32u_tl(t0, t0);
5234 tcg_gen_ext32u_tl(t1, t1);
5235 tcg_gen_extu_tl_i64(t2, t0);
5236 tcg_gen_extu_tl_i64(t3, t1);
5237 tcg_gen_mul_i64(t2, t2, t3);
5238 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
5239 tcg_gen_add_i64(t2, t2, t3);
5240 tcg_temp_free_i64(t3);
5241 gen_move_low32(cpu_LO[acc], t2);
5242 gen_move_high32(cpu_HI[acc], t2);
5243 if (rd) {
5244 gen_move_low32(cpu_gpr[rd], t2);
5246 tcg_temp_free_i64(t2);
5248 break;
5249 default:
5250 MIPS_INVAL("mul/madd TXx9");
5251 generate_exception_end(ctx, EXCP_RI);
5252 goto out;
5255 out:
5256 tcg_temp_free(t0);
5257 tcg_temp_free(t1);
5260 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
5261 int rd, int rs, int rt)
5263 TCGv t0 = tcg_temp_new();
5264 TCGv t1 = tcg_temp_new();
5266 gen_load_gpr(t0, rs);
5267 gen_load_gpr(t1, rt);
5269 switch (opc) {
5270 case OPC_VR54XX_MULS:
5271 gen_helper_muls(t0, cpu_env, t0, t1);
5272 break;
5273 case OPC_VR54XX_MULSU:
5274 gen_helper_mulsu(t0, cpu_env, t0, t1);
5275 break;
5276 case OPC_VR54XX_MACC:
5277 gen_helper_macc(t0, cpu_env, t0, t1);
5278 break;
5279 case OPC_VR54XX_MACCU:
5280 gen_helper_maccu(t0, cpu_env, t0, t1);
5281 break;
5282 case OPC_VR54XX_MSAC:
5283 gen_helper_msac(t0, cpu_env, t0, t1);
5284 break;
5285 case OPC_VR54XX_MSACU:
5286 gen_helper_msacu(t0, cpu_env, t0, t1);
5287 break;
5288 case OPC_VR54XX_MULHI:
5289 gen_helper_mulhi(t0, cpu_env, t0, t1);
5290 break;
5291 case OPC_VR54XX_MULHIU:
5292 gen_helper_mulhiu(t0, cpu_env, t0, t1);
5293 break;
5294 case OPC_VR54XX_MULSHI:
5295 gen_helper_mulshi(t0, cpu_env, t0, t1);
5296 break;
5297 case OPC_VR54XX_MULSHIU:
5298 gen_helper_mulshiu(t0, cpu_env, t0, t1);
5299 break;
5300 case OPC_VR54XX_MACCHI:
5301 gen_helper_macchi(t0, cpu_env, t0, t1);
5302 break;
5303 case OPC_VR54XX_MACCHIU:
5304 gen_helper_macchiu(t0, cpu_env, t0, t1);
5305 break;
5306 case OPC_VR54XX_MSACHI:
5307 gen_helper_msachi(t0, cpu_env, t0, t1);
5308 break;
5309 case OPC_VR54XX_MSACHIU:
5310 gen_helper_msachiu(t0, cpu_env, t0, t1);
5311 break;
5312 default:
5313 MIPS_INVAL("mul vr54xx");
5314 generate_exception_end(ctx, EXCP_RI);
5315 goto out;
5317 gen_store_gpr(t0, rd);
5319 out:
5320 tcg_temp_free(t0);
5321 tcg_temp_free(t1);
5324 static void gen_cl(DisasContext *ctx, uint32_t opc,
5325 int rd, int rs)
5327 TCGv t0;
5329 if (rd == 0) {
5330 /* Treat as NOP. */
5331 return;
5333 t0 = cpu_gpr[rd];
5334 gen_load_gpr(t0, rs);
5336 switch (opc) {
5337 case OPC_CLO:
5338 case R6_OPC_CLO:
5339 #if defined(TARGET_MIPS64)
5340 case OPC_DCLO:
5341 case R6_OPC_DCLO:
5342 #endif
5343 tcg_gen_not_tl(t0, t0);
5344 break;
5347 switch (opc) {
5348 case OPC_CLO:
5349 case R6_OPC_CLO:
5350 case OPC_CLZ:
5351 case R6_OPC_CLZ:
5352 tcg_gen_ext32u_tl(t0, t0);
5353 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
5354 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
5355 break;
5356 #if defined(TARGET_MIPS64)
5357 case OPC_DCLO:
5358 case R6_OPC_DCLO:
5359 case OPC_DCLZ:
5360 case R6_OPC_DCLZ:
5361 tcg_gen_clzi_i64(t0, t0, 64);
5362 break;
5363 #endif
5367 /* Godson integer instructions */
5368 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
5369 int rd, int rs, int rt)
5371 TCGv t0, t1;
5373 if (rd == 0) {
5374 /* Treat as NOP. */
5375 return;
5378 switch (opc) {
5379 case OPC_MULT_G_2E:
5380 case OPC_MULT_G_2F:
5381 case OPC_MULTU_G_2E:
5382 case OPC_MULTU_G_2F:
5383 #if defined(TARGET_MIPS64)
5384 case OPC_DMULT_G_2E:
5385 case OPC_DMULT_G_2F:
5386 case OPC_DMULTU_G_2E:
5387 case OPC_DMULTU_G_2F:
5388 #endif
5389 t0 = tcg_temp_new();
5390 t1 = tcg_temp_new();
5391 break;
5392 default:
5393 t0 = tcg_temp_local_new();
5394 t1 = tcg_temp_local_new();
5395 break;
5398 gen_load_gpr(t0, rs);
5399 gen_load_gpr(t1, rt);
5401 switch (opc) {
5402 case OPC_MULT_G_2E:
5403 case OPC_MULT_G_2F:
5404 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5405 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5406 break;
5407 case OPC_MULTU_G_2E:
5408 case OPC_MULTU_G_2F:
5409 tcg_gen_ext32u_tl(t0, t0);
5410 tcg_gen_ext32u_tl(t1, t1);
5411 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5412 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5413 break;
5414 case OPC_DIV_G_2E:
5415 case OPC_DIV_G_2F:
5417 TCGLabel *l1 = gen_new_label();
5418 TCGLabel *l2 = gen_new_label();
5419 TCGLabel *l3 = gen_new_label();
5420 tcg_gen_ext32s_tl(t0, t0);
5421 tcg_gen_ext32s_tl(t1, t1);
5422 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5423 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5424 tcg_gen_br(l3);
5425 gen_set_label(l1);
5426 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5427 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5428 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5429 tcg_gen_br(l3);
5430 gen_set_label(l2);
5431 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5432 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5433 gen_set_label(l3);
5435 break;
5436 case OPC_DIVU_G_2E:
5437 case OPC_DIVU_G_2F:
5439 TCGLabel *l1 = gen_new_label();
5440 TCGLabel *l2 = gen_new_label();
5441 tcg_gen_ext32u_tl(t0, t0);
5442 tcg_gen_ext32u_tl(t1, t1);
5443 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5444 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5445 tcg_gen_br(l2);
5446 gen_set_label(l1);
5447 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5448 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5449 gen_set_label(l2);
5451 break;
5452 case OPC_MOD_G_2E:
5453 case OPC_MOD_G_2F:
5455 TCGLabel *l1 = gen_new_label();
5456 TCGLabel *l2 = gen_new_label();
5457 TCGLabel *l3 = gen_new_label();
5458 tcg_gen_ext32u_tl(t0, t0);
5459 tcg_gen_ext32u_tl(t1, t1);
5460 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5461 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
5462 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
5463 gen_set_label(l1);
5464 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5465 tcg_gen_br(l3);
5466 gen_set_label(l2);
5467 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5468 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5469 gen_set_label(l3);
5471 break;
5472 case OPC_MODU_G_2E:
5473 case OPC_MODU_G_2F:
5475 TCGLabel *l1 = gen_new_label();
5476 TCGLabel *l2 = gen_new_label();
5477 tcg_gen_ext32u_tl(t0, t0);
5478 tcg_gen_ext32u_tl(t1, t1);
5479 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5480 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5481 tcg_gen_br(l2);
5482 gen_set_label(l1);
5483 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5484 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
5485 gen_set_label(l2);
5487 break;
5488 #if defined(TARGET_MIPS64)
5489 case OPC_DMULT_G_2E:
5490 case OPC_DMULT_G_2F:
5491 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5492 break;
5493 case OPC_DMULTU_G_2E:
5494 case OPC_DMULTU_G_2F:
5495 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
5496 break;
5497 case OPC_DDIV_G_2E:
5498 case OPC_DDIV_G_2F:
5500 TCGLabel *l1 = gen_new_label();
5501 TCGLabel *l2 = gen_new_label();
5502 TCGLabel *l3 = gen_new_label();
5503 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5504 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5505 tcg_gen_br(l3);
5506 gen_set_label(l1);
5507 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5508 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5509 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5510 tcg_gen_br(l3);
5511 gen_set_label(l2);
5512 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
5513 gen_set_label(l3);
5515 break;
5516 case OPC_DDIVU_G_2E:
5517 case OPC_DDIVU_G_2F:
5519 TCGLabel *l1 = gen_new_label();
5520 TCGLabel *l2 = gen_new_label();
5521 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5522 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5523 tcg_gen_br(l2);
5524 gen_set_label(l1);
5525 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
5526 gen_set_label(l2);
5528 break;
5529 case OPC_DMOD_G_2E:
5530 case OPC_DMOD_G_2F:
5532 TCGLabel *l1 = gen_new_label();
5533 TCGLabel *l2 = gen_new_label();
5534 TCGLabel *l3 = gen_new_label();
5535 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
5536 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
5537 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
5538 gen_set_label(l1);
5539 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5540 tcg_gen_br(l3);
5541 gen_set_label(l2);
5542 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
5543 gen_set_label(l3);
5545 break;
5546 case OPC_DMODU_G_2E:
5547 case OPC_DMODU_G_2F:
5549 TCGLabel *l1 = gen_new_label();
5550 TCGLabel *l2 = gen_new_label();
5551 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
5552 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5553 tcg_gen_br(l2);
5554 gen_set_label(l1);
5555 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
5556 gen_set_label(l2);
5558 break;
5559 #endif
5562 tcg_temp_free(t0);
5563 tcg_temp_free(t1);
5566 /* Loongson multimedia instructions */
5567 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
5569 uint32_t opc, shift_max;
5570 TCGv_i64 t0, t1;
5571 TCGCond cond;
5573 opc = MASK_LMMI(ctx->opcode);
5574 switch (opc) {
5575 case OPC_ADD_CP2:
5576 case OPC_SUB_CP2:
5577 case OPC_DADD_CP2:
5578 case OPC_DSUB_CP2:
5579 t0 = tcg_temp_local_new_i64();
5580 t1 = tcg_temp_local_new_i64();
5581 break;
5582 default:
5583 t0 = tcg_temp_new_i64();
5584 t1 = tcg_temp_new_i64();
5585 break;
5588 check_cp1_enabled(ctx);
5589 gen_load_fpr64(ctx, t0, rs);
5590 gen_load_fpr64(ctx, t1, rt);
5592 switch (opc) {
5593 case OPC_PADDSH:
5594 gen_helper_paddsh(t0, t0, t1);
5595 break;
5596 case OPC_PADDUSH:
5597 gen_helper_paddush(t0, t0, t1);
5598 break;
5599 case OPC_PADDH:
5600 gen_helper_paddh(t0, t0, t1);
5601 break;
5602 case OPC_PADDW:
5603 gen_helper_paddw(t0, t0, t1);
5604 break;
5605 case OPC_PADDSB:
5606 gen_helper_paddsb(t0, t0, t1);
5607 break;
5608 case OPC_PADDUSB:
5609 gen_helper_paddusb(t0, t0, t1);
5610 break;
5611 case OPC_PADDB:
5612 gen_helper_paddb(t0, t0, t1);
5613 break;
5615 case OPC_PSUBSH:
5616 gen_helper_psubsh(t0, t0, t1);
5617 break;
5618 case OPC_PSUBUSH:
5619 gen_helper_psubush(t0, t0, t1);
5620 break;
5621 case OPC_PSUBH:
5622 gen_helper_psubh(t0, t0, t1);
5623 break;
5624 case OPC_PSUBW:
5625 gen_helper_psubw(t0, t0, t1);
5626 break;
5627 case OPC_PSUBSB:
5628 gen_helper_psubsb(t0, t0, t1);
5629 break;
5630 case OPC_PSUBUSB:
5631 gen_helper_psubusb(t0, t0, t1);
5632 break;
5633 case OPC_PSUBB:
5634 gen_helper_psubb(t0, t0, t1);
5635 break;
5637 case OPC_PSHUFH:
5638 gen_helper_pshufh(t0, t0, t1);
5639 break;
5640 case OPC_PACKSSWH:
5641 gen_helper_packsswh(t0, t0, t1);
5642 break;
5643 case OPC_PACKSSHB:
5644 gen_helper_packsshb(t0, t0, t1);
5645 break;
5646 case OPC_PACKUSHB:
5647 gen_helper_packushb(t0, t0, t1);
5648 break;
5650 case OPC_PUNPCKLHW:
5651 gen_helper_punpcklhw(t0, t0, t1);
5652 break;
5653 case OPC_PUNPCKHHW:
5654 gen_helper_punpckhhw(t0, t0, t1);
5655 break;
5656 case OPC_PUNPCKLBH:
5657 gen_helper_punpcklbh(t0, t0, t1);
5658 break;
5659 case OPC_PUNPCKHBH:
5660 gen_helper_punpckhbh(t0, t0, t1);
5661 break;
5662 case OPC_PUNPCKLWD:
5663 gen_helper_punpcklwd(t0, t0, t1);
5664 break;
5665 case OPC_PUNPCKHWD:
5666 gen_helper_punpckhwd(t0, t0, t1);
5667 break;
5669 case OPC_PAVGH:
5670 gen_helper_pavgh(t0, t0, t1);
5671 break;
5672 case OPC_PAVGB:
5673 gen_helper_pavgb(t0, t0, t1);
5674 break;
5675 case OPC_PMAXSH:
5676 gen_helper_pmaxsh(t0, t0, t1);
5677 break;
5678 case OPC_PMINSH:
5679 gen_helper_pminsh(t0, t0, t1);
5680 break;
5681 case OPC_PMAXUB:
5682 gen_helper_pmaxub(t0, t0, t1);
5683 break;
5684 case OPC_PMINUB:
5685 gen_helper_pminub(t0, t0, t1);
5686 break;
5688 case OPC_PCMPEQW:
5689 gen_helper_pcmpeqw(t0, t0, t1);
5690 break;
5691 case OPC_PCMPGTW:
5692 gen_helper_pcmpgtw(t0, t0, t1);
5693 break;
5694 case OPC_PCMPEQH:
5695 gen_helper_pcmpeqh(t0, t0, t1);
5696 break;
5697 case OPC_PCMPGTH:
5698 gen_helper_pcmpgth(t0, t0, t1);
5699 break;
5700 case OPC_PCMPEQB:
5701 gen_helper_pcmpeqb(t0, t0, t1);
5702 break;
5703 case OPC_PCMPGTB:
5704 gen_helper_pcmpgtb(t0, t0, t1);
5705 break;
5707 case OPC_PSLLW:
5708 gen_helper_psllw(t0, t0, t1);
5709 break;
5710 case OPC_PSLLH:
5711 gen_helper_psllh(t0, t0, t1);
5712 break;
5713 case OPC_PSRLW:
5714 gen_helper_psrlw(t0, t0, t1);
5715 break;
5716 case OPC_PSRLH:
5717 gen_helper_psrlh(t0, t0, t1);
5718 break;
5719 case OPC_PSRAW:
5720 gen_helper_psraw(t0, t0, t1);
5721 break;
5722 case OPC_PSRAH:
5723 gen_helper_psrah(t0, t0, t1);
5724 break;
5726 case OPC_PMULLH:
5727 gen_helper_pmullh(t0, t0, t1);
5728 break;
5729 case OPC_PMULHH:
5730 gen_helper_pmulhh(t0, t0, t1);
5731 break;
5732 case OPC_PMULHUH:
5733 gen_helper_pmulhuh(t0, t0, t1);
5734 break;
5735 case OPC_PMADDHW:
5736 gen_helper_pmaddhw(t0, t0, t1);
5737 break;
5739 case OPC_PASUBUB:
5740 gen_helper_pasubub(t0, t0, t1);
5741 break;
5742 case OPC_BIADD:
5743 gen_helper_biadd(t0, t0);
5744 break;
5745 case OPC_PMOVMSKB:
5746 gen_helper_pmovmskb(t0, t0);
5747 break;
5749 case OPC_PADDD:
5750 tcg_gen_add_i64(t0, t0, t1);
5751 break;
5752 case OPC_PSUBD:
5753 tcg_gen_sub_i64(t0, t0, t1);
5754 break;
5755 case OPC_XOR_CP2:
5756 tcg_gen_xor_i64(t0, t0, t1);
5757 break;
5758 case OPC_NOR_CP2:
5759 tcg_gen_nor_i64(t0, t0, t1);
5760 break;
5761 case OPC_AND_CP2:
5762 tcg_gen_and_i64(t0, t0, t1);
5763 break;
5764 case OPC_OR_CP2:
5765 tcg_gen_or_i64(t0, t0, t1);
5766 break;
5768 case OPC_PANDN:
5769 tcg_gen_andc_i64(t0, t1, t0);
5770 break;
5772 case OPC_PINSRH_0:
5773 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
5774 break;
5775 case OPC_PINSRH_1:
5776 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
5777 break;
5778 case OPC_PINSRH_2:
5779 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
5780 break;
5781 case OPC_PINSRH_3:
5782 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
5783 break;
5785 case OPC_PEXTRH:
5786 tcg_gen_andi_i64(t1, t1, 3);
5787 tcg_gen_shli_i64(t1, t1, 4);
5788 tcg_gen_shr_i64(t0, t0, t1);
5789 tcg_gen_ext16u_i64(t0, t0);
5790 break;
5792 case OPC_ADDU_CP2:
5793 tcg_gen_add_i64(t0, t0, t1);
5794 tcg_gen_ext32s_i64(t0, t0);
5795 break;
5796 case OPC_SUBU_CP2:
5797 tcg_gen_sub_i64(t0, t0, t1);
5798 tcg_gen_ext32s_i64(t0, t0);
5799 break;
5801 case OPC_SLL_CP2:
5802 shift_max = 32;
5803 goto do_shift;
5804 case OPC_SRL_CP2:
5805 shift_max = 32;
5806 goto do_shift;
5807 case OPC_SRA_CP2:
5808 shift_max = 32;
5809 goto do_shift;
5810 case OPC_DSLL_CP2:
5811 shift_max = 64;
5812 goto do_shift;
5813 case OPC_DSRL_CP2:
5814 shift_max = 64;
5815 goto do_shift;
5816 case OPC_DSRA_CP2:
5817 shift_max = 64;
5818 goto do_shift;
5819 do_shift:
5820 /* Make sure shift count isn't TCG undefined behaviour. */
5821 tcg_gen_andi_i64(t1, t1, shift_max - 1);
5823 switch (opc) {
5824 case OPC_SLL_CP2:
5825 case OPC_DSLL_CP2:
5826 tcg_gen_shl_i64(t0, t0, t1);
5827 break;
5828 case OPC_SRA_CP2:
5829 case OPC_DSRA_CP2:
5831 * Since SRA is UndefinedResult without sign-extended inputs,
5832 * we can treat SRA and DSRA the same.
5834 tcg_gen_sar_i64(t0, t0, t1);
5835 break;
5836 case OPC_SRL_CP2:
5837 /* We want to shift in zeros for SRL; zero-extend first. */
5838 tcg_gen_ext32u_i64(t0, t0);
5839 /* FALLTHRU */
5840 case OPC_DSRL_CP2:
5841 tcg_gen_shr_i64(t0, t0, t1);
5842 break;
5845 if (shift_max == 32) {
5846 tcg_gen_ext32s_i64(t0, t0);
5849 /* Shifts larger than MAX produce zero. */
5850 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
5851 tcg_gen_neg_i64(t1, t1);
5852 tcg_gen_and_i64(t0, t0, t1);
5853 break;
5855 case OPC_ADD_CP2:
5856 case OPC_DADD_CP2:
5858 TCGv_i64 t2 = tcg_temp_new_i64();
5859 TCGLabel *lab = gen_new_label();
5861 tcg_gen_mov_i64(t2, t0);
5862 tcg_gen_add_i64(t0, t1, t2);
5863 if (opc == OPC_ADD_CP2) {
5864 tcg_gen_ext32s_i64(t0, t0);
5866 tcg_gen_xor_i64(t1, t1, t2);
5867 tcg_gen_xor_i64(t2, t2, t0);
5868 tcg_gen_andc_i64(t1, t2, t1);
5869 tcg_temp_free_i64(t2);
5870 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5871 generate_exception(ctx, EXCP_OVERFLOW);
5872 gen_set_label(lab);
5873 break;
5876 case OPC_SUB_CP2:
5877 case OPC_DSUB_CP2:
5879 TCGv_i64 t2 = tcg_temp_new_i64();
5880 TCGLabel *lab = gen_new_label();
5882 tcg_gen_mov_i64(t2, t0);
5883 tcg_gen_sub_i64(t0, t1, t2);
5884 if (opc == OPC_SUB_CP2) {
5885 tcg_gen_ext32s_i64(t0, t0);
5887 tcg_gen_xor_i64(t1, t1, t2);
5888 tcg_gen_xor_i64(t2, t2, t0);
5889 tcg_gen_and_i64(t1, t1, t2);
5890 tcg_temp_free_i64(t2);
5891 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
5892 generate_exception(ctx, EXCP_OVERFLOW);
5893 gen_set_label(lab);
5894 break;
5897 case OPC_PMULUW:
5898 tcg_gen_ext32u_i64(t0, t0);
5899 tcg_gen_ext32u_i64(t1, t1);
5900 tcg_gen_mul_i64(t0, t0, t1);
5901 break;
5903 case OPC_SEQU_CP2:
5904 case OPC_SEQ_CP2:
5905 cond = TCG_COND_EQ;
5906 goto do_cc_cond;
5907 break;
5908 case OPC_SLTU_CP2:
5909 cond = TCG_COND_LTU;
5910 goto do_cc_cond;
5911 break;
5912 case OPC_SLT_CP2:
5913 cond = TCG_COND_LT;
5914 goto do_cc_cond;
5915 break;
5916 case OPC_SLEU_CP2:
5917 cond = TCG_COND_LEU;
5918 goto do_cc_cond;
5919 break;
5920 case OPC_SLE_CP2:
5921 cond = TCG_COND_LE;
5922 do_cc_cond:
5924 int cc = (ctx->opcode >> 8) & 0x7;
5925 TCGv_i64 t64 = tcg_temp_new_i64();
5926 TCGv_i32 t32 = tcg_temp_new_i32();
5928 tcg_gen_setcond_i64(cond, t64, t0, t1);
5929 tcg_gen_extrl_i64_i32(t32, t64);
5930 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
5931 get_fp_bit(cc), 1);
5933 tcg_temp_free_i32(t32);
5934 tcg_temp_free_i64(t64);
5936 goto no_rd;
5937 break;
5938 default:
5939 MIPS_INVAL("loongson_cp2");
5940 generate_exception_end(ctx, EXCP_RI);
5941 return;
5944 gen_store_fpr64(ctx, t0, rd);
5946 no_rd:
5947 tcg_temp_free_i64(t0);
5948 tcg_temp_free_i64(t1);
5951 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
5952 int rs, int rd)
5954 TCGv t0, t1, t2;
5955 TCGv_i32 fp0;
5956 #if defined(TARGET_MIPS64)
5957 int lsq_rt1 = ctx->opcode & 0x1f;
5958 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
5959 #endif
5960 int shf_offset = sextract32(ctx->opcode, 6, 8);
5962 t0 = tcg_temp_new();
5964 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
5965 #if defined(TARGET_MIPS64)
5966 case OPC_GSLQ:
5967 t1 = tcg_temp_new();
5968 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5969 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5970 ctx->default_tcg_memop_mask);
5971 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5972 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5973 ctx->default_tcg_memop_mask);
5974 gen_store_gpr(t1, rt);
5975 gen_store_gpr(t0, lsq_rt1);
5976 tcg_temp_free(t1);
5977 break;
5978 case OPC_GSLQC1:
5979 check_cp1_enabled(ctx);
5980 t1 = tcg_temp_new();
5981 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5982 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5983 ctx->default_tcg_memop_mask);
5984 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5985 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
5986 ctx->default_tcg_memop_mask);
5987 gen_store_fpr64(ctx, t1, rt);
5988 gen_store_fpr64(ctx, t0, lsq_rt1);
5989 tcg_temp_free(t1);
5990 break;
5991 case OPC_GSSQ:
5992 t1 = tcg_temp_new();
5993 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
5994 gen_load_gpr(t1, rt);
5995 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
5996 ctx->default_tcg_memop_mask);
5997 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
5998 gen_load_gpr(t1, lsq_rt1);
5999 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6000 ctx->default_tcg_memop_mask);
6001 tcg_temp_free(t1);
6002 break;
6003 case OPC_GSSQC1:
6004 check_cp1_enabled(ctx);
6005 t1 = tcg_temp_new();
6006 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
6007 gen_load_fpr64(ctx, t1, rt);
6008 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6009 ctx->default_tcg_memop_mask);
6010 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
6011 gen_load_fpr64(ctx, t1, lsq_rt1);
6012 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6013 ctx->default_tcg_memop_mask);
6014 tcg_temp_free(t1);
6015 break;
6016 #endif
6017 case OPC_GSSHFL:
6018 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6019 case OPC_GSLWLC1:
6020 check_cp1_enabled(ctx);
6021 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6022 t1 = tcg_temp_new();
6023 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6024 tcg_gen_andi_tl(t1, t0, 3);
6025 #ifndef TARGET_WORDS_BIGENDIAN
6026 tcg_gen_xori_tl(t1, t1, 3);
6027 #endif
6028 tcg_gen_shli_tl(t1, t1, 3);
6029 tcg_gen_andi_tl(t0, t0, ~3);
6030 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
6031 tcg_gen_shl_tl(t0, t0, t1);
6032 t2 = tcg_const_tl(-1);
6033 tcg_gen_shl_tl(t2, t2, t1);
6034 fp0 = tcg_temp_new_i32();
6035 gen_load_fpr32(ctx, fp0, rt);
6036 tcg_gen_ext_i32_tl(t1, fp0);
6037 tcg_gen_andc_tl(t1, t1, t2);
6038 tcg_temp_free(t2);
6039 tcg_gen_or_tl(t0, t0, t1);
6040 tcg_temp_free(t1);
6041 #if defined(TARGET_MIPS64)
6042 tcg_gen_extrl_i64_i32(fp0, t0);
6043 #else
6044 tcg_gen_ext32s_tl(fp0, t0);
6045 #endif
6046 gen_store_fpr32(ctx, fp0, rt);
6047 tcg_temp_free_i32(fp0);
6048 break;
6049 case OPC_GSLWRC1:
6050 check_cp1_enabled(ctx);
6051 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6052 t1 = tcg_temp_new();
6053 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6054 tcg_gen_andi_tl(t1, t0, 3);
6055 #ifdef TARGET_WORDS_BIGENDIAN
6056 tcg_gen_xori_tl(t1, t1, 3);
6057 #endif
6058 tcg_gen_shli_tl(t1, t1, 3);
6059 tcg_gen_andi_tl(t0, t0, ~3);
6060 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
6061 tcg_gen_shr_tl(t0, t0, t1);
6062 tcg_gen_xori_tl(t1, t1, 31);
6063 t2 = tcg_const_tl(0xfffffffeull);
6064 tcg_gen_shl_tl(t2, t2, t1);
6065 fp0 = tcg_temp_new_i32();
6066 gen_load_fpr32(ctx, fp0, rt);
6067 tcg_gen_ext_i32_tl(t1, fp0);
6068 tcg_gen_and_tl(t1, t1, t2);
6069 tcg_temp_free(t2);
6070 tcg_gen_or_tl(t0, t0, t1);
6071 tcg_temp_free(t1);
6072 #if defined(TARGET_MIPS64)
6073 tcg_gen_extrl_i64_i32(fp0, t0);
6074 #else
6075 tcg_gen_ext32s_tl(fp0, t0);
6076 #endif
6077 gen_store_fpr32(ctx, fp0, rt);
6078 tcg_temp_free_i32(fp0);
6079 break;
6080 #if defined(TARGET_MIPS64)
6081 case OPC_GSLDLC1:
6082 check_cp1_enabled(ctx);
6083 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6084 t1 = tcg_temp_new();
6085 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6086 tcg_gen_andi_tl(t1, t0, 7);
6087 #ifndef TARGET_WORDS_BIGENDIAN
6088 tcg_gen_xori_tl(t1, t1, 7);
6089 #endif
6090 tcg_gen_shli_tl(t1, t1, 3);
6091 tcg_gen_andi_tl(t0, t0, ~7);
6092 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6093 tcg_gen_shl_tl(t0, t0, t1);
6094 t2 = tcg_const_tl(-1);
6095 tcg_gen_shl_tl(t2, t2, t1);
6096 gen_load_fpr64(ctx, t1, rt);
6097 tcg_gen_andc_tl(t1, t1, t2);
6098 tcg_temp_free(t2);
6099 tcg_gen_or_tl(t0, t0, t1);
6100 tcg_temp_free(t1);
6101 gen_store_fpr64(ctx, t0, rt);
6102 break;
6103 case OPC_GSLDRC1:
6104 check_cp1_enabled(ctx);
6105 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6106 t1 = tcg_temp_new();
6107 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
6108 tcg_gen_andi_tl(t1, t0, 7);
6109 #ifdef TARGET_WORDS_BIGENDIAN
6110 tcg_gen_xori_tl(t1, t1, 7);
6111 #endif
6112 tcg_gen_shli_tl(t1, t1, 3);
6113 tcg_gen_andi_tl(t0, t0, ~7);
6114 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
6115 tcg_gen_shr_tl(t0, t0, t1);
6116 tcg_gen_xori_tl(t1, t1, 63);
6117 t2 = tcg_const_tl(0xfffffffffffffffeull);
6118 tcg_gen_shl_tl(t2, t2, t1);
6119 gen_load_fpr64(ctx, t1, rt);
6120 tcg_gen_and_tl(t1, t1, t2);
6121 tcg_temp_free(t2);
6122 tcg_gen_or_tl(t0, t0, t1);
6123 tcg_temp_free(t1);
6124 gen_store_fpr64(ctx, t0, rt);
6125 break;
6126 #endif
6127 default:
6128 MIPS_INVAL("loongson_gsshfl");
6129 generate_exception_end(ctx, EXCP_RI);
6130 break;
6132 break;
6133 case OPC_GSSHFS:
6134 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
6135 case OPC_GSSWLC1:
6136 check_cp1_enabled(ctx);
6137 t1 = tcg_temp_new();
6138 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6139 fp0 = tcg_temp_new_i32();
6140 gen_load_fpr32(ctx, fp0, rt);
6141 tcg_gen_ext_i32_tl(t1, fp0);
6142 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
6143 tcg_temp_free_i32(fp0);
6144 tcg_temp_free(t1);
6145 break;
6146 case OPC_GSSWRC1:
6147 check_cp1_enabled(ctx);
6148 t1 = tcg_temp_new();
6149 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6150 fp0 = tcg_temp_new_i32();
6151 gen_load_fpr32(ctx, fp0, rt);
6152 tcg_gen_ext_i32_tl(t1, fp0);
6153 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
6154 tcg_temp_free_i32(fp0);
6155 tcg_temp_free(t1);
6156 break;
6157 #if defined(TARGET_MIPS64)
6158 case OPC_GSSDLC1:
6159 check_cp1_enabled(ctx);
6160 t1 = tcg_temp_new();
6161 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6162 gen_load_fpr64(ctx, t1, rt);
6163 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
6164 tcg_temp_free(t1);
6165 break;
6166 case OPC_GSSDRC1:
6167 check_cp1_enabled(ctx);
6168 t1 = tcg_temp_new();
6169 gen_base_offset_addr(ctx, t0, rs, shf_offset);
6170 gen_load_fpr64(ctx, t1, rt);
6171 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
6172 tcg_temp_free(t1);
6173 break;
6174 #endif
6175 default:
6176 MIPS_INVAL("loongson_gsshfs");
6177 generate_exception_end(ctx, EXCP_RI);
6178 break;
6180 break;
6181 default:
6182 MIPS_INVAL("loongson_gslsq");
6183 generate_exception_end(ctx, EXCP_RI);
6184 break;
6186 tcg_temp_free(t0);
6189 /* Loongson EXT LDC2/SDC2 */
6190 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
6191 int rs, int rd)
6193 int offset = sextract32(ctx->opcode, 3, 8);
6194 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
6195 TCGv t0, t1;
6196 TCGv_i32 fp0;
6198 /* Pre-conditions */
6199 switch (opc) {
6200 case OPC_GSLBX:
6201 case OPC_GSLHX:
6202 case OPC_GSLWX:
6203 case OPC_GSLDX:
6204 /* prefetch, implement as NOP */
6205 if (rt == 0) {
6206 return;
6208 break;
6209 case OPC_GSSBX:
6210 case OPC_GSSHX:
6211 case OPC_GSSWX:
6212 case OPC_GSSDX:
6213 break;
6214 case OPC_GSLWXC1:
6215 #if defined(TARGET_MIPS64)
6216 case OPC_GSLDXC1:
6217 #endif
6218 check_cp1_enabled(ctx);
6219 /* prefetch, implement as NOP */
6220 if (rt == 0) {
6221 return;
6223 break;
6224 case OPC_GSSWXC1:
6225 #if defined(TARGET_MIPS64)
6226 case OPC_GSSDXC1:
6227 #endif
6228 check_cp1_enabled(ctx);
6229 break;
6230 default:
6231 MIPS_INVAL("loongson_lsdc2");
6232 generate_exception_end(ctx, EXCP_RI);
6233 return;
6234 break;
6237 t0 = tcg_temp_new();
6239 gen_base_offset_addr(ctx, t0, rs, offset);
6240 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6242 switch (opc) {
6243 case OPC_GSLBX:
6244 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
6245 gen_store_gpr(t0, rt);
6246 break;
6247 case OPC_GSLHX:
6248 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
6249 ctx->default_tcg_memop_mask);
6250 gen_store_gpr(t0, rt);
6251 break;
6252 case OPC_GSLWX:
6253 gen_base_offset_addr(ctx, t0, rs, offset);
6254 if (rd) {
6255 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6257 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
6258 ctx->default_tcg_memop_mask);
6259 gen_store_gpr(t0, rt);
6260 break;
6261 #if defined(TARGET_MIPS64)
6262 case OPC_GSLDX:
6263 gen_base_offset_addr(ctx, t0, rs, offset);
6264 if (rd) {
6265 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6267 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6268 ctx->default_tcg_memop_mask);
6269 gen_store_gpr(t0, rt);
6270 break;
6271 #endif
6272 case OPC_GSLWXC1:
6273 check_cp1_enabled(ctx);
6274 gen_base_offset_addr(ctx, t0, rs, offset);
6275 if (rd) {
6276 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6278 fp0 = tcg_temp_new_i32();
6279 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
6280 ctx->default_tcg_memop_mask);
6281 gen_store_fpr32(ctx, fp0, rt);
6282 tcg_temp_free_i32(fp0);
6283 break;
6284 #if defined(TARGET_MIPS64)
6285 case OPC_GSLDXC1:
6286 check_cp1_enabled(ctx);
6287 gen_base_offset_addr(ctx, t0, rs, offset);
6288 if (rd) {
6289 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
6291 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
6292 ctx->default_tcg_memop_mask);
6293 gen_store_fpr64(ctx, t0, rt);
6294 break;
6295 #endif
6296 case OPC_GSSBX:
6297 t1 = tcg_temp_new();
6298 gen_load_gpr(t1, rt);
6299 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
6300 tcg_temp_free(t1);
6301 break;
6302 case OPC_GSSHX:
6303 t1 = tcg_temp_new();
6304 gen_load_gpr(t1, rt);
6305 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
6306 ctx->default_tcg_memop_mask);
6307 tcg_temp_free(t1);
6308 break;
6309 case OPC_GSSWX:
6310 t1 = tcg_temp_new();
6311 gen_load_gpr(t1, rt);
6312 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
6313 ctx->default_tcg_memop_mask);
6314 tcg_temp_free(t1);
6315 break;
6316 #if defined(TARGET_MIPS64)
6317 case OPC_GSSDX:
6318 t1 = tcg_temp_new();
6319 gen_load_gpr(t1, rt);
6320 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
6321 ctx->default_tcg_memop_mask);
6322 tcg_temp_free(t1);
6323 break;
6324 #endif
6325 case OPC_GSSWXC1:
6326 fp0 = tcg_temp_new_i32();
6327 gen_load_fpr32(ctx, fp0, rt);
6328 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
6329 ctx->default_tcg_memop_mask);
6330 tcg_temp_free_i32(fp0);
6331 break;
6332 #if defined(TARGET_MIPS64)
6333 case OPC_GSSDXC1:
6334 t1 = tcg_temp_new();
6335 gen_load_fpr64(ctx, t1, rt);
6336 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
6337 ctx->default_tcg_memop_mask);
6338 tcg_temp_free(t1);
6339 break;
6340 #endif
6341 default:
6342 break;
6345 tcg_temp_free(t0);
6348 /* Traps */
6349 static void gen_trap(DisasContext *ctx, uint32_t opc,
6350 int rs, int rt, int16_t imm)
6352 int cond;
6353 TCGv t0 = tcg_temp_new();
6354 TCGv t1 = tcg_temp_new();
6356 cond = 0;
6357 /* Load needed operands */
6358 switch (opc) {
6359 case OPC_TEQ:
6360 case OPC_TGE:
6361 case OPC_TGEU:
6362 case OPC_TLT:
6363 case OPC_TLTU:
6364 case OPC_TNE:
6365 /* Compare two registers */
6366 if (rs != rt) {
6367 gen_load_gpr(t0, rs);
6368 gen_load_gpr(t1, rt);
6369 cond = 1;
6371 break;
6372 case OPC_TEQI:
6373 case OPC_TGEI:
6374 case OPC_TGEIU:
6375 case OPC_TLTI:
6376 case OPC_TLTIU:
6377 case OPC_TNEI:
6378 /* Compare register to immediate */
6379 if (rs != 0 || imm != 0) {
6380 gen_load_gpr(t0, rs);
6381 tcg_gen_movi_tl(t1, (int32_t)imm);
6382 cond = 1;
6384 break;
6386 if (cond == 0) {
6387 switch (opc) {
6388 case OPC_TEQ: /* rs == rs */
6389 case OPC_TEQI: /* r0 == 0 */
6390 case OPC_TGE: /* rs >= rs */
6391 case OPC_TGEI: /* r0 >= 0 */
6392 case OPC_TGEU: /* rs >= rs unsigned */
6393 case OPC_TGEIU: /* r0 >= 0 unsigned */
6394 /* Always trap */
6395 generate_exception_end(ctx, EXCP_TRAP);
6396 break;
6397 case OPC_TLT: /* rs < rs */
6398 case OPC_TLTI: /* r0 < 0 */
6399 case OPC_TLTU: /* rs < rs unsigned */
6400 case OPC_TLTIU: /* r0 < 0 unsigned */
6401 case OPC_TNE: /* rs != rs */
6402 case OPC_TNEI: /* r0 != 0 */
6403 /* Never trap: treat as NOP. */
6404 break;
6406 } else {
6407 TCGLabel *l1 = gen_new_label();
6409 switch (opc) {
6410 case OPC_TEQ:
6411 case OPC_TEQI:
6412 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6413 break;
6414 case OPC_TGE:
6415 case OPC_TGEI:
6416 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6417 break;
6418 case OPC_TGEU:
6419 case OPC_TGEIU:
6420 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6421 break;
6422 case OPC_TLT:
6423 case OPC_TLTI:
6424 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6425 break;
6426 case OPC_TLTU:
6427 case OPC_TLTIU:
6428 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6429 break;
6430 case OPC_TNE:
6431 case OPC_TNEI:
6432 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6433 break;
6435 generate_exception(ctx, EXCP_TRAP);
6436 gen_set_label(l1);
6438 tcg_temp_free(t0);
6439 tcg_temp_free(t1);
6442 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
6444 if (unlikely(ctx->base.singlestep_enabled)) {
6445 return false;
6448 #ifndef CONFIG_USER_ONLY
6449 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
6450 #else
6451 return true;
6452 #endif
6455 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
6457 if (use_goto_tb(ctx, dest)) {
6458 tcg_gen_goto_tb(n);
6459 gen_save_pc(dest);
6460 tcg_gen_exit_tb(ctx->base.tb, n);
6461 } else {
6462 gen_save_pc(dest);
6463 if (ctx->base.singlestep_enabled) {
6464 save_cpu_state(ctx, 0);
6465 gen_helper_raise_exception_debug(cpu_env);
6467 tcg_gen_lookup_and_goto_ptr();
6471 /* Branches (before delay slot) */
6472 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
6473 int insn_bytes,
6474 int rs, int rt, int32_t offset,
6475 int delayslot_size)
6477 target_ulong btgt = -1;
6478 int blink = 0;
6479 int bcond_compute = 0;
6480 TCGv t0 = tcg_temp_new();
6481 TCGv t1 = tcg_temp_new();
6483 if (ctx->hflags & MIPS_HFLAG_BMASK) {
6484 #ifdef MIPS_DEBUG_DISAS
6485 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
6486 TARGET_FMT_lx "\n", ctx->base.pc_next);
6487 #endif
6488 generate_exception_end(ctx, EXCP_RI);
6489 goto out;
6492 /* Load needed operands */
6493 switch (opc) {
6494 case OPC_BEQ:
6495 case OPC_BEQL:
6496 case OPC_BNE:
6497 case OPC_BNEL:
6498 /* Compare two registers */
6499 if (rs != rt) {
6500 gen_load_gpr(t0, rs);
6501 gen_load_gpr(t1, rt);
6502 bcond_compute = 1;
6504 btgt = ctx->base.pc_next + insn_bytes + offset;
6505 break;
6506 case OPC_BGEZ:
6507 case OPC_BGEZAL:
6508 case OPC_BGEZALL:
6509 case OPC_BGEZL:
6510 case OPC_BGTZ:
6511 case OPC_BGTZL:
6512 case OPC_BLEZ:
6513 case OPC_BLEZL:
6514 case OPC_BLTZ:
6515 case OPC_BLTZAL:
6516 case OPC_BLTZALL:
6517 case OPC_BLTZL:
6518 /* Compare to zero */
6519 if (rs != 0) {
6520 gen_load_gpr(t0, rs);
6521 bcond_compute = 1;
6523 btgt = ctx->base.pc_next + insn_bytes + offset;
6524 break;
6525 case OPC_BPOSGE32:
6526 #if defined(TARGET_MIPS64)
6527 case OPC_BPOSGE64:
6528 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
6529 #else
6530 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6531 #endif
6532 bcond_compute = 1;
6533 btgt = ctx->base.pc_next + insn_bytes + offset;
6534 break;
6535 case OPC_J:
6536 case OPC_JAL:
6537 case OPC_JALX:
6538 /* Jump to immediate */
6539 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
6540 (uint32_t)offset;
6541 break;
6542 case OPC_JR:
6543 case OPC_JALR:
6544 /* Jump to register */
6545 if (offset != 0 && offset != 16) {
6547 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6548 * others are reserved.
6550 MIPS_INVAL("jump hint");
6551 generate_exception_end(ctx, EXCP_RI);
6552 goto out;
6554 gen_load_gpr(btarget, rs);
6555 break;
6556 default:
6557 MIPS_INVAL("branch/jump");
6558 generate_exception_end(ctx, EXCP_RI);
6559 goto out;
6561 if (bcond_compute == 0) {
6562 /* No condition to be computed */
6563 switch (opc) {
6564 case OPC_BEQ: /* rx == rx */
6565 case OPC_BEQL: /* rx == rx likely */
6566 case OPC_BGEZ: /* 0 >= 0 */
6567 case OPC_BGEZL: /* 0 >= 0 likely */
6568 case OPC_BLEZ: /* 0 <= 0 */
6569 case OPC_BLEZL: /* 0 <= 0 likely */
6570 /* Always take */
6571 ctx->hflags |= MIPS_HFLAG_B;
6572 break;
6573 case OPC_BGEZAL: /* 0 >= 0 */
6574 case OPC_BGEZALL: /* 0 >= 0 likely */
6575 /* Always take and link */
6576 blink = 31;
6577 ctx->hflags |= MIPS_HFLAG_B;
6578 break;
6579 case OPC_BNE: /* rx != rx */
6580 case OPC_BGTZ: /* 0 > 0 */
6581 case OPC_BLTZ: /* 0 < 0 */
6582 /* Treat as NOP. */
6583 goto out;
6584 case OPC_BLTZAL: /* 0 < 0 */
6586 * Handle as an unconditional branch to get correct delay
6587 * slot checking.
6589 blink = 31;
6590 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
6591 ctx->hflags |= MIPS_HFLAG_B;
6592 break;
6593 case OPC_BLTZALL: /* 0 < 0 likely */
6594 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6595 /* Skip the instruction in the delay slot */
6596 ctx->base.pc_next += 4;
6597 goto out;
6598 case OPC_BNEL: /* rx != rx likely */
6599 case OPC_BGTZL: /* 0 > 0 likely */
6600 case OPC_BLTZL: /* 0 < 0 likely */
6601 /* Skip the instruction in the delay slot */
6602 ctx->base.pc_next += 4;
6603 goto out;
6604 case OPC_J:
6605 ctx->hflags |= MIPS_HFLAG_B;
6606 break;
6607 case OPC_JALX:
6608 ctx->hflags |= MIPS_HFLAG_BX;
6609 /* Fallthrough */
6610 case OPC_JAL:
6611 blink = 31;
6612 ctx->hflags |= MIPS_HFLAG_B;
6613 break;
6614 case OPC_JR:
6615 ctx->hflags |= MIPS_HFLAG_BR;
6616 break;
6617 case OPC_JALR:
6618 blink = rt;
6619 ctx->hflags |= MIPS_HFLAG_BR;
6620 break;
6621 default:
6622 MIPS_INVAL("branch/jump");
6623 generate_exception_end(ctx, EXCP_RI);
6624 goto out;
6626 } else {
6627 switch (opc) {
6628 case OPC_BEQ:
6629 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6630 goto not_likely;
6631 case OPC_BEQL:
6632 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6633 goto likely;
6634 case OPC_BNE:
6635 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6636 goto not_likely;
6637 case OPC_BNEL:
6638 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6639 goto likely;
6640 case OPC_BGEZ:
6641 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6642 goto not_likely;
6643 case OPC_BGEZL:
6644 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6645 goto likely;
6646 case OPC_BGEZAL:
6647 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6648 blink = 31;
6649 goto not_likely;
6650 case OPC_BGEZALL:
6651 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6652 blink = 31;
6653 goto likely;
6654 case OPC_BGTZ:
6655 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6656 goto not_likely;
6657 case OPC_BGTZL:
6658 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
6659 goto likely;
6660 case OPC_BLEZ:
6661 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6662 goto not_likely;
6663 case OPC_BLEZL:
6664 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
6665 goto likely;
6666 case OPC_BLTZ:
6667 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6668 goto not_likely;
6669 case OPC_BLTZL:
6670 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6671 goto likely;
6672 case OPC_BPOSGE32:
6673 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6674 goto not_likely;
6675 #if defined(TARGET_MIPS64)
6676 case OPC_BPOSGE64:
6677 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
6678 goto not_likely;
6679 #endif
6680 case OPC_BLTZAL:
6681 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6682 blink = 31;
6683 not_likely:
6684 ctx->hflags |= MIPS_HFLAG_BC;
6685 break;
6686 case OPC_BLTZALL:
6687 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6688 blink = 31;
6689 likely:
6690 ctx->hflags |= MIPS_HFLAG_BL;
6691 break;
6692 default:
6693 MIPS_INVAL("conditional branch/jump");
6694 generate_exception_end(ctx, EXCP_RI);
6695 goto out;
6699 ctx->btarget = btgt;
6701 switch (delayslot_size) {
6702 case 2:
6703 ctx->hflags |= MIPS_HFLAG_BDS16;
6704 break;
6705 case 4:
6706 ctx->hflags |= MIPS_HFLAG_BDS32;
6707 break;
6710 if (blink > 0) {
6711 int post_delay = insn_bytes + delayslot_size;
6712 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
6714 tcg_gen_movi_tl(cpu_gpr[blink],
6715 ctx->base.pc_next + post_delay + lowbit);
6718 out:
6719 if (insn_bytes == 2) {
6720 ctx->hflags |= MIPS_HFLAG_B16;
6722 tcg_temp_free(t0);
6723 tcg_temp_free(t1);
6727 /* nanoMIPS Branches */
6728 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
6729 int insn_bytes,
6730 int rs, int rt, int32_t offset)
6732 target_ulong btgt = -1;
6733 int bcond_compute = 0;
6734 TCGv t0 = tcg_temp_new();
6735 TCGv t1 = tcg_temp_new();
6737 /* Load needed operands */
6738 switch (opc) {
6739 case OPC_BEQ:
6740 case OPC_BNE:
6741 /* Compare two registers */
6742 if (rs != rt) {
6743 gen_load_gpr(t0, rs);
6744 gen_load_gpr(t1, rt);
6745 bcond_compute = 1;
6747 btgt = ctx->base.pc_next + insn_bytes + offset;
6748 break;
6749 case OPC_BGEZAL:
6750 /* Compare to zero */
6751 if (rs != 0) {
6752 gen_load_gpr(t0, rs);
6753 bcond_compute = 1;
6755 btgt = ctx->base.pc_next + insn_bytes + offset;
6756 break;
6757 case OPC_BPOSGE32:
6758 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
6759 bcond_compute = 1;
6760 btgt = ctx->base.pc_next + insn_bytes + offset;
6761 break;
6762 case OPC_JR:
6763 case OPC_JALR:
6764 /* Jump to register */
6765 if (offset != 0 && offset != 16) {
6767 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
6768 * others are reserved.
6770 MIPS_INVAL("jump hint");
6771 generate_exception_end(ctx, EXCP_RI);
6772 goto out;
6774 gen_load_gpr(btarget, rs);
6775 break;
6776 default:
6777 MIPS_INVAL("branch/jump");
6778 generate_exception_end(ctx, EXCP_RI);
6779 goto out;
6781 if (bcond_compute == 0) {
6782 /* No condition to be computed */
6783 switch (opc) {
6784 case OPC_BEQ: /* rx == rx */
6785 /* Always take */
6786 ctx->hflags |= MIPS_HFLAG_B;
6787 break;
6788 case OPC_BGEZAL: /* 0 >= 0 */
6789 /* Always take and link */
6790 tcg_gen_movi_tl(cpu_gpr[31],
6791 ctx->base.pc_next + insn_bytes);
6792 ctx->hflags |= MIPS_HFLAG_B;
6793 break;
6794 case OPC_BNE: /* rx != rx */
6795 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
6796 /* Skip the instruction in the delay slot */
6797 ctx->base.pc_next += 4;
6798 goto out;
6799 case OPC_JR:
6800 ctx->hflags |= MIPS_HFLAG_BR;
6801 break;
6802 case OPC_JALR:
6803 if (rt > 0) {
6804 tcg_gen_movi_tl(cpu_gpr[rt],
6805 ctx->base.pc_next + insn_bytes);
6807 ctx->hflags |= MIPS_HFLAG_BR;
6808 break;
6809 default:
6810 MIPS_INVAL("branch/jump");
6811 generate_exception_end(ctx, EXCP_RI);
6812 goto out;
6814 } else {
6815 switch (opc) {
6816 case OPC_BEQ:
6817 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
6818 goto not_likely;
6819 case OPC_BNE:
6820 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
6821 goto not_likely;
6822 case OPC_BGEZAL:
6823 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6824 tcg_gen_movi_tl(cpu_gpr[31],
6825 ctx->base.pc_next + insn_bytes);
6826 goto not_likely;
6827 case OPC_BPOSGE32:
6828 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
6829 not_likely:
6830 ctx->hflags |= MIPS_HFLAG_BC;
6831 break;
6832 default:
6833 MIPS_INVAL("conditional branch/jump");
6834 generate_exception_end(ctx, EXCP_RI);
6835 goto out;
6839 ctx->btarget = btgt;
6841 out:
6842 if (insn_bytes == 2) {
6843 ctx->hflags |= MIPS_HFLAG_B16;
6845 tcg_temp_free(t0);
6846 tcg_temp_free(t1);
6850 /* special3 bitfield operations */
6851 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
6852 int rs, int lsb, int msb)
6854 TCGv t0 = tcg_temp_new();
6855 TCGv t1 = tcg_temp_new();
6857 gen_load_gpr(t1, rs);
6858 switch (opc) {
6859 case OPC_EXT:
6860 if (lsb + msb > 31) {
6861 goto fail;
6863 if (msb != 31) {
6864 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6865 } else {
6867 * The two checks together imply that lsb == 0,
6868 * so this is a simple sign-extension.
6870 tcg_gen_ext32s_tl(t0, t1);
6872 break;
6873 #if defined(TARGET_MIPS64)
6874 case OPC_DEXTU:
6875 lsb += 32;
6876 goto do_dext;
6877 case OPC_DEXTM:
6878 msb += 32;
6879 goto do_dext;
6880 case OPC_DEXT:
6881 do_dext:
6882 if (lsb + msb > 63) {
6883 goto fail;
6885 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
6886 break;
6887 #endif
6888 case OPC_INS:
6889 if (lsb > msb) {
6890 goto fail;
6892 gen_load_gpr(t0, rt);
6893 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6894 tcg_gen_ext32s_tl(t0, t0);
6895 break;
6896 #if defined(TARGET_MIPS64)
6897 case OPC_DINSU:
6898 lsb += 32;
6899 /* FALLTHRU */
6900 case OPC_DINSM:
6901 msb += 32;
6902 /* FALLTHRU */
6903 case OPC_DINS:
6904 if (lsb > msb) {
6905 goto fail;
6907 gen_load_gpr(t0, rt);
6908 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
6909 break;
6910 #endif
6911 default:
6912 fail:
6913 MIPS_INVAL("bitops");
6914 generate_exception_end(ctx, EXCP_RI);
6915 tcg_temp_free(t0);
6916 tcg_temp_free(t1);
6917 return;
6919 gen_store_gpr(t0, rt);
6920 tcg_temp_free(t0);
6921 tcg_temp_free(t1);
6924 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
6926 TCGv t0;
6928 if (rd == 0) {
6929 /* If no destination, treat it as a NOP. */
6930 return;
6933 t0 = tcg_temp_new();
6934 gen_load_gpr(t0, rt);
6935 switch (op2) {
6936 case OPC_WSBH:
6938 TCGv t1 = tcg_temp_new();
6939 TCGv t2 = tcg_const_tl(0x00FF00FF);
6941 tcg_gen_shri_tl(t1, t0, 8);
6942 tcg_gen_and_tl(t1, t1, t2);
6943 tcg_gen_and_tl(t0, t0, t2);
6944 tcg_gen_shli_tl(t0, t0, 8);
6945 tcg_gen_or_tl(t0, t0, t1);
6946 tcg_temp_free(t2);
6947 tcg_temp_free(t1);
6948 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6950 break;
6951 case OPC_SEB:
6952 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
6953 break;
6954 case OPC_SEH:
6955 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
6956 break;
6957 #if defined(TARGET_MIPS64)
6958 case OPC_DSBH:
6960 TCGv t1 = tcg_temp_new();
6961 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
6963 tcg_gen_shri_tl(t1, t0, 8);
6964 tcg_gen_and_tl(t1, t1, t2);
6965 tcg_gen_and_tl(t0, t0, t2);
6966 tcg_gen_shli_tl(t0, t0, 8);
6967 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6968 tcg_temp_free(t2);
6969 tcg_temp_free(t1);
6971 break;
6972 case OPC_DSHD:
6974 TCGv t1 = tcg_temp_new();
6975 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
6977 tcg_gen_shri_tl(t1, t0, 16);
6978 tcg_gen_and_tl(t1, t1, t2);
6979 tcg_gen_and_tl(t0, t0, t2);
6980 tcg_gen_shli_tl(t0, t0, 16);
6981 tcg_gen_or_tl(t0, t0, t1);
6982 tcg_gen_shri_tl(t1, t0, 32);
6983 tcg_gen_shli_tl(t0, t0, 32);
6984 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
6985 tcg_temp_free(t2);
6986 tcg_temp_free(t1);
6988 break;
6989 #endif
6990 default:
6991 MIPS_INVAL("bsfhl");
6992 generate_exception_end(ctx, EXCP_RI);
6993 tcg_temp_free(t0);
6994 return;
6996 tcg_temp_free(t0);
6999 static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
7000 int imm2)
7002 TCGv t0;
7003 TCGv t1;
7004 if (rd == 0) {
7005 /* Treat as NOP. */
7006 return;
7008 t0 = tcg_temp_new();
7009 t1 = tcg_temp_new();
7010 gen_load_gpr(t0, rs);
7011 gen_load_gpr(t1, rt);
7012 tcg_gen_shli_tl(t0, t0, imm2 + 1);
7013 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
7014 if (opc == OPC_LSA) {
7015 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
7018 tcg_temp_free(t1);
7019 tcg_temp_free(t0);
7021 return;
7024 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
7025 int rt, int bits)
7027 TCGv t0;
7028 if (rd == 0) {
7029 /* Treat as NOP. */
7030 return;
7032 t0 = tcg_temp_new();
7033 if (bits == 0 || bits == wordsz) {
7034 if (bits == 0) {
7035 gen_load_gpr(t0, rt);
7036 } else {
7037 gen_load_gpr(t0, rs);
7039 switch (wordsz) {
7040 case 32:
7041 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
7042 break;
7043 #if defined(TARGET_MIPS64)
7044 case 64:
7045 tcg_gen_mov_tl(cpu_gpr[rd], t0);
7046 break;
7047 #endif
7049 } else {
7050 TCGv t1 = tcg_temp_new();
7051 gen_load_gpr(t0, rt);
7052 gen_load_gpr(t1, rs);
7053 switch (wordsz) {
7054 case 32:
7056 TCGv_i64 t2 = tcg_temp_new_i64();
7057 tcg_gen_concat_tl_i64(t2, t1, t0);
7058 tcg_gen_shri_i64(t2, t2, 32 - bits);
7059 gen_move_low32(cpu_gpr[rd], t2);
7060 tcg_temp_free_i64(t2);
7062 break;
7063 #if defined(TARGET_MIPS64)
7064 case 64:
7065 tcg_gen_shli_tl(t0, t0, bits);
7066 tcg_gen_shri_tl(t1, t1, 64 - bits);
7067 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
7068 break;
7069 #endif
7071 tcg_temp_free(t1);
7074 tcg_temp_free(t0);
7077 static void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7078 int bp)
7080 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
7083 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
7084 int shift)
7086 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
7089 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
7091 TCGv t0;
7092 if (rd == 0) {
7093 /* Treat as NOP. */
7094 return;
7096 t0 = tcg_temp_new();
7097 gen_load_gpr(t0, rt);
7098 switch (opc) {
7099 case OPC_BITSWAP:
7100 gen_helper_bitswap(cpu_gpr[rd], t0);
7101 break;
7102 #if defined(TARGET_MIPS64)
7103 case OPC_DBITSWAP:
7104 gen_helper_dbitswap(cpu_gpr[rd], t0);
7105 break;
7106 #endif
7108 tcg_temp_free(t0);
7111 #ifndef CONFIG_USER_ONLY
7112 /* CP0 (MMU and control) */
7113 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
7115 TCGv_i64 t0 = tcg_temp_new_i64();
7116 TCGv_i64 t1 = tcg_temp_new_i64();
7118 tcg_gen_ext_tl_i64(t0, arg);
7119 tcg_gen_ld_i64(t1, cpu_env, off);
7120 #if defined(TARGET_MIPS64)
7121 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
7122 #else
7123 tcg_gen_concat32_i64(t1, t1, t0);
7124 #endif
7125 tcg_gen_st_i64(t1, cpu_env, off);
7126 tcg_temp_free_i64(t1);
7127 tcg_temp_free_i64(t0);
7130 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
7132 TCGv_i64 t0 = tcg_temp_new_i64();
7133 TCGv_i64 t1 = tcg_temp_new_i64();
7135 tcg_gen_ext_tl_i64(t0, arg);
7136 tcg_gen_ld_i64(t1, cpu_env, off);
7137 tcg_gen_concat32_i64(t1, t1, t0);
7138 tcg_gen_st_i64(t1, cpu_env, off);
7139 tcg_temp_free_i64(t1);
7140 tcg_temp_free_i64(t0);
7143 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
7145 TCGv_i64 t0 = tcg_temp_new_i64();
7147 tcg_gen_ld_i64(t0, cpu_env, off);
7148 #if defined(TARGET_MIPS64)
7149 tcg_gen_shri_i64(t0, t0, 30);
7150 #else
7151 tcg_gen_shri_i64(t0, t0, 32);
7152 #endif
7153 gen_move_low32(arg, t0);
7154 tcg_temp_free_i64(t0);
7157 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
7159 TCGv_i64 t0 = tcg_temp_new_i64();
7161 tcg_gen_ld_i64(t0, cpu_env, off);
7162 tcg_gen_shri_i64(t0, t0, 32 + shift);
7163 gen_move_low32(arg, t0);
7164 tcg_temp_free_i64(t0);
7167 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
7169 TCGv_i32 t0 = tcg_temp_new_i32();
7171 tcg_gen_ld_i32(t0, cpu_env, off);
7172 tcg_gen_ext_i32_tl(arg, t0);
7173 tcg_temp_free_i32(t0);
7176 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
7178 tcg_gen_ld_tl(arg, cpu_env, off);
7179 tcg_gen_ext32s_tl(arg, arg);
7182 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
7184 TCGv_i32 t0 = tcg_temp_new_i32();
7186 tcg_gen_trunc_tl_i32(t0, arg);
7187 tcg_gen_st_i32(t0, cpu_env, off);
7188 tcg_temp_free_i32(t0);
7191 #define CP0_CHECK(c) \
7192 do { \
7193 if (!(c)) { \
7194 goto cp0_unimplemented; \
7196 } while (0)
7198 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7200 const char *register_name = "invalid";
7202 switch (reg) {
7203 case CP0_REGISTER_02:
7204 switch (sel) {
7205 case 0:
7206 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7207 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7208 register_name = "EntryLo0";
7209 break;
7210 default:
7211 goto cp0_unimplemented;
7213 break;
7214 case CP0_REGISTER_03:
7215 switch (sel) {
7216 case CP0_REG03__ENTRYLO1:
7217 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7218 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7219 register_name = "EntryLo1";
7220 break;
7221 default:
7222 goto cp0_unimplemented;
7224 break;
7225 case CP0_REGISTER_09:
7226 switch (sel) {
7227 case CP0_REG09__SAAR:
7228 CP0_CHECK(ctx->saar);
7229 gen_helper_mfhc0_saar(arg, cpu_env);
7230 register_name = "SAAR";
7231 break;
7232 default:
7233 goto cp0_unimplemented;
7235 break;
7236 case CP0_REGISTER_17:
7237 switch (sel) {
7238 case CP0_REG17__LLADDR:
7239 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
7240 ctx->CP0_LLAddr_shift);
7241 register_name = "LLAddr";
7242 break;
7243 case CP0_REG17__MAAR:
7244 CP0_CHECK(ctx->mrp);
7245 gen_helper_mfhc0_maar(arg, cpu_env);
7246 register_name = "MAAR";
7247 break;
7248 default:
7249 goto cp0_unimplemented;
7251 break;
7252 case CP0_REGISTER_19:
7253 switch (sel) {
7254 case CP0_REG19__WATCHHI0:
7255 case CP0_REG19__WATCHHI1:
7256 case CP0_REG19__WATCHHI2:
7257 case CP0_REG19__WATCHHI3:
7258 case CP0_REG19__WATCHHI4:
7259 case CP0_REG19__WATCHHI5:
7260 case CP0_REG19__WATCHHI6:
7261 case CP0_REG19__WATCHHI7:
7262 /* upper 32 bits are only available when Config5MI != 0 */
7263 CP0_CHECK(ctx->mi);
7264 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
7265 register_name = "WatchHi";
7266 break;
7267 default:
7268 goto cp0_unimplemented;
7270 break;
7271 case CP0_REGISTER_28:
7272 switch (sel) {
7273 case 0:
7274 case 2:
7275 case 4:
7276 case 6:
7277 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
7278 register_name = "TagLo";
7279 break;
7280 default:
7281 goto cp0_unimplemented;
7283 break;
7284 default:
7285 goto cp0_unimplemented;
7287 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
7288 return;
7290 cp0_unimplemented:
7291 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
7292 register_name, reg, sel);
7293 tcg_gen_movi_tl(arg, 0);
7296 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7298 const char *register_name = "invalid";
7299 uint64_t mask = ctx->PAMask >> 36;
7301 switch (reg) {
7302 case CP0_REGISTER_02:
7303 switch (sel) {
7304 case 0:
7305 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7306 tcg_gen_andi_tl(arg, arg, mask);
7307 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
7308 register_name = "EntryLo0";
7309 break;
7310 default:
7311 goto cp0_unimplemented;
7313 break;
7314 case CP0_REGISTER_03:
7315 switch (sel) {
7316 case CP0_REG03__ENTRYLO1:
7317 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
7318 tcg_gen_andi_tl(arg, arg, mask);
7319 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
7320 register_name = "EntryLo1";
7321 break;
7322 default:
7323 goto cp0_unimplemented;
7325 break;
7326 case CP0_REGISTER_09:
7327 switch (sel) {
7328 case CP0_REG09__SAAR:
7329 CP0_CHECK(ctx->saar);
7330 gen_helper_mthc0_saar(cpu_env, arg);
7331 register_name = "SAAR";
7332 break;
7333 default:
7334 goto cp0_unimplemented;
7336 break;
7337 case CP0_REGISTER_17:
7338 switch (sel) {
7339 case CP0_REG17__LLADDR:
7341 * LLAddr is read-only (the only exception is bit 0 if LLB is
7342 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
7343 * relevant for modern MIPS cores supporting MTHC0, therefore
7344 * treating MTHC0 to LLAddr as NOP.
7346 register_name = "LLAddr";
7347 break;
7348 case CP0_REG17__MAAR:
7349 CP0_CHECK(ctx->mrp);
7350 gen_helper_mthc0_maar(cpu_env, arg);
7351 register_name = "MAAR";
7352 break;
7353 default:
7354 goto cp0_unimplemented;
7356 break;
7357 case CP0_REGISTER_19:
7358 switch (sel) {
7359 case CP0_REG19__WATCHHI0:
7360 case CP0_REG19__WATCHHI1:
7361 case CP0_REG19__WATCHHI2:
7362 case CP0_REG19__WATCHHI3:
7363 case CP0_REG19__WATCHHI4:
7364 case CP0_REG19__WATCHHI5:
7365 case CP0_REG19__WATCHHI6:
7366 case CP0_REG19__WATCHHI7:
7367 /* upper 32 bits are only available when Config5MI != 0 */
7368 CP0_CHECK(ctx->mi);
7369 gen_helper_0e1i(mthc0_watchhi, arg, sel);
7370 register_name = "WatchHi";
7371 break;
7372 default:
7373 goto cp0_unimplemented;
7375 break;
7376 case CP0_REGISTER_28:
7377 switch (sel) {
7378 case 0:
7379 case 2:
7380 case 4:
7381 case 6:
7382 tcg_gen_andi_tl(arg, arg, mask);
7383 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
7384 register_name = "TagLo";
7385 break;
7386 default:
7387 goto cp0_unimplemented;
7389 break;
7390 default:
7391 goto cp0_unimplemented;
7393 trace_mips_translate_c0("mthc0", register_name, reg, sel);
7395 cp0_unimplemented:
7396 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
7397 register_name, reg, sel);
7400 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
7402 if (ctx->insn_flags & ISA_MIPS32R6) {
7403 tcg_gen_movi_tl(arg, 0);
7404 } else {
7405 tcg_gen_movi_tl(arg, ~0);
7409 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7411 const char *register_name = "invalid";
7413 if (sel != 0) {
7414 check_insn(ctx, ISA_MIPS32);
7417 switch (reg) {
7418 case CP0_REGISTER_00:
7419 switch (sel) {
7420 case CP0_REG00__INDEX:
7421 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7422 register_name = "Index";
7423 break;
7424 case CP0_REG00__MVPCONTROL:
7425 CP0_CHECK(ctx->insn_flags & ASE_MT);
7426 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7427 register_name = "MVPControl";
7428 break;
7429 case CP0_REG00__MVPCONF0:
7430 CP0_CHECK(ctx->insn_flags & ASE_MT);
7431 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7432 register_name = "MVPConf0";
7433 break;
7434 case CP0_REG00__MVPCONF1:
7435 CP0_CHECK(ctx->insn_flags & ASE_MT);
7436 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7437 register_name = "MVPConf1";
7438 break;
7439 case CP0_REG00__VPCONTROL:
7440 CP0_CHECK(ctx->vp);
7441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7442 register_name = "VPControl";
7443 break;
7444 default:
7445 goto cp0_unimplemented;
7447 break;
7448 case CP0_REGISTER_01:
7449 switch (sel) {
7450 case CP0_REG01__RANDOM:
7451 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7452 gen_helper_mfc0_random(arg, cpu_env);
7453 register_name = "Random";
7454 break;
7455 case CP0_REG01__VPECONTROL:
7456 CP0_CHECK(ctx->insn_flags & ASE_MT);
7457 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7458 register_name = "VPEControl";
7459 break;
7460 case CP0_REG01__VPECONF0:
7461 CP0_CHECK(ctx->insn_flags & ASE_MT);
7462 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7463 register_name = "VPEConf0";
7464 break;
7465 case CP0_REG01__VPECONF1:
7466 CP0_CHECK(ctx->insn_flags & ASE_MT);
7467 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7468 register_name = "VPEConf1";
7469 break;
7470 case CP0_REG01__YQMASK:
7471 CP0_CHECK(ctx->insn_flags & ASE_MT);
7472 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
7473 register_name = "YQMask";
7474 break;
7475 case CP0_REG01__VPESCHEDULE:
7476 CP0_CHECK(ctx->insn_flags & ASE_MT);
7477 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
7478 register_name = "VPESchedule";
7479 break;
7480 case CP0_REG01__VPESCHEFBACK:
7481 CP0_CHECK(ctx->insn_flags & ASE_MT);
7482 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
7483 register_name = "VPEScheFBack";
7484 break;
7485 case CP0_REG01__VPEOPT:
7486 CP0_CHECK(ctx->insn_flags & ASE_MT);
7487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7488 register_name = "VPEOpt";
7489 break;
7490 default:
7491 goto cp0_unimplemented;
7493 break;
7494 case CP0_REGISTER_02:
7495 switch (sel) {
7496 case CP0_REG02__ENTRYLO0:
7498 TCGv_i64 tmp = tcg_temp_new_i64();
7499 tcg_gen_ld_i64(tmp, cpu_env,
7500 offsetof(CPUMIPSState, CP0_EntryLo0));
7501 #if defined(TARGET_MIPS64)
7502 if (ctx->rxi) {
7503 /* Move RI/XI fields to bits 31:30 */
7504 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7505 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7507 #endif
7508 gen_move_low32(arg, tmp);
7509 tcg_temp_free_i64(tmp);
7511 register_name = "EntryLo0";
7512 break;
7513 case CP0_REG02__TCSTATUS:
7514 CP0_CHECK(ctx->insn_flags & ASE_MT);
7515 gen_helper_mfc0_tcstatus(arg, cpu_env);
7516 register_name = "TCStatus";
7517 break;
7518 case CP0_REG02__TCBIND:
7519 CP0_CHECK(ctx->insn_flags & ASE_MT);
7520 gen_helper_mfc0_tcbind(arg, cpu_env);
7521 register_name = "TCBind";
7522 break;
7523 case CP0_REG02__TCRESTART:
7524 CP0_CHECK(ctx->insn_flags & ASE_MT);
7525 gen_helper_mfc0_tcrestart(arg, cpu_env);
7526 register_name = "TCRestart";
7527 break;
7528 case CP0_REG02__TCHALT:
7529 CP0_CHECK(ctx->insn_flags & ASE_MT);
7530 gen_helper_mfc0_tchalt(arg, cpu_env);
7531 register_name = "TCHalt";
7532 break;
7533 case CP0_REG02__TCCONTEXT:
7534 CP0_CHECK(ctx->insn_flags & ASE_MT);
7535 gen_helper_mfc0_tccontext(arg, cpu_env);
7536 register_name = "TCContext";
7537 break;
7538 case CP0_REG02__TCSCHEDULE:
7539 CP0_CHECK(ctx->insn_flags & ASE_MT);
7540 gen_helper_mfc0_tcschedule(arg, cpu_env);
7541 register_name = "TCSchedule";
7542 break;
7543 case CP0_REG02__TCSCHEFBACK:
7544 CP0_CHECK(ctx->insn_flags & ASE_MT);
7545 gen_helper_mfc0_tcschefback(arg, cpu_env);
7546 register_name = "TCScheFBack";
7547 break;
7548 default:
7549 goto cp0_unimplemented;
7551 break;
7552 case CP0_REGISTER_03:
7553 switch (sel) {
7554 case CP0_REG03__ENTRYLO1:
7556 TCGv_i64 tmp = tcg_temp_new_i64();
7557 tcg_gen_ld_i64(tmp, cpu_env,
7558 offsetof(CPUMIPSState, CP0_EntryLo1));
7559 #if defined(TARGET_MIPS64)
7560 if (ctx->rxi) {
7561 /* Move RI/XI fields to bits 31:30 */
7562 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
7563 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
7565 #endif
7566 gen_move_low32(arg, tmp);
7567 tcg_temp_free_i64(tmp);
7569 register_name = "EntryLo1";
7570 break;
7571 case CP0_REG03__GLOBALNUM:
7572 CP0_CHECK(ctx->vp);
7573 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7574 register_name = "GlobalNumber";
7575 break;
7576 default:
7577 goto cp0_unimplemented;
7579 break;
7580 case CP0_REGISTER_04:
7581 switch (sel) {
7582 case CP0_REG04__CONTEXT:
7583 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7584 tcg_gen_ext32s_tl(arg, arg);
7585 register_name = "Context";
7586 break;
7587 case CP0_REG04__CONTEXTCONFIG:
7588 /* SmartMIPS ASE */
7589 /* gen_helper_mfc0_contextconfig(arg); */
7590 register_name = "ContextConfig";
7591 goto cp0_unimplemented;
7592 case CP0_REG04__USERLOCAL:
7593 CP0_CHECK(ctx->ulri);
7594 tcg_gen_ld_tl(arg, cpu_env,
7595 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7596 tcg_gen_ext32s_tl(arg, arg);
7597 register_name = "UserLocal";
7598 break;
7599 case CP0_REG04__MMID:
7600 CP0_CHECK(ctx->mi);
7601 gen_helper_mtc0_memorymapid(cpu_env, arg);
7602 register_name = "MMID";
7603 break;
7604 default:
7605 goto cp0_unimplemented;
7607 break;
7608 case CP0_REGISTER_05:
7609 switch (sel) {
7610 case CP0_REG05__PAGEMASK:
7611 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7612 register_name = "PageMask";
7613 break;
7614 case CP0_REG05__PAGEGRAIN:
7615 check_insn(ctx, ISA_MIPS32R2);
7616 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7617 register_name = "PageGrain";
7618 break;
7619 case CP0_REG05__SEGCTL0:
7620 CP0_CHECK(ctx->sc);
7621 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7622 tcg_gen_ext32s_tl(arg, arg);
7623 register_name = "SegCtl0";
7624 break;
7625 case CP0_REG05__SEGCTL1:
7626 CP0_CHECK(ctx->sc);
7627 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7628 tcg_gen_ext32s_tl(arg, arg);
7629 register_name = "SegCtl1";
7630 break;
7631 case CP0_REG05__SEGCTL2:
7632 CP0_CHECK(ctx->sc);
7633 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7634 tcg_gen_ext32s_tl(arg, arg);
7635 register_name = "SegCtl2";
7636 break;
7637 case CP0_REG05__PWBASE:
7638 check_pw(ctx);
7639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
7640 register_name = "PWBase";
7641 break;
7642 case CP0_REG05__PWFIELD:
7643 check_pw(ctx);
7644 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
7645 register_name = "PWField";
7646 break;
7647 case CP0_REG05__PWSIZE:
7648 check_pw(ctx);
7649 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
7650 register_name = "PWSize";
7651 break;
7652 default:
7653 goto cp0_unimplemented;
7655 break;
7656 case CP0_REGISTER_06:
7657 switch (sel) {
7658 case CP0_REG06__WIRED:
7659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7660 register_name = "Wired";
7661 break;
7662 case CP0_REG06__SRSCONF0:
7663 check_insn(ctx, ISA_MIPS32R2);
7664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7665 register_name = "SRSConf0";
7666 break;
7667 case CP0_REG06__SRSCONF1:
7668 check_insn(ctx, ISA_MIPS32R2);
7669 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7670 register_name = "SRSConf1";
7671 break;
7672 case CP0_REG06__SRSCONF2:
7673 check_insn(ctx, ISA_MIPS32R2);
7674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7675 register_name = "SRSConf2";
7676 break;
7677 case CP0_REG06__SRSCONF3:
7678 check_insn(ctx, ISA_MIPS32R2);
7679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7680 register_name = "SRSConf3";
7681 break;
7682 case CP0_REG06__SRSCONF4:
7683 check_insn(ctx, ISA_MIPS32R2);
7684 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7685 register_name = "SRSConf4";
7686 break;
7687 case CP0_REG06__PWCTL:
7688 check_pw(ctx);
7689 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7690 register_name = "PWCtl";
7691 break;
7692 default:
7693 goto cp0_unimplemented;
7695 break;
7696 case CP0_REGISTER_07:
7697 switch (sel) {
7698 case CP0_REG07__HWRENA:
7699 check_insn(ctx, ISA_MIPS32R2);
7700 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7701 register_name = "HWREna";
7702 break;
7703 default:
7704 goto cp0_unimplemented;
7706 break;
7707 case CP0_REGISTER_08:
7708 switch (sel) {
7709 case CP0_REG08__BADVADDR:
7710 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7711 tcg_gen_ext32s_tl(arg, arg);
7712 register_name = "BadVAddr";
7713 break;
7714 case CP0_REG08__BADINSTR:
7715 CP0_CHECK(ctx->bi);
7716 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7717 register_name = "BadInstr";
7718 break;
7719 case CP0_REG08__BADINSTRP:
7720 CP0_CHECK(ctx->bp);
7721 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7722 register_name = "BadInstrP";
7723 break;
7724 case CP0_REG08__BADINSTRX:
7725 CP0_CHECK(ctx->bi);
7726 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7727 tcg_gen_andi_tl(arg, arg, ~0xffff);
7728 register_name = "BadInstrX";
7729 break;
7730 default:
7731 goto cp0_unimplemented;
7733 break;
7734 case CP0_REGISTER_09:
7735 switch (sel) {
7736 case CP0_REG09__COUNT:
7737 /* Mark as an IO operation because we read the time. */
7738 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7739 gen_io_start();
7741 gen_helper_mfc0_count(arg, cpu_env);
7743 * Break the TB to be able to take timer interrupts immediately
7744 * after reading count. DISAS_STOP isn't sufficient, we need to
7745 * ensure we break completely out of translated code.
7747 gen_save_pc(ctx->base.pc_next + 4);
7748 ctx->base.is_jmp = DISAS_EXIT;
7749 register_name = "Count";
7750 break;
7751 case CP0_REG09__SAARI:
7752 CP0_CHECK(ctx->saar);
7753 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7754 register_name = "SAARI";
7755 break;
7756 case CP0_REG09__SAAR:
7757 CP0_CHECK(ctx->saar);
7758 gen_helper_mfc0_saar(arg, cpu_env);
7759 register_name = "SAAR";
7760 break;
7761 default:
7762 goto cp0_unimplemented;
7764 break;
7765 case CP0_REGISTER_10:
7766 switch (sel) {
7767 case CP0_REG10__ENTRYHI:
7768 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7769 tcg_gen_ext32s_tl(arg, arg);
7770 register_name = "EntryHi";
7771 break;
7772 default:
7773 goto cp0_unimplemented;
7775 break;
7776 case CP0_REGISTER_11:
7777 switch (sel) {
7778 case CP0_REG11__COMPARE:
7779 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7780 register_name = "Compare";
7781 break;
7782 /* 6,7 are implementation dependent */
7783 default:
7784 goto cp0_unimplemented;
7786 break;
7787 case CP0_REGISTER_12:
7788 switch (sel) {
7789 case CP0_REG12__STATUS:
7790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7791 register_name = "Status";
7792 break;
7793 case CP0_REG12__INTCTL:
7794 check_insn(ctx, ISA_MIPS32R2);
7795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7796 register_name = "IntCtl";
7797 break;
7798 case CP0_REG12__SRSCTL:
7799 check_insn(ctx, ISA_MIPS32R2);
7800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7801 register_name = "SRSCtl";
7802 break;
7803 case CP0_REG12__SRSMAP:
7804 check_insn(ctx, ISA_MIPS32R2);
7805 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7806 register_name = "SRSMap";
7807 break;
7808 default:
7809 goto cp0_unimplemented;
7811 break;
7812 case CP0_REGISTER_13:
7813 switch (sel) {
7814 case CP0_REG13__CAUSE:
7815 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7816 register_name = "Cause";
7817 break;
7818 default:
7819 goto cp0_unimplemented;
7821 break;
7822 case CP0_REGISTER_14:
7823 switch (sel) {
7824 case CP0_REG14__EPC:
7825 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7826 tcg_gen_ext32s_tl(arg, arg);
7827 register_name = "EPC";
7828 break;
7829 default:
7830 goto cp0_unimplemented;
7832 break;
7833 case CP0_REGISTER_15:
7834 switch (sel) {
7835 case CP0_REG15__PRID:
7836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7837 register_name = "PRid";
7838 break;
7839 case CP0_REG15__EBASE:
7840 check_insn(ctx, ISA_MIPS32R2);
7841 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7842 tcg_gen_ext32s_tl(arg, arg);
7843 register_name = "EBase";
7844 break;
7845 case CP0_REG15__CMGCRBASE:
7846 check_insn(ctx, ISA_MIPS32R2);
7847 CP0_CHECK(ctx->cmgcr);
7848 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7849 tcg_gen_ext32s_tl(arg, arg);
7850 register_name = "CMGCRBase";
7851 break;
7852 default:
7853 goto cp0_unimplemented;
7855 break;
7856 case CP0_REGISTER_16:
7857 switch (sel) {
7858 case CP0_REG16__CONFIG:
7859 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7860 register_name = "Config";
7861 break;
7862 case CP0_REG16__CONFIG1:
7863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7864 register_name = "Config1";
7865 break;
7866 case CP0_REG16__CONFIG2:
7867 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7868 register_name = "Config2";
7869 break;
7870 case CP0_REG16__CONFIG3:
7871 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7872 register_name = "Config3";
7873 break;
7874 case CP0_REG16__CONFIG4:
7875 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7876 register_name = "Config4";
7877 break;
7878 case CP0_REG16__CONFIG5:
7879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7880 register_name = "Config5";
7881 break;
7882 /* 6,7 are implementation dependent */
7883 case CP0_REG16__CONFIG6:
7884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7885 register_name = "Config6";
7886 break;
7887 case CP0_REG16__CONFIG7:
7888 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7889 register_name = "Config7";
7890 break;
7891 default:
7892 goto cp0_unimplemented;
7894 break;
7895 case CP0_REGISTER_17:
7896 switch (sel) {
7897 case CP0_REG17__LLADDR:
7898 gen_helper_mfc0_lladdr(arg, cpu_env);
7899 register_name = "LLAddr";
7900 break;
7901 case CP0_REG17__MAAR:
7902 CP0_CHECK(ctx->mrp);
7903 gen_helper_mfc0_maar(arg, cpu_env);
7904 register_name = "MAAR";
7905 break;
7906 case CP0_REG17__MAARI:
7907 CP0_CHECK(ctx->mrp);
7908 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7909 register_name = "MAARI";
7910 break;
7911 default:
7912 goto cp0_unimplemented;
7914 break;
7915 case CP0_REGISTER_18:
7916 switch (sel) {
7917 case CP0_REG18__WATCHLO0:
7918 case CP0_REG18__WATCHLO1:
7919 case CP0_REG18__WATCHLO2:
7920 case CP0_REG18__WATCHLO3:
7921 case CP0_REG18__WATCHLO4:
7922 case CP0_REG18__WATCHLO5:
7923 case CP0_REG18__WATCHLO6:
7924 case CP0_REG18__WATCHLO7:
7925 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7926 gen_helper_1e0i(mfc0_watchlo, arg, sel);
7927 register_name = "WatchLo";
7928 break;
7929 default:
7930 goto cp0_unimplemented;
7932 break;
7933 case CP0_REGISTER_19:
7934 switch (sel) {
7935 case CP0_REG19__WATCHHI0:
7936 case CP0_REG19__WATCHHI1:
7937 case CP0_REG19__WATCHHI2:
7938 case CP0_REG19__WATCHHI3:
7939 case CP0_REG19__WATCHHI4:
7940 case CP0_REG19__WATCHHI5:
7941 case CP0_REG19__WATCHHI6:
7942 case CP0_REG19__WATCHHI7:
7943 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7944 gen_helper_1e0i(mfc0_watchhi, arg, sel);
7945 register_name = "WatchHi";
7946 break;
7947 default:
7948 goto cp0_unimplemented;
7950 break;
7951 case CP0_REGISTER_20:
7952 switch (sel) {
7953 case CP0_REG20__XCONTEXT:
7954 #if defined(TARGET_MIPS64)
7955 check_insn(ctx, ISA_MIPS3);
7956 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
7957 tcg_gen_ext32s_tl(arg, arg);
7958 register_name = "XContext";
7959 break;
7960 #endif
7961 default:
7962 goto cp0_unimplemented;
7964 break;
7965 case CP0_REGISTER_21:
7966 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7967 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
7968 switch (sel) {
7969 case 0:
7970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7971 register_name = "Framemask";
7972 break;
7973 default:
7974 goto cp0_unimplemented;
7976 break;
7977 case CP0_REGISTER_22:
7978 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7979 register_name = "'Diagnostic"; /* implementation dependent */
7980 break;
7981 case CP0_REGISTER_23:
7982 switch (sel) {
7983 case CP0_REG23__DEBUG:
7984 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
7985 register_name = "Debug";
7986 break;
7987 case CP0_REG23__TRACECONTROL:
7988 /* PDtrace support */
7989 /* gen_helper_mfc0_tracecontrol(arg); */
7990 register_name = "TraceControl";
7991 goto cp0_unimplemented;
7992 case CP0_REG23__TRACECONTROL2:
7993 /* PDtrace support */
7994 /* gen_helper_mfc0_tracecontrol2(arg); */
7995 register_name = "TraceControl2";
7996 goto cp0_unimplemented;
7997 case CP0_REG23__USERTRACEDATA1:
7998 /* PDtrace support */
7999 /* gen_helper_mfc0_usertracedata1(arg);*/
8000 register_name = "UserTraceData1";
8001 goto cp0_unimplemented;
8002 case CP0_REG23__TRACEIBPC:
8003 /* PDtrace support */
8004 /* gen_helper_mfc0_traceibpc(arg); */
8005 register_name = "TraceIBPC";
8006 goto cp0_unimplemented;
8007 case CP0_REG23__TRACEDBPC:
8008 /* PDtrace support */
8009 /* gen_helper_mfc0_tracedbpc(arg); */
8010 register_name = "TraceDBPC";
8011 goto cp0_unimplemented;
8012 default:
8013 goto cp0_unimplemented;
8015 break;
8016 case CP0_REGISTER_24:
8017 switch (sel) {
8018 case CP0_REG24__DEPC:
8019 /* EJTAG support */
8020 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8021 tcg_gen_ext32s_tl(arg, arg);
8022 register_name = "DEPC";
8023 break;
8024 default:
8025 goto cp0_unimplemented;
8027 break;
8028 case CP0_REGISTER_25:
8029 switch (sel) {
8030 case CP0_REG25__PERFCTL0:
8031 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8032 register_name = "Performance0";
8033 break;
8034 case CP0_REG25__PERFCNT0:
8035 /* gen_helper_mfc0_performance1(arg); */
8036 register_name = "Performance1";
8037 goto cp0_unimplemented;
8038 case CP0_REG25__PERFCTL1:
8039 /* gen_helper_mfc0_performance2(arg); */
8040 register_name = "Performance2";
8041 goto cp0_unimplemented;
8042 case CP0_REG25__PERFCNT1:
8043 /* gen_helper_mfc0_performance3(arg); */
8044 register_name = "Performance3";
8045 goto cp0_unimplemented;
8046 case CP0_REG25__PERFCTL2:
8047 /* gen_helper_mfc0_performance4(arg); */
8048 register_name = "Performance4";
8049 goto cp0_unimplemented;
8050 case CP0_REG25__PERFCNT2:
8051 /* gen_helper_mfc0_performance5(arg); */
8052 register_name = "Performance5";
8053 goto cp0_unimplemented;
8054 case CP0_REG25__PERFCTL3:
8055 /* gen_helper_mfc0_performance6(arg); */
8056 register_name = "Performance6";
8057 goto cp0_unimplemented;
8058 case CP0_REG25__PERFCNT3:
8059 /* gen_helper_mfc0_performance7(arg); */
8060 register_name = "Performance7";
8061 goto cp0_unimplemented;
8062 default:
8063 goto cp0_unimplemented;
8065 break;
8066 case CP0_REGISTER_26:
8067 switch (sel) {
8068 case CP0_REG26__ERRCTL:
8069 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8070 register_name = "ErrCtl";
8071 break;
8072 default:
8073 goto cp0_unimplemented;
8075 break;
8076 case CP0_REGISTER_27:
8077 switch (sel) {
8078 case CP0_REG27__CACHERR:
8079 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8080 register_name = "CacheErr";
8081 break;
8082 default:
8083 goto cp0_unimplemented;
8085 break;
8086 case CP0_REGISTER_28:
8087 switch (sel) {
8088 case CP0_REG28__TAGLO:
8089 case CP0_REG28__TAGLO1:
8090 case CP0_REG28__TAGLO2:
8091 case CP0_REG28__TAGLO3:
8093 TCGv_i64 tmp = tcg_temp_new_i64();
8094 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
8095 gen_move_low32(arg, tmp);
8096 tcg_temp_free_i64(tmp);
8098 register_name = "TagLo";
8099 break;
8100 case CP0_REG28__DATALO:
8101 case CP0_REG28__DATALO1:
8102 case CP0_REG28__DATALO2:
8103 case CP0_REG28__DATALO3:
8104 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8105 register_name = "DataLo";
8106 break;
8107 default:
8108 goto cp0_unimplemented;
8110 break;
8111 case CP0_REGISTER_29:
8112 switch (sel) {
8113 case CP0_REG29__TAGHI:
8114 case CP0_REG29__TAGHI1:
8115 case CP0_REG29__TAGHI2:
8116 case CP0_REG29__TAGHI3:
8117 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8118 register_name = "TagHi";
8119 break;
8120 case CP0_REG29__DATAHI:
8121 case CP0_REG29__DATAHI1:
8122 case CP0_REG29__DATAHI2:
8123 case CP0_REG29__DATAHI3:
8124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8125 register_name = "DataHi";
8126 break;
8127 default:
8128 goto cp0_unimplemented;
8130 break;
8131 case CP0_REGISTER_30:
8132 switch (sel) {
8133 case CP0_REG30__ERROREPC:
8134 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8135 tcg_gen_ext32s_tl(arg, arg);
8136 register_name = "ErrorEPC";
8137 break;
8138 default:
8139 goto cp0_unimplemented;
8141 break;
8142 case CP0_REGISTER_31:
8143 switch (sel) {
8144 case CP0_REG31__DESAVE:
8145 /* EJTAG support */
8146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8147 register_name = "DESAVE";
8148 break;
8149 case CP0_REG31__KSCRATCH1:
8150 case CP0_REG31__KSCRATCH2:
8151 case CP0_REG31__KSCRATCH3:
8152 case CP0_REG31__KSCRATCH4:
8153 case CP0_REG31__KSCRATCH5:
8154 case CP0_REG31__KSCRATCH6:
8155 CP0_CHECK(ctx->kscrexist & (1 << sel));
8156 tcg_gen_ld_tl(arg, cpu_env,
8157 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8158 tcg_gen_ext32s_tl(arg, arg);
8159 register_name = "KScratch";
8160 break;
8161 default:
8162 goto cp0_unimplemented;
8164 break;
8165 default:
8166 goto cp0_unimplemented;
8168 trace_mips_translate_c0("mfc0", register_name, reg, sel);
8169 return;
8171 cp0_unimplemented:
8172 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
8173 register_name, reg, sel);
8174 gen_mfc0_unimplemented(ctx, arg);
8177 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8179 const char *register_name = "invalid";
8181 if (sel != 0) {
8182 check_insn(ctx, ISA_MIPS32);
8185 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8186 gen_io_start();
8189 switch (reg) {
8190 case CP0_REGISTER_00:
8191 switch (sel) {
8192 case CP0_REG00__INDEX:
8193 gen_helper_mtc0_index(cpu_env, arg);
8194 register_name = "Index";
8195 break;
8196 case CP0_REG00__MVPCONTROL:
8197 CP0_CHECK(ctx->insn_flags & ASE_MT);
8198 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8199 register_name = "MVPControl";
8200 break;
8201 case CP0_REG00__MVPCONF0:
8202 CP0_CHECK(ctx->insn_flags & ASE_MT);
8203 /* ignored */
8204 register_name = "MVPConf0";
8205 break;
8206 case CP0_REG00__MVPCONF1:
8207 CP0_CHECK(ctx->insn_flags & ASE_MT);
8208 /* ignored */
8209 register_name = "MVPConf1";
8210 break;
8211 case CP0_REG00__VPCONTROL:
8212 CP0_CHECK(ctx->vp);
8213 /* ignored */
8214 register_name = "VPControl";
8215 break;
8216 default:
8217 goto cp0_unimplemented;
8219 break;
8220 case CP0_REGISTER_01:
8221 switch (sel) {
8222 case CP0_REG01__RANDOM:
8223 /* ignored */
8224 register_name = "Random";
8225 break;
8226 case CP0_REG01__VPECONTROL:
8227 CP0_CHECK(ctx->insn_flags & ASE_MT);
8228 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8229 register_name = "VPEControl";
8230 break;
8231 case CP0_REG01__VPECONF0:
8232 CP0_CHECK(ctx->insn_flags & ASE_MT);
8233 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8234 register_name = "VPEConf0";
8235 break;
8236 case CP0_REG01__VPECONF1:
8237 CP0_CHECK(ctx->insn_flags & ASE_MT);
8238 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8239 register_name = "VPEConf1";
8240 break;
8241 case CP0_REG01__YQMASK:
8242 CP0_CHECK(ctx->insn_flags & ASE_MT);
8243 gen_helper_mtc0_yqmask(cpu_env, arg);
8244 register_name = "YQMask";
8245 break;
8246 case CP0_REG01__VPESCHEDULE:
8247 CP0_CHECK(ctx->insn_flags & ASE_MT);
8248 tcg_gen_st_tl(arg, cpu_env,
8249 offsetof(CPUMIPSState, CP0_VPESchedule));
8250 register_name = "VPESchedule";
8251 break;
8252 case CP0_REG01__VPESCHEFBACK:
8253 CP0_CHECK(ctx->insn_flags & ASE_MT);
8254 tcg_gen_st_tl(arg, cpu_env,
8255 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8256 register_name = "VPEScheFBack";
8257 break;
8258 case CP0_REG01__VPEOPT:
8259 CP0_CHECK(ctx->insn_flags & ASE_MT);
8260 gen_helper_mtc0_vpeopt(cpu_env, arg);
8261 register_name = "VPEOpt";
8262 break;
8263 default:
8264 goto cp0_unimplemented;
8266 break;
8267 case CP0_REGISTER_02:
8268 switch (sel) {
8269 case CP0_REG02__ENTRYLO0:
8270 gen_helper_mtc0_entrylo0(cpu_env, arg);
8271 register_name = "EntryLo0";
8272 break;
8273 case CP0_REG02__TCSTATUS:
8274 CP0_CHECK(ctx->insn_flags & ASE_MT);
8275 gen_helper_mtc0_tcstatus(cpu_env, arg);
8276 register_name = "TCStatus";
8277 break;
8278 case CP0_REG02__TCBIND:
8279 CP0_CHECK(ctx->insn_flags & ASE_MT);
8280 gen_helper_mtc0_tcbind(cpu_env, arg);
8281 register_name = "TCBind";
8282 break;
8283 case CP0_REG02__TCRESTART:
8284 CP0_CHECK(ctx->insn_flags & ASE_MT);
8285 gen_helper_mtc0_tcrestart(cpu_env, arg);
8286 register_name = "TCRestart";
8287 break;
8288 case CP0_REG02__TCHALT:
8289 CP0_CHECK(ctx->insn_flags & ASE_MT);
8290 gen_helper_mtc0_tchalt(cpu_env, arg);
8291 register_name = "TCHalt";
8292 break;
8293 case CP0_REG02__TCCONTEXT:
8294 CP0_CHECK(ctx->insn_flags & ASE_MT);
8295 gen_helper_mtc0_tccontext(cpu_env, arg);
8296 register_name = "TCContext";
8297 break;
8298 case CP0_REG02__TCSCHEDULE:
8299 CP0_CHECK(ctx->insn_flags & ASE_MT);
8300 gen_helper_mtc0_tcschedule(cpu_env, arg);
8301 register_name = "TCSchedule";
8302 break;
8303 case CP0_REG02__TCSCHEFBACK:
8304 CP0_CHECK(ctx->insn_flags & ASE_MT);
8305 gen_helper_mtc0_tcschefback(cpu_env, arg);
8306 register_name = "TCScheFBack";
8307 break;
8308 default:
8309 goto cp0_unimplemented;
8311 break;
8312 case CP0_REGISTER_03:
8313 switch (sel) {
8314 case CP0_REG03__ENTRYLO1:
8315 gen_helper_mtc0_entrylo1(cpu_env, arg);
8316 register_name = "EntryLo1";
8317 break;
8318 case CP0_REG03__GLOBALNUM:
8319 CP0_CHECK(ctx->vp);
8320 /* ignored */
8321 register_name = "GlobalNumber";
8322 break;
8323 default:
8324 goto cp0_unimplemented;
8326 break;
8327 case CP0_REGISTER_04:
8328 switch (sel) {
8329 case CP0_REG04__CONTEXT:
8330 gen_helper_mtc0_context(cpu_env, arg);
8331 register_name = "Context";
8332 break;
8333 case CP0_REG04__CONTEXTCONFIG:
8334 /* SmartMIPS ASE */
8335 /* gen_helper_mtc0_contextconfig(arg); */
8336 register_name = "ContextConfig";
8337 goto cp0_unimplemented;
8338 case CP0_REG04__USERLOCAL:
8339 CP0_CHECK(ctx->ulri);
8340 tcg_gen_st_tl(arg, cpu_env,
8341 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8342 register_name = "UserLocal";
8343 break;
8344 case CP0_REG04__MMID:
8345 CP0_CHECK(ctx->mi);
8346 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8347 register_name = "MMID";
8348 break;
8349 default:
8350 goto cp0_unimplemented;
8352 break;
8353 case CP0_REGISTER_05:
8354 switch (sel) {
8355 case CP0_REG05__PAGEMASK:
8356 gen_helper_mtc0_pagemask(cpu_env, arg);
8357 register_name = "PageMask";
8358 break;
8359 case CP0_REG05__PAGEGRAIN:
8360 check_insn(ctx, ISA_MIPS32R2);
8361 gen_helper_mtc0_pagegrain(cpu_env, arg);
8362 register_name = "PageGrain";
8363 ctx->base.is_jmp = DISAS_STOP;
8364 break;
8365 case CP0_REG05__SEGCTL0:
8366 CP0_CHECK(ctx->sc);
8367 gen_helper_mtc0_segctl0(cpu_env, arg);
8368 register_name = "SegCtl0";
8369 break;
8370 case CP0_REG05__SEGCTL1:
8371 CP0_CHECK(ctx->sc);
8372 gen_helper_mtc0_segctl1(cpu_env, arg);
8373 register_name = "SegCtl1";
8374 break;
8375 case CP0_REG05__SEGCTL2:
8376 CP0_CHECK(ctx->sc);
8377 gen_helper_mtc0_segctl2(cpu_env, arg);
8378 register_name = "SegCtl2";
8379 break;
8380 case CP0_REG05__PWBASE:
8381 check_pw(ctx);
8382 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
8383 register_name = "PWBase";
8384 break;
8385 case CP0_REG05__PWFIELD:
8386 check_pw(ctx);
8387 gen_helper_mtc0_pwfield(cpu_env, arg);
8388 register_name = "PWField";
8389 break;
8390 case CP0_REG05__PWSIZE:
8391 check_pw(ctx);
8392 gen_helper_mtc0_pwsize(cpu_env, arg);
8393 register_name = "PWSize";
8394 break;
8395 default:
8396 goto cp0_unimplemented;
8398 break;
8399 case CP0_REGISTER_06:
8400 switch (sel) {
8401 case CP0_REG06__WIRED:
8402 gen_helper_mtc0_wired(cpu_env, arg);
8403 register_name = "Wired";
8404 break;
8405 case CP0_REG06__SRSCONF0:
8406 check_insn(ctx, ISA_MIPS32R2);
8407 gen_helper_mtc0_srsconf0(cpu_env, arg);
8408 register_name = "SRSConf0";
8409 break;
8410 case CP0_REG06__SRSCONF1:
8411 check_insn(ctx, ISA_MIPS32R2);
8412 gen_helper_mtc0_srsconf1(cpu_env, arg);
8413 register_name = "SRSConf1";
8414 break;
8415 case CP0_REG06__SRSCONF2:
8416 check_insn(ctx, ISA_MIPS32R2);
8417 gen_helper_mtc0_srsconf2(cpu_env, arg);
8418 register_name = "SRSConf2";
8419 break;
8420 case CP0_REG06__SRSCONF3:
8421 check_insn(ctx, ISA_MIPS32R2);
8422 gen_helper_mtc0_srsconf3(cpu_env, arg);
8423 register_name = "SRSConf3";
8424 break;
8425 case CP0_REG06__SRSCONF4:
8426 check_insn(ctx, ISA_MIPS32R2);
8427 gen_helper_mtc0_srsconf4(cpu_env, arg);
8428 register_name = "SRSConf4";
8429 break;
8430 case CP0_REG06__PWCTL:
8431 check_pw(ctx);
8432 gen_helper_mtc0_pwctl(cpu_env, arg);
8433 register_name = "PWCtl";
8434 break;
8435 default:
8436 goto cp0_unimplemented;
8438 break;
8439 case CP0_REGISTER_07:
8440 switch (sel) {
8441 case CP0_REG07__HWRENA:
8442 check_insn(ctx, ISA_MIPS32R2);
8443 gen_helper_mtc0_hwrena(cpu_env, arg);
8444 ctx->base.is_jmp = DISAS_STOP;
8445 register_name = "HWREna";
8446 break;
8447 default:
8448 goto cp0_unimplemented;
8450 break;
8451 case CP0_REGISTER_08:
8452 switch (sel) {
8453 case CP0_REG08__BADVADDR:
8454 /* ignored */
8455 register_name = "BadVAddr";
8456 break;
8457 case CP0_REG08__BADINSTR:
8458 /* ignored */
8459 register_name = "BadInstr";
8460 break;
8461 case CP0_REG08__BADINSTRP:
8462 /* ignored */
8463 register_name = "BadInstrP";
8464 break;
8465 case CP0_REG08__BADINSTRX:
8466 /* ignored */
8467 register_name = "BadInstrX";
8468 break;
8469 default:
8470 goto cp0_unimplemented;
8472 break;
8473 case CP0_REGISTER_09:
8474 switch (sel) {
8475 case CP0_REG09__COUNT:
8476 gen_helper_mtc0_count(cpu_env, arg);
8477 register_name = "Count";
8478 break;
8479 case CP0_REG09__SAARI:
8480 CP0_CHECK(ctx->saar);
8481 gen_helper_mtc0_saari(cpu_env, arg);
8482 register_name = "SAARI";
8483 break;
8484 case CP0_REG09__SAAR:
8485 CP0_CHECK(ctx->saar);
8486 gen_helper_mtc0_saar(cpu_env, arg);
8487 register_name = "SAAR";
8488 break;
8489 default:
8490 goto cp0_unimplemented;
8492 break;
8493 case CP0_REGISTER_10:
8494 switch (sel) {
8495 case CP0_REG10__ENTRYHI:
8496 gen_helper_mtc0_entryhi(cpu_env, arg);
8497 register_name = "EntryHi";
8498 break;
8499 default:
8500 goto cp0_unimplemented;
8502 break;
8503 case CP0_REGISTER_11:
8504 switch (sel) {
8505 case CP0_REG11__COMPARE:
8506 gen_helper_mtc0_compare(cpu_env, arg);
8507 register_name = "Compare";
8508 break;
8509 /* 6,7 are implementation dependent */
8510 default:
8511 goto cp0_unimplemented;
8513 break;
8514 case CP0_REGISTER_12:
8515 switch (sel) {
8516 case CP0_REG12__STATUS:
8517 save_cpu_state(ctx, 1);
8518 gen_helper_mtc0_status(cpu_env, arg);
8519 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8520 gen_save_pc(ctx->base.pc_next + 4);
8521 ctx->base.is_jmp = DISAS_EXIT;
8522 register_name = "Status";
8523 break;
8524 case CP0_REG12__INTCTL:
8525 check_insn(ctx, ISA_MIPS32R2);
8526 gen_helper_mtc0_intctl(cpu_env, arg);
8527 /* Stop translation as we may have switched the execution mode */
8528 ctx->base.is_jmp = DISAS_STOP;
8529 register_name = "IntCtl";
8530 break;
8531 case CP0_REG12__SRSCTL:
8532 check_insn(ctx, ISA_MIPS32R2);
8533 gen_helper_mtc0_srsctl(cpu_env, arg);
8534 /* Stop translation as we may have switched the execution mode */
8535 ctx->base.is_jmp = DISAS_STOP;
8536 register_name = "SRSCtl";
8537 break;
8538 case CP0_REG12__SRSMAP:
8539 check_insn(ctx, ISA_MIPS32R2);
8540 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8541 /* Stop translation as we may have switched the execution mode */
8542 ctx->base.is_jmp = DISAS_STOP;
8543 register_name = "SRSMap";
8544 break;
8545 default:
8546 goto cp0_unimplemented;
8548 break;
8549 case CP0_REGISTER_13:
8550 switch (sel) {
8551 case CP0_REG13__CAUSE:
8552 save_cpu_state(ctx, 1);
8553 gen_helper_mtc0_cause(cpu_env, arg);
8555 * Stop translation as we may have triggered an interrupt.
8556 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8557 * translated code to check for pending interrupts.
8559 gen_save_pc(ctx->base.pc_next + 4);
8560 ctx->base.is_jmp = DISAS_EXIT;
8561 register_name = "Cause";
8562 break;
8563 default:
8564 goto cp0_unimplemented;
8566 break;
8567 case CP0_REGISTER_14:
8568 switch (sel) {
8569 case CP0_REG14__EPC:
8570 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8571 register_name = "EPC";
8572 break;
8573 default:
8574 goto cp0_unimplemented;
8576 break;
8577 case CP0_REGISTER_15:
8578 switch (sel) {
8579 case CP0_REG15__PRID:
8580 /* ignored */
8581 register_name = "PRid";
8582 break;
8583 case CP0_REG15__EBASE:
8584 check_insn(ctx, ISA_MIPS32R2);
8585 gen_helper_mtc0_ebase(cpu_env, arg);
8586 register_name = "EBase";
8587 break;
8588 default:
8589 goto cp0_unimplemented;
8591 break;
8592 case CP0_REGISTER_16:
8593 switch (sel) {
8594 case CP0_REG16__CONFIG:
8595 gen_helper_mtc0_config0(cpu_env, arg);
8596 register_name = "Config";
8597 /* Stop translation as we may have switched the execution mode */
8598 ctx->base.is_jmp = DISAS_STOP;
8599 break;
8600 case CP0_REG16__CONFIG1:
8601 /* ignored, read only */
8602 register_name = "Config1";
8603 break;
8604 case CP0_REG16__CONFIG2:
8605 gen_helper_mtc0_config2(cpu_env, arg);
8606 register_name = "Config2";
8607 /* Stop translation as we may have switched the execution mode */
8608 ctx->base.is_jmp = DISAS_STOP;
8609 break;
8610 case CP0_REG16__CONFIG3:
8611 gen_helper_mtc0_config3(cpu_env, arg);
8612 register_name = "Config3";
8613 /* Stop translation as we may have switched the execution mode */
8614 ctx->base.is_jmp = DISAS_STOP;
8615 break;
8616 case CP0_REG16__CONFIG4:
8617 gen_helper_mtc0_config4(cpu_env, arg);
8618 register_name = "Config4";
8619 ctx->base.is_jmp = DISAS_STOP;
8620 break;
8621 case CP0_REG16__CONFIG5:
8622 gen_helper_mtc0_config5(cpu_env, arg);
8623 register_name = "Config5";
8624 /* Stop translation as we may have switched the execution mode */
8625 ctx->base.is_jmp = DISAS_STOP;
8626 break;
8627 /* 6,7 are implementation dependent */
8628 case CP0_REG16__CONFIG6:
8629 /* ignored */
8630 register_name = "Config6";
8631 break;
8632 case CP0_REG16__CONFIG7:
8633 /* ignored */
8634 register_name = "Config7";
8635 break;
8636 default:
8637 register_name = "Invalid config selector";
8638 goto cp0_unimplemented;
8640 break;
8641 case CP0_REGISTER_17:
8642 switch (sel) {
8643 case CP0_REG17__LLADDR:
8644 gen_helper_mtc0_lladdr(cpu_env, arg);
8645 register_name = "LLAddr";
8646 break;
8647 case CP0_REG17__MAAR:
8648 CP0_CHECK(ctx->mrp);
8649 gen_helper_mtc0_maar(cpu_env, arg);
8650 register_name = "MAAR";
8651 break;
8652 case CP0_REG17__MAARI:
8653 CP0_CHECK(ctx->mrp);
8654 gen_helper_mtc0_maari(cpu_env, arg);
8655 register_name = "MAARI";
8656 break;
8657 default:
8658 goto cp0_unimplemented;
8660 break;
8661 case CP0_REGISTER_18:
8662 switch (sel) {
8663 case CP0_REG18__WATCHLO0:
8664 case CP0_REG18__WATCHLO1:
8665 case CP0_REG18__WATCHLO2:
8666 case CP0_REG18__WATCHLO3:
8667 case CP0_REG18__WATCHLO4:
8668 case CP0_REG18__WATCHLO5:
8669 case CP0_REG18__WATCHLO6:
8670 case CP0_REG18__WATCHLO7:
8671 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8672 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8673 register_name = "WatchLo";
8674 break;
8675 default:
8676 goto cp0_unimplemented;
8678 break;
8679 case CP0_REGISTER_19:
8680 switch (sel) {
8681 case CP0_REG19__WATCHHI0:
8682 case CP0_REG19__WATCHHI1:
8683 case CP0_REG19__WATCHHI2:
8684 case CP0_REG19__WATCHHI3:
8685 case CP0_REG19__WATCHHI4:
8686 case CP0_REG19__WATCHHI5:
8687 case CP0_REG19__WATCHHI6:
8688 case CP0_REG19__WATCHHI7:
8689 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8690 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8691 register_name = "WatchHi";
8692 break;
8693 default:
8694 goto cp0_unimplemented;
8696 break;
8697 case CP0_REGISTER_20:
8698 switch (sel) {
8699 case CP0_REG20__XCONTEXT:
8700 #if defined(TARGET_MIPS64)
8701 check_insn(ctx, ISA_MIPS3);
8702 gen_helper_mtc0_xcontext(cpu_env, arg);
8703 register_name = "XContext";
8704 break;
8705 #endif
8706 default:
8707 goto cp0_unimplemented;
8709 break;
8710 case CP0_REGISTER_21:
8711 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8712 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8713 switch (sel) {
8714 case 0:
8715 gen_helper_mtc0_framemask(cpu_env, arg);
8716 register_name = "Framemask";
8717 break;
8718 default:
8719 goto cp0_unimplemented;
8721 break;
8722 case CP0_REGISTER_22:
8723 /* ignored */
8724 register_name = "Diagnostic"; /* implementation dependent */
8725 break;
8726 case CP0_REGISTER_23:
8727 switch (sel) {
8728 case CP0_REG23__DEBUG:
8729 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8730 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8731 gen_save_pc(ctx->base.pc_next + 4);
8732 ctx->base.is_jmp = DISAS_EXIT;
8733 register_name = "Debug";
8734 break;
8735 case CP0_REG23__TRACECONTROL:
8736 /* PDtrace support */
8737 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8738 register_name = "TraceControl";
8739 /* Stop translation as we may have switched the execution mode */
8740 ctx->base.is_jmp = DISAS_STOP;
8741 goto cp0_unimplemented;
8742 case CP0_REG23__TRACECONTROL2:
8743 /* PDtrace support */
8744 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8745 register_name = "TraceControl2";
8746 /* Stop translation as we may have switched the execution mode */
8747 ctx->base.is_jmp = DISAS_STOP;
8748 goto cp0_unimplemented;
8749 case CP0_REG23__USERTRACEDATA1:
8750 /* Stop translation as we may have switched the execution mode */
8751 ctx->base.is_jmp = DISAS_STOP;
8752 /* PDtrace support */
8753 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8754 register_name = "UserTraceData";
8755 /* Stop translation as we may have switched the execution mode */
8756 ctx->base.is_jmp = DISAS_STOP;
8757 goto cp0_unimplemented;
8758 case CP0_REG23__TRACEIBPC:
8759 /* PDtrace support */
8760 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8761 /* Stop translation as we may have switched the execution mode */
8762 ctx->base.is_jmp = DISAS_STOP;
8763 register_name = "TraceIBPC";
8764 goto cp0_unimplemented;
8765 case CP0_REG23__TRACEDBPC:
8766 /* PDtrace support */
8767 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8768 /* Stop translation as we may have switched the execution mode */
8769 ctx->base.is_jmp = DISAS_STOP;
8770 register_name = "TraceDBPC";
8771 goto cp0_unimplemented;
8772 default:
8773 goto cp0_unimplemented;
8775 break;
8776 case CP0_REGISTER_24:
8777 switch (sel) {
8778 case CP0_REG24__DEPC:
8779 /* EJTAG support */
8780 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8781 register_name = "DEPC";
8782 break;
8783 default:
8784 goto cp0_unimplemented;
8786 break;
8787 case CP0_REGISTER_25:
8788 switch (sel) {
8789 case CP0_REG25__PERFCTL0:
8790 gen_helper_mtc0_performance0(cpu_env, arg);
8791 register_name = "Performance0";
8792 break;
8793 case CP0_REG25__PERFCNT0:
8794 /* gen_helper_mtc0_performance1(arg); */
8795 register_name = "Performance1";
8796 goto cp0_unimplemented;
8797 case CP0_REG25__PERFCTL1:
8798 /* gen_helper_mtc0_performance2(arg); */
8799 register_name = "Performance2";
8800 goto cp0_unimplemented;
8801 case CP0_REG25__PERFCNT1:
8802 /* gen_helper_mtc0_performance3(arg); */
8803 register_name = "Performance3";
8804 goto cp0_unimplemented;
8805 case CP0_REG25__PERFCTL2:
8806 /* gen_helper_mtc0_performance4(arg); */
8807 register_name = "Performance4";
8808 goto cp0_unimplemented;
8809 case CP0_REG25__PERFCNT2:
8810 /* gen_helper_mtc0_performance5(arg); */
8811 register_name = "Performance5";
8812 goto cp0_unimplemented;
8813 case CP0_REG25__PERFCTL3:
8814 /* gen_helper_mtc0_performance6(arg); */
8815 register_name = "Performance6";
8816 goto cp0_unimplemented;
8817 case CP0_REG25__PERFCNT3:
8818 /* gen_helper_mtc0_performance7(arg); */
8819 register_name = "Performance7";
8820 goto cp0_unimplemented;
8821 default:
8822 goto cp0_unimplemented;
8824 break;
8825 case CP0_REGISTER_26:
8826 switch (sel) {
8827 case CP0_REG26__ERRCTL:
8828 gen_helper_mtc0_errctl(cpu_env, arg);
8829 ctx->base.is_jmp = DISAS_STOP;
8830 register_name = "ErrCtl";
8831 break;
8832 default:
8833 goto cp0_unimplemented;
8835 break;
8836 case CP0_REGISTER_27:
8837 switch (sel) {
8838 case CP0_REG27__CACHERR:
8839 /* ignored */
8840 register_name = "CacheErr";
8841 break;
8842 default:
8843 goto cp0_unimplemented;
8845 break;
8846 case CP0_REGISTER_28:
8847 switch (sel) {
8848 case CP0_REG28__TAGLO:
8849 case CP0_REG28__TAGLO1:
8850 case CP0_REG28__TAGLO2:
8851 case CP0_REG28__TAGLO3:
8852 gen_helper_mtc0_taglo(cpu_env, arg);
8853 register_name = "TagLo";
8854 break;
8855 case CP0_REG28__DATALO:
8856 case CP0_REG28__DATALO1:
8857 case CP0_REG28__DATALO2:
8858 case CP0_REG28__DATALO3:
8859 gen_helper_mtc0_datalo(cpu_env, arg);
8860 register_name = "DataLo";
8861 break;
8862 default:
8863 goto cp0_unimplemented;
8865 break;
8866 case CP0_REGISTER_29:
8867 switch (sel) {
8868 case CP0_REG29__TAGHI:
8869 case CP0_REG29__TAGHI1:
8870 case CP0_REG29__TAGHI2:
8871 case CP0_REG29__TAGHI3:
8872 gen_helper_mtc0_taghi(cpu_env, arg);
8873 register_name = "TagHi";
8874 break;
8875 case CP0_REG29__DATAHI:
8876 case CP0_REG29__DATAHI1:
8877 case CP0_REG29__DATAHI2:
8878 case CP0_REG29__DATAHI3:
8879 gen_helper_mtc0_datahi(cpu_env, arg);
8880 register_name = "DataHi";
8881 break;
8882 default:
8883 register_name = "invalid sel";
8884 goto cp0_unimplemented;
8886 break;
8887 case CP0_REGISTER_30:
8888 switch (sel) {
8889 case CP0_REG30__ERROREPC:
8890 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8891 register_name = "ErrorEPC";
8892 break;
8893 default:
8894 goto cp0_unimplemented;
8896 break;
8897 case CP0_REGISTER_31:
8898 switch (sel) {
8899 case CP0_REG31__DESAVE:
8900 /* EJTAG support */
8901 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8902 register_name = "DESAVE";
8903 break;
8904 case CP0_REG31__KSCRATCH1:
8905 case CP0_REG31__KSCRATCH2:
8906 case CP0_REG31__KSCRATCH3:
8907 case CP0_REG31__KSCRATCH4:
8908 case CP0_REG31__KSCRATCH5:
8909 case CP0_REG31__KSCRATCH6:
8910 CP0_CHECK(ctx->kscrexist & (1 << sel));
8911 tcg_gen_st_tl(arg, cpu_env,
8912 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8913 register_name = "KScratch";
8914 break;
8915 default:
8916 goto cp0_unimplemented;
8918 break;
8919 default:
8920 goto cp0_unimplemented;
8922 trace_mips_translate_c0("mtc0", register_name, reg, sel);
8924 /* For simplicity assume that all writes can cause interrupts. */
8925 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8927 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8928 * translated code to check for pending interrupts.
8930 gen_save_pc(ctx->base.pc_next + 4);
8931 ctx->base.is_jmp = DISAS_EXIT;
8933 return;
8935 cp0_unimplemented:
8936 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
8937 register_name, reg, sel);
8940 #if defined(TARGET_MIPS64)
8941 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8943 const char *register_name = "invalid";
8945 if (sel != 0) {
8946 check_insn(ctx, ISA_MIPS32);
8949 switch (reg) {
8950 case CP0_REGISTER_00:
8951 switch (sel) {
8952 case CP0_REG00__INDEX:
8953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
8954 register_name = "Index";
8955 break;
8956 case CP0_REG00__MVPCONTROL:
8957 CP0_CHECK(ctx->insn_flags & ASE_MT);
8958 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
8959 register_name = "MVPControl";
8960 break;
8961 case CP0_REG00__MVPCONF0:
8962 CP0_CHECK(ctx->insn_flags & ASE_MT);
8963 gen_helper_mfc0_mvpconf0(arg, cpu_env);
8964 register_name = "MVPConf0";
8965 break;
8966 case CP0_REG00__MVPCONF1:
8967 CP0_CHECK(ctx->insn_flags & ASE_MT);
8968 gen_helper_mfc0_mvpconf1(arg, cpu_env);
8969 register_name = "MVPConf1";
8970 break;
8971 case CP0_REG00__VPCONTROL:
8972 CP0_CHECK(ctx->vp);
8973 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
8974 register_name = "VPControl";
8975 break;
8976 default:
8977 goto cp0_unimplemented;
8979 break;
8980 case CP0_REGISTER_01:
8981 switch (sel) {
8982 case CP0_REG01__RANDOM:
8983 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
8984 gen_helper_mfc0_random(arg, cpu_env);
8985 register_name = "Random";
8986 break;
8987 case CP0_REG01__VPECONTROL:
8988 CP0_CHECK(ctx->insn_flags & ASE_MT);
8989 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
8990 register_name = "VPEControl";
8991 break;
8992 case CP0_REG01__VPECONF0:
8993 CP0_CHECK(ctx->insn_flags & ASE_MT);
8994 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
8995 register_name = "VPEConf0";
8996 break;
8997 case CP0_REG01__VPECONF1:
8998 CP0_CHECK(ctx->insn_flags & ASE_MT);
8999 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
9000 register_name = "VPEConf1";
9001 break;
9002 case CP0_REG01__YQMASK:
9003 CP0_CHECK(ctx->insn_flags & ASE_MT);
9004 tcg_gen_ld_tl(arg, cpu_env,
9005 offsetof(CPUMIPSState, CP0_YQMask));
9006 register_name = "YQMask";
9007 break;
9008 case CP0_REG01__VPESCHEDULE:
9009 CP0_CHECK(ctx->insn_flags & ASE_MT);
9010 tcg_gen_ld_tl(arg, cpu_env,
9011 offsetof(CPUMIPSState, CP0_VPESchedule));
9012 register_name = "VPESchedule";
9013 break;
9014 case CP0_REG01__VPESCHEFBACK:
9015 CP0_CHECK(ctx->insn_flags & ASE_MT);
9016 tcg_gen_ld_tl(arg, cpu_env,
9017 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9018 register_name = "VPEScheFBack";
9019 break;
9020 case CP0_REG01__VPEOPT:
9021 CP0_CHECK(ctx->insn_flags & ASE_MT);
9022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
9023 register_name = "VPEOpt";
9024 break;
9025 default:
9026 goto cp0_unimplemented;
9028 break;
9029 case CP0_REGISTER_02:
9030 switch (sel) {
9031 case CP0_REG02__ENTRYLO0:
9032 tcg_gen_ld_tl(arg, cpu_env,
9033 offsetof(CPUMIPSState, CP0_EntryLo0));
9034 register_name = "EntryLo0";
9035 break;
9036 case CP0_REG02__TCSTATUS:
9037 CP0_CHECK(ctx->insn_flags & ASE_MT);
9038 gen_helper_mfc0_tcstatus(arg, cpu_env);
9039 register_name = "TCStatus";
9040 break;
9041 case CP0_REG02__TCBIND:
9042 CP0_CHECK(ctx->insn_flags & ASE_MT);
9043 gen_helper_mfc0_tcbind(arg, cpu_env);
9044 register_name = "TCBind";
9045 break;
9046 case CP0_REG02__TCRESTART:
9047 CP0_CHECK(ctx->insn_flags & ASE_MT);
9048 gen_helper_dmfc0_tcrestart(arg, cpu_env);
9049 register_name = "TCRestart";
9050 break;
9051 case CP0_REG02__TCHALT:
9052 CP0_CHECK(ctx->insn_flags & ASE_MT);
9053 gen_helper_dmfc0_tchalt(arg, cpu_env);
9054 register_name = "TCHalt";
9055 break;
9056 case CP0_REG02__TCCONTEXT:
9057 CP0_CHECK(ctx->insn_flags & ASE_MT);
9058 gen_helper_dmfc0_tccontext(arg, cpu_env);
9059 register_name = "TCContext";
9060 break;
9061 case CP0_REG02__TCSCHEDULE:
9062 CP0_CHECK(ctx->insn_flags & ASE_MT);
9063 gen_helper_dmfc0_tcschedule(arg, cpu_env);
9064 register_name = "TCSchedule";
9065 break;
9066 case CP0_REG02__TCSCHEFBACK:
9067 CP0_CHECK(ctx->insn_flags & ASE_MT);
9068 gen_helper_dmfc0_tcschefback(arg, cpu_env);
9069 register_name = "TCScheFBack";
9070 break;
9071 default:
9072 goto cp0_unimplemented;
9074 break;
9075 case CP0_REGISTER_03:
9076 switch (sel) {
9077 case CP0_REG03__ENTRYLO1:
9078 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
9079 register_name = "EntryLo1";
9080 break;
9081 case CP0_REG03__GLOBALNUM:
9082 CP0_CHECK(ctx->vp);
9083 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
9084 register_name = "GlobalNumber";
9085 break;
9086 default:
9087 goto cp0_unimplemented;
9089 break;
9090 case CP0_REGISTER_04:
9091 switch (sel) {
9092 case CP0_REG04__CONTEXT:
9093 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
9094 register_name = "Context";
9095 break;
9096 case CP0_REG04__CONTEXTCONFIG:
9097 /* SmartMIPS ASE */
9098 /* gen_helper_dmfc0_contextconfig(arg); */
9099 register_name = "ContextConfig";
9100 goto cp0_unimplemented;
9101 case CP0_REG04__USERLOCAL:
9102 CP0_CHECK(ctx->ulri);
9103 tcg_gen_ld_tl(arg, cpu_env,
9104 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9105 register_name = "UserLocal";
9106 break;
9107 case CP0_REG04__MMID:
9108 CP0_CHECK(ctx->mi);
9109 gen_helper_mtc0_memorymapid(cpu_env, arg);
9110 register_name = "MMID";
9111 break;
9112 default:
9113 goto cp0_unimplemented;
9115 break;
9116 case CP0_REGISTER_05:
9117 switch (sel) {
9118 case CP0_REG05__PAGEMASK:
9119 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
9120 register_name = "PageMask";
9121 break;
9122 case CP0_REG05__PAGEGRAIN:
9123 check_insn(ctx, ISA_MIPS32R2);
9124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
9125 register_name = "PageGrain";
9126 break;
9127 case CP0_REG05__SEGCTL0:
9128 CP0_CHECK(ctx->sc);
9129 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
9130 register_name = "SegCtl0";
9131 break;
9132 case CP0_REG05__SEGCTL1:
9133 CP0_CHECK(ctx->sc);
9134 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
9135 register_name = "SegCtl1";
9136 break;
9137 case CP0_REG05__SEGCTL2:
9138 CP0_CHECK(ctx->sc);
9139 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
9140 register_name = "SegCtl2";
9141 break;
9142 case CP0_REG05__PWBASE:
9143 check_pw(ctx);
9144 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9145 register_name = "PWBase";
9146 break;
9147 case CP0_REG05__PWFIELD:
9148 check_pw(ctx);
9149 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
9150 register_name = "PWField";
9151 break;
9152 case CP0_REG05__PWSIZE:
9153 check_pw(ctx);
9154 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
9155 register_name = "PWSize";
9156 break;
9157 default:
9158 goto cp0_unimplemented;
9160 break;
9161 case CP0_REGISTER_06:
9162 switch (sel) {
9163 case CP0_REG06__WIRED:
9164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
9165 register_name = "Wired";
9166 break;
9167 case CP0_REG06__SRSCONF0:
9168 check_insn(ctx, ISA_MIPS32R2);
9169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
9170 register_name = "SRSConf0";
9171 break;
9172 case CP0_REG06__SRSCONF1:
9173 check_insn(ctx, ISA_MIPS32R2);
9174 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
9175 register_name = "SRSConf1";
9176 break;
9177 case CP0_REG06__SRSCONF2:
9178 check_insn(ctx, ISA_MIPS32R2);
9179 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
9180 register_name = "SRSConf2";
9181 break;
9182 case CP0_REG06__SRSCONF3:
9183 check_insn(ctx, ISA_MIPS32R2);
9184 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
9185 register_name = "SRSConf3";
9186 break;
9187 case CP0_REG06__SRSCONF4:
9188 check_insn(ctx, ISA_MIPS32R2);
9189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
9190 register_name = "SRSConf4";
9191 break;
9192 case CP0_REG06__PWCTL:
9193 check_pw(ctx);
9194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
9195 register_name = "PWCtl";
9196 break;
9197 default:
9198 goto cp0_unimplemented;
9200 break;
9201 case CP0_REGISTER_07:
9202 switch (sel) {
9203 case CP0_REG07__HWRENA:
9204 check_insn(ctx, ISA_MIPS32R2);
9205 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
9206 register_name = "HWREna";
9207 break;
9208 default:
9209 goto cp0_unimplemented;
9211 break;
9212 case CP0_REGISTER_08:
9213 switch (sel) {
9214 case CP0_REG08__BADVADDR:
9215 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
9216 register_name = "BadVAddr";
9217 break;
9218 case CP0_REG08__BADINSTR:
9219 CP0_CHECK(ctx->bi);
9220 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
9221 register_name = "BadInstr";
9222 break;
9223 case CP0_REG08__BADINSTRP:
9224 CP0_CHECK(ctx->bp);
9225 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
9226 register_name = "BadInstrP";
9227 break;
9228 case CP0_REG08__BADINSTRX:
9229 CP0_CHECK(ctx->bi);
9230 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
9231 tcg_gen_andi_tl(arg, arg, ~0xffff);
9232 register_name = "BadInstrX";
9233 break;
9234 default:
9235 goto cp0_unimplemented;
9237 break;
9238 case CP0_REGISTER_09:
9239 switch (sel) {
9240 case CP0_REG09__COUNT:
9241 /* Mark as an IO operation because we read the time. */
9242 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9243 gen_io_start();
9245 gen_helper_mfc0_count(arg, cpu_env);
9247 * Break the TB to be able to take timer interrupts immediately
9248 * after reading count. DISAS_STOP isn't sufficient, we need to
9249 * ensure we break completely out of translated code.
9251 gen_save_pc(ctx->base.pc_next + 4);
9252 ctx->base.is_jmp = DISAS_EXIT;
9253 register_name = "Count";
9254 break;
9255 case CP0_REG09__SAARI:
9256 CP0_CHECK(ctx->saar);
9257 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
9258 register_name = "SAARI";
9259 break;
9260 case CP0_REG09__SAAR:
9261 CP0_CHECK(ctx->saar);
9262 gen_helper_dmfc0_saar(arg, cpu_env);
9263 register_name = "SAAR";
9264 break;
9265 default:
9266 goto cp0_unimplemented;
9268 break;
9269 case CP0_REGISTER_10:
9270 switch (sel) {
9271 case CP0_REG10__ENTRYHI:
9272 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
9273 register_name = "EntryHi";
9274 break;
9275 default:
9276 goto cp0_unimplemented;
9278 break;
9279 case CP0_REGISTER_11:
9280 switch (sel) {
9281 case CP0_REG11__COMPARE:
9282 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
9283 register_name = "Compare";
9284 break;
9285 /* 6,7 are implementation dependent */
9286 default:
9287 goto cp0_unimplemented;
9289 break;
9290 case CP0_REGISTER_12:
9291 switch (sel) {
9292 case CP0_REG12__STATUS:
9293 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
9294 register_name = "Status";
9295 break;
9296 case CP0_REG12__INTCTL:
9297 check_insn(ctx, ISA_MIPS32R2);
9298 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
9299 register_name = "IntCtl";
9300 break;
9301 case CP0_REG12__SRSCTL:
9302 check_insn(ctx, ISA_MIPS32R2);
9303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
9304 register_name = "SRSCtl";
9305 break;
9306 case CP0_REG12__SRSMAP:
9307 check_insn(ctx, ISA_MIPS32R2);
9308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
9309 register_name = "SRSMap";
9310 break;
9311 default:
9312 goto cp0_unimplemented;
9314 break;
9315 case CP0_REGISTER_13:
9316 switch (sel) {
9317 case CP0_REG13__CAUSE:
9318 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
9319 register_name = "Cause";
9320 break;
9321 default:
9322 goto cp0_unimplemented;
9324 break;
9325 case CP0_REGISTER_14:
9326 switch (sel) {
9327 case CP0_REG14__EPC:
9328 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
9329 register_name = "EPC";
9330 break;
9331 default:
9332 goto cp0_unimplemented;
9334 break;
9335 case CP0_REGISTER_15:
9336 switch (sel) {
9337 case CP0_REG15__PRID:
9338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
9339 register_name = "PRid";
9340 break;
9341 case CP0_REG15__EBASE:
9342 check_insn(ctx, ISA_MIPS32R2);
9343 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
9344 register_name = "EBase";
9345 break;
9346 case CP0_REG15__CMGCRBASE:
9347 check_insn(ctx, ISA_MIPS32R2);
9348 CP0_CHECK(ctx->cmgcr);
9349 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
9350 register_name = "CMGCRBase";
9351 break;
9352 default:
9353 goto cp0_unimplemented;
9355 break;
9356 case CP0_REGISTER_16:
9357 switch (sel) {
9358 case CP0_REG16__CONFIG:
9359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
9360 register_name = "Config";
9361 break;
9362 case CP0_REG16__CONFIG1:
9363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
9364 register_name = "Config1";
9365 break;
9366 case CP0_REG16__CONFIG2:
9367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
9368 register_name = "Config2";
9369 break;
9370 case CP0_REG16__CONFIG3:
9371 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
9372 register_name = "Config3";
9373 break;
9374 case CP0_REG16__CONFIG4:
9375 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
9376 register_name = "Config4";
9377 break;
9378 case CP0_REG16__CONFIG5:
9379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
9380 register_name = "Config5";
9381 break;
9382 /* 6,7 are implementation dependent */
9383 case CP0_REG16__CONFIG6:
9384 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
9385 register_name = "Config6";
9386 break;
9387 case CP0_REG16__CONFIG7:
9388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
9389 register_name = "Config7";
9390 break;
9391 default:
9392 goto cp0_unimplemented;
9394 break;
9395 case CP0_REGISTER_17:
9396 switch (sel) {
9397 case CP0_REG17__LLADDR:
9398 gen_helper_dmfc0_lladdr(arg, cpu_env);
9399 register_name = "LLAddr";
9400 break;
9401 case CP0_REG17__MAAR:
9402 CP0_CHECK(ctx->mrp);
9403 gen_helper_dmfc0_maar(arg, cpu_env);
9404 register_name = "MAAR";
9405 break;
9406 case CP0_REG17__MAARI:
9407 CP0_CHECK(ctx->mrp);
9408 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
9409 register_name = "MAARI";
9410 break;
9411 default:
9412 goto cp0_unimplemented;
9414 break;
9415 case CP0_REGISTER_18:
9416 switch (sel) {
9417 case CP0_REG18__WATCHLO0:
9418 case CP0_REG18__WATCHLO1:
9419 case CP0_REG18__WATCHLO2:
9420 case CP0_REG18__WATCHLO3:
9421 case CP0_REG18__WATCHLO4:
9422 case CP0_REG18__WATCHLO5:
9423 case CP0_REG18__WATCHLO6:
9424 case CP0_REG18__WATCHLO7:
9425 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9426 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
9427 register_name = "WatchLo";
9428 break;
9429 default:
9430 goto cp0_unimplemented;
9432 break;
9433 case CP0_REGISTER_19:
9434 switch (sel) {
9435 case CP0_REG19__WATCHHI0:
9436 case CP0_REG19__WATCHHI1:
9437 case CP0_REG19__WATCHHI2:
9438 case CP0_REG19__WATCHHI3:
9439 case CP0_REG19__WATCHHI4:
9440 case CP0_REG19__WATCHHI5:
9441 case CP0_REG19__WATCHHI6:
9442 case CP0_REG19__WATCHHI7:
9443 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
9444 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
9445 register_name = "WatchHi";
9446 break;
9447 default:
9448 goto cp0_unimplemented;
9450 break;
9451 case CP0_REGISTER_20:
9452 switch (sel) {
9453 case CP0_REG20__XCONTEXT:
9454 check_insn(ctx, ISA_MIPS3);
9455 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
9456 register_name = "XContext";
9457 break;
9458 default:
9459 goto cp0_unimplemented;
9461 break;
9462 case CP0_REGISTER_21:
9463 /* Officially reserved, but sel 0 is used for R1x000 framemask */
9464 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
9465 switch (sel) {
9466 case 0:
9467 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
9468 register_name = "Framemask";
9469 break;
9470 default:
9471 goto cp0_unimplemented;
9473 break;
9474 case CP0_REGISTER_22:
9475 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9476 register_name = "'Diagnostic"; /* implementation dependent */
9477 break;
9478 case CP0_REGISTER_23:
9479 switch (sel) {
9480 case CP0_REG23__DEBUG:
9481 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
9482 register_name = "Debug";
9483 break;
9484 case CP0_REG23__TRACECONTROL:
9485 /* PDtrace support */
9486 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
9487 register_name = "TraceControl";
9488 goto cp0_unimplemented;
9489 case CP0_REG23__TRACECONTROL2:
9490 /* PDtrace support */
9491 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
9492 register_name = "TraceControl2";
9493 goto cp0_unimplemented;
9494 case CP0_REG23__USERTRACEDATA1:
9495 /* PDtrace support */
9496 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
9497 register_name = "UserTraceData1";
9498 goto cp0_unimplemented;
9499 case CP0_REG23__TRACEIBPC:
9500 /* PDtrace support */
9501 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
9502 register_name = "TraceIBPC";
9503 goto cp0_unimplemented;
9504 case CP0_REG23__TRACEDBPC:
9505 /* PDtrace support */
9506 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
9507 register_name = "TraceDBPC";
9508 goto cp0_unimplemented;
9509 default:
9510 goto cp0_unimplemented;
9512 break;
9513 case CP0_REGISTER_24:
9514 switch (sel) {
9515 case CP0_REG24__DEPC:
9516 /* EJTAG support */
9517 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
9518 register_name = "DEPC";
9519 break;
9520 default:
9521 goto cp0_unimplemented;
9523 break;
9524 case CP0_REGISTER_25:
9525 switch (sel) {
9526 case CP0_REG25__PERFCTL0:
9527 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
9528 register_name = "Performance0";
9529 break;
9530 case CP0_REG25__PERFCNT0:
9531 /* gen_helper_dmfc0_performance1(arg); */
9532 register_name = "Performance1";
9533 goto cp0_unimplemented;
9534 case CP0_REG25__PERFCTL1:
9535 /* gen_helper_dmfc0_performance2(arg); */
9536 register_name = "Performance2";
9537 goto cp0_unimplemented;
9538 case CP0_REG25__PERFCNT1:
9539 /* gen_helper_dmfc0_performance3(arg); */
9540 register_name = "Performance3";
9541 goto cp0_unimplemented;
9542 case CP0_REG25__PERFCTL2:
9543 /* gen_helper_dmfc0_performance4(arg); */
9544 register_name = "Performance4";
9545 goto cp0_unimplemented;
9546 case CP0_REG25__PERFCNT2:
9547 /* gen_helper_dmfc0_performance5(arg); */
9548 register_name = "Performance5";
9549 goto cp0_unimplemented;
9550 case CP0_REG25__PERFCTL3:
9551 /* gen_helper_dmfc0_performance6(arg); */
9552 register_name = "Performance6";
9553 goto cp0_unimplemented;
9554 case CP0_REG25__PERFCNT3:
9555 /* gen_helper_dmfc0_performance7(arg); */
9556 register_name = "Performance7";
9557 goto cp0_unimplemented;
9558 default:
9559 goto cp0_unimplemented;
9561 break;
9562 case CP0_REGISTER_26:
9563 switch (sel) {
9564 case CP0_REG26__ERRCTL:
9565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
9566 register_name = "ErrCtl";
9567 break;
9568 default:
9569 goto cp0_unimplemented;
9571 break;
9572 case CP0_REGISTER_27:
9573 switch (sel) {
9574 /* ignored */
9575 case CP0_REG27__CACHERR:
9576 tcg_gen_movi_tl(arg, 0); /* unimplemented */
9577 register_name = "CacheErr";
9578 break;
9579 default:
9580 goto cp0_unimplemented;
9582 break;
9583 case CP0_REGISTER_28:
9584 switch (sel) {
9585 case CP0_REG28__TAGLO:
9586 case CP0_REG28__TAGLO1:
9587 case CP0_REG28__TAGLO2:
9588 case CP0_REG28__TAGLO3:
9589 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
9590 register_name = "TagLo";
9591 break;
9592 case CP0_REG28__DATALO:
9593 case CP0_REG28__DATALO1:
9594 case CP0_REG28__DATALO2:
9595 case CP0_REG28__DATALO3:
9596 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
9597 register_name = "DataLo";
9598 break;
9599 default:
9600 goto cp0_unimplemented;
9602 break;
9603 case CP0_REGISTER_29:
9604 switch (sel) {
9605 case CP0_REG29__TAGHI:
9606 case CP0_REG29__TAGHI1:
9607 case CP0_REG29__TAGHI2:
9608 case CP0_REG29__TAGHI3:
9609 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
9610 register_name = "TagHi";
9611 break;
9612 case CP0_REG29__DATAHI:
9613 case CP0_REG29__DATAHI1:
9614 case CP0_REG29__DATAHI2:
9615 case CP0_REG29__DATAHI3:
9616 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
9617 register_name = "DataHi";
9618 break;
9619 default:
9620 goto cp0_unimplemented;
9622 break;
9623 case CP0_REGISTER_30:
9624 switch (sel) {
9625 case CP0_REG30__ERROREPC:
9626 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
9627 register_name = "ErrorEPC";
9628 break;
9629 default:
9630 goto cp0_unimplemented;
9632 break;
9633 case CP0_REGISTER_31:
9634 switch (sel) {
9635 case CP0_REG31__DESAVE:
9636 /* EJTAG support */
9637 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
9638 register_name = "DESAVE";
9639 break;
9640 case CP0_REG31__KSCRATCH1:
9641 case CP0_REG31__KSCRATCH2:
9642 case CP0_REG31__KSCRATCH3:
9643 case CP0_REG31__KSCRATCH4:
9644 case CP0_REG31__KSCRATCH5:
9645 case CP0_REG31__KSCRATCH6:
9646 CP0_CHECK(ctx->kscrexist & (1 << sel));
9647 tcg_gen_ld_tl(arg, cpu_env,
9648 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
9649 register_name = "KScratch";
9650 break;
9651 default:
9652 goto cp0_unimplemented;
9654 break;
9655 default:
9656 goto cp0_unimplemented;
9658 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
9659 return;
9661 cp0_unimplemented:
9662 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
9663 register_name, reg, sel);
9664 gen_mfc0_unimplemented(ctx, arg);
9667 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
9669 const char *register_name = "invalid";
9671 if (sel != 0) {
9672 check_insn(ctx, ISA_MIPS32);
9675 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
9676 gen_io_start();
9679 switch (reg) {
9680 case CP0_REGISTER_00:
9681 switch (sel) {
9682 case CP0_REG00__INDEX:
9683 gen_helper_mtc0_index(cpu_env, arg);
9684 register_name = "Index";
9685 break;
9686 case CP0_REG00__MVPCONTROL:
9687 CP0_CHECK(ctx->insn_flags & ASE_MT);
9688 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
9689 register_name = "MVPControl";
9690 break;
9691 case CP0_REG00__MVPCONF0:
9692 CP0_CHECK(ctx->insn_flags & ASE_MT);
9693 /* ignored */
9694 register_name = "MVPConf0";
9695 break;
9696 case CP0_REG00__MVPCONF1:
9697 CP0_CHECK(ctx->insn_flags & ASE_MT);
9698 /* ignored */
9699 register_name = "MVPConf1";
9700 break;
9701 case CP0_REG00__VPCONTROL:
9702 CP0_CHECK(ctx->vp);
9703 /* ignored */
9704 register_name = "VPControl";
9705 break;
9706 default:
9707 goto cp0_unimplemented;
9709 break;
9710 case CP0_REGISTER_01:
9711 switch (sel) {
9712 case CP0_REG01__RANDOM:
9713 /* ignored */
9714 register_name = "Random";
9715 break;
9716 case CP0_REG01__VPECONTROL:
9717 CP0_CHECK(ctx->insn_flags & ASE_MT);
9718 gen_helper_mtc0_vpecontrol(cpu_env, arg);
9719 register_name = "VPEControl";
9720 break;
9721 case CP0_REG01__VPECONF0:
9722 CP0_CHECK(ctx->insn_flags & ASE_MT);
9723 gen_helper_mtc0_vpeconf0(cpu_env, arg);
9724 register_name = "VPEConf0";
9725 break;
9726 case CP0_REG01__VPECONF1:
9727 CP0_CHECK(ctx->insn_flags & ASE_MT);
9728 gen_helper_mtc0_vpeconf1(cpu_env, arg);
9729 register_name = "VPEConf1";
9730 break;
9731 case CP0_REG01__YQMASK:
9732 CP0_CHECK(ctx->insn_flags & ASE_MT);
9733 gen_helper_mtc0_yqmask(cpu_env, arg);
9734 register_name = "YQMask";
9735 break;
9736 case CP0_REG01__VPESCHEDULE:
9737 CP0_CHECK(ctx->insn_flags & ASE_MT);
9738 tcg_gen_st_tl(arg, cpu_env,
9739 offsetof(CPUMIPSState, CP0_VPESchedule));
9740 register_name = "VPESchedule";
9741 break;
9742 case CP0_REG01__VPESCHEFBACK:
9743 CP0_CHECK(ctx->insn_flags & ASE_MT);
9744 tcg_gen_st_tl(arg, cpu_env,
9745 offsetof(CPUMIPSState, CP0_VPEScheFBack));
9746 register_name = "VPEScheFBack";
9747 break;
9748 case CP0_REG01__VPEOPT:
9749 CP0_CHECK(ctx->insn_flags & ASE_MT);
9750 gen_helper_mtc0_vpeopt(cpu_env, arg);
9751 register_name = "VPEOpt";
9752 break;
9753 default:
9754 goto cp0_unimplemented;
9756 break;
9757 case CP0_REGISTER_02:
9758 switch (sel) {
9759 case CP0_REG02__ENTRYLO0:
9760 gen_helper_dmtc0_entrylo0(cpu_env, arg);
9761 register_name = "EntryLo0";
9762 break;
9763 case CP0_REG02__TCSTATUS:
9764 CP0_CHECK(ctx->insn_flags & ASE_MT);
9765 gen_helper_mtc0_tcstatus(cpu_env, arg);
9766 register_name = "TCStatus";
9767 break;
9768 case CP0_REG02__TCBIND:
9769 CP0_CHECK(ctx->insn_flags & ASE_MT);
9770 gen_helper_mtc0_tcbind(cpu_env, arg);
9771 register_name = "TCBind";
9772 break;
9773 case CP0_REG02__TCRESTART:
9774 CP0_CHECK(ctx->insn_flags & ASE_MT);
9775 gen_helper_mtc0_tcrestart(cpu_env, arg);
9776 register_name = "TCRestart";
9777 break;
9778 case CP0_REG02__TCHALT:
9779 CP0_CHECK(ctx->insn_flags & ASE_MT);
9780 gen_helper_mtc0_tchalt(cpu_env, arg);
9781 register_name = "TCHalt";
9782 break;
9783 case CP0_REG02__TCCONTEXT:
9784 CP0_CHECK(ctx->insn_flags & ASE_MT);
9785 gen_helper_mtc0_tccontext(cpu_env, arg);
9786 register_name = "TCContext";
9787 break;
9788 case CP0_REG02__TCSCHEDULE:
9789 CP0_CHECK(ctx->insn_flags & ASE_MT);
9790 gen_helper_mtc0_tcschedule(cpu_env, arg);
9791 register_name = "TCSchedule";
9792 break;
9793 case CP0_REG02__TCSCHEFBACK:
9794 CP0_CHECK(ctx->insn_flags & ASE_MT);
9795 gen_helper_mtc0_tcschefback(cpu_env, arg);
9796 register_name = "TCScheFBack";
9797 break;
9798 default:
9799 goto cp0_unimplemented;
9801 break;
9802 case CP0_REGISTER_03:
9803 switch (sel) {
9804 case CP0_REG03__ENTRYLO1:
9805 gen_helper_dmtc0_entrylo1(cpu_env, arg);
9806 register_name = "EntryLo1";
9807 break;
9808 case CP0_REG03__GLOBALNUM:
9809 CP0_CHECK(ctx->vp);
9810 /* ignored */
9811 register_name = "GlobalNumber";
9812 break;
9813 default:
9814 goto cp0_unimplemented;
9816 break;
9817 case CP0_REGISTER_04:
9818 switch (sel) {
9819 case CP0_REG04__CONTEXT:
9820 gen_helper_mtc0_context(cpu_env, arg);
9821 register_name = "Context";
9822 break;
9823 case CP0_REG04__CONTEXTCONFIG:
9824 /* SmartMIPS ASE */
9825 /* gen_helper_dmtc0_contextconfig(arg); */
9826 register_name = "ContextConfig";
9827 goto cp0_unimplemented;
9828 case CP0_REG04__USERLOCAL:
9829 CP0_CHECK(ctx->ulri);
9830 tcg_gen_st_tl(arg, cpu_env,
9831 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9832 register_name = "UserLocal";
9833 break;
9834 case CP0_REG04__MMID:
9835 CP0_CHECK(ctx->mi);
9836 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
9837 register_name = "MMID";
9838 break;
9839 default:
9840 goto cp0_unimplemented;
9842 break;
9843 case CP0_REGISTER_05:
9844 switch (sel) {
9845 case CP0_REG05__PAGEMASK:
9846 gen_helper_mtc0_pagemask(cpu_env, arg);
9847 register_name = "PageMask";
9848 break;
9849 case CP0_REG05__PAGEGRAIN:
9850 check_insn(ctx, ISA_MIPS32R2);
9851 gen_helper_mtc0_pagegrain(cpu_env, arg);
9852 register_name = "PageGrain";
9853 break;
9854 case CP0_REG05__SEGCTL0:
9855 CP0_CHECK(ctx->sc);
9856 gen_helper_mtc0_segctl0(cpu_env, arg);
9857 register_name = "SegCtl0";
9858 break;
9859 case CP0_REG05__SEGCTL1:
9860 CP0_CHECK(ctx->sc);
9861 gen_helper_mtc0_segctl1(cpu_env, arg);
9862 register_name = "SegCtl1";
9863 break;
9864 case CP0_REG05__SEGCTL2:
9865 CP0_CHECK(ctx->sc);
9866 gen_helper_mtc0_segctl2(cpu_env, arg);
9867 register_name = "SegCtl2";
9868 break;
9869 case CP0_REG05__PWBASE:
9870 check_pw(ctx);
9871 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
9872 register_name = "PWBase";
9873 break;
9874 case CP0_REG05__PWFIELD:
9875 check_pw(ctx);
9876 gen_helper_mtc0_pwfield(cpu_env, arg);
9877 register_name = "PWField";
9878 break;
9879 case CP0_REG05__PWSIZE:
9880 check_pw(ctx);
9881 gen_helper_mtc0_pwsize(cpu_env, arg);
9882 register_name = "PWSize";
9883 break;
9884 default:
9885 goto cp0_unimplemented;
9887 break;
9888 case CP0_REGISTER_06:
9889 switch (sel) {
9890 case CP0_REG06__WIRED:
9891 gen_helper_mtc0_wired(cpu_env, arg);
9892 register_name = "Wired";
9893 break;
9894 case CP0_REG06__SRSCONF0:
9895 check_insn(ctx, ISA_MIPS32R2);
9896 gen_helper_mtc0_srsconf0(cpu_env, arg);
9897 register_name = "SRSConf0";
9898 break;
9899 case CP0_REG06__SRSCONF1:
9900 check_insn(ctx, ISA_MIPS32R2);
9901 gen_helper_mtc0_srsconf1(cpu_env, arg);
9902 register_name = "SRSConf1";
9903 break;
9904 case CP0_REG06__SRSCONF2:
9905 check_insn(ctx, ISA_MIPS32R2);
9906 gen_helper_mtc0_srsconf2(cpu_env, arg);
9907 register_name = "SRSConf2";
9908 break;
9909 case CP0_REG06__SRSCONF3:
9910 check_insn(ctx, ISA_MIPS32R2);
9911 gen_helper_mtc0_srsconf3(cpu_env, arg);
9912 register_name = "SRSConf3";
9913 break;
9914 case CP0_REG06__SRSCONF4:
9915 check_insn(ctx, ISA_MIPS32R2);
9916 gen_helper_mtc0_srsconf4(cpu_env, arg);
9917 register_name = "SRSConf4";
9918 break;
9919 case CP0_REG06__PWCTL:
9920 check_pw(ctx);
9921 gen_helper_mtc0_pwctl(cpu_env, arg);
9922 register_name = "PWCtl";
9923 break;
9924 default:
9925 goto cp0_unimplemented;
9927 break;
9928 case CP0_REGISTER_07:
9929 switch (sel) {
9930 case CP0_REG07__HWRENA:
9931 check_insn(ctx, ISA_MIPS32R2);
9932 gen_helper_mtc0_hwrena(cpu_env, arg);
9933 ctx->base.is_jmp = DISAS_STOP;
9934 register_name = "HWREna";
9935 break;
9936 default:
9937 goto cp0_unimplemented;
9939 break;
9940 case CP0_REGISTER_08:
9941 switch (sel) {
9942 case CP0_REG08__BADVADDR:
9943 /* ignored */
9944 register_name = "BadVAddr";
9945 break;
9946 case CP0_REG08__BADINSTR:
9947 /* ignored */
9948 register_name = "BadInstr";
9949 break;
9950 case CP0_REG08__BADINSTRP:
9951 /* ignored */
9952 register_name = "BadInstrP";
9953 break;
9954 case CP0_REG08__BADINSTRX:
9955 /* ignored */
9956 register_name = "BadInstrX";
9957 break;
9958 default:
9959 goto cp0_unimplemented;
9961 break;
9962 case CP0_REGISTER_09:
9963 switch (sel) {
9964 case CP0_REG09__COUNT:
9965 gen_helper_mtc0_count(cpu_env, arg);
9966 register_name = "Count";
9967 break;
9968 case CP0_REG09__SAARI:
9969 CP0_CHECK(ctx->saar);
9970 gen_helper_mtc0_saari(cpu_env, arg);
9971 register_name = "SAARI";
9972 break;
9973 case CP0_REG09__SAAR:
9974 CP0_CHECK(ctx->saar);
9975 gen_helper_mtc0_saar(cpu_env, arg);
9976 register_name = "SAAR";
9977 break;
9978 default:
9979 goto cp0_unimplemented;
9981 /* Stop translation as we may have switched the execution mode */
9982 ctx->base.is_jmp = DISAS_STOP;
9983 break;
9984 case CP0_REGISTER_10:
9985 switch (sel) {
9986 case CP0_REG10__ENTRYHI:
9987 gen_helper_mtc0_entryhi(cpu_env, arg);
9988 register_name = "EntryHi";
9989 break;
9990 default:
9991 goto cp0_unimplemented;
9993 break;
9994 case CP0_REGISTER_11:
9995 switch (sel) {
9996 case CP0_REG11__COMPARE:
9997 gen_helper_mtc0_compare(cpu_env, arg);
9998 register_name = "Compare";
9999 break;
10000 /* 6,7 are implementation dependent */
10001 default:
10002 goto cp0_unimplemented;
10004 /* Stop translation as we may have switched the execution mode */
10005 ctx->base.is_jmp = DISAS_STOP;
10006 break;
10007 case CP0_REGISTER_12:
10008 switch (sel) {
10009 case CP0_REG12__STATUS:
10010 save_cpu_state(ctx, 1);
10011 gen_helper_mtc0_status(cpu_env, arg);
10012 /* DISAS_STOP isn't good enough here, hflags may have changed. */
10013 gen_save_pc(ctx->base.pc_next + 4);
10014 ctx->base.is_jmp = DISAS_EXIT;
10015 register_name = "Status";
10016 break;
10017 case CP0_REG12__INTCTL:
10018 check_insn(ctx, ISA_MIPS32R2);
10019 gen_helper_mtc0_intctl(cpu_env, arg);
10020 /* Stop translation as we may have switched the execution mode */
10021 ctx->base.is_jmp = DISAS_STOP;
10022 register_name = "IntCtl";
10023 break;
10024 case CP0_REG12__SRSCTL:
10025 check_insn(ctx, ISA_MIPS32R2);
10026 gen_helper_mtc0_srsctl(cpu_env, arg);
10027 /* Stop translation as we may have switched the execution mode */
10028 ctx->base.is_jmp = DISAS_STOP;
10029 register_name = "SRSCtl";
10030 break;
10031 case CP0_REG12__SRSMAP:
10032 check_insn(ctx, ISA_MIPS32R2);
10033 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
10034 /* Stop translation as we may have switched the execution mode */
10035 ctx->base.is_jmp = DISAS_STOP;
10036 register_name = "SRSMap";
10037 break;
10038 default:
10039 goto cp0_unimplemented;
10041 break;
10042 case CP0_REGISTER_13:
10043 switch (sel) {
10044 case CP0_REG13__CAUSE:
10045 save_cpu_state(ctx, 1);
10046 gen_helper_mtc0_cause(cpu_env, arg);
10048 * Stop translation as we may have triggered an interrupt.
10049 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10050 * translated code to check for pending interrupts.
10052 gen_save_pc(ctx->base.pc_next + 4);
10053 ctx->base.is_jmp = DISAS_EXIT;
10054 register_name = "Cause";
10055 break;
10056 default:
10057 goto cp0_unimplemented;
10059 break;
10060 case CP0_REGISTER_14:
10061 switch (sel) {
10062 case CP0_REG14__EPC:
10063 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
10064 register_name = "EPC";
10065 break;
10066 default:
10067 goto cp0_unimplemented;
10069 break;
10070 case CP0_REGISTER_15:
10071 switch (sel) {
10072 case CP0_REG15__PRID:
10073 /* ignored */
10074 register_name = "PRid";
10075 break;
10076 case CP0_REG15__EBASE:
10077 check_insn(ctx, ISA_MIPS32R2);
10078 gen_helper_mtc0_ebase(cpu_env, arg);
10079 register_name = "EBase";
10080 break;
10081 default:
10082 goto cp0_unimplemented;
10084 break;
10085 case CP0_REGISTER_16:
10086 switch (sel) {
10087 case CP0_REG16__CONFIG:
10088 gen_helper_mtc0_config0(cpu_env, arg);
10089 register_name = "Config";
10090 /* Stop translation as we may have switched the execution mode */
10091 ctx->base.is_jmp = DISAS_STOP;
10092 break;
10093 case CP0_REG16__CONFIG1:
10094 /* ignored, read only */
10095 register_name = "Config1";
10096 break;
10097 case CP0_REG16__CONFIG2:
10098 gen_helper_mtc0_config2(cpu_env, arg);
10099 register_name = "Config2";
10100 /* Stop translation as we may have switched the execution mode */
10101 ctx->base.is_jmp = DISAS_STOP;
10102 break;
10103 case CP0_REG16__CONFIG3:
10104 gen_helper_mtc0_config3(cpu_env, arg);
10105 register_name = "Config3";
10106 /* Stop translation as we may have switched the execution mode */
10107 ctx->base.is_jmp = DISAS_STOP;
10108 break;
10109 case CP0_REG16__CONFIG4:
10110 /* currently ignored */
10111 register_name = "Config4";
10112 break;
10113 case CP0_REG16__CONFIG5:
10114 gen_helper_mtc0_config5(cpu_env, arg);
10115 register_name = "Config5";
10116 /* Stop translation as we may have switched the execution mode */
10117 ctx->base.is_jmp = DISAS_STOP;
10118 break;
10119 /* 6,7 are implementation dependent */
10120 default:
10121 register_name = "Invalid config selector";
10122 goto cp0_unimplemented;
10124 break;
10125 case CP0_REGISTER_17:
10126 switch (sel) {
10127 case CP0_REG17__LLADDR:
10128 gen_helper_mtc0_lladdr(cpu_env, arg);
10129 register_name = "LLAddr";
10130 break;
10131 case CP0_REG17__MAAR:
10132 CP0_CHECK(ctx->mrp);
10133 gen_helper_mtc0_maar(cpu_env, arg);
10134 register_name = "MAAR";
10135 break;
10136 case CP0_REG17__MAARI:
10137 CP0_CHECK(ctx->mrp);
10138 gen_helper_mtc0_maari(cpu_env, arg);
10139 register_name = "MAARI";
10140 break;
10141 default:
10142 goto cp0_unimplemented;
10144 break;
10145 case CP0_REGISTER_18:
10146 switch (sel) {
10147 case CP0_REG18__WATCHLO0:
10148 case CP0_REG18__WATCHLO1:
10149 case CP0_REG18__WATCHLO2:
10150 case CP0_REG18__WATCHLO3:
10151 case CP0_REG18__WATCHLO4:
10152 case CP0_REG18__WATCHLO5:
10153 case CP0_REG18__WATCHLO6:
10154 case CP0_REG18__WATCHLO7:
10155 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10156 gen_helper_0e1i(mtc0_watchlo, arg, sel);
10157 register_name = "WatchLo";
10158 break;
10159 default:
10160 goto cp0_unimplemented;
10162 break;
10163 case CP0_REGISTER_19:
10164 switch (sel) {
10165 case CP0_REG19__WATCHHI0:
10166 case CP0_REG19__WATCHHI1:
10167 case CP0_REG19__WATCHHI2:
10168 case CP0_REG19__WATCHHI3:
10169 case CP0_REG19__WATCHHI4:
10170 case CP0_REG19__WATCHHI5:
10171 case CP0_REG19__WATCHHI6:
10172 case CP0_REG19__WATCHHI7:
10173 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
10174 gen_helper_0e1i(mtc0_watchhi, arg, sel);
10175 register_name = "WatchHi";
10176 break;
10177 default:
10178 goto cp0_unimplemented;
10180 break;
10181 case CP0_REGISTER_20:
10182 switch (sel) {
10183 case CP0_REG20__XCONTEXT:
10184 check_insn(ctx, ISA_MIPS3);
10185 gen_helper_mtc0_xcontext(cpu_env, arg);
10186 register_name = "XContext";
10187 break;
10188 default:
10189 goto cp0_unimplemented;
10191 break;
10192 case CP0_REGISTER_21:
10193 /* Officially reserved, but sel 0 is used for R1x000 framemask */
10194 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS32R6));
10195 switch (sel) {
10196 case 0:
10197 gen_helper_mtc0_framemask(cpu_env, arg);
10198 register_name = "Framemask";
10199 break;
10200 default:
10201 goto cp0_unimplemented;
10203 break;
10204 case CP0_REGISTER_22:
10205 /* ignored */
10206 register_name = "Diagnostic"; /* implementation dependent */
10207 break;
10208 case CP0_REGISTER_23:
10209 switch (sel) {
10210 case CP0_REG23__DEBUG:
10211 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
10212 /* DISAS_STOP isn't good enough here, hflags may have changed. */
10213 gen_save_pc(ctx->base.pc_next + 4);
10214 ctx->base.is_jmp = DISAS_EXIT;
10215 register_name = "Debug";
10216 break;
10217 case CP0_REG23__TRACECONTROL:
10218 /* PDtrace support */
10219 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
10220 /* Stop translation as we may have switched the execution mode */
10221 ctx->base.is_jmp = DISAS_STOP;
10222 register_name = "TraceControl";
10223 goto cp0_unimplemented;
10224 case CP0_REG23__TRACECONTROL2:
10225 /* PDtrace support */
10226 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
10227 /* Stop translation as we may have switched the execution mode */
10228 ctx->base.is_jmp = DISAS_STOP;
10229 register_name = "TraceControl2";
10230 goto cp0_unimplemented;
10231 case CP0_REG23__USERTRACEDATA1:
10232 /* PDtrace support */
10233 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
10234 /* Stop translation as we may have switched the execution mode */
10235 ctx->base.is_jmp = DISAS_STOP;
10236 register_name = "UserTraceData1";
10237 goto cp0_unimplemented;
10238 case CP0_REG23__TRACEIBPC:
10239 /* PDtrace support */
10240 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
10241 /* Stop translation as we may have switched the execution mode */
10242 ctx->base.is_jmp = DISAS_STOP;
10243 register_name = "TraceIBPC";
10244 goto cp0_unimplemented;
10245 case CP0_REG23__TRACEDBPC:
10246 /* PDtrace support */
10247 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
10248 /* Stop translation as we may have switched the execution mode */
10249 ctx->base.is_jmp = DISAS_STOP;
10250 register_name = "TraceDBPC";
10251 goto cp0_unimplemented;
10252 default:
10253 goto cp0_unimplemented;
10255 break;
10256 case CP0_REGISTER_24:
10257 switch (sel) {
10258 case CP0_REG24__DEPC:
10259 /* EJTAG support */
10260 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
10261 register_name = "DEPC";
10262 break;
10263 default:
10264 goto cp0_unimplemented;
10266 break;
10267 case CP0_REGISTER_25:
10268 switch (sel) {
10269 case CP0_REG25__PERFCTL0:
10270 gen_helper_mtc0_performance0(cpu_env, arg);
10271 register_name = "Performance0";
10272 break;
10273 case CP0_REG25__PERFCNT0:
10274 /* gen_helper_mtc0_performance1(cpu_env, arg); */
10275 register_name = "Performance1";
10276 goto cp0_unimplemented;
10277 case CP0_REG25__PERFCTL1:
10278 /* gen_helper_mtc0_performance2(cpu_env, arg); */
10279 register_name = "Performance2";
10280 goto cp0_unimplemented;
10281 case CP0_REG25__PERFCNT1:
10282 /* gen_helper_mtc0_performance3(cpu_env, arg); */
10283 register_name = "Performance3";
10284 goto cp0_unimplemented;
10285 case CP0_REG25__PERFCTL2:
10286 /* gen_helper_mtc0_performance4(cpu_env, arg); */
10287 register_name = "Performance4";
10288 goto cp0_unimplemented;
10289 case CP0_REG25__PERFCNT2:
10290 /* gen_helper_mtc0_performance5(cpu_env, arg); */
10291 register_name = "Performance5";
10292 goto cp0_unimplemented;
10293 case CP0_REG25__PERFCTL3:
10294 /* gen_helper_mtc0_performance6(cpu_env, arg); */
10295 register_name = "Performance6";
10296 goto cp0_unimplemented;
10297 case CP0_REG25__PERFCNT3:
10298 /* gen_helper_mtc0_performance7(cpu_env, arg); */
10299 register_name = "Performance7";
10300 goto cp0_unimplemented;
10301 default:
10302 goto cp0_unimplemented;
10304 break;
10305 case CP0_REGISTER_26:
10306 switch (sel) {
10307 case CP0_REG26__ERRCTL:
10308 gen_helper_mtc0_errctl(cpu_env, arg);
10309 ctx->base.is_jmp = DISAS_STOP;
10310 register_name = "ErrCtl";
10311 break;
10312 default:
10313 goto cp0_unimplemented;
10315 break;
10316 case CP0_REGISTER_27:
10317 switch (sel) {
10318 case CP0_REG27__CACHERR:
10319 /* ignored */
10320 register_name = "CacheErr";
10321 break;
10322 default:
10323 goto cp0_unimplemented;
10325 break;
10326 case CP0_REGISTER_28:
10327 switch (sel) {
10328 case CP0_REG28__TAGLO:
10329 case CP0_REG28__TAGLO1:
10330 case CP0_REG28__TAGLO2:
10331 case CP0_REG28__TAGLO3:
10332 gen_helper_mtc0_taglo(cpu_env, arg);
10333 register_name = "TagLo";
10334 break;
10335 case CP0_REG28__DATALO:
10336 case CP0_REG28__DATALO1:
10337 case CP0_REG28__DATALO2:
10338 case CP0_REG28__DATALO3:
10339 gen_helper_mtc0_datalo(cpu_env, arg);
10340 register_name = "DataLo";
10341 break;
10342 default:
10343 goto cp0_unimplemented;
10345 break;
10346 case CP0_REGISTER_29:
10347 switch (sel) {
10348 case CP0_REG29__TAGHI:
10349 case CP0_REG29__TAGHI1:
10350 case CP0_REG29__TAGHI2:
10351 case CP0_REG29__TAGHI3:
10352 gen_helper_mtc0_taghi(cpu_env, arg);
10353 register_name = "TagHi";
10354 break;
10355 case CP0_REG29__DATAHI:
10356 case CP0_REG29__DATAHI1:
10357 case CP0_REG29__DATAHI2:
10358 case CP0_REG29__DATAHI3:
10359 gen_helper_mtc0_datahi(cpu_env, arg);
10360 register_name = "DataHi";
10361 break;
10362 default:
10363 register_name = "invalid sel";
10364 goto cp0_unimplemented;
10366 break;
10367 case CP0_REGISTER_30:
10368 switch (sel) {
10369 case CP0_REG30__ERROREPC:
10370 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
10371 register_name = "ErrorEPC";
10372 break;
10373 default:
10374 goto cp0_unimplemented;
10376 break;
10377 case CP0_REGISTER_31:
10378 switch (sel) {
10379 case CP0_REG31__DESAVE:
10380 /* EJTAG support */
10381 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
10382 register_name = "DESAVE";
10383 break;
10384 case CP0_REG31__KSCRATCH1:
10385 case CP0_REG31__KSCRATCH2:
10386 case CP0_REG31__KSCRATCH3:
10387 case CP0_REG31__KSCRATCH4:
10388 case CP0_REG31__KSCRATCH5:
10389 case CP0_REG31__KSCRATCH6:
10390 CP0_CHECK(ctx->kscrexist & (1 << sel));
10391 tcg_gen_st_tl(arg, cpu_env,
10392 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
10393 register_name = "KScratch";
10394 break;
10395 default:
10396 goto cp0_unimplemented;
10398 break;
10399 default:
10400 goto cp0_unimplemented;
10402 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
10404 /* For simplicity assume that all writes can cause interrupts. */
10405 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
10407 * DISAS_STOP isn't sufficient, we need to ensure we break out of
10408 * translated code to check for pending interrupts.
10410 gen_save_pc(ctx->base.pc_next + 4);
10411 ctx->base.is_jmp = DISAS_EXIT;
10413 return;
10415 cp0_unimplemented:
10416 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
10417 register_name, reg, sel);
10419 #endif /* TARGET_MIPS64 */
10421 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
10422 int u, int sel, int h)
10424 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10425 TCGv t0 = tcg_temp_local_new();
10427 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10428 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10429 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10430 tcg_gen_movi_tl(t0, -1);
10431 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10432 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10433 tcg_gen_movi_tl(t0, -1);
10434 } else if (u == 0) {
10435 switch (rt) {
10436 case 1:
10437 switch (sel) {
10438 case 1:
10439 gen_helper_mftc0_vpecontrol(t0, cpu_env);
10440 break;
10441 case 2:
10442 gen_helper_mftc0_vpeconf0(t0, cpu_env);
10443 break;
10444 default:
10445 goto die;
10446 break;
10448 break;
10449 case 2:
10450 switch (sel) {
10451 case 1:
10452 gen_helper_mftc0_tcstatus(t0, cpu_env);
10453 break;
10454 case 2:
10455 gen_helper_mftc0_tcbind(t0, cpu_env);
10456 break;
10457 case 3:
10458 gen_helper_mftc0_tcrestart(t0, cpu_env);
10459 break;
10460 case 4:
10461 gen_helper_mftc0_tchalt(t0, cpu_env);
10462 break;
10463 case 5:
10464 gen_helper_mftc0_tccontext(t0, cpu_env);
10465 break;
10466 case 6:
10467 gen_helper_mftc0_tcschedule(t0, cpu_env);
10468 break;
10469 case 7:
10470 gen_helper_mftc0_tcschefback(t0, cpu_env);
10471 break;
10472 default:
10473 gen_mfc0(ctx, t0, rt, sel);
10474 break;
10476 break;
10477 case 10:
10478 switch (sel) {
10479 case 0:
10480 gen_helper_mftc0_entryhi(t0, cpu_env);
10481 break;
10482 default:
10483 gen_mfc0(ctx, t0, rt, sel);
10484 break;
10486 break;
10487 case 12:
10488 switch (sel) {
10489 case 0:
10490 gen_helper_mftc0_status(t0, cpu_env);
10491 break;
10492 default:
10493 gen_mfc0(ctx, t0, rt, sel);
10494 break;
10496 break;
10497 case 13:
10498 switch (sel) {
10499 case 0:
10500 gen_helper_mftc0_cause(t0, cpu_env);
10501 break;
10502 default:
10503 goto die;
10504 break;
10506 break;
10507 case 14:
10508 switch (sel) {
10509 case 0:
10510 gen_helper_mftc0_epc(t0, cpu_env);
10511 break;
10512 default:
10513 goto die;
10514 break;
10516 break;
10517 case 15:
10518 switch (sel) {
10519 case 1:
10520 gen_helper_mftc0_ebase(t0, cpu_env);
10521 break;
10522 default:
10523 goto die;
10524 break;
10526 break;
10527 case 16:
10528 switch (sel) {
10529 case 0:
10530 case 1:
10531 case 2:
10532 case 3:
10533 case 4:
10534 case 5:
10535 case 6:
10536 case 7:
10537 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
10538 break;
10539 default:
10540 goto die;
10541 break;
10543 break;
10544 case 23:
10545 switch (sel) {
10546 case 0:
10547 gen_helper_mftc0_debug(t0, cpu_env);
10548 break;
10549 default:
10550 gen_mfc0(ctx, t0, rt, sel);
10551 break;
10553 break;
10554 default:
10555 gen_mfc0(ctx, t0, rt, sel);
10557 } else {
10558 switch (sel) {
10559 /* GPR registers. */
10560 case 0:
10561 gen_helper_1e0i(mftgpr, t0, rt);
10562 break;
10563 /* Auxiliary CPU registers */
10564 case 1:
10565 switch (rt) {
10566 case 0:
10567 gen_helper_1e0i(mftlo, t0, 0);
10568 break;
10569 case 1:
10570 gen_helper_1e0i(mfthi, t0, 0);
10571 break;
10572 case 2:
10573 gen_helper_1e0i(mftacx, t0, 0);
10574 break;
10575 case 4:
10576 gen_helper_1e0i(mftlo, t0, 1);
10577 break;
10578 case 5:
10579 gen_helper_1e0i(mfthi, t0, 1);
10580 break;
10581 case 6:
10582 gen_helper_1e0i(mftacx, t0, 1);
10583 break;
10584 case 8:
10585 gen_helper_1e0i(mftlo, t0, 2);
10586 break;
10587 case 9:
10588 gen_helper_1e0i(mfthi, t0, 2);
10589 break;
10590 case 10:
10591 gen_helper_1e0i(mftacx, t0, 2);
10592 break;
10593 case 12:
10594 gen_helper_1e0i(mftlo, t0, 3);
10595 break;
10596 case 13:
10597 gen_helper_1e0i(mfthi, t0, 3);
10598 break;
10599 case 14:
10600 gen_helper_1e0i(mftacx, t0, 3);
10601 break;
10602 case 16:
10603 gen_helper_mftdsp(t0, cpu_env);
10604 break;
10605 default:
10606 goto die;
10608 break;
10609 /* Floating point (COP1). */
10610 case 2:
10611 /* XXX: For now we support only a single FPU context. */
10612 if (h == 0) {
10613 TCGv_i32 fp0 = tcg_temp_new_i32();
10615 gen_load_fpr32(ctx, fp0, rt);
10616 tcg_gen_ext_i32_tl(t0, fp0);
10617 tcg_temp_free_i32(fp0);
10618 } else {
10619 TCGv_i32 fp0 = tcg_temp_new_i32();
10621 gen_load_fpr32h(ctx, fp0, rt);
10622 tcg_gen_ext_i32_tl(t0, fp0);
10623 tcg_temp_free_i32(fp0);
10625 break;
10626 case 3:
10627 /* XXX: For now we support only a single FPU context. */
10628 gen_helper_1e0i(cfc1, t0, rt);
10629 break;
10630 /* COP2: Not implemented. */
10631 case 4:
10632 case 5:
10633 /* fall through */
10634 default:
10635 goto die;
10638 trace_mips_translate_tr("mftr", rt, u, sel, h);
10639 gen_store_gpr(t0, rd);
10640 tcg_temp_free(t0);
10641 return;
10643 die:
10644 tcg_temp_free(t0);
10645 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
10646 generate_exception_end(ctx, EXCP_RI);
10649 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
10650 int u, int sel, int h)
10652 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
10653 TCGv t0 = tcg_temp_local_new();
10655 gen_load_gpr(t0, rt);
10656 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
10657 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
10658 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
10659 /* NOP */
10661 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
10662 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
10663 /* NOP */
10665 } else if (u == 0) {
10666 switch (rd) {
10667 case 1:
10668 switch (sel) {
10669 case 1:
10670 gen_helper_mttc0_vpecontrol(cpu_env, t0);
10671 break;
10672 case 2:
10673 gen_helper_mttc0_vpeconf0(cpu_env, t0);
10674 break;
10675 default:
10676 goto die;
10677 break;
10679 break;
10680 case 2:
10681 switch (sel) {
10682 case 1:
10683 gen_helper_mttc0_tcstatus(cpu_env, t0);
10684 break;
10685 case 2:
10686 gen_helper_mttc0_tcbind(cpu_env, t0);
10687 break;
10688 case 3:
10689 gen_helper_mttc0_tcrestart(cpu_env, t0);
10690 break;
10691 case 4:
10692 gen_helper_mttc0_tchalt(cpu_env, t0);
10693 break;
10694 case 5:
10695 gen_helper_mttc0_tccontext(cpu_env, t0);
10696 break;
10697 case 6:
10698 gen_helper_mttc0_tcschedule(cpu_env, t0);
10699 break;
10700 case 7:
10701 gen_helper_mttc0_tcschefback(cpu_env, t0);
10702 break;
10703 default:
10704 gen_mtc0(ctx, t0, rd, sel);
10705 break;
10707 break;
10708 case 10:
10709 switch (sel) {
10710 case 0:
10711 gen_helper_mttc0_entryhi(cpu_env, t0);
10712 break;
10713 default:
10714 gen_mtc0(ctx, t0, rd, sel);
10715 break;
10717 break;
10718 case 12:
10719 switch (sel) {
10720 case 0:
10721 gen_helper_mttc0_status(cpu_env, t0);
10722 break;
10723 default:
10724 gen_mtc0(ctx, t0, rd, sel);
10725 break;
10727 break;
10728 case 13:
10729 switch (sel) {
10730 case 0:
10731 gen_helper_mttc0_cause(cpu_env, t0);
10732 break;
10733 default:
10734 goto die;
10735 break;
10737 break;
10738 case 15:
10739 switch (sel) {
10740 case 1:
10741 gen_helper_mttc0_ebase(cpu_env, t0);
10742 break;
10743 default:
10744 goto die;
10745 break;
10747 break;
10748 case 23:
10749 switch (sel) {
10750 case 0:
10751 gen_helper_mttc0_debug(cpu_env, t0);
10752 break;
10753 default:
10754 gen_mtc0(ctx, t0, rd, sel);
10755 break;
10757 break;
10758 default:
10759 gen_mtc0(ctx, t0, rd, sel);
10761 } else {
10762 switch (sel) {
10763 /* GPR registers. */
10764 case 0:
10765 gen_helper_0e1i(mttgpr, t0, rd);
10766 break;
10767 /* Auxiliary CPU registers */
10768 case 1:
10769 switch (rd) {
10770 case 0:
10771 gen_helper_0e1i(mttlo, t0, 0);
10772 break;
10773 case 1:
10774 gen_helper_0e1i(mtthi, t0, 0);
10775 break;
10776 case 2:
10777 gen_helper_0e1i(mttacx, t0, 0);
10778 break;
10779 case 4:
10780 gen_helper_0e1i(mttlo, t0, 1);
10781 break;
10782 case 5:
10783 gen_helper_0e1i(mtthi, t0, 1);
10784 break;
10785 case 6:
10786 gen_helper_0e1i(mttacx, t0, 1);
10787 break;
10788 case 8:
10789 gen_helper_0e1i(mttlo, t0, 2);
10790 break;
10791 case 9:
10792 gen_helper_0e1i(mtthi, t0, 2);
10793 break;
10794 case 10:
10795 gen_helper_0e1i(mttacx, t0, 2);
10796 break;
10797 case 12:
10798 gen_helper_0e1i(mttlo, t0, 3);
10799 break;
10800 case 13:
10801 gen_helper_0e1i(mtthi, t0, 3);
10802 break;
10803 case 14:
10804 gen_helper_0e1i(mttacx, t0, 3);
10805 break;
10806 case 16:
10807 gen_helper_mttdsp(cpu_env, t0);
10808 break;
10809 default:
10810 goto die;
10812 break;
10813 /* Floating point (COP1). */
10814 case 2:
10815 /* XXX: For now we support only a single FPU context. */
10816 if (h == 0) {
10817 TCGv_i32 fp0 = tcg_temp_new_i32();
10819 tcg_gen_trunc_tl_i32(fp0, t0);
10820 gen_store_fpr32(ctx, fp0, rd);
10821 tcg_temp_free_i32(fp0);
10822 } else {
10823 TCGv_i32 fp0 = tcg_temp_new_i32();
10825 tcg_gen_trunc_tl_i32(fp0, t0);
10826 gen_store_fpr32h(ctx, fp0, rd);
10827 tcg_temp_free_i32(fp0);
10829 break;
10830 case 3:
10831 /* XXX: For now we support only a single FPU context. */
10833 TCGv_i32 fs_tmp = tcg_const_i32(rd);
10835 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10836 tcg_temp_free_i32(fs_tmp);
10838 /* Stop translation as we may have changed hflags */
10839 ctx->base.is_jmp = DISAS_STOP;
10840 break;
10841 /* COP2: Not implemented. */
10842 case 4:
10843 case 5:
10844 /* fall through */
10845 default:
10846 goto die;
10849 trace_mips_translate_tr("mttr", rd, u, sel, h);
10850 tcg_temp_free(t0);
10851 return;
10853 die:
10854 tcg_temp_free(t0);
10855 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
10856 generate_exception_end(ctx, EXCP_RI);
10859 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
10860 int rt, int rd)
10862 const char *opn = "ldst";
10864 check_cp0_enabled(ctx);
10865 switch (opc) {
10866 case OPC_MFC0:
10867 if (rt == 0) {
10868 /* Treat as NOP. */
10869 return;
10871 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10872 opn = "mfc0";
10873 break;
10874 case OPC_MTC0:
10876 TCGv t0 = tcg_temp_new();
10878 gen_load_gpr(t0, rt);
10879 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
10880 tcg_temp_free(t0);
10882 opn = "mtc0";
10883 break;
10884 #if defined(TARGET_MIPS64)
10885 case OPC_DMFC0:
10886 check_insn(ctx, ISA_MIPS3);
10887 if (rt == 0) {
10888 /* Treat as NOP. */
10889 return;
10891 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10892 opn = "dmfc0";
10893 break;
10894 case OPC_DMTC0:
10895 check_insn(ctx, ISA_MIPS3);
10897 TCGv t0 = tcg_temp_new();
10899 gen_load_gpr(t0, rt);
10900 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
10901 tcg_temp_free(t0);
10903 opn = "dmtc0";
10904 break;
10905 #endif
10906 case OPC_MFHC0:
10907 check_mvh(ctx);
10908 if (rt == 0) {
10909 /* Treat as NOP. */
10910 return;
10912 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
10913 opn = "mfhc0";
10914 break;
10915 case OPC_MTHC0:
10916 check_mvh(ctx);
10918 TCGv t0 = tcg_temp_new();
10919 gen_load_gpr(t0, rt);
10920 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
10921 tcg_temp_free(t0);
10923 opn = "mthc0";
10924 break;
10925 case OPC_MFTR:
10926 check_cp0_enabled(ctx);
10927 if (rd == 0) {
10928 /* Treat as NOP. */
10929 return;
10931 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
10932 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10933 opn = "mftr";
10934 break;
10935 case OPC_MTTR:
10936 check_cp0_enabled(ctx);
10937 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
10938 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
10939 opn = "mttr";
10940 break;
10941 case OPC_TLBWI:
10942 opn = "tlbwi";
10943 if (!env->tlb->helper_tlbwi) {
10944 goto die;
10946 gen_helper_tlbwi(cpu_env);
10947 break;
10948 case OPC_TLBINV:
10949 opn = "tlbinv";
10950 if (ctx->ie >= 2) {
10951 if (!env->tlb->helper_tlbinv) {
10952 goto die;
10954 gen_helper_tlbinv(cpu_env);
10955 } /* treat as nop if TLBINV not supported */
10956 break;
10957 case OPC_TLBINVF:
10958 opn = "tlbinvf";
10959 if (ctx->ie >= 2) {
10960 if (!env->tlb->helper_tlbinvf) {
10961 goto die;
10963 gen_helper_tlbinvf(cpu_env);
10964 } /* treat as nop if TLBINV not supported */
10965 break;
10966 case OPC_TLBWR:
10967 opn = "tlbwr";
10968 if (!env->tlb->helper_tlbwr) {
10969 goto die;
10971 gen_helper_tlbwr(cpu_env);
10972 break;
10973 case OPC_TLBP:
10974 opn = "tlbp";
10975 if (!env->tlb->helper_tlbp) {
10976 goto die;
10978 gen_helper_tlbp(cpu_env);
10979 break;
10980 case OPC_TLBR:
10981 opn = "tlbr";
10982 if (!env->tlb->helper_tlbr) {
10983 goto die;
10985 gen_helper_tlbr(cpu_env);
10986 break;
10987 case OPC_ERET: /* OPC_ERETNC */
10988 if ((ctx->insn_flags & ISA_MIPS32R6) &&
10989 (ctx->hflags & MIPS_HFLAG_BMASK)) {
10990 goto die;
10991 } else {
10992 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
10993 if (ctx->opcode & (1 << bit_shift)) {
10994 /* OPC_ERETNC */
10995 opn = "eretnc";
10996 check_insn(ctx, ISA_MIPS32R5);
10997 gen_helper_eretnc(cpu_env);
10998 } else {
10999 /* OPC_ERET */
11000 opn = "eret";
11001 check_insn(ctx, ISA_MIPS2);
11002 gen_helper_eret(cpu_env);
11004 ctx->base.is_jmp = DISAS_EXIT;
11006 break;
11007 case OPC_DERET:
11008 opn = "deret";
11009 check_insn(ctx, ISA_MIPS32);
11010 if ((ctx->insn_flags & ISA_MIPS32R6) &&
11011 (ctx->hflags & MIPS_HFLAG_BMASK)) {
11012 goto die;
11014 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11015 MIPS_INVAL(opn);
11016 generate_exception_end(ctx, EXCP_RI);
11017 } else {
11018 gen_helper_deret(cpu_env);
11019 ctx->base.is_jmp = DISAS_EXIT;
11021 break;
11022 case OPC_WAIT:
11023 opn = "wait";
11024 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
11025 if ((ctx->insn_flags & ISA_MIPS32R6) &&
11026 (ctx->hflags & MIPS_HFLAG_BMASK)) {
11027 goto die;
11029 /* If we get an exception, we want to restart at next instruction */
11030 ctx->base.pc_next += 4;
11031 save_cpu_state(ctx, 1);
11032 ctx->base.pc_next -= 4;
11033 gen_helper_wait(cpu_env);
11034 ctx->base.is_jmp = DISAS_NORETURN;
11035 break;
11036 default:
11037 die:
11038 MIPS_INVAL(opn);
11039 generate_exception_end(ctx, EXCP_RI);
11040 return;
11042 (void)opn; /* avoid a compiler warning */
11044 #endif /* !CONFIG_USER_ONLY */
11046 /* CP1 Branches (before delay slot) */
11047 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
11048 int32_t cc, int32_t offset)
11050 target_ulong btarget;
11051 TCGv_i32 t0 = tcg_temp_new_i32();
11053 if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11054 generate_exception_end(ctx, EXCP_RI);
11055 goto out;
11058 if (cc != 0) {
11059 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
11062 btarget = ctx->base.pc_next + 4 + offset;
11064 switch (op) {
11065 case OPC_BC1F:
11066 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11067 tcg_gen_not_i32(t0, t0);
11068 tcg_gen_andi_i32(t0, t0, 1);
11069 tcg_gen_extu_i32_tl(bcond, t0);
11070 goto not_likely;
11071 case OPC_BC1FL:
11072 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11073 tcg_gen_not_i32(t0, t0);
11074 tcg_gen_andi_i32(t0, t0, 1);
11075 tcg_gen_extu_i32_tl(bcond, t0);
11076 goto likely;
11077 case OPC_BC1T:
11078 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11079 tcg_gen_andi_i32(t0, t0, 1);
11080 tcg_gen_extu_i32_tl(bcond, t0);
11081 goto not_likely;
11082 case OPC_BC1TL:
11083 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11084 tcg_gen_andi_i32(t0, t0, 1);
11085 tcg_gen_extu_i32_tl(bcond, t0);
11086 likely:
11087 ctx->hflags |= MIPS_HFLAG_BL;
11088 break;
11089 case OPC_BC1FANY2:
11091 TCGv_i32 t1 = tcg_temp_new_i32();
11092 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11093 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11094 tcg_gen_nand_i32(t0, t0, t1);
11095 tcg_temp_free_i32(t1);
11096 tcg_gen_andi_i32(t0, t0, 1);
11097 tcg_gen_extu_i32_tl(bcond, t0);
11099 goto not_likely;
11100 case OPC_BC1TANY2:
11102 TCGv_i32 t1 = tcg_temp_new_i32();
11103 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11104 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11105 tcg_gen_or_i32(t0, t0, t1);
11106 tcg_temp_free_i32(t1);
11107 tcg_gen_andi_i32(t0, t0, 1);
11108 tcg_gen_extu_i32_tl(bcond, t0);
11110 goto not_likely;
11111 case OPC_BC1FANY4:
11113 TCGv_i32 t1 = tcg_temp_new_i32();
11114 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11115 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11116 tcg_gen_and_i32(t0, t0, t1);
11117 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11118 tcg_gen_and_i32(t0, t0, t1);
11119 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11120 tcg_gen_nand_i32(t0, t0, t1);
11121 tcg_temp_free_i32(t1);
11122 tcg_gen_andi_i32(t0, t0, 1);
11123 tcg_gen_extu_i32_tl(bcond, t0);
11125 goto not_likely;
11126 case OPC_BC1TANY4:
11128 TCGv_i32 t1 = tcg_temp_new_i32();
11129 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
11130 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
11131 tcg_gen_or_i32(t0, t0, t1);
11132 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
11133 tcg_gen_or_i32(t0, t0, t1);
11134 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
11135 tcg_gen_or_i32(t0, t0, t1);
11136 tcg_temp_free_i32(t1);
11137 tcg_gen_andi_i32(t0, t0, 1);
11138 tcg_gen_extu_i32_tl(bcond, t0);
11140 not_likely:
11141 ctx->hflags |= MIPS_HFLAG_BC;
11142 break;
11143 default:
11144 MIPS_INVAL("cp1 cond branch");
11145 generate_exception_end(ctx, EXCP_RI);
11146 goto out;
11148 ctx->btarget = btarget;
11149 ctx->hflags |= MIPS_HFLAG_BDS32;
11150 out:
11151 tcg_temp_free_i32(t0);
11154 /* R6 CP1 Branches */
11155 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
11156 int32_t ft, int32_t offset,
11157 int delayslot_size)
11159 target_ulong btarget;
11160 TCGv_i64 t0 = tcg_temp_new_i64();
11162 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11163 #ifdef MIPS_DEBUG_DISAS
11164 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
11165 "\n", ctx->base.pc_next);
11166 #endif
11167 generate_exception_end(ctx, EXCP_RI);
11168 goto out;
11171 gen_load_fpr64(ctx, t0, ft);
11172 tcg_gen_andi_i64(t0, t0, 1);
11174 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11176 switch (op) {
11177 case OPC_BC1EQZ:
11178 tcg_gen_xori_i64(t0, t0, 1);
11179 ctx->hflags |= MIPS_HFLAG_BC;
11180 break;
11181 case OPC_BC1NEZ:
11182 /* t0 already set */
11183 ctx->hflags |= MIPS_HFLAG_BC;
11184 break;
11185 default:
11186 MIPS_INVAL("cp1 cond branch");
11187 generate_exception_end(ctx, EXCP_RI);
11188 goto out;
11191 tcg_gen_trunc_i64_tl(bcond, t0);
11193 ctx->btarget = btarget;
11195 switch (delayslot_size) {
11196 case 2:
11197 ctx->hflags |= MIPS_HFLAG_BDS16;
11198 break;
11199 case 4:
11200 ctx->hflags |= MIPS_HFLAG_BDS32;
11201 break;
11204 out:
11205 tcg_temp_free_i64(t0);
11208 /* Coprocessor 1 (FPU) */
11210 #define FOP(func, fmt) (((fmt) << 21) | (func))
11212 enum fopcode {
11213 OPC_ADD_S = FOP(0, FMT_S),
11214 OPC_SUB_S = FOP(1, FMT_S),
11215 OPC_MUL_S = FOP(2, FMT_S),
11216 OPC_DIV_S = FOP(3, FMT_S),
11217 OPC_SQRT_S = FOP(4, FMT_S),
11218 OPC_ABS_S = FOP(5, FMT_S),
11219 OPC_MOV_S = FOP(6, FMT_S),
11220 OPC_NEG_S = FOP(7, FMT_S),
11221 OPC_ROUND_L_S = FOP(8, FMT_S),
11222 OPC_TRUNC_L_S = FOP(9, FMT_S),
11223 OPC_CEIL_L_S = FOP(10, FMT_S),
11224 OPC_FLOOR_L_S = FOP(11, FMT_S),
11225 OPC_ROUND_W_S = FOP(12, FMT_S),
11226 OPC_TRUNC_W_S = FOP(13, FMT_S),
11227 OPC_CEIL_W_S = FOP(14, FMT_S),
11228 OPC_FLOOR_W_S = FOP(15, FMT_S),
11229 OPC_SEL_S = FOP(16, FMT_S),
11230 OPC_MOVCF_S = FOP(17, FMT_S),
11231 OPC_MOVZ_S = FOP(18, FMT_S),
11232 OPC_MOVN_S = FOP(19, FMT_S),
11233 OPC_SELEQZ_S = FOP(20, FMT_S),
11234 OPC_RECIP_S = FOP(21, FMT_S),
11235 OPC_RSQRT_S = FOP(22, FMT_S),
11236 OPC_SELNEZ_S = FOP(23, FMT_S),
11237 OPC_MADDF_S = FOP(24, FMT_S),
11238 OPC_MSUBF_S = FOP(25, FMT_S),
11239 OPC_RINT_S = FOP(26, FMT_S),
11240 OPC_CLASS_S = FOP(27, FMT_S),
11241 OPC_MIN_S = FOP(28, FMT_S),
11242 OPC_RECIP2_S = FOP(28, FMT_S),
11243 OPC_MINA_S = FOP(29, FMT_S),
11244 OPC_RECIP1_S = FOP(29, FMT_S),
11245 OPC_MAX_S = FOP(30, FMT_S),
11246 OPC_RSQRT1_S = FOP(30, FMT_S),
11247 OPC_MAXA_S = FOP(31, FMT_S),
11248 OPC_RSQRT2_S = FOP(31, FMT_S),
11249 OPC_CVT_D_S = FOP(33, FMT_S),
11250 OPC_CVT_W_S = FOP(36, FMT_S),
11251 OPC_CVT_L_S = FOP(37, FMT_S),
11252 OPC_CVT_PS_S = FOP(38, FMT_S),
11253 OPC_CMP_F_S = FOP(48, FMT_S),
11254 OPC_CMP_UN_S = FOP(49, FMT_S),
11255 OPC_CMP_EQ_S = FOP(50, FMT_S),
11256 OPC_CMP_UEQ_S = FOP(51, FMT_S),
11257 OPC_CMP_OLT_S = FOP(52, FMT_S),
11258 OPC_CMP_ULT_S = FOP(53, FMT_S),
11259 OPC_CMP_OLE_S = FOP(54, FMT_S),
11260 OPC_CMP_ULE_S = FOP(55, FMT_S),
11261 OPC_CMP_SF_S = FOP(56, FMT_S),
11262 OPC_CMP_NGLE_S = FOP(57, FMT_S),
11263 OPC_CMP_SEQ_S = FOP(58, FMT_S),
11264 OPC_CMP_NGL_S = FOP(59, FMT_S),
11265 OPC_CMP_LT_S = FOP(60, FMT_S),
11266 OPC_CMP_NGE_S = FOP(61, FMT_S),
11267 OPC_CMP_LE_S = FOP(62, FMT_S),
11268 OPC_CMP_NGT_S = FOP(63, FMT_S),
11270 OPC_ADD_D = FOP(0, FMT_D),
11271 OPC_SUB_D = FOP(1, FMT_D),
11272 OPC_MUL_D = FOP(2, FMT_D),
11273 OPC_DIV_D = FOP(3, FMT_D),
11274 OPC_SQRT_D = FOP(4, FMT_D),
11275 OPC_ABS_D = FOP(5, FMT_D),
11276 OPC_MOV_D = FOP(6, FMT_D),
11277 OPC_NEG_D = FOP(7, FMT_D),
11278 OPC_ROUND_L_D = FOP(8, FMT_D),
11279 OPC_TRUNC_L_D = FOP(9, FMT_D),
11280 OPC_CEIL_L_D = FOP(10, FMT_D),
11281 OPC_FLOOR_L_D = FOP(11, FMT_D),
11282 OPC_ROUND_W_D = FOP(12, FMT_D),
11283 OPC_TRUNC_W_D = FOP(13, FMT_D),
11284 OPC_CEIL_W_D = FOP(14, FMT_D),
11285 OPC_FLOOR_W_D = FOP(15, FMT_D),
11286 OPC_SEL_D = FOP(16, FMT_D),
11287 OPC_MOVCF_D = FOP(17, FMT_D),
11288 OPC_MOVZ_D = FOP(18, FMT_D),
11289 OPC_MOVN_D = FOP(19, FMT_D),
11290 OPC_SELEQZ_D = FOP(20, FMT_D),
11291 OPC_RECIP_D = FOP(21, FMT_D),
11292 OPC_RSQRT_D = FOP(22, FMT_D),
11293 OPC_SELNEZ_D = FOP(23, FMT_D),
11294 OPC_MADDF_D = FOP(24, FMT_D),
11295 OPC_MSUBF_D = FOP(25, FMT_D),
11296 OPC_RINT_D = FOP(26, FMT_D),
11297 OPC_CLASS_D = FOP(27, FMT_D),
11298 OPC_MIN_D = FOP(28, FMT_D),
11299 OPC_RECIP2_D = FOP(28, FMT_D),
11300 OPC_MINA_D = FOP(29, FMT_D),
11301 OPC_RECIP1_D = FOP(29, FMT_D),
11302 OPC_MAX_D = FOP(30, FMT_D),
11303 OPC_RSQRT1_D = FOP(30, FMT_D),
11304 OPC_MAXA_D = FOP(31, FMT_D),
11305 OPC_RSQRT2_D = FOP(31, FMT_D),
11306 OPC_CVT_S_D = FOP(32, FMT_D),
11307 OPC_CVT_W_D = FOP(36, FMT_D),
11308 OPC_CVT_L_D = FOP(37, FMT_D),
11309 OPC_CMP_F_D = FOP(48, FMT_D),
11310 OPC_CMP_UN_D = FOP(49, FMT_D),
11311 OPC_CMP_EQ_D = FOP(50, FMT_D),
11312 OPC_CMP_UEQ_D = FOP(51, FMT_D),
11313 OPC_CMP_OLT_D = FOP(52, FMT_D),
11314 OPC_CMP_ULT_D = FOP(53, FMT_D),
11315 OPC_CMP_OLE_D = FOP(54, FMT_D),
11316 OPC_CMP_ULE_D = FOP(55, FMT_D),
11317 OPC_CMP_SF_D = FOP(56, FMT_D),
11318 OPC_CMP_NGLE_D = FOP(57, FMT_D),
11319 OPC_CMP_SEQ_D = FOP(58, FMT_D),
11320 OPC_CMP_NGL_D = FOP(59, FMT_D),
11321 OPC_CMP_LT_D = FOP(60, FMT_D),
11322 OPC_CMP_NGE_D = FOP(61, FMT_D),
11323 OPC_CMP_LE_D = FOP(62, FMT_D),
11324 OPC_CMP_NGT_D = FOP(63, FMT_D),
11326 OPC_CVT_S_W = FOP(32, FMT_W),
11327 OPC_CVT_D_W = FOP(33, FMT_W),
11328 OPC_CVT_S_L = FOP(32, FMT_L),
11329 OPC_CVT_D_L = FOP(33, FMT_L),
11330 OPC_CVT_PS_PW = FOP(38, FMT_W),
11332 OPC_ADD_PS = FOP(0, FMT_PS),
11333 OPC_SUB_PS = FOP(1, FMT_PS),
11334 OPC_MUL_PS = FOP(2, FMT_PS),
11335 OPC_DIV_PS = FOP(3, FMT_PS),
11336 OPC_ABS_PS = FOP(5, FMT_PS),
11337 OPC_MOV_PS = FOP(6, FMT_PS),
11338 OPC_NEG_PS = FOP(7, FMT_PS),
11339 OPC_MOVCF_PS = FOP(17, FMT_PS),
11340 OPC_MOVZ_PS = FOP(18, FMT_PS),
11341 OPC_MOVN_PS = FOP(19, FMT_PS),
11342 OPC_ADDR_PS = FOP(24, FMT_PS),
11343 OPC_MULR_PS = FOP(26, FMT_PS),
11344 OPC_RECIP2_PS = FOP(28, FMT_PS),
11345 OPC_RECIP1_PS = FOP(29, FMT_PS),
11346 OPC_RSQRT1_PS = FOP(30, FMT_PS),
11347 OPC_RSQRT2_PS = FOP(31, FMT_PS),
11349 OPC_CVT_S_PU = FOP(32, FMT_PS),
11350 OPC_CVT_PW_PS = FOP(36, FMT_PS),
11351 OPC_CVT_S_PL = FOP(40, FMT_PS),
11352 OPC_PLL_PS = FOP(44, FMT_PS),
11353 OPC_PLU_PS = FOP(45, FMT_PS),
11354 OPC_PUL_PS = FOP(46, FMT_PS),
11355 OPC_PUU_PS = FOP(47, FMT_PS),
11356 OPC_CMP_F_PS = FOP(48, FMT_PS),
11357 OPC_CMP_UN_PS = FOP(49, FMT_PS),
11358 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
11359 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
11360 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
11361 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
11362 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
11363 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
11364 OPC_CMP_SF_PS = FOP(56, FMT_PS),
11365 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
11366 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
11367 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
11368 OPC_CMP_LT_PS = FOP(60, FMT_PS),
11369 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
11370 OPC_CMP_LE_PS = FOP(62, FMT_PS),
11371 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
11374 enum r6_f_cmp_op {
11375 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
11376 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
11377 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
11378 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
11379 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
11380 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
11381 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
11382 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
11383 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
11384 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
11385 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
11386 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
11387 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
11388 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
11389 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
11390 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
11391 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
11392 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
11393 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
11394 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
11395 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
11396 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
11398 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
11399 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
11400 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
11401 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
11402 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
11403 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
11404 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
11405 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
11406 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
11407 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
11408 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
11409 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
11410 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
11411 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
11412 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
11413 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
11414 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
11415 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
11416 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
11417 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
11418 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
11419 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
11422 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
11424 TCGv t0 = tcg_temp_new();
11426 switch (opc) {
11427 case OPC_MFC1:
11429 TCGv_i32 fp0 = tcg_temp_new_i32();
11431 gen_load_fpr32(ctx, fp0, fs);
11432 tcg_gen_ext_i32_tl(t0, fp0);
11433 tcg_temp_free_i32(fp0);
11435 gen_store_gpr(t0, rt);
11436 break;
11437 case OPC_MTC1:
11438 gen_load_gpr(t0, rt);
11440 TCGv_i32 fp0 = tcg_temp_new_i32();
11442 tcg_gen_trunc_tl_i32(fp0, t0);
11443 gen_store_fpr32(ctx, fp0, fs);
11444 tcg_temp_free_i32(fp0);
11446 break;
11447 case OPC_CFC1:
11448 gen_helper_1e0i(cfc1, t0, fs);
11449 gen_store_gpr(t0, rt);
11450 break;
11451 case OPC_CTC1:
11452 gen_load_gpr(t0, rt);
11453 save_cpu_state(ctx, 0);
11455 TCGv_i32 fs_tmp = tcg_const_i32(fs);
11457 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
11458 tcg_temp_free_i32(fs_tmp);
11460 /* Stop translation as we may have changed hflags */
11461 ctx->base.is_jmp = DISAS_STOP;
11462 break;
11463 #if defined(TARGET_MIPS64)
11464 case OPC_DMFC1:
11465 gen_load_fpr64(ctx, t0, fs);
11466 gen_store_gpr(t0, rt);
11467 break;
11468 case OPC_DMTC1:
11469 gen_load_gpr(t0, rt);
11470 gen_store_fpr64(ctx, t0, fs);
11471 break;
11472 #endif
11473 case OPC_MFHC1:
11475 TCGv_i32 fp0 = tcg_temp_new_i32();
11477 gen_load_fpr32h(ctx, fp0, fs);
11478 tcg_gen_ext_i32_tl(t0, fp0);
11479 tcg_temp_free_i32(fp0);
11481 gen_store_gpr(t0, rt);
11482 break;
11483 case OPC_MTHC1:
11484 gen_load_gpr(t0, rt);
11486 TCGv_i32 fp0 = tcg_temp_new_i32();
11488 tcg_gen_trunc_tl_i32(fp0, t0);
11489 gen_store_fpr32h(ctx, fp0, fs);
11490 tcg_temp_free_i32(fp0);
11492 break;
11493 default:
11494 MIPS_INVAL("cp1 move");
11495 generate_exception_end(ctx, EXCP_RI);
11496 goto out;
11499 out:
11500 tcg_temp_free(t0);
11503 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
11505 TCGLabel *l1;
11506 TCGCond cond;
11507 TCGv_i32 t0;
11509 if (rd == 0) {
11510 /* Treat as NOP. */
11511 return;
11514 if (tf) {
11515 cond = TCG_COND_EQ;
11516 } else {
11517 cond = TCG_COND_NE;
11520 l1 = gen_new_label();
11521 t0 = tcg_temp_new_i32();
11522 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11523 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11524 tcg_temp_free_i32(t0);
11525 if (rs == 0) {
11526 tcg_gen_movi_tl(cpu_gpr[rd], 0);
11527 } else {
11528 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
11530 gen_set_label(l1);
11533 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
11534 int tf)
11536 int cond;
11537 TCGv_i32 t0 = tcg_temp_new_i32();
11538 TCGLabel *l1 = gen_new_label();
11540 if (tf) {
11541 cond = TCG_COND_EQ;
11542 } else {
11543 cond = TCG_COND_NE;
11546 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11547 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11548 gen_load_fpr32(ctx, t0, fs);
11549 gen_store_fpr32(ctx, t0, fd);
11550 gen_set_label(l1);
11551 tcg_temp_free_i32(t0);
11554 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
11555 int tf)
11557 int cond;
11558 TCGv_i32 t0 = tcg_temp_new_i32();
11559 TCGv_i64 fp0;
11560 TCGLabel *l1 = gen_new_label();
11562 if (tf) {
11563 cond = TCG_COND_EQ;
11564 } else {
11565 cond = TCG_COND_NE;
11568 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11569 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11570 tcg_temp_free_i32(t0);
11571 fp0 = tcg_temp_new_i64();
11572 gen_load_fpr64(ctx, fp0, fs);
11573 gen_store_fpr64(ctx, fp0, fd);
11574 tcg_temp_free_i64(fp0);
11575 gen_set_label(l1);
11578 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
11579 int cc, int tf)
11581 int cond;
11582 TCGv_i32 t0 = tcg_temp_new_i32();
11583 TCGLabel *l1 = gen_new_label();
11584 TCGLabel *l2 = gen_new_label();
11586 if (tf) {
11587 cond = TCG_COND_EQ;
11588 } else {
11589 cond = TCG_COND_NE;
11592 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
11593 tcg_gen_brcondi_i32(cond, t0, 0, l1);
11594 gen_load_fpr32(ctx, t0, fs);
11595 gen_store_fpr32(ctx, t0, fd);
11596 gen_set_label(l1);
11598 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
11599 tcg_gen_brcondi_i32(cond, t0, 0, l2);
11600 gen_load_fpr32h(ctx, t0, fs);
11601 gen_store_fpr32h(ctx, t0, fd);
11602 tcg_temp_free_i32(t0);
11603 gen_set_label(l2);
11606 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11607 int fs)
11609 TCGv_i32 t1 = tcg_const_i32(0);
11610 TCGv_i32 fp0 = tcg_temp_new_i32();
11611 TCGv_i32 fp1 = tcg_temp_new_i32();
11612 TCGv_i32 fp2 = tcg_temp_new_i32();
11613 gen_load_fpr32(ctx, fp0, fd);
11614 gen_load_fpr32(ctx, fp1, ft);
11615 gen_load_fpr32(ctx, fp2, fs);
11617 switch (op1) {
11618 case OPC_SEL_S:
11619 tcg_gen_andi_i32(fp0, fp0, 1);
11620 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11621 break;
11622 case OPC_SELEQZ_S:
11623 tcg_gen_andi_i32(fp1, fp1, 1);
11624 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11625 break;
11626 case OPC_SELNEZ_S:
11627 tcg_gen_andi_i32(fp1, fp1, 1);
11628 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11629 break;
11630 default:
11631 MIPS_INVAL("gen_sel_s");
11632 generate_exception_end(ctx, EXCP_RI);
11633 break;
11636 gen_store_fpr32(ctx, fp0, fd);
11637 tcg_temp_free_i32(fp2);
11638 tcg_temp_free_i32(fp1);
11639 tcg_temp_free_i32(fp0);
11640 tcg_temp_free_i32(t1);
11643 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
11644 int fs)
11646 TCGv_i64 t1 = tcg_const_i64(0);
11647 TCGv_i64 fp0 = tcg_temp_new_i64();
11648 TCGv_i64 fp1 = tcg_temp_new_i64();
11649 TCGv_i64 fp2 = tcg_temp_new_i64();
11650 gen_load_fpr64(ctx, fp0, fd);
11651 gen_load_fpr64(ctx, fp1, ft);
11652 gen_load_fpr64(ctx, fp2, fs);
11654 switch (op1) {
11655 case OPC_SEL_D:
11656 tcg_gen_andi_i64(fp0, fp0, 1);
11657 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
11658 break;
11659 case OPC_SELEQZ_D:
11660 tcg_gen_andi_i64(fp1, fp1, 1);
11661 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
11662 break;
11663 case OPC_SELNEZ_D:
11664 tcg_gen_andi_i64(fp1, fp1, 1);
11665 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
11666 break;
11667 default:
11668 MIPS_INVAL("gen_sel_d");
11669 generate_exception_end(ctx, EXCP_RI);
11670 break;
11673 gen_store_fpr64(ctx, fp0, fd);
11674 tcg_temp_free_i64(fp2);
11675 tcg_temp_free_i64(fp1);
11676 tcg_temp_free_i64(fp0);
11677 tcg_temp_free_i64(t1);
11680 static void gen_farith(DisasContext *ctx, enum fopcode op1,
11681 int ft, int fs, int fd, int cc)
11683 uint32_t func = ctx->opcode & 0x3f;
11684 switch (op1) {
11685 case OPC_ADD_S:
11687 TCGv_i32 fp0 = tcg_temp_new_i32();
11688 TCGv_i32 fp1 = tcg_temp_new_i32();
11690 gen_load_fpr32(ctx, fp0, fs);
11691 gen_load_fpr32(ctx, fp1, ft);
11692 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
11693 tcg_temp_free_i32(fp1);
11694 gen_store_fpr32(ctx, fp0, fd);
11695 tcg_temp_free_i32(fp0);
11697 break;
11698 case OPC_SUB_S:
11700 TCGv_i32 fp0 = tcg_temp_new_i32();
11701 TCGv_i32 fp1 = tcg_temp_new_i32();
11703 gen_load_fpr32(ctx, fp0, fs);
11704 gen_load_fpr32(ctx, fp1, ft);
11705 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
11706 tcg_temp_free_i32(fp1);
11707 gen_store_fpr32(ctx, fp0, fd);
11708 tcg_temp_free_i32(fp0);
11710 break;
11711 case OPC_MUL_S:
11713 TCGv_i32 fp0 = tcg_temp_new_i32();
11714 TCGv_i32 fp1 = tcg_temp_new_i32();
11716 gen_load_fpr32(ctx, fp0, fs);
11717 gen_load_fpr32(ctx, fp1, ft);
11718 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
11719 tcg_temp_free_i32(fp1);
11720 gen_store_fpr32(ctx, fp0, fd);
11721 tcg_temp_free_i32(fp0);
11723 break;
11724 case OPC_DIV_S:
11726 TCGv_i32 fp0 = tcg_temp_new_i32();
11727 TCGv_i32 fp1 = tcg_temp_new_i32();
11729 gen_load_fpr32(ctx, fp0, fs);
11730 gen_load_fpr32(ctx, fp1, ft);
11731 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
11732 tcg_temp_free_i32(fp1);
11733 gen_store_fpr32(ctx, fp0, fd);
11734 tcg_temp_free_i32(fp0);
11736 break;
11737 case OPC_SQRT_S:
11739 TCGv_i32 fp0 = tcg_temp_new_i32();
11741 gen_load_fpr32(ctx, fp0, fs);
11742 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
11743 gen_store_fpr32(ctx, fp0, fd);
11744 tcg_temp_free_i32(fp0);
11746 break;
11747 case OPC_ABS_S:
11749 TCGv_i32 fp0 = tcg_temp_new_i32();
11751 gen_load_fpr32(ctx, fp0, fs);
11752 if (ctx->abs2008) {
11753 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
11754 } else {
11755 gen_helper_float_abs_s(fp0, fp0);
11757 gen_store_fpr32(ctx, fp0, fd);
11758 tcg_temp_free_i32(fp0);
11760 break;
11761 case OPC_MOV_S:
11763 TCGv_i32 fp0 = tcg_temp_new_i32();
11765 gen_load_fpr32(ctx, fp0, fs);
11766 gen_store_fpr32(ctx, fp0, fd);
11767 tcg_temp_free_i32(fp0);
11769 break;
11770 case OPC_NEG_S:
11772 TCGv_i32 fp0 = tcg_temp_new_i32();
11774 gen_load_fpr32(ctx, fp0, fs);
11775 if (ctx->abs2008) {
11776 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
11777 } else {
11778 gen_helper_float_chs_s(fp0, fp0);
11780 gen_store_fpr32(ctx, fp0, fd);
11781 tcg_temp_free_i32(fp0);
11783 break;
11784 case OPC_ROUND_L_S:
11785 check_cp1_64bitmode(ctx);
11787 TCGv_i32 fp32 = tcg_temp_new_i32();
11788 TCGv_i64 fp64 = tcg_temp_new_i64();
11790 gen_load_fpr32(ctx, fp32, fs);
11791 if (ctx->nan2008) {
11792 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
11793 } else {
11794 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
11796 tcg_temp_free_i32(fp32);
11797 gen_store_fpr64(ctx, fp64, fd);
11798 tcg_temp_free_i64(fp64);
11800 break;
11801 case OPC_TRUNC_L_S:
11802 check_cp1_64bitmode(ctx);
11804 TCGv_i32 fp32 = tcg_temp_new_i32();
11805 TCGv_i64 fp64 = tcg_temp_new_i64();
11807 gen_load_fpr32(ctx, fp32, fs);
11808 if (ctx->nan2008) {
11809 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
11810 } else {
11811 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
11813 tcg_temp_free_i32(fp32);
11814 gen_store_fpr64(ctx, fp64, fd);
11815 tcg_temp_free_i64(fp64);
11817 break;
11818 case OPC_CEIL_L_S:
11819 check_cp1_64bitmode(ctx);
11821 TCGv_i32 fp32 = tcg_temp_new_i32();
11822 TCGv_i64 fp64 = tcg_temp_new_i64();
11824 gen_load_fpr32(ctx, fp32, fs);
11825 if (ctx->nan2008) {
11826 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
11827 } else {
11828 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
11830 tcg_temp_free_i32(fp32);
11831 gen_store_fpr64(ctx, fp64, fd);
11832 tcg_temp_free_i64(fp64);
11834 break;
11835 case OPC_FLOOR_L_S:
11836 check_cp1_64bitmode(ctx);
11838 TCGv_i32 fp32 = tcg_temp_new_i32();
11839 TCGv_i64 fp64 = tcg_temp_new_i64();
11841 gen_load_fpr32(ctx, fp32, fs);
11842 if (ctx->nan2008) {
11843 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
11844 } else {
11845 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
11847 tcg_temp_free_i32(fp32);
11848 gen_store_fpr64(ctx, fp64, fd);
11849 tcg_temp_free_i64(fp64);
11851 break;
11852 case OPC_ROUND_W_S:
11854 TCGv_i32 fp0 = tcg_temp_new_i32();
11856 gen_load_fpr32(ctx, fp0, fs);
11857 if (ctx->nan2008) {
11858 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
11859 } else {
11860 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
11862 gen_store_fpr32(ctx, fp0, fd);
11863 tcg_temp_free_i32(fp0);
11865 break;
11866 case OPC_TRUNC_W_S:
11868 TCGv_i32 fp0 = tcg_temp_new_i32();
11870 gen_load_fpr32(ctx, fp0, fs);
11871 if (ctx->nan2008) {
11872 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
11873 } else {
11874 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
11876 gen_store_fpr32(ctx, fp0, fd);
11877 tcg_temp_free_i32(fp0);
11879 break;
11880 case OPC_CEIL_W_S:
11882 TCGv_i32 fp0 = tcg_temp_new_i32();
11884 gen_load_fpr32(ctx, fp0, fs);
11885 if (ctx->nan2008) {
11886 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
11887 } else {
11888 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
11890 gen_store_fpr32(ctx, fp0, fd);
11891 tcg_temp_free_i32(fp0);
11893 break;
11894 case OPC_FLOOR_W_S:
11896 TCGv_i32 fp0 = tcg_temp_new_i32();
11898 gen_load_fpr32(ctx, fp0, fs);
11899 if (ctx->nan2008) {
11900 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
11901 } else {
11902 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
11904 gen_store_fpr32(ctx, fp0, fd);
11905 tcg_temp_free_i32(fp0);
11907 break;
11908 case OPC_SEL_S:
11909 check_insn(ctx, ISA_MIPS32R6);
11910 gen_sel_s(ctx, op1, fd, ft, fs);
11911 break;
11912 case OPC_SELEQZ_S:
11913 check_insn(ctx, ISA_MIPS32R6);
11914 gen_sel_s(ctx, op1, fd, ft, fs);
11915 break;
11916 case OPC_SELNEZ_S:
11917 check_insn(ctx, ISA_MIPS32R6);
11918 gen_sel_s(ctx, op1, fd, ft, fs);
11919 break;
11920 case OPC_MOVCF_S:
11921 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11922 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11923 break;
11924 case OPC_MOVZ_S:
11925 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11927 TCGLabel *l1 = gen_new_label();
11928 TCGv_i32 fp0;
11930 if (ft != 0) {
11931 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11933 fp0 = tcg_temp_new_i32();
11934 gen_load_fpr32(ctx, fp0, fs);
11935 gen_store_fpr32(ctx, fp0, fd);
11936 tcg_temp_free_i32(fp0);
11937 gen_set_label(l1);
11939 break;
11940 case OPC_MOVN_S:
11941 check_insn_opc_removed(ctx, ISA_MIPS32R6);
11943 TCGLabel *l1 = gen_new_label();
11944 TCGv_i32 fp0;
11946 if (ft != 0) {
11947 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11948 fp0 = tcg_temp_new_i32();
11949 gen_load_fpr32(ctx, fp0, fs);
11950 gen_store_fpr32(ctx, fp0, fd);
11951 tcg_temp_free_i32(fp0);
11952 gen_set_label(l1);
11955 break;
11956 case OPC_RECIP_S:
11958 TCGv_i32 fp0 = tcg_temp_new_i32();
11960 gen_load_fpr32(ctx, fp0, fs);
11961 gen_helper_float_recip_s(fp0, cpu_env, fp0);
11962 gen_store_fpr32(ctx, fp0, fd);
11963 tcg_temp_free_i32(fp0);
11965 break;
11966 case OPC_RSQRT_S:
11968 TCGv_i32 fp0 = tcg_temp_new_i32();
11970 gen_load_fpr32(ctx, fp0, fs);
11971 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
11972 gen_store_fpr32(ctx, fp0, fd);
11973 tcg_temp_free_i32(fp0);
11975 break;
11976 case OPC_MADDF_S:
11977 check_insn(ctx, ISA_MIPS32R6);
11979 TCGv_i32 fp0 = tcg_temp_new_i32();
11980 TCGv_i32 fp1 = tcg_temp_new_i32();
11981 TCGv_i32 fp2 = tcg_temp_new_i32();
11982 gen_load_fpr32(ctx, fp0, fs);
11983 gen_load_fpr32(ctx, fp1, ft);
11984 gen_load_fpr32(ctx, fp2, fd);
11985 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
11986 gen_store_fpr32(ctx, fp2, fd);
11987 tcg_temp_free_i32(fp2);
11988 tcg_temp_free_i32(fp1);
11989 tcg_temp_free_i32(fp0);
11991 break;
11992 case OPC_MSUBF_S:
11993 check_insn(ctx, ISA_MIPS32R6);
11995 TCGv_i32 fp0 = tcg_temp_new_i32();
11996 TCGv_i32 fp1 = tcg_temp_new_i32();
11997 TCGv_i32 fp2 = tcg_temp_new_i32();
11998 gen_load_fpr32(ctx, fp0, fs);
11999 gen_load_fpr32(ctx, fp1, ft);
12000 gen_load_fpr32(ctx, fp2, fd);
12001 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
12002 gen_store_fpr32(ctx, fp2, fd);
12003 tcg_temp_free_i32(fp2);
12004 tcg_temp_free_i32(fp1);
12005 tcg_temp_free_i32(fp0);
12007 break;
12008 case OPC_RINT_S:
12009 check_insn(ctx, ISA_MIPS32R6);
12011 TCGv_i32 fp0 = tcg_temp_new_i32();
12012 gen_load_fpr32(ctx, fp0, fs);
12013 gen_helper_float_rint_s(fp0, cpu_env, fp0);
12014 gen_store_fpr32(ctx, fp0, fd);
12015 tcg_temp_free_i32(fp0);
12017 break;
12018 case OPC_CLASS_S:
12019 check_insn(ctx, ISA_MIPS32R6);
12021 TCGv_i32 fp0 = tcg_temp_new_i32();
12022 gen_load_fpr32(ctx, fp0, fs);
12023 gen_helper_float_class_s(fp0, cpu_env, fp0);
12024 gen_store_fpr32(ctx, fp0, fd);
12025 tcg_temp_free_i32(fp0);
12027 break;
12028 case OPC_MIN_S: /* OPC_RECIP2_S */
12029 if (ctx->insn_flags & ISA_MIPS32R6) {
12030 /* OPC_MIN_S */
12031 TCGv_i32 fp0 = tcg_temp_new_i32();
12032 TCGv_i32 fp1 = tcg_temp_new_i32();
12033 TCGv_i32 fp2 = tcg_temp_new_i32();
12034 gen_load_fpr32(ctx, fp0, fs);
12035 gen_load_fpr32(ctx, fp1, ft);
12036 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
12037 gen_store_fpr32(ctx, fp2, fd);
12038 tcg_temp_free_i32(fp2);
12039 tcg_temp_free_i32(fp1);
12040 tcg_temp_free_i32(fp0);
12041 } else {
12042 /* OPC_RECIP2_S */
12043 check_cp1_64bitmode(ctx);
12045 TCGv_i32 fp0 = tcg_temp_new_i32();
12046 TCGv_i32 fp1 = tcg_temp_new_i32();
12048 gen_load_fpr32(ctx, fp0, fs);
12049 gen_load_fpr32(ctx, fp1, ft);
12050 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
12051 tcg_temp_free_i32(fp1);
12052 gen_store_fpr32(ctx, fp0, fd);
12053 tcg_temp_free_i32(fp0);
12056 break;
12057 case OPC_MINA_S: /* OPC_RECIP1_S */
12058 if (ctx->insn_flags & ISA_MIPS32R6) {
12059 /* OPC_MINA_S */
12060 TCGv_i32 fp0 = tcg_temp_new_i32();
12061 TCGv_i32 fp1 = tcg_temp_new_i32();
12062 TCGv_i32 fp2 = tcg_temp_new_i32();
12063 gen_load_fpr32(ctx, fp0, fs);
12064 gen_load_fpr32(ctx, fp1, ft);
12065 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
12066 gen_store_fpr32(ctx, fp2, fd);
12067 tcg_temp_free_i32(fp2);
12068 tcg_temp_free_i32(fp1);
12069 tcg_temp_free_i32(fp0);
12070 } else {
12071 /* OPC_RECIP1_S */
12072 check_cp1_64bitmode(ctx);
12074 TCGv_i32 fp0 = tcg_temp_new_i32();
12076 gen_load_fpr32(ctx, fp0, fs);
12077 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
12078 gen_store_fpr32(ctx, fp0, fd);
12079 tcg_temp_free_i32(fp0);
12082 break;
12083 case OPC_MAX_S: /* OPC_RSQRT1_S */
12084 if (ctx->insn_flags & ISA_MIPS32R6) {
12085 /* OPC_MAX_S */
12086 TCGv_i32 fp0 = tcg_temp_new_i32();
12087 TCGv_i32 fp1 = tcg_temp_new_i32();
12088 gen_load_fpr32(ctx, fp0, fs);
12089 gen_load_fpr32(ctx, fp1, ft);
12090 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
12091 gen_store_fpr32(ctx, fp1, fd);
12092 tcg_temp_free_i32(fp1);
12093 tcg_temp_free_i32(fp0);
12094 } else {
12095 /* OPC_RSQRT1_S */
12096 check_cp1_64bitmode(ctx);
12098 TCGv_i32 fp0 = tcg_temp_new_i32();
12100 gen_load_fpr32(ctx, fp0, fs);
12101 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
12102 gen_store_fpr32(ctx, fp0, fd);
12103 tcg_temp_free_i32(fp0);
12106 break;
12107 case OPC_MAXA_S: /* OPC_RSQRT2_S */
12108 if (ctx->insn_flags & ISA_MIPS32R6) {
12109 /* OPC_MAXA_S */
12110 TCGv_i32 fp0 = tcg_temp_new_i32();
12111 TCGv_i32 fp1 = tcg_temp_new_i32();
12112 gen_load_fpr32(ctx, fp0, fs);
12113 gen_load_fpr32(ctx, fp1, ft);
12114 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
12115 gen_store_fpr32(ctx, fp1, fd);
12116 tcg_temp_free_i32(fp1);
12117 tcg_temp_free_i32(fp0);
12118 } else {
12119 /* OPC_RSQRT2_S */
12120 check_cp1_64bitmode(ctx);
12122 TCGv_i32 fp0 = tcg_temp_new_i32();
12123 TCGv_i32 fp1 = tcg_temp_new_i32();
12125 gen_load_fpr32(ctx, fp0, fs);
12126 gen_load_fpr32(ctx, fp1, ft);
12127 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
12128 tcg_temp_free_i32(fp1);
12129 gen_store_fpr32(ctx, fp0, fd);
12130 tcg_temp_free_i32(fp0);
12133 break;
12134 case OPC_CVT_D_S:
12135 check_cp1_registers(ctx, fd);
12137 TCGv_i32 fp32 = tcg_temp_new_i32();
12138 TCGv_i64 fp64 = tcg_temp_new_i64();
12140 gen_load_fpr32(ctx, fp32, fs);
12141 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
12142 tcg_temp_free_i32(fp32);
12143 gen_store_fpr64(ctx, fp64, fd);
12144 tcg_temp_free_i64(fp64);
12146 break;
12147 case OPC_CVT_W_S:
12149 TCGv_i32 fp0 = tcg_temp_new_i32();
12151 gen_load_fpr32(ctx, fp0, fs);
12152 if (ctx->nan2008) {
12153 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
12154 } else {
12155 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
12157 gen_store_fpr32(ctx, fp0, fd);
12158 tcg_temp_free_i32(fp0);
12160 break;
12161 case OPC_CVT_L_S:
12162 check_cp1_64bitmode(ctx);
12164 TCGv_i32 fp32 = tcg_temp_new_i32();
12165 TCGv_i64 fp64 = tcg_temp_new_i64();
12167 gen_load_fpr32(ctx, fp32, fs);
12168 if (ctx->nan2008) {
12169 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
12170 } else {
12171 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
12173 tcg_temp_free_i32(fp32);
12174 gen_store_fpr64(ctx, fp64, fd);
12175 tcg_temp_free_i64(fp64);
12177 break;
12178 case OPC_CVT_PS_S:
12179 check_ps(ctx);
12181 TCGv_i64 fp64 = tcg_temp_new_i64();
12182 TCGv_i32 fp32_0 = tcg_temp_new_i32();
12183 TCGv_i32 fp32_1 = tcg_temp_new_i32();
12185 gen_load_fpr32(ctx, fp32_0, fs);
12186 gen_load_fpr32(ctx, fp32_1, ft);
12187 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
12188 tcg_temp_free_i32(fp32_1);
12189 tcg_temp_free_i32(fp32_0);
12190 gen_store_fpr64(ctx, fp64, fd);
12191 tcg_temp_free_i64(fp64);
12193 break;
12194 case OPC_CMP_F_S:
12195 case OPC_CMP_UN_S:
12196 case OPC_CMP_EQ_S:
12197 case OPC_CMP_UEQ_S:
12198 case OPC_CMP_OLT_S:
12199 case OPC_CMP_ULT_S:
12200 case OPC_CMP_OLE_S:
12201 case OPC_CMP_ULE_S:
12202 case OPC_CMP_SF_S:
12203 case OPC_CMP_NGLE_S:
12204 case OPC_CMP_SEQ_S:
12205 case OPC_CMP_NGL_S:
12206 case OPC_CMP_LT_S:
12207 case OPC_CMP_NGE_S:
12208 case OPC_CMP_LE_S:
12209 case OPC_CMP_NGT_S:
12210 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12211 if (ctx->opcode & (1 << 6)) {
12212 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
12213 } else {
12214 gen_cmp_s(ctx, func - 48, ft, fs, cc);
12216 break;
12217 case OPC_ADD_D:
12218 check_cp1_registers(ctx, fs | ft | fd);
12220 TCGv_i64 fp0 = tcg_temp_new_i64();
12221 TCGv_i64 fp1 = tcg_temp_new_i64();
12223 gen_load_fpr64(ctx, fp0, fs);
12224 gen_load_fpr64(ctx, fp1, ft);
12225 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
12226 tcg_temp_free_i64(fp1);
12227 gen_store_fpr64(ctx, fp0, fd);
12228 tcg_temp_free_i64(fp0);
12230 break;
12231 case OPC_SUB_D:
12232 check_cp1_registers(ctx, fs | ft | fd);
12234 TCGv_i64 fp0 = tcg_temp_new_i64();
12235 TCGv_i64 fp1 = tcg_temp_new_i64();
12237 gen_load_fpr64(ctx, fp0, fs);
12238 gen_load_fpr64(ctx, fp1, ft);
12239 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
12240 tcg_temp_free_i64(fp1);
12241 gen_store_fpr64(ctx, fp0, fd);
12242 tcg_temp_free_i64(fp0);
12244 break;
12245 case OPC_MUL_D:
12246 check_cp1_registers(ctx, fs | ft | fd);
12248 TCGv_i64 fp0 = tcg_temp_new_i64();
12249 TCGv_i64 fp1 = tcg_temp_new_i64();
12251 gen_load_fpr64(ctx, fp0, fs);
12252 gen_load_fpr64(ctx, fp1, ft);
12253 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
12254 tcg_temp_free_i64(fp1);
12255 gen_store_fpr64(ctx, fp0, fd);
12256 tcg_temp_free_i64(fp0);
12258 break;
12259 case OPC_DIV_D:
12260 check_cp1_registers(ctx, fs | ft | fd);
12262 TCGv_i64 fp0 = tcg_temp_new_i64();
12263 TCGv_i64 fp1 = tcg_temp_new_i64();
12265 gen_load_fpr64(ctx, fp0, fs);
12266 gen_load_fpr64(ctx, fp1, ft);
12267 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
12268 tcg_temp_free_i64(fp1);
12269 gen_store_fpr64(ctx, fp0, fd);
12270 tcg_temp_free_i64(fp0);
12272 break;
12273 case OPC_SQRT_D:
12274 check_cp1_registers(ctx, fs | fd);
12276 TCGv_i64 fp0 = tcg_temp_new_i64();
12278 gen_load_fpr64(ctx, fp0, fs);
12279 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
12280 gen_store_fpr64(ctx, fp0, fd);
12281 tcg_temp_free_i64(fp0);
12283 break;
12284 case OPC_ABS_D:
12285 check_cp1_registers(ctx, fs | fd);
12287 TCGv_i64 fp0 = tcg_temp_new_i64();
12289 gen_load_fpr64(ctx, fp0, fs);
12290 if (ctx->abs2008) {
12291 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
12292 } else {
12293 gen_helper_float_abs_d(fp0, fp0);
12295 gen_store_fpr64(ctx, fp0, fd);
12296 tcg_temp_free_i64(fp0);
12298 break;
12299 case OPC_MOV_D:
12300 check_cp1_registers(ctx, fs | fd);
12302 TCGv_i64 fp0 = tcg_temp_new_i64();
12304 gen_load_fpr64(ctx, fp0, fs);
12305 gen_store_fpr64(ctx, fp0, fd);
12306 tcg_temp_free_i64(fp0);
12308 break;
12309 case OPC_NEG_D:
12310 check_cp1_registers(ctx, fs | fd);
12312 TCGv_i64 fp0 = tcg_temp_new_i64();
12314 gen_load_fpr64(ctx, fp0, fs);
12315 if (ctx->abs2008) {
12316 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
12317 } else {
12318 gen_helper_float_chs_d(fp0, fp0);
12320 gen_store_fpr64(ctx, fp0, fd);
12321 tcg_temp_free_i64(fp0);
12323 break;
12324 case OPC_ROUND_L_D:
12325 check_cp1_64bitmode(ctx);
12327 TCGv_i64 fp0 = tcg_temp_new_i64();
12329 gen_load_fpr64(ctx, fp0, fs);
12330 if (ctx->nan2008) {
12331 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
12332 } else {
12333 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
12335 gen_store_fpr64(ctx, fp0, fd);
12336 tcg_temp_free_i64(fp0);
12338 break;
12339 case OPC_TRUNC_L_D:
12340 check_cp1_64bitmode(ctx);
12342 TCGv_i64 fp0 = tcg_temp_new_i64();
12344 gen_load_fpr64(ctx, fp0, fs);
12345 if (ctx->nan2008) {
12346 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
12347 } else {
12348 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
12350 gen_store_fpr64(ctx, fp0, fd);
12351 tcg_temp_free_i64(fp0);
12353 break;
12354 case OPC_CEIL_L_D:
12355 check_cp1_64bitmode(ctx);
12357 TCGv_i64 fp0 = tcg_temp_new_i64();
12359 gen_load_fpr64(ctx, fp0, fs);
12360 if (ctx->nan2008) {
12361 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
12362 } else {
12363 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
12365 gen_store_fpr64(ctx, fp0, fd);
12366 tcg_temp_free_i64(fp0);
12368 break;
12369 case OPC_FLOOR_L_D:
12370 check_cp1_64bitmode(ctx);
12372 TCGv_i64 fp0 = tcg_temp_new_i64();
12374 gen_load_fpr64(ctx, fp0, fs);
12375 if (ctx->nan2008) {
12376 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
12377 } else {
12378 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
12380 gen_store_fpr64(ctx, fp0, fd);
12381 tcg_temp_free_i64(fp0);
12383 break;
12384 case OPC_ROUND_W_D:
12385 check_cp1_registers(ctx, fs);
12387 TCGv_i32 fp32 = tcg_temp_new_i32();
12388 TCGv_i64 fp64 = tcg_temp_new_i64();
12390 gen_load_fpr64(ctx, fp64, fs);
12391 if (ctx->nan2008) {
12392 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
12393 } else {
12394 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
12396 tcg_temp_free_i64(fp64);
12397 gen_store_fpr32(ctx, fp32, fd);
12398 tcg_temp_free_i32(fp32);
12400 break;
12401 case OPC_TRUNC_W_D:
12402 check_cp1_registers(ctx, fs);
12404 TCGv_i32 fp32 = tcg_temp_new_i32();
12405 TCGv_i64 fp64 = tcg_temp_new_i64();
12407 gen_load_fpr64(ctx, fp64, fs);
12408 if (ctx->nan2008) {
12409 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
12410 } else {
12411 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
12413 tcg_temp_free_i64(fp64);
12414 gen_store_fpr32(ctx, fp32, fd);
12415 tcg_temp_free_i32(fp32);
12417 break;
12418 case OPC_CEIL_W_D:
12419 check_cp1_registers(ctx, fs);
12421 TCGv_i32 fp32 = tcg_temp_new_i32();
12422 TCGv_i64 fp64 = tcg_temp_new_i64();
12424 gen_load_fpr64(ctx, fp64, fs);
12425 if (ctx->nan2008) {
12426 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
12427 } else {
12428 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
12430 tcg_temp_free_i64(fp64);
12431 gen_store_fpr32(ctx, fp32, fd);
12432 tcg_temp_free_i32(fp32);
12434 break;
12435 case OPC_FLOOR_W_D:
12436 check_cp1_registers(ctx, fs);
12438 TCGv_i32 fp32 = tcg_temp_new_i32();
12439 TCGv_i64 fp64 = tcg_temp_new_i64();
12441 gen_load_fpr64(ctx, fp64, fs);
12442 if (ctx->nan2008) {
12443 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
12444 } else {
12445 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
12447 tcg_temp_free_i64(fp64);
12448 gen_store_fpr32(ctx, fp32, fd);
12449 tcg_temp_free_i32(fp32);
12451 break;
12452 case OPC_SEL_D:
12453 check_insn(ctx, ISA_MIPS32R6);
12454 gen_sel_d(ctx, op1, fd, ft, fs);
12455 break;
12456 case OPC_SELEQZ_D:
12457 check_insn(ctx, ISA_MIPS32R6);
12458 gen_sel_d(ctx, op1, fd, ft, fs);
12459 break;
12460 case OPC_SELNEZ_D:
12461 check_insn(ctx, ISA_MIPS32R6);
12462 gen_sel_d(ctx, op1, fd, ft, fs);
12463 break;
12464 case OPC_MOVCF_D:
12465 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12466 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12467 break;
12468 case OPC_MOVZ_D:
12469 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12471 TCGLabel *l1 = gen_new_label();
12472 TCGv_i64 fp0;
12474 if (ft != 0) {
12475 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12477 fp0 = tcg_temp_new_i64();
12478 gen_load_fpr64(ctx, fp0, fs);
12479 gen_store_fpr64(ctx, fp0, fd);
12480 tcg_temp_free_i64(fp0);
12481 gen_set_label(l1);
12483 break;
12484 case OPC_MOVN_D:
12485 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12487 TCGLabel *l1 = gen_new_label();
12488 TCGv_i64 fp0;
12490 if (ft != 0) {
12491 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12492 fp0 = tcg_temp_new_i64();
12493 gen_load_fpr64(ctx, fp0, fs);
12494 gen_store_fpr64(ctx, fp0, fd);
12495 tcg_temp_free_i64(fp0);
12496 gen_set_label(l1);
12499 break;
12500 case OPC_RECIP_D:
12501 check_cp1_registers(ctx, fs | fd);
12503 TCGv_i64 fp0 = tcg_temp_new_i64();
12505 gen_load_fpr64(ctx, fp0, fs);
12506 gen_helper_float_recip_d(fp0, cpu_env, fp0);
12507 gen_store_fpr64(ctx, fp0, fd);
12508 tcg_temp_free_i64(fp0);
12510 break;
12511 case OPC_RSQRT_D:
12512 check_cp1_registers(ctx, fs | fd);
12514 TCGv_i64 fp0 = tcg_temp_new_i64();
12516 gen_load_fpr64(ctx, fp0, fs);
12517 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
12518 gen_store_fpr64(ctx, fp0, fd);
12519 tcg_temp_free_i64(fp0);
12521 break;
12522 case OPC_MADDF_D:
12523 check_insn(ctx, ISA_MIPS32R6);
12525 TCGv_i64 fp0 = tcg_temp_new_i64();
12526 TCGv_i64 fp1 = tcg_temp_new_i64();
12527 TCGv_i64 fp2 = tcg_temp_new_i64();
12528 gen_load_fpr64(ctx, fp0, fs);
12529 gen_load_fpr64(ctx, fp1, ft);
12530 gen_load_fpr64(ctx, fp2, fd);
12531 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
12532 gen_store_fpr64(ctx, fp2, fd);
12533 tcg_temp_free_i64(fp2);
12534 tcg_temp_free_i64(fp1);
12535 tcg_temp_free_i64(fp0);
12537 break;
12538 case OPC_MSUBF_D:
12539 check_insn(ctx, ISA_MIPS32R6);
12541 TCGv_i64 fp0 = tcg_temp_new_i64();
12542 TCGv_i64 fp1 = tcg_temp_new_i64();
12543 TCGv_i64 fp2 = tcg_temp_new_i64();
12544 gen_load_fpr64(ctx, fp0, fs);
12545 gen_load_fpr64(ctx, fp1, ft);
12546 gen_load_fpr64(ctx, fp2, fd);
12547 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
12548 gen_store_fpr64(ctx, fp2, fd);
12549 tcg_temp_free_i64(fp2);
12550 tcg_temp_free_i64(fp1);
12551 tcg_temp_free_i64(fp0);
12553 break;
12554 case OPC_RINT_D:
12555 check_insn(ctx, ISA_MIPS32R6);
12557 TCGv_i64 fp0 = tcg_temp_new_i64();
12558 gen_load_fpr64(ctx, fp0, fs);
12559 gen_helper_float_rint_d(fp0, cpu_env, fp0);
12560 gen_store_fpr64(ctx, fp0, fd);
12561 tcg_temp_free_i64(fp0);
12563 break;
12564 case OPC_CLASS_D:
12565 check_insn(ctx, ISA_MIPS32R6);
12567 TCGv_i64 fp0 = tcg_temp_new_i64();
12568 gen_load_fpr64(ctx, fp0, fs);
12569 gen_helper_float_class_d(fp0, cpu_env, fp0);
12570 gen_store_fpr64(ctx, fp0, fd);
12571 tcg_temp_free_i64(fp0);
12573 break;
12574 case OPC_MIN_D: /* OPC_RECIP2_D */
12575 if (ctx->insn_flags & ISA_MIPS32R6) {
12576 /* OPC_MIN_D */
12577 TCGv_i64 fp0 = tcg_temp_new_i64();
12578 TCGv_i64 fp1 = tcg_temp_new_i64();
12579 gen_load_fpr64(ctx, fp0, fs);
12580 gen_load_fpr64(ctx, fp1, ft);
12581 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
12582 gen_store_fpr64(ctx, fp1, fd);
12583 tcg_temp_free_i64(fp1);
12584 tcg_temp_free_i64(fp0);
12585 } else {
12586 /* OPC_RECIP2_D */
12587 check_cp1_64bitmode(ctx);
12589 TCGv_i64 fp0 = tcg_temp_new_i64();
12590 TCGv_i64 fp1 = tcg_temp_new_i64();
12592 gen_load_fpr64(ctx, fp0, fs);
12593 gen_load_fpr64(ctx, fp1, ft);
12594 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
12595 tcg_temp_free_i64(fp1);
12596 gen_store_fpr64(ctx, fp0, fd);
12597 tcg_temp_free_i64(fp0);
12600 break;
12601 case OPC_MINA_D: /* OPC_RECIP1_D */
12602 if (ctx->insn_flags & ISA_MIPS32R6) {
12603 /* OPC_MINA_D */
12604 TCGv_i64 fp0 = tcg_temp_new_i64();
12605 TCGv_i64 fp1 = tcg_temp_new_i64();
12606 gen_load_fpr64(ctx, fp0, fs);
12607 gen_load_fpr64(ctx, fp1, ft);
12608 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
12609 gen_store_fpr64(ctx, fp1, fd);
12610 tcg_temp_free_i64(fp1);
12611 tcg_temp_free_i64(fp0);
12612 } else {
12613 /* OPC_RECIP1_D */
12614 check_cp1_64bitmode(ctx);
12616 TCGv_i64 fp0 = tcg_temp_new_i64();
12618 gen_load_fpr64(ctx, fp0, fs);
12619 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
12620 gen_store_fpr64(ctx, fp0, fd);
12621 tcg_temp_free_i64(fp0);
12624 break;
12625 case OPC_MAX_D: /* OPC_RSQRT1_D */
12626 if (ctx->insn_flags & ISA_MIPS32R6) {
12627 /* OPC_MAX_D */
12628 TCGv_i64 fp0 = tcg_temp_new_i64();
12629 TCGv_i64 fp1 = tcg_temp_new_i64();
12630 gen_load_fpr64(ctx, fp0, fs);
12631 gen_load_fpr64(ctx, fp1, ft);
12632 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
12633 gen_store_fpr64(ctx, fp1, fd);
12634 tcg_temp_free_i64(fp1);
12635 tcg_temp_free_i64(fp0);
12636 } else {
12637 /* OPC_RSQRT1_D */
12638 check_cp1_64bitmode(ctx);
12640 TCGv_i64 fp0 = tcg_temp_new_i64();
12642 gen_load_fpr64(ctx, fp0, fs);
12643 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
12644 gen_store_fpr64(ctx, fp0, fd);
12645 tcg_temp_free_i64(fp0);
12648 break;
12649 case OPC_MAXA_D: /* OPC_RSQRT2_D */
12650 if (ctx->insn_flags & ISA_MIPS32R6) {
12651 /* OPC_MAXA_D */
12652 TCGv_i64 fp0 = tcg_temp_new_i64();
12653 TCGv_i64 fp1 = tcg_temp_new_i64();
12654 gen_load_fpr64(ctx, fp0, fs);
12655 gen_load_fpr64(ctx, fp1, ft);
12656 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
12657 gen_store_fpr64(ctx, fp1, fd);
12658 tcg_temp_free_i64(fp1);
12659 tcg_temp_free_i64(fp0);
12660 } else {
12661 /* OPC_RSQRT2_D */
12662 check_cp1_64bitmode(ctx);
12664 TCGv_i64 fp0 = tcg_temp_new_i64();
12665 TCGv_i64 fp1 = tcg_temp_new_i64();
12667 gen_load_fpr64(ctx, fp0, fs);
12668 gen_load_fpr64(ctx, fp1, ft);
12669 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
12670 tcg_temp_free_i64(fp1);
12671 gen_store_fpr64(ctx, fp0, fd);
12672 tcg_temp_free_i64(fp0);
12675 break;
12676 case OPC_CMP_F_D:
12677 case OPC_CMP_UN_D:
12678 case OPC_CMP_EQ_D:
12679 case OPC_CMP_UEQ_D:
12680 case OPC_CMP_OLT_D:
12681 case OPC_CMP_ULT_D:
12682 case OPC_CMP_OLE_D:
12683 case OPC_CMP_ULE_D:
12684 case OPC_CMP_SF_D:
12685 case OPC_CMP_NGLE_D:
12686 case OPC_CMP_SEQ_D:
12687 case OPC_CMP_NGL_D:
12688 case OPC_CMP_LT_D:
12689 case OPC_CMP_NGE_D:
12690 case OPC_CMP_LE_D:
12691 case OPC_CMP_NGT_D:
12692 check_insn_opc_removed(ctx, ISA_MIPS32R6);
12693 if (ctx->opcode & (1 << 6)) {
12694 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
12695 } else {
12696 gen_cmp_d(ctx, func - 48, ft, fs, cc);
12698 break;
12699 case OPC_CVT_S_D:
12700 check_cp1_registers(ctx, fs);
12702 TCGv_i32 fp32 = tcg_temp_new_i32();
12703 TCGv_i64 fp64 = tcg_temp_new_i64();
12705 gen_load_fpr64(ctx, fp64, fs);
12706 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
12707 tcg_temp_free_i64(fp64);
12708 gen_store_fpr32(ctx, fp32, fd);
12709 tcg_temp_free_i32(fp32);
12711 break;
12712 case OPC_CVT_W_D:
12713 check_cp1_registers(ctx, fs);
12715 TCGv_i32 fp32 = tcg_temp_new_i32();
12716 TCGv_i64 fp64 = tcg_temp_new_i64();
12718 gen_load_fpr64(ctx, fp64, fs);
12719 if (ctx->nan2008) {
12720 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
12721 } else {
12722 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
12724 tcg_temp_free_i64(fp64);
12725 gen_store_fpr32(ctx, fp32, fd);
12726 tcg_temp_free_i32(fp32);
12728 break;
12729 case OPC_CVT_L_D:
12730 check_cp1_64bitmode(ctx);
12732 TCGv_i64 fp0 = tcg_temp_new_i64();
12734 gen_load_fpr64(ctx, fp0, fs);
12735 if (ctx->nan2008) {
12736 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
12737 } else {
12738 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
12740 gen_store_fpr64(ctx, fp0, fd);
12741 tcg_temp_free_i64(fp0);
12743 break;
12744 case OPC_CVT_S_W:
12746 TCGv_i32 fp0 = tcg_temp_new_i32();
12748 gen_load_fpr32(ctx, fp0, fs);
12749 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
12750 gen_store_fpr32(ctx, fp0, fd);
12751 tcg_temp_free_i32(fp0);
12753 break;
12754 case OPC_CVT_D_W:
12755 check_cp1_registers(ctx, fd);
12757 TCGv_i32 fp32 = tcg_temp_new_i32();
12758 TCGv_i64 fp64 = tcg_temp_new_i64();
12760 gen_load_fpr32(ctx, fp32, fs);
12761 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
12762 tcg_temp_free_i32(fp32);
12763 gen_store_fpr64(ctx, fp64, fd);
12764 tcg_temp_free_i64(fp64);
12766 break;
12767 case OPC_CVT_S_L:
12768 check_cp1_64bitmode(ctx);
12770 TCGv_i32 fp32 = tcg_temp_new_i32();
12771 TCGv_i64 fp64 = tcg_temp_new_i64();
12773 gen_load_fpr64(ctx, fp64, fs);
12774 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
12775 tcg_temp_free_i64(fp64);
12776 gen_store_fpr32(ctx, fp32, fd);
12777 tcg_temp_free_i32(fp32);
12779 break;
12780 case OPC_CVT_D_L:
12781 check_cp1_64bitmode(ctx);
12783 TCGv_i64 fp0 = tcg_temp_new_i64();
12785 gen_load_fpr64(ctx, fp0, fs);
12786 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
12787 gen_store_fpr64(ctx, fp0, fd);
12788 tcg_temp_free_i64(fp0);
12790 break;
12791 case OPC_CVT_PS_PW:
12792 check_ps(ctx);
12794 TCGv_i64 fp0 = tcg_temp_new_i64();
12796 gen_load_fpr64(ctx, fp0, fs);
12797 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
12798 gen_store_fpr64(ctx, fp0, fd);
12799 tcg_temp_free_i64(fp0);
12801 break;
12802 case OPC_ADD_PS:
12803 check_ps(ctx);
12805 TCGv_i64 fp0 = tcg_temp_new_i64();
12806 TCGv_i64 fp1 = tcg_temp_new_i64();
12808 gen_load_fpr64(ctx, fp0, fs);
12809 gen_load_fpr64(ctx, fp1, ft);
12810 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
12811 tcg_temp_free_i64(fp1);
12812 gen_store_fpr64(ctx, fp0, fd);
12813 tcg_temp_free_i64(fp0);
12815 break;
12816 case OPC_SUB_PS:
12817 check_ps(ctx);
12819 TCGv_i64 fp0 = tcg_temp_new_i64();
12820 TCGv_i64 fp1 = tcg_temp_new_i64();
12822 gen_load_fpr64(ctx, fp0, fs);
12823 gen_load_fpr64(ctx, fp1, ft);
12824 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
12825 tcg_temp_free_i64(fp1);
12826 gen_store_fpr64(ctx, fp0, fd);
12827 tcg_temp_free_i64(fp0);
12829 break;
12830 case OPC_MUL_PS:
12831 check_ps(ctx);
12833 TCGv_i64 fp0 = tcg_temp_new_i64();
12834 TCGv_i64 fp1 = tcg_temp_new_i64();
12836 gen_load_fpr64(ctx, fp0, fs);
12837 gen_load_fpr64(ctx, fp1, ft);
12838 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
12839 tcg_temp_free_i64(fp1);
12840 gen_store_fpr64(ctx, fp0, fd);
12841 tcg_temp_free_i64(fp0);
12843 break;
12844 case OPC_ABS_PS:
12845 check_ps(ctx);
12847 TCGv_i64 fp0 = tcg_temp_new_i64();
12849 gen_load_fpr64(ctx, fp0, fs);
12850 gen_helper_float_abs_ps(fp0, fp0);
12851 gen_store_fpr64(ctx, fp0, fd);
12852 tcg_temp_free_i64(fp0);
12854 break;
12855 case OPC_MOV_PS:
12856 check_ps(ctx);
12858 TCGv_i64 fp0 = tcg_temp_new_i64();
12860 gen_load_fpr64(ctx, fp0, fs);
12861 gen_store_fpr64(ctx, fp0, fd);
12862 tcg_temp_free_i64(fp0);
12864 break;
12865 case OPC_NEG_PS:
12866 check_ps(ctx);
12868 TCGv_i64 fp0 = tcg_temp_new_i64();
12870 gen_load_fpr64(ctx, fp0, fs);
12871 gen_helper_float_chs_ps(fp0, fp0);
12872 gen_store_fpr64(ctx, fp0, fd);
12873 tcg_temp_free_i64(fp0);
12875 break;
12876 case OPC_MOVCF_PS:
12877 check_ps(ctx);
12878 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
12879 break;
12880 case OPC_MOVZ_PS:
12881 check_ps(ctx);
12883 TCGLabel *l1 = gen_new_label();
12884 TCGv_i64 fp0;
12886 if (ft != 0) {
12887 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
12889 fp0 = tcg_temp_new_i64();
12890 gen_load_fpr64(ctx, fp0, fs);
12891 gen_store_fpr64(ctx, fp0, fd);
12892 tcg_temp_free_i64(fp0);
12893 gen_set_label(l1);
12895 break;
12896 case OPC_MOVN_PS:
12897 check_ps(ctx);
12899 TCGLabel *l1 = gen_new_label();
12900 TCGv_i64 fp0;
12902 if (ft != 0) {
12903 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
12904 fp0 = tcg_temp_new_i64();
12905 gen_load_fpr64(ctx, fp0, fs);
12906 gen_store_fpr64(ctx, fp0, fd);
12907 tcg_temp_free_i64(fp0);
12908 gen_set_label(l1);
12911 break;
12912 case OPC_ADDR_PS:
12913 check_ps(ctx);
12915 TCGv_i64 fp0 = tcg_temp_new_i64();
12916 TCGv_i64 fp1 = tcg_temp_new_i64();
12918 gen_load_fpr64(ctx, fp0, ft);
12919 gen_load_fpr64(ctx, fp1, fs);
12920 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
12921 tcg_temp_free_i64(fp1);
12922 gen_store_fpr64(ctx, fp0, fd);
12923 tcg_temp_free_i64(fp0);
12925 break;
12926 case OPC_MULR_PS:
12927 check_ps(ctx);
12929 TCGv_i64 fp0 = tcg_temp_new_i64();
12930 TCGv_i64 fp1 = tcg_temp_new_i64();
12932 gen_load_fpr64(ctx, fp0, ft);
12933 gen_load_fpr64(ctx, fp1, fs);
12934 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
12935 tcg_temp_free_i64(fp1);
12936 gen_store_fpr64(ctx, fp0, fd);
12937 tcg_temp_free_i64(fp0);
12939 break;
12940 case OPC_RECIP2_PS:
12941 check_ps(ctx);
12943 TCGv_i64 fp0 = tcg_temp_new_i64();
12944 TCGv_i64 fp1 = tcg_temp_new_i64();
12946 gen_load_fpr64(ctx, fp0, fs);
12947 gen_load_fpr64(ctx, fp1, ft);
12948 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
12949 tcg_temp_free_i64(fp1);
12950 gen_store_fpr64(ctx, fp0, fd);
12951 tcg_temp_free_i64(fp0);
12953 break;
12954 case OPC_RECIP1_PS:
12955 check_ps(ctx);
12957 TCGv_i64 fp0 = tcg_temp_new_i64();
12959 gen_load_fpr64(ctx, fp0, fs);
12960 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
12961 gen_store_fpr64(ctx, fp0, fd);
12962 tcg_temp_free_i64(fp0);
12964 break;
12965 case OPC_RSQRT1_PS:
12966 check_ps(ctx);
12968 TCGv_i64 fp0 = tcg_temp_new_i64();
12970 gen_load_fpr64(ctx, fp0, fs);
12971 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
12972 gen_store_fpr64(ctx, fp0, fd);
12973 tcg_temp_free_i64(fp0);
12975 break;
12976 case OPC_RSQRT2_PS:
12977 check_ps(ctx);
12979 TCGv_i64 fp0 = tcg_temp_new_i64();
12980 TCGv_i64 fp1 = tcg_temp_new_i64();
12982 gen_load_fpr64(ctx, fp0, fs);
12983 gen_load_fpr64(ctx, fp1, ft);
12984 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
12985 tcg_temp_free_i64(fp1);
12986 gen_store_fpr64(ctx, fp0, fd);
12987 tcg_temp_free_i64(fp0);
12989 break;
12990 case OPC_CVT_S_PU:
12991 check_cp1_64bitmode(ctx);
12993 TCGv_i32 fp0 = tcg_temp_new_i32();
12995 gen_load_fpr32h(ctx, fp0, fs);
12996 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
12997 gen_store_fpr32(ctx, fp0, fd);
12998 tcg_temp_free_i32(fp0);
13000 break;
13001 case OPC_CVT_PW_PS:
13002 check_ps(ctx);
13004 TCGv_i64 fp0 = tcg_temp_new_i64();
13006 gen_load_fpr64(ctx, fp0, fs);
13007 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
13008 gen_store_fpr64(ctx, fp0, fd);
13009 tcg_temp_free_i64(fp0);
13011 break;
13012 case OPC_CVT_S_PL:
13013 check_cp1_64bitmode(ctx);
13015 TCGv_i32 fp0 = tcg_temp_new_i32();
13017 gen_load_fpr32(ctx, fp0, fs);
13018 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
13019 gen_store_fpr32(ctx, fp0, fd);
13020 tcg_temp_free_i32(fp0);
13022 break;
13023 case OPC_PLL_PS:
13024 check_ps(ctx);
13026 TCGv_i32 fp0 = tcg_temp_new_i32();
13027 TCGv_i32 fp1 = tcg_temp_new_i32();
13029 gen_load_fpr32(ctx, fp0, fs);
13030 gen_load_fpr32(ctx, fp1, ft);
13031 gen_store_fpr32h(ctx, fp0, fd);
13032 gen_store_fpr32(ctx, fp1, fd);
13033 tcg_temp_free_i32(fp0);
13034 tcg_temp_free_i32(fp1);
13036 break;
13037 case OPC_PLU_PS:
13038 check_ps(ctx);
13040 TCGv_i32 fp0 = tcg_temp_new_i32();
13041 TCGv_i32 fp1 = tcg_temp_new_i32();
13043 gen_load_fpr32(ctx, fp0, fs);
13044 gen_load_fpr32h(ctx, fp1, ft);
13045 gen_store_fpr32(ctx, fp1, fd);
13046 gen_store_fpr32h(ctx, fp0, fd);
13047 tcg_temp_free_i32(fp0);
13048 tcg_temp_free_i32(fp1);
13050 break;
13051 case OPC_PUL_PS:
13052 check_ps(ctx);
13054 TCGv_i32 fp0 = tcg_temp_new_i32();
13055 TCGv_i32 fp1 = tcg_temp_new_i32();
13057 gen_load_fpr32h(ctx, fp0, fs);
13058 gen_load_fpr32(ctx, fp1, ft);
13059 gen_store_fpr32(ctx, fp1, fd);
13060 gen_store_fpr32h(ctx, fp0, fd);
13061 tcg_temp_free_i32(fp0);
13062 tcg_temp_free_i32(fp1);
13064 break;
13065 case OPC_PUU_PS:
13066 check_ps(ctx);
13068 TCGv_i32 fp0 = tcg_temp_new_i32();
13069 TCGv_i32 fp1 = tcg_temp_new_i32();
13071 gen_load_fpr32h(ctx, fp0, fs);
13072 gen_load_fpr32h(ctx, fp1, ft);
13073 gen_store_fpr32(ctx, fp1, fd);
13074 gen_store_fpr32h(ctx, fp0, fd);
13075 tcg_temp_free_i32(fp0);
13076 tcg_temp_free_i32(fp1);
13078 break;
13079 case OPC_CMP_F_PS:
13080 case OPC_CMP_UN_PS:
13081 case OPC_CMP_EQ_PS:
13082 case OPC_CMP_UEQ_PS:
13083 case OPC_CMP_OLT_PS:
13084 case OPC_CMP_ULT_PS:
13085 case OPC_CMP_OLE_PS:
13086 case OPC_CMP_ULE_PS:
13087 case OPC_CMP_SF_PS:
13088 case OPC_CMP_NGLE_PS:
13089 case OPC_CMP_SEQ_PS:
13090 case OPC_CMP_NGL_PS:
13091 case OPC_CMP_LT_PS:
13092 case OPC_CMP_NGE_PS:
13093 case OPC_CMP_LE_PS:
13094 case OPC_CMP_NGT_PS:
13095 if (ctx->opcode & (1 << 6)) {
13096 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
13097 } else {
13098 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
13100 break;
13101 default:
13102 MIPS_INVAL("farith");
13103 generate_exception_end(ctx, EXCP_RI);
13104 return;
13108 /* Coprocessor 3 (FPU) */
13109 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
13110 int fd, int fs, int base, int index)
13112 TCGv t0 = tcg_temp_new();
13114 if (base == 0) {
13115 gen_load_gpr(t0, index);
13116 } else if (index == 0) {
13117 gen_load_gpr(t0, base);
13118 } else {
13119 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
13122 * Don't do NOP if destination is zero: we must perform the actual
13123 * memory access.
13125 switch (opc) {
13126 case OPC_LWXC1:
13127 check_cop1x(ctx);
13129 TCGv_i32 fp0 = tcg_temp_new_i32();
13131 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
13132 tcg_gen_trunc_tl_i32(fp0, t0);
13133 gen_store_fpr32(ctx, fp0, fd);
13134 tcg_temp_free_i32(fp0);
13136 break;
13137 case OPC_LDXC1:
13138 check_cop1x(ctx);
13139 check_cp1_registers(ctx, fd);
13141 TCGv_i64 fp0 = tcg_temp_new_i64();
13142 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13143 gen_store_fpr64(ctx, fp0, fd);
13144 tcg_temp_free_i64(fp0);
13146 break;
13147 case OPC_LUXC1:
13148 check_cp1_64bitmode(ctx);
13149 tcg_gen_andi_tl(t0, t0, ~0x7);
13151 TCGv_i64 fp0 = tcg_temp_new_i64();
13153 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13154 gen_store_fpr64(ctx, fp0, fd);
13155 tcg_temp_free_i64(fp0);
13157 break;
13158 case OPC_SWXC1:
13159 check_cop1x(ctx);
13161 TCGv_i32 fp0 = tcg_temp_new_i32();
13162 gen_load_fpr32(ctx, fp0, fs);
13163 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
13164 tcg_temp_free_i32(fp0);
13166 break;
13167 case OPC_SDXC1:
13168 check_cop1x(ctx);
13169 check_cp1_registers(ctx, fs);
13171 TCGv_i64 fp0 = tcg_temp_new_i64();
13172 gen_load_fpr64(ctx, fp0, fs);
13173 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13174 tcg_temp_free_i64(fp0);
13176 break;
13177 case OPC_SUXC1:
13178 check_cp1_64bitmode(ctx);
13179 tcg_gen_andi_tl(t0, t0, ~0x7);
13181 TCGv_i64 fp0 = tcg_temp_new_i64();
13182 gen_load_fpr64(ctx, fp0, fs);
13183 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
13184 tcg_temp_free_i64(fp0);
13186 break;
13188 tcg_temp_free(t0);
13191 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
13192 int fd, int fr, int fs, int ft)
13194 switch (opc) {
13195 case OPC_ALNV_PS:
13196 check_ps(ctx);
13198 TCGv t0 = tcg_temp_local_new();
13199 TCGv_i32 fp = tcg_temp_new_i32();
13200 TCGv_i32 fph = tcg_temp_new_i32();
13201 TCGLabel *l1 = gen_new_label();
13202 TCGLabel *l2 = gen_new_label();
13204 gen_load_gpr(t0, fr);
13205 tcg_gen_andi_tl(t0, t0, 0x7);
13207 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
13208 gen_load_fpr32(ctx, fp, fs);
13209 gen_load_fpr32h(ctx, fph, fs);
13210 gen_store_fpr32(ctx, fp, fd);
13211 gen_store_fpr32h(ctx, fph, fd);
13212 tcg_gen_br(l2);
13213 gen_set_label(l1);
13214 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
13215 tcg_temp_free(t0);
13216 #ifdef TARGET_WORDS_BIGENDIAN
13217 gen_load_fpr32(ctx, fp, fs);
13218 gen_load_fpr32h(ctx, fph, ft);
13219 gen_store_fpr32h(ctx, fp, fd);
13220 gen_store_fpr32(ctx, fph, fd);
13221 #else
13222 gen_load_fpr32h(ctx, fph, fs);
13223 gen_load_fpr32(ctx, fp, ft);
13224 gen_store_fpr32(ctx, fph, fd);
13225 gen_store_fpr32h(ctx, fp, fd);
13226 #endif
13227 gen_set_label(l2);
13228 tcg_temp_free_i32(fp);
13229 tcg_temp_free_i32(fph);
13231 break;
13232 case OPC_MADD_S:
13233 check_cop1x(ctx);
13235 TCGv_i32 fp0 = tcg_temp_new_i32();
13236 TCGv_i32 fp1 = tcg_temp_new_i32();
13237 TCGv_i32 fp2 = tcg_temp_new_i32();
13239 gen_load_fpr32(ctx, fp0, fs);
13240 gen_load_fpr32(ctx, fp1, ft);
13241 gen_load_fpr32(ctx, fp2, fr);
13242 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
13243 tcg_temp_free_i32(fp0);
13244 tcg_temp_free_i32(fp1);
13245 gen_store_fpr32(ctx, fp2, fd);
13246 tcg_temp_free_i32(fp2);
13248 break;
13249 case OPC_MADD_D:
13250 check_cop1x(ctx);
13251 check_cp1_registers(ctx, fd | fs | ft | fr);
13253 TCGv_i64 fp0 = tcg_temp_new_i64();
13254 TCGv_i64 fp1 = tcg_temp_new_i64();
13255 TCGv_i64 fp2 = tcg_temp_new_i64();
13257 gen_load_fpr64(ctx, fp0, fs);
13258 gen_load_fpr64(ctx, fp1, ft);
13259 gen_load_fpr64(ctx, fp2, fr);
13260 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
13261 tcg_temp_free_i64(fp0);
13262 tcg_temp_free_i64(fp1);
13263 gen_store_fpr64(ctx, fp2, fd);
13264 tcg_temp_free_i64(fp2);
13266 break;
13267 case OPC_MADD_PS:
13268 check_ps(ctx);
13270 TCGv_i64 fp0 = tcg_temp_new_i64();
13271 TCGv_i64 fp1 = tcg_temp_new_i64();
13272 TCGv_i64 fp2 = tcg_temp_new_i64();
13274 gen_load_fpr64(ctx, fp0, fs);
13275 gen_load_fpr64(ctx, fp1, ft);
13276 gen_load_fpr64(ctx, fp2, fr);
13277 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
13278 tcg_temp_free_i64(fp0);
13279 tcg_temp_free_i64(fp1);
13280 gen_store_fpr64(ctx, fp2, fd);
13281 tcg_temp_free_i64(fp2);
13283 break;
13284 case OPC_MSUB_S:
13285 check_cop1x(ctx);
13287 TCGv_i32 fp0 = tcg_temp_new_i32();
13288 TCGv_i32 fp1 = tcg_temp_new_i32();
13289 TCGv_i32 fp2 = tcg_temp_new_i32();
13291 gen_load_fpr32(ctx, fp0, fs);
13292 gen_load_fpr32(ctx, fp1, ft);
13293 gen_load_fpr32(ctx, fp2, fr);
13294 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
13295 tcg_temp_free_i32(fp0);
13296 tcg_temp_free_i32(fp1);
13297 gen_store_fpr32(ctx, fp2, fd);
13298 tcg_temp_free_i32(fp2);
13300 break;
13301 case OPC_MSUB_D:
13302 check_cop1x(ctx);
13303 check_cp1_registers(ctx, fd | fs | ft | fr);
13305 TCGv_i64 fp0 = tcg_temp_new_i64();
13306 TCGv_i64 fp1 = tcg_temp_new_i64();
13307 TCGv_i64 fp2 = tcg_temp_new_i64();
13309 gen_load_fpr64(ctx, fp0, fs);
13310 gen_load_fpr64(ctx, fp1, ft);
13311 gen_load_fpr64(ctx, fp2, fr);
13312 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
13313 tcg_temp_free_i64(fp0);
13314 tcg_temp_free_i64(fp1);
13315 gen_store_fpr64(ctx, fp2, fd);
13316 tcg_temp_free_i64(fp2);
13318 break;
13319 case OPC_MSUB_PS:
13320 check_ps(ctx);
13322 TCGv_i64 fp0 = tcg_temp_new_i64();
13323 TCGv_i64 fp1 = tcg_temp_new_i64();
13324 TCGv_i64 fp2 = tcg_temp_new_i64();
13326 gen_load_fpr64(ctx, fp0, fs);
13327 gen_load_fpr64(ctx, fp1, ft);
13328 gen_load_fpr64(ctx, fp2, fr);
13329 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
13330 tcg_temp_free_i64(fp0);
13331 tcg_temp_free_i64(fp1);
13332 gen_store_fpr64(ctx, fp2, fd);
13333 tcg_temp_free_i64(fp2);
13335 break;
13336 case OPC_NMADD_S:
13337 check_cop1x(ctx);
13339 TCGv_i32 fp0 = tcg_temp_new_i32();
13340 TCGv_i32 fp1 = tcg_temp_new_i32();
13341 TCGv_i32 fp2 = tcg_temp_new_i32();
13343 gen_load_fpr32(ctx, fp0, fs);
13344 gen_load_fpr32(ctx, fp1, ft);
13345 gen_load_fpr32(ctx, fp2, fr);
13346 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
13347 tcg_temp_free_i32(fp0);
13348 tcg_temp_free_i32(fp1);
13349 gen_store_fpr32(ctx, fp2, fd);
13350 tcg_temp_free_i32(fp2);
13352 break;
13353 case OPC_NMADD_D:
13354 check_cop1x(ctx);
13355 check_cp1_registers(ctx, fd | fs | ft | fr);
13357 TCGv_i64 fp0 = tcg_temp_new_i64();
13358 TCGv_i64 fp1 = tcg_temp_new_i64();
13359 TCGv_i64 fp2 = tcg_temp_new_i64();
13361 gen_load_fpr64(ctx, fp0, fs);
13362 gen_load_fpr64(ctx, fp1, ft);
13363 gen_load_fpr64(ctx, fp2, fr);
13364 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
13365 tcg_temp_free_i64(fp0);
13366 tcg_temp_free_i64(fp1);
13367 gen_store_fpr64(ctx, fp2, fd);
13368 tcg_temp_free_i64(fp2);
13370 break;
13371 case OPC_NMADD_PS:
13372 check_ps(ctx);
13374 TCGv_i64 fp0 = tcg_temp_new_i64();
13375 TCGv_i64 fp1 = tcg_temp_new_i64();
13376 TCGv_i64 fp2 = tcg_temp_new_i64();
13378 gen_load_fpr64(ctx, fp0, fs);
13379 gen_load_fpr64(ctx, fp1, ft);
13380 gen_load_fpr64(ctx, fp2, fr);
13381 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
13382 tcg_temp_free_i64(fp0);
13383 tcg_temp_free_i64(fp1);
13384 gen_store_fpr64(ctx, fp2, fd);
13385 tcg_temp_free_i64(fp2);
13387 break;
13388 case OPC_NMSUB_S:
13389 check_cop1x(ctx);
13391 TCGv_i32 fp0 = tcg_temp_new_i32();
13392 TCGv_i32 fp1 = tcg_temp_new_i32();
13393 TCGv_i32 fp2 = tcg_temp_new_i32();
13395 gen_load_fpr32(ctx, fp0, fs);
13396 gen_load_fpr32(ctx, fp1, ft);
13397 gen_load_fpr32(ctx, fp2, fr);
13398 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
13399 tcg_temp_free_i32(fp0);
13400 tcg_temp_free_i32(fp1);
13401 gen_store_fpr32(ctx, fp2, fd);
13402 tcg_temp_free_i32(fp2);
13404 break;
13405 case OPC_NMSUB_D:
13406 check_cop1x(ctx);
13407 check_cp1_registers(ctx, fd | fs | ft | fr);
13409 TCGv_i64 fp0 = tcg_temp_new_i64();
13410 TCGv_i64 fp1 = tcg_temp_new_i64();
13411 TCGv_i64 fp2 = tcg_temp_new_i64();
13413 gen_load_fpr64(ctx, fp0, fs);
13414 gen_load_fpr64(ctx, fp1, ft);
13415 gen_load_fpr64(ctx, fp2, fr);
13416 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
13417 tcg_temp_free_i64(fp0);
13418 tcg_temp_free_i64(fp1);
13419 gen_store_fpr64(ctx, fp2, fd);
13420 tcg_temp_free_i64(fp2);
13422 break;
13423 case OPC_NMSUB_PS:
13424 check_ps(ctx);
13426 TCGv_i64 fp0 = tcg_temp_new_i64();
13427 TCGv_i64 fp1 = tcg_temp_new_i64();
13428 TCGv_i64 fp2 = tcg_temp_new_i64();
13430 gen_load_fpr64(ctx, fp0, fs);
13431 gen_load_fpr64(ctx, fp1, ft);
13432 gen_load_fpr64(ctx, fp2, fr);
13433 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
13434 tcg_temp_free_i64(fp0);
13435 tcg_temp_free_i64(fp1);
13436 gen_store_fpr64(ctx, fp2, fd);
13437 tcg_temp_free_i64(fp2);
13439 break;
13440 default:
13441 MIPS_INVAL("flt3_arith");
13442 generate_exception_end(ctx, EXCP_RI);
13443 return;
13447 static void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
13449 TCGv t0;
13451 #if !defined(CONFIG_USER_ONLY)
13453 * The Linux kernel will emulate rdhwr if it's not supported natively.
13454 * Therefore only check the ISA in system mode.
13456 check_insn(ctx, ISA_MIPS32R2);
13457 #endif
13458 t0 = tcg_temp_new();
13460 switch (rd) {
13461 case 0:
13462 gen_helper_rdhwr_cpunum(t0, cpu_env);
13463 gen_store_gpr(t0, rt);
13464 break;
13465 case 1:
13466 gen_helper_rdhwr_synci_step(t0, cpu_env);
13467 gen_store_gpr(t0, rt);
13468 break;
13469 case 2:
13470 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
13471 gen_io_start();
13473 gen_helper_rdhwr_cc(t0, cpu_env);
13474 gen_store_gpr(t0, rt);
13476 * Break the TB to be able to take timer interrupts immediately
13477 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
13478 * we break completely out of translated code.
13480 gen_save_pc(ctx->base.pc_next + 4);
13481 ctx->base.is_jmp = DISAS_EXIT;
13482 break;
13483 case 3:
13484 gen_helper_rdhwr_ccres(t0, cpu_env);
13485 gen_store_gpr(t0, rt);
13486 break;
13487 case 4:
13488 check_insn(ctx, ISA_MIPS32R6);
13489 if (sel != 0) {
13491 * Performance counter registers are not implemented other than
13492 * control register 0.
13494 generate_exception(ctx, EXCP_RI);
13496 gen_helper_rdhwr_performance(t0, cpu_env);
13497 gen_store_gpr(t0, rt);
13498 break;
13499 case 5:
13500 check_insn(ctx, ISA_MIPS32R6);
13501 gen_helper_rdhwr_xnp(t0, cpu_env);
13502 gen_store_gpr(t0, rt);
13503 break;
13504 case 29:
13505 #if defined(CONFIG_USER_ONLY)
13506 tcg_gen_ld_tl(t0, cpu_env,
13507 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13508 gen_store_gpr(t0, rt);
13509 break;
13510 #else
13511 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
13512 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
13513 tcg_gen_ld_tl(t0, cpu_env,
13514 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
13515 gen_store_gpr(t0, rt);
13516 } else {
13517 generate_exception_end(ctx, EXCP_RI);
13519 break;
13520 #endif
13521 default: /* Invalid */
13522 MIPS_INVAL("rdhwr");
13523 generate_exception_end(ctx, EXCP_RI);
13524 break;
13526 tcg_temp_free(t0);
13529 static inline void clear_branch_hflags(DisasContext *ctx)
13531 ctx->hflags &= ~MIPS_HFLAG_BMASK;
13532 if (ctx->base.is_jmp == DISAS_NEXT) {
13533 save_cpu_state(ctx, 0);
13534 } else {
13536 * It is not safe to save ctx->hflags as hflags may be changed
13537 * in execution time by the instruction in delay / forbidden slot.
13539 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
13543 static void gen_branch(DisasContext *ctx, int insn_bytes)
13545 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13546 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
13547 /* Branches completion */
13548 clear_branch_hflags(ctx);
13549 ctx->base.is_jmp = DISAS_NORETURN;
13550 /* FIXME: Need to clear can_do_io. */
13551 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
13552 case MIPS_HFLAG_FBNSLOT:
13553 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
13554 break;
13555 case MIPS_HFLAG_B:
13556 /* unconditional branch */
13557 if (proc_hflags & MIPS_HFLAG_BX) {
13558 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
13560 gen_goto_tb(ctx, 0, ctx->btarget);
13561 break;
13562 case MIPS_HFLAG_BL:
13563 /* blikely taken case */
13564 gen_goto_tb(ctx, 0, ctx->btarget);
13565 break;
13566 case MIPS_HFLAG_BC:
13567 /* Conditional branch */
13569 TCGLabel *l1 = gen_new_label();
13571 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
13572 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
13573 gen_set_label(l1);
13574 gen_goto_tb(ctx, 0, ctx->btarget);
13576 break;
13577 case MIPS_HFLAG_BR:
13578 /* unconditional branch to register */
13579 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
13580 TCGv t0 = tcg_temp_new();
13581 TCGv_i32 t1 = tcg_temp_new_i32();
13583 tcg_gen_andi_tl(t0, btarget, 0x1);
13584 tcg_gen_trunc_tl_i32(t1, t0);
13585 tcg_temp_free(t0);
13586 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
13587 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
13588 tcg_gen_or_i32(hflags, hflags, t1);
13589 tcg_temp_free_i32(t1);
13591 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
13592 } else {
13593 tcg_gen_mov_tl(cpu_PC, btarget);
13595 if (ctx->base.singlestep_enabled) {
13596 save_cpu_state(ctx, 0);
13597 gen_helper_raise_exception_debug(cpu_env);
13599 tcg_gen_lookup_and_goto_ptr();
13600 break;
13601 default:
13602 fprintf(stderr, "unknown branch 0x%x\n", proc_hflags);
13603 abort();
13608 /* Compact Branches */
13609 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
13610 int rs, int rt, int32_t offset)
13612 int bcond_compute = 0;
13613 TCGv t0 = tcg_temp_new();
13614 TCGv t1 = tcg_temp_new();
13615 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
13617 if (ctx->hflags & MIPS_HFLAG_BMASK) {
13618 #ifdef MIPS_DEBUG_DISAS
13619 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
13620 "\n", ctx->base.pc_next);
13621 #endif
13622 generate_exception_end(ctx, EXCP_RI);
13623 goto out;
13626 /* Load needed operands and calculate btarget */
13627 switch (opc) {
13628 /* compact branch */
13629 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13630 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13631 gen_load_gpr(t0, rs);
13632 gen_load_gpr(t1, rt);
13633 bcond_compute = 1;
13634 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13635 if (rs <= rt && rs == 0) {
13636 /* OPC_BEQZALC, OPC_BNEZALC */
13637 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13639 break;
13640 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13641 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13642 gen_load_gpr(t0, rs);
13643 gen_load_gpr(t1, rt);
13644 bcond_compute = 1;
13645 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13646 break;
13647 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13648 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13649 if (rs == 0 || rs == rt) {
13650 /* OPC_BLEZALC, OPC_BGEZALC */
13651 /* OPC_BGTZALC, OPC_BLTZALC */
13652 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13654 gen_load_gpr(t0, rs);
13655 gen_load_gpr(t1, rt);
13656 bcond_compute = 1;
13657 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13658 break;
13659 case OPC_BC:
13660 case OPC_BALC:
13661 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13662 break;
13663 case OPC_BEQZC:
13664 case OPC_BNEZC:
13665 if (rs != 0) {
13666 /* OPC_BEQZC, OPC_BNEZC */
13667 gen_load_gpr(t0, rs);
13668 bcond_compute = 1;
13669 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
13670 } else {
13671 /* OPC_JIC, OPC_JIALC */
13672 TCGv tbase = tcg_temp_new();
13673 TCGv toffset = tcg_temp_new();
13675 gen_load_gpr(tbase, rt);
13676 tcg_gen_movi_tl(toffset, offset);
13677 gen_op_addr_add(ctx, btarget, tbase, toffset);
13678 tcg_temp_free(tbase);
13679 tcg_temp_free(toffset);
13681 break;
13682 default:
13683 MIPS_INVAL("Compact branch/jump");
13684 generate_exception_end(ctx, EXCP_RI);
13685 goto out;
13688 if (bcond_compute == 0) {
13689 /* Uncoditional compact branch */
13690 switch (opc) {
13691 case OPC_JIALC:
13692 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13693 /* Fallthrough */
13694 case OPC_JIC:
13695 ctx->hflags |= MIPS_HFLAG_BR;
13696 break;
13697 case OPC_BALC:
13698 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
13699 /* Fallthrough */
13700 case OPC_BC:
13701 ctx->hflags |= MIPS_HFLAG_B;
13702 break;
13703 default:
13704 MIPS_INVAL("Compact branch/jump");
13705 generate_exception_end(ctx, EXCP_RI);
13706 goto out;
13709 /* Generating branch here as compact branches don't have delay slot */
13710 gen_branch(ctx, 4);
13711 } else {
13712 /* Conditional compact branch */
13713 TCGLabel *fs = gen_new_label();
13714 save_cpu_state(ctx, 0);
13716 switch (opc) {
13717 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
13718 if (rs == 0 && rt != 0) {
13719 /* OPC_BLEZALC */
13720 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13721 } else if (rs != 0 && rt != 0 && rs == rt) {
13722 /* OPC_BGEZALC */
13723 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13724 } else {
13725 /* OPC_BGEUC */
13726 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
13728 break;
13729 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
13730 if (rs == 0 && rt != 0) {
13731 /* OPC_BGTZALC */
13732 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13733 } else if (rs != 0 && rt != 0 && rs == rt) {
13734 /* OPC_BLTZALC */
13735 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13736 } else {
13737 /* OPC_BLTUC */
13738 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
13740 break;
13741 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
13742 if (rs == 0 && rt != 0) {
13743 /* OPC_BLEZC */
13744 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
13745 } else if (rs != 0 && rt != 0 && rs == rt) {
13746 /* OPC_BGEZC */
13747 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
13748 } else {
13749 /* OPC_BGEC */
13750 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
13752 break;
13753 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
13754 if (rs == 0 && rt != 0) {
13755 /* OPC_BGTZC */
13756 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
13757 } else if (rs != 0 && rt != 0 && rs == rt) {
13758 /* OPC_BLTZC */
13759 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
13760 } else {
13761 /* OPC_BLTC */
13762 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
13764 break;
13765 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
13766 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
13767 if (rs >= rt) {
13768 /* OPC_BOVC, OPC_BNVC */
13769 TCGv t2 = tcg_temp_new();
13770 TCGv t3 = tcg_temp_new();
13771 TCGv t4 = tcg_temp_new();
13772 TCGv input_overflow = tcg_temp_new();
13774 gen_load_gpr(t0, rs);
13775 gen_load_gpr(t1, rt);
13776 tcg_gen_ext32s_tl(t2, t0);
13777 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
13778 tcg_gen_ext32s_tl(t3, t1);
13779 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
13780 tcg_gen_or_tl(input_overflow, input_overflow, t4);
13782 tcg_gen_add_tl(t4, t2, t3);
13783 tcg_gen_ext32s_tl(t4, t4);
13784 tcg_gen_xor_tl(t2, t2, t3);
13785 tcg_gen_xor_tl(t3, t4, t3);
13786 tcg_gen_andc_tl(t2, t3, t2);
13787 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
13788 tcg_gen_or_tl(t4, t4, input_overflow);
13789 if (opc == OPC_BOVC) {
13790 /* OPC_BOVC */
13791 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
13792 } else {
13793 /* OPC_BNVC */
13794 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
13796 tcg_temp_free(input_overflow);
13797 tcg_temp_free(t4);
13798 tcg_temp_free(t3);
13799 tcg_temp_free(t2);
13800 } else if (rs < rt && rs == 0) {
13801 /* OPC_BEQZALC, OPC_BNEZALC */
13802 if (opc == OPC_BEQZALC) {
13803 /* OPC_BEQZALC */
13804 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
13805 } else {
13806 /* OPC_BNEZALC */
13807 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
13809 } else {
13810 /* OPC_BEQC, OPC_BNEC */
13811 if (opc == OPC_BEQC) {
13812 /* OPC_BEQC */
13813 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
13814 } else {
13815 /* OPC_BNEC */
13816 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
13819 break;
13820 case OPC_BEQZC:
13821 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
13822 break;
13823 case OPC_BNEZC:
13824 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
13825 break;
13826 default:
13827 MIPS_INVAL("Compact conditional branch/jump");
13828 generate_exception_end(ctx, EXCP_RI);
13829 goto out;
13832 /* Generating branch here as compact branches don't have delay slot */
13833 gen_goto_tb(ctx, 1, ctx->btarget);
13834 gen_set_label(fs);
13836 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
13839 out:
13840 tcg_temp_free(t0);
13841 tcg_temp_free(t1);
13844 /* ISA extensions (ASEs) */
13845 /* MIPS16 extension to MIPS32 */
13847 /* MIPS16 major opcodes */
13848 enum {
13849 M16_OPC_ADDIUSP = 0x00,
13850 M16_OPC_ADDIUPC = 0x01,
13851 M16_OPC_B = 0x02,
13852 M16_OPC_JAL = 0x03,
13853 M16_OPC_BEQZ = 0x04,
13854 M16_OPC_BNEQZ = 0x05,
13855 M16_OPC_SHIFT = 0x06,
13856 M16_OPC_LD = 0x07,
13857 M16_OPC_RRIA = 0x08,
13858 M16_OPC_ADDIU8 = 0x09,
13859 M16_OPC_SLTI = 0x0a,
13860 M16_OPC_SLTIU = 0x0b,
13861 M16_OPC_I8 = 0x0c,
13862 M16_OPC_LI = 0x0d,
13863 M16_OPC_CMPI = 0x0e,
13864 M16_OPC_SD = 0x0f,
13865 M16_OPC_LB = 0x10,
13866 M16_OPC_LH = 0x11,
13867 M16_OPC_LWSP = 0x12,
13868 M16_OPC_LW = 0x13,
13869 M16_OPC_LBU = 0x14,
13870 M16_OPC_LHU = 0x15,
13871 M16_OPC_LWPC = 0x16,
13872 M16_OPC_LWU = 0x17,
13873 M16_OPC_SB = 0x18,
13874 M16_OPC_SH = 0x19,
13875 M16_OPC_SWSP = 0x1a,
13876 M16_OPC_SW = 0x1b,
13877 M16_OPC_RRR = 0x1c,
13878 M16_OPC_RR = 0x1d,
13879 M16_OPC_EXTEND = 0x1e,
13880 M16_OPC_I64 = 0x1f
13883 /* I8 funct field */
13884 enum {
13885 I8_BTEQZ = 0x0,
13886 I8_BTNEZ = 0x1,
13887 I8_SWRASP = 0x2,
13888 I8_ADJSP = 0x3,
13889 I8_SVRS = 0x4,
13890 I8_MOV32R = 0x5,
13891 I8_MOVR32 = 0x7
13894 /* RRR f field */
13895 enum {
13896 RRR_DADDU = 0x0,
13897 RRR_ADDU = 0x1,
13898 RRR_DSUBU = 0x2,
13899 RRR_SUBU = 0x3
13902 /* RR funct field */
13903 enum {
13904 RR_JR = 0x00,
13905 RR_SDBBP = 0x01,
13906 RR_SLT = 0x02,
13907 RR_SLTU = 0x03,
13908 RR_SLLV = 0x04,
13909 RR_BREAK = 0x05,
13910 RR_SRLV = 0x06,
13911 RR_SRAV = 0x07,
13912 RR_DSRL = 0x08,
13913 RR_CMP = 0x0a,
13914 RR_NEG = 0x0b,
13915 RR_AND = 0x0c,
13916 RR_OR = 0x0d,
13917 RR_XOR = 0x0e,
13918 RR_NOT = 0x0f,
13919 RR_MFHI = 0x10,
13920 RR_CNVT = 0x11,
13921 RR_MFLO = 0x12,
13922 RR_DSRA = 0x13,
13923 RR_DSLLV = 0x14,
13924 RR_DSRLV = 0x16,
13925 RR_DSRAV = 0x17,
13926 RR_MULT = 0x18,
13927 RR_MULTU = 0x19,
13928 RR_DIV = 0x1a,
13929 RR_DIVU = 0x1b,
13930 RR_DMULT = 0x1c,
13931 RR_DMULTU = 0x1d,
13932 RR_DDIV = 0x1e,
13933 RR_DDIVU = 0x1f
13936 /* I64 funct field */
13937 enum {
13938 I64_LDSP = 0x0,
13939 I64_SDSP = 0x1,
13940 I64_SDRASP = 0x2,
13941 I64_DADJSP = 0x3,
13942 I64_LDPC = 0x4,
13943 I64_DADDIU5 = 0x5,
13944 I64_DADDIUPC = 0x6,
13945 I64_DADDIUSP = 0x7
13948 /* RR ry field for CNVT */
13949 enum {
13950 RR_RY_CNVT_ZEB = 0x0,
13951 RR_RY_CNVT_ZEH = 0x1,
13952 RR_RY_CNVT_ZEW = 0x2,
13953 RR_RY_CNVT_SEB = 0x4,
13954 RR_RY_CNVT_SEH = 0x5,
13955 RR_RY_CNVT_SEW = 0x6,
13958 static int xlat(int r)
13960 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
13962 return map[r];
13965 static void gen_mips16_save(DisasContext *ctx,
13966 int xsregs, int aregs,
13967 int do_ra, int do_s0, int do_s1,
13968 int framesize)
13970 TCGv t0 = tcg_temp_new();
13971 TCGv t1 = tcg_temp_new();
13972 TCGv t2 = tcg_temp_new();
13973 int args, astatic;
13975 switch (aregs) {
13976 case 0:
13977 case 1:
13978 case 2:
13979 case 3:
13980 case 11:
13981 args = 0;
13982 break;
13983 case 4:
13984 case 5:
13985 case 6:
13986 case 7:
13987 args = 1;
13988 break;
13989 case 8:
13990 case 9:
13991 case 10:
13992 args = 2;
13993 break;
13994 case 12:
13995 case 13:
13996 args = 3;
13997 break;
13998 case 14:
13999 args = 4;
14000 break;
14001 default:
14002 generate_exception_end(ctx, EXCP_RI);
14003 return;
14006 switch (args) {
14007 case 4:
14008 gen_base_offset_addr(ctx, t0, 29, 12);
14009 gen_load_gpr(t1, 7);
14010 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14011 /* Fall through */
14012 case 3:
14013 gen_base_offset_addr(ctx, t0, 29, 8);
14014 gen_load_gpr(t1, 6);
14015 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14016 /* Fall through */
14017 case 2:
14018 gen_base_offset_addr(ctx, t0, 29, 4);
14019 gen_load_gpr(t1, 5);
14020 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14021 /* Fall through */
14022 case 1:
14023 gen_base_offset_addr(ctx, t0, 29, 0);
14024 gen_load_gpr(t1, 4);
14025 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14028 gen_load_gpr(t0, 29);
14030 #define DECR_AND_STORE(reg) do { \
14031 tcg_gen_movi_tl(t2, -4); \
14032 gen_op_addr_add(ctx, t0, t0, t2); \
14033 gen_load_gpr(t1, reg); \
14034 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
14035 } while (0)
14037 if (do_ra) {
14038 DECR_AND_STORE(31);
14041 switch (xsregs) {
14042 case 7:
14043 DECR_AND_STORE(30);
14044 /* Fall through */
14045 case 6:
14046 DECR_AND_STORE(23);
14047 /* Fall through */
14048 case 5:
14049 DECR_AND_STORE(22);
14050 /* Fall through */
14051 case 4:
14052 DECR_AND_STORE(21);
14053 /* Fall through */
14054 case 3:
14055 DECR_AND_STORE(20);
14056 /* Fall through */
14057 case 2:
14058 DECR_AND_STORE(19);
14059 /* Fall through */
14060 case 1:
14061 DECR_AND_STORE(18);
14064 if (do_s1) {
14065 DECR_AND_STORE(17);
14067 if (do_s0) {
14068 DECR_AND_STORE(16);
14071 switch (aregs) {
14072 case 0:
14073 case 4:
14074 case 8:
14075 case 12:
14076 case 14:
14077 astatic = 0;
14078 break;
14079 case 1:
14080 case 5:
14081 case 9:
14082 case 13:
14083 astatic = 1;
14084 break;
14085 case 2:
14086 case 6:
14087 case 10:
14088 astatic = 2;
14089 break;
14090 case 3:
14091 case 7:
14092 astatic = 3;
14093 break;
14094 case 11:
14095 astatic = 4;
14096 break;
14097 default:
14098 generate_exception_end(ctx, EXCP_RI);
14099 return;
14102 if (astatic > 0) {
14103 DECR_AND_STORE(7);
14104 if (astatic > 1) {
14105 DECR_AND_STORE(6);
14106 if (astatic > 2) {
14107 DECR_AND_STORE(5);
14108 if (astatic > 3) {
14109 DECR_AND_STORE(4);
14114 #undef DECR_AND_STORE
14116 tcg_gen_movi_tl(t2, -framesize);
14117 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14118 tcg_temp_free(t0);
14119 tcg_temp_free(t1);
14120 tcg_temp_free(t2);
14123 static void gen_mips16_restore(DisasContext *ctx,
14124 int xsregs, int aregs,
14125 int do_ra, int do_s0, int do_s1,
14126 int framesize)
14128 int astatic;
14129 TCGv t0 = tcg_temp_new();
14130 TCGv t1 = tcg_temp_new();
14131 TCGv t2 = tcg_temp_new();
14133 tcg_gen_movi_tl(t2, framesize);
14134 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
14136 #define DECR_AND_LOAD(reg) do { \
14137 tcg_gen_movi_tl(t2, -4); \
14138 gen_op_addr_add(ctx, t0, t0, t2); \
14139 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
14140 gen_store_gpr(t1, reg); \
14141 } while (0)
14143 if (do_ra) {
14144 DECR_AND_LOAD(31);
14147 switch (xsregs) {
14148 case 7:
14149 DECR_AND_LOAD(30);
14150 /* Fall through */
14151 case 6:
14152 DECR_AND_LOAD(23);
14153 /* Fall through */
14154 case 5:
14155 DECR_AND_LOAD(22);
14156 /* Fall through */
14157 case 4:
14158 DECR_AND_LOAD(21);
14159 /* Fall through */
14160 case 3:
14161 DECR_AND_LOAD(20);
14162 /* Fall through */
14163 case 2:
14164 DECR_AND_LOAD(19);
14165 /* Fall through */
14166 case 1:
14167 DECR_AND_LOAD(18);
14170 if (do_s1) {
14171 DECR_AND_LOAD(17);
14173 if (do_s0) {
14174 DECR_AND_LOAD(16);
14177 switch (aregs) {
14178 case 0:
14179 case 4:
14180 case 8:
14181 case 12:
14182 case 14:
14183 astatic = 0;
14184 break;
14185 case 1:
14186 case 5:
14187 case 9:
14188 case 13:
14189 astatic = 1;
14190 break;
14191 case 2:
14192 case 6:
14193 case 10:
14194 astatic = 2;
14195 break;
14196 case 3:
14197 case 7:
14198 astatic = 3;
14199 break;
14200 case 11:
14201 astatic = 4;
14202 break;
14203 default:
14204 generate_exception_end(ctx, EXCP_RI);
14205 return;
14208 if (astatic > 0) {
14209 DECR_AND_LOAD(7);
14210 if (astatic > 1) {
14211 DECR_AND_LOAD(6);
14212 if (astatic > 2) {
14213 DECR_AND_LOAD(5);
14214 if (astatic > 3) {
14215 DECR_AND_LOAD(4);
14220 #undef DECR_AND_LOAD
14222 tcg_gen_movi_tl(t2, framesize);
14223 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
14224 tcg_temp_free(t0);
14225 tcg_temp_free(t1);
14226 tcg_temp_free(t2);
14229 static void gen_addiupc(DisasContext *ctx, int rx, int imm,
14230 int is_64_bit, int extended)
14232 TCGv t0;
14234 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14235 generate_exception_end(ctx, EXCP_RI);
14236 return;
14239 t0 = tcg_temp_new();
14241 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
14242 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
14243 if (!is_64_bit) {
14244 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14247 tcg_temp_free(t0);
14250 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
14251 int16_t offset)
14253 TCGv_i32 t0 = tcg_const_i32(op);
14254 TCGv t1 = tcg_temp_new();
14255 gen_base_offset_addr(ctx, t1, base, offset);
14256 gen_helper_cache(cpu_env, t1, t0);
14259 #if defined(TARGET_MIPS64)
14260 static void decode_i64_mips16(DisasContext *ctx,
14261 int ry, int funct, int16_t offset,
14262 int extended)
14264 switch (funct) {
14265 case I64_LDSP:
14266 check_insn(ctx, ISA_MIPS3);
14267 check_mips_64(ctx);
14268 offset = extended ? offset : offset << 3;
14269 gen_ld(ctx, OPC_LD, ry, 29, offset);
14270 break;
14271 case I64_SDSP:
14272 check_insn(ctx, ISA_MIPS3);
14273 check_mips_64(ctx);
14274 offset = extended ? offset : offset << 3;
14275 gen_st(ctx, OPC_SD, ry, 29, offset);
14276 break;
14277 case I64_SDRASP:
14278 check_insn(ctx, ISA_MIPS3);
14279 check_mips_64(ctx);
14280 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
14281 gen_st(ctx, OPC_SD, 31, 29, offset);
14282 break;
14283 case I64_DADJSP:
14284 check_insn(ctx, ISA_MIPS3);
14285 check_mips_64(ctx);
14286 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
14287 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
14288 break;
14289 case I64_LDPC:
14290 check_insn(ctx, ISA_MIPS3);
14291 check_mips_64(ctx);
14292 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
14293 generate_exception_end(ctx, EXCP_RI);
14294 } else {
14295 offset = extended ? offset : offset << 3;
14296 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
14298 break;
14299 case I64_DADDIU5:
14300 check_insn(ctx, ISA_MIPS3);
14301 check_mips_64(ctx);
14302 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
14303 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
14304 break;
14305 case I64_DADDIUPC:
14306 check_insn(ctx, ISA_MIPS3);
14307 check_mips_64(ctx);
14308 offset = extended ? offset : offset << 2;
14309 gen_addiupc(ctx, ry, offset, 1, extended);
14310 break;
14311 case I64_DADDIUSP:
14312 check_insn(ctx, ISA_MIPS3);
14313 check_mips_64(ctx);
14314 offset = extended ? offset : offset << 2;
14315 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
14316 break;
14319 #endif
14321 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14323 int extend = cpu_lduw_code(env, ctx->base.pc_next + 2);
14324 int op, rx, ry, funct, sa;
14325 int16_t imm, offset;
14327 ctx->opcode = (ctx->opcode << 16) | extend;
14328 op = (ctx->opcode >> 11) & 0x1f;
14329 sa = (ctx->opcode >> 22) & 0x1f;
14330 funct = (ctx->opcode >> 8) & 0x7;
14331 rx = xlat((ctx->opcode >> 8) & 0x7);
14332 ry = xlat((ctx->opcode >> 5) & 0x7);
14333 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
14334 | ((ctx->opcode >> 21) & 0x3f) << 5
14335 | (ctx->opcode & 0x1f));
14338 * The extended opcodes cleverly reuse the opcodes from their 16-bit
14339 * counterparts.
14341 switch (op) {
14342 case M16_OPC_ADDIUSP:
14343 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14344 break;
14345 case M16_OPC_ADDIUPC:
14346 gen_addiupc(ctx, rx, imm, 0, 1);
14347 break;
14348 case M16_OPC_B:
14349 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
14350 /* No delay slot, so just process as a normal instruction */
14351 break;
14352 case M16_OPC_BEQZ:
14353 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
14354 /* No delay slot, so just process as a normal instruction */
14355 break;
14356 case M16_OPC_BNEQZ:
14357 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
14358 /* No delay slot, so just process as a normal instruction */
14359 break;
14360 case M16_OPC_SHIFT:
14361 switch (ctx->opcode & 0x3) {
14362 case 0x0:
14363 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14364 break;
14365 case 0x1:
14366 #if defined(TARGET_MIPS64)
14367 check_mips_64(ctx);
14368 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14369 #else
14370 generate_exception_end(ctx, EXCP_RI);
14371 #endif
14372 break;
14373 case 0x2:
14374 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14375 break;
14376 case 0x3:
14377 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14378 break;
14380 break;
14381 #if defined(TARGET_MIPS64)
14382 case M16_OPC_LD:
14383 check_insn(ctx, ISA_MIPS3);
14384 check_mips_64(ctx);
14385 gen_ld(ctx, OPC_LD, ry, rx, offset);
14386 break;
14387 #endif
14388 case M16_OPC_RRIA:
14389 imm = ctx->opcode & 0xf;
14390 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
14391 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
14392 imm = (int16_t) (imm << 1) >> 1;
14393 if ((ctx->opcode >> 4) & 0x1) {
14394 #if defined(TARGET_MIPS64)
14395 check_mips_64(ctx);
14396 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14397 #else
14398 generate_exception_end(ctx, EXCP_RI);
14399 #endif
14400 } else {
14401 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14403 break;
14404 case M16_OPC_ADDIU8:
14405 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14406 break;
14407 case M16_OPC_SLTI:
14408 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14409 break;
14410 case M16_OPC_SLTIU:
14411 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14412 break;
14413 case M16_OPC_I8:
14414 switch (funct) {
14415 case I8_BTEQZ:
14416 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
14417 break;
14418 case I8_BTNEZ:
14419 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
14420 break;
14421 case I8_SWRASP:
14422 gen_st(ctx, OPC_SW, 31, 29, imm);
14423 break;
14424 case I8_ADJSP:
14425 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
14426 break;
14427 case I8_SVRS:
14428 check_insn(ctx, ISA_MIPS32);
14430 int xsregs = (ctx->opcode >> 24) & 0x7;
14431 int aregs = (ctx->opcode >> 16) & 0xf;
14432 int do_ra = (ctx->opcode >> 6) & 0x1;
14433 int do_s0 = (ctx->opcode >> 5) & 0x1;
14434 int do_s1 = (ctx->opcode >> 4) & 0x1;
14435 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
14436 | (ctx->opcode & 0xf)) << 3;
14438 if (ctx->opcode & (1 << 7)) {
14439 gen_mips16_save(ctx, xsregs, aregs,
14440 do_ra, do_s0, do_s1,
14441 framesize);
14442 } else {
14443 gen_mips16_restore(ctx, xsregs, aregs,
14444 do_ra, do_s0, do_s1,
14445 framesize);
14448 break;
14449 default:
14450 generate_exception_end(ctx, EXCP_RI);
14451 break;
14453 break;
14454 case M16_OPC_LI:
14455 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
14456 break;
14457 case M16_OPC_CMPI:
14458 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
14459 break;
14460 #if defined(TARGET_MIPS64)
14461 case M16_OPC_SD:
14462 check_insn(ctx, ISA_MIPS3);
14463 check_mips_64(ctx);
14464 gen_st(ctx, OPC_SD, ry, rx, offset);
14465 break;
14466 #endif
14467 case M16_OPC_LB:
14468 gen_ld(ctx, OPC_LB, ry, rx, offset);
14469 break;
14470 case M16_OPC_LH:
14471 gen_ld(ctx, OPC_LH, ry, rx, offset);
14472 break;
14473 case M16_OPC_LWSP:
14474 gen_ld(ctx, OPC_LW, rx, 29, offset);
14475 break;
14476 case M16_OPC_LW:
14477 gen_ld(ctx, OPC_LW, ry, rx, offset);
14478 break;
14479 case M16_OPC_LBU:
14480 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14481 break;
14482 case M16_OPC_LHU:
14483 gen_ld(ctx, OPC_LHU, ry, rx, offset);
14484 break;
14485 case M16_OPC_LWPC:
14486 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
14487 break;
14488 #if defined(TARGET_MIPS64)
14489 case M16_OPC_LWU:
14490 check_insn(ctx, ISA_MIPS3);
14491 check_mips_64(ctx);
14492 gen_ld(ctx, OPC_LWU, ry, rx, offset);
14493 break;
14494 #endif
14495 case M16_OPC_SB:
14496 gen_st(ctx, OPC_SB, ry, rx, offset);
14497 break;
14498 case M16_OPC_SH:
14499 gen_st(ctx, OPC_SH, ry, rx, offset);
14500 break;
14501 case M16_OPC_SWSP:
14502 gen_st(ctx, OPC_SW, rx, 29, offset);
14503 break;
14504 case M16_OPC_SW:
14505 gen_st(ctx, OPC_SW, ry, rx, offset);
14506 break;
14507 #if defined(TARGET_MIPS64)
14508 case M16_OPC_I64:
14509 decode_i64_mips16(ctx, ry, funct, offset, 1);
14510 break;
14511 #endif
14512 default:
14513 generate_exception_end(ctx, EXCP_RI);
14514 break;
14517 return 4;
14520 static inline bool is_uhi(int sdbbp_code)
14522 #ifdef CONFIG_USER_ONLY
14523 return false;
14524 #else
14525 return semihosting_enabled() && sdbbp_code == 1;
14526 #endif
14529 #ifdef CONFIG_USER_ONLY
14530 /* The above should dead-code away any calls to this..*/
14531 static inline void gen_helper_do_semihosting(void *env)
14533 g_assert_not_reached();
14535 #endif
14537 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
14539 int rx, ry;
14540 int sa;
14541 int op, cnvt_op, op1, offset;
14542 int funct;
14543 int n_bytes;
14545 op = (ctx->opcode >> 11) & 0x1f;
14546 sa = (ctx->opcode >> 2) & 0x7;
14547 sa = sa == 0 ? 8 : sa;
14548 rx = xlat((ctx->opcode >> 8) & 0x7);
14549 cnvt_op = (ctx->opcode >> 5) & 0x7;
14550 ry = xlat((ctx->opcode >> 5) & 0x7);
14551 op1 = offset = ctx->opcode & 0x1f;
14553 n_bytes = 2;
14555 switch (op) {
14556 case M16_OPC_ADDIUSP:
14558 int16_t imm = ((uint8_t) ctx->opcode) << 2;
14560 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
14562 break;
14563 case M16_OPC_ADDIUPC:
14564 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
14565 break;
14566 case M16_OPC_B:
14567 offset = (ctx->opcode & 0x7ff) << 1;
14568 offset = (int16_t)(offset << 4) >> 4;
14569 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
14570 /* No delay slot, so just process as a normal instruction */
14571 break;
14572 case M16_OPC_JAL:
14573 offset = cpu_lduw_code(env, ctx->base.pc_next + 2);
14574 offset = (((ctx->opcode & 0x1f) << 21)
14575 | ((ctx->opcode >> 5) & 0x1f) << 16
14576 | offset) << 2;
14577 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
14578 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
14579 n_bytes = 4;
14580 break;
14581 case M16_OPC_BEQZ:
14582 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
14583 ((int8_t)ctx->opcode) << 1, 0);
14584 /* No delay slot, so just process as a normal instruction */
14585 break;
14586 case M16_OPC_BNEQZ:
14587 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
14588 ((int8_t)ctx->opcode) << 1, 0);
14589 /* No delay slot, so just process as a normal instruction */
14590 break;
14591 case M16_OPC_SHIFT:
14592 switch (ctx->opcode & 0x3) {
14593 case 0x0:
14594 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
14595 break;
14596 case 0x1:
14597 #if defined(TARGET_MIPS64)
14598 check_insn(ctx, ISA_MIPS3);
14599 check_mips_64(ctx);
14600 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
14601 #else
14602 generate_exception_end(ctx, EXCP_RI);
14603 #endif
14604 break;
14605 case 0x2:
14606 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
14607 break;
14608 case 0x3:
14609 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
14610 break;
14612 break;
14613 #if defined(TARGET_MIPS64)
14614 case M16_OPC_LD:
14615 check_insn(ctx, ISA_MIPS3);
14616 check_mips_64(ctx);
14617 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
14618 break;
14619 #endif
14620 case M16_OPC_RRIA:
14622 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
14624 if ((ctx->opcode >> 4) & 1) {
14625 #if defined(TARGET_MIPS64)
14626 check_insn(ctx, ISA_MIPS3);
14627 check_mips_64(ctx);
14628 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
14629 #else
14630 generate_exception_end(ctx, EXCP_RI);
14631 #endif
14632 } else {
14633 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
14636 break;
14637 case M16_OPC_ADDIU8:
14639 int16_t imm = (int8_t) ctx->opcode;
14641 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
14643 break;
14644 case M16_OPC_SLTI:
14646 int16_t imm = (uint8_t) ctx->opcode;
14647 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
14649 break;
14650 case M16_OPC_SLTIU:
14652 int16_t imm = (uint8_t) ctx->opcode;
14653 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
14655 break;
14656 case M16_OPC_I8:
14658 int reg32;
14660 funct = (ctx->opcode >> 8) & 0x7;
14661 switch (funct) {
14662 case I8_BTEQZ:
14663 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
14664 ((int8_t)ctx->opcode) << 1, 0);
14665 break;
14666 case I8_BTNEZ:
14667 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
14668 ((int8_t)ctx->opcode) << 1, 0);
14669 break;
14670 case I8_SWRASP:
14671 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
14672 break;
14673 case I8_ADJSP:
14674 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
14675 ((int8_t)ctx->opcode) << 3);
14676 break;
14677 case I8_SVRS:
14678 check_insn(ctx, ISA_MIPS32);
14680 int do_ra = ctx->opcode & (1 << 6);
14681 int do_s0 = ctx->opcode & (1 << 5);
14682 int do_s1 = ctx->opcode & (1 << 4);
14683 int framesize = ctx->opcode & 0xf;
14685 if (framesize == 0) {
14686 framesize = 128;
14687 } else {
14688 framesize = framesize << 3;
14691 if (ctx->opcode & (1 << 7)) {
14692 gen_mips16_save(ctx, 0, 0,
14693 do_ra, do_s0, do_s1, framesize);
14694 } else {
14695 gen_mips16_restore(ctx, 0, 0,
14696 do_ra, do_s0, do_s1, framesize);
14699 break;
14700 case I8_MOV32R:
14702 int rz = xlat(ctx->opcode & 0x7);
14704 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
14705 ((ctx->opcode >> 5) & 0x7);
14706 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
14708 break;
14709 case I8_MOVR32:
14710 reg32 = ctx->opcode & 0x1f;
14711 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
14712 break;
14713 default:
14714 generate_exception_end(ctx, EXCP_RI);
14715 break;
14718 break;
14719 case M16_OPC_LI:
14721 int16_t imm = (uint8_t) ctx->opcode;
14723 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
14725 break;
14726 case M16_OPC_CMPI:
14728 int16_t imm = (uint8_t) ctx->opcode;
14729 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
14731 break;
14732 #if defined(TARGET_MIPS64)
14733 case M16_OPC_SD:
14734 check_insn(ctx, ISA_MIPS3);
14735 check_mips_64(ctx);
14736 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
14737 break;
14738 #endif
14739 case M16_OPC_LB:
14740 gen_ld(ctx, OPC_LB, ry, rx, offset);
14741 break;
14742 case M16_OPC_LH:
14743 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
14744 break;
14745 case M16_OPC_LWSP:
14746 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14747 break;
14748 case M16_OPC_LW:
14749 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
14750 break;
14751 case M16_OPC_LBU:
14752 gen_ld(ctx, OPC_LBU, ry, rx, offset);
14753 break;
14754 case M16_OPC_LHU:
14755 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
14756 break;
14757 case M16_OPC_LWPC:
14758 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
14759 break;
14760 #if defined(TARGET_MIPS64)
14761 case M16_OPC_LWU:
14762 check_insn(ctx, ISA_MIPS3);
14763 check_mips_64(ctx);
14764 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
14765 break;
14766 #endif
14767 case M16_OPC_SB:
14768 gen_st(ctx, OPC_SB, ry, rx, offset);
14769 break;
14770 case M16_OPC_SH:
14771 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
14772 break;
14773 case M16_OPC_SWSP:
14774 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
14775 break;
14776 case M16_OPC_SW:
14777 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
14778 break;
14779 case M16_OPC_RRR:
14781 int rz = xlat((ctx->opcode >> 2) & 0x7);
14782 int mips32_op;
14784 switch (ctx->opcode & 0x3) {
14785 case RRR_ADDU:
14786 mips32_op = OPC_ADDU;
14787 break;
14788 case RRR_SUBU:
14789 mips32_op = OPC_SUBU;
14790 break;
14791 #if defined(TARGET_MIPS64)
14792 case RRR_DADDU:
14793 mips32_op = OPC_DADDU;
14794 check_insn(ctx, ISA_MIPS3);
14795 check_mips_64(ctx);
14796 break;
14797 case RRR_DSUBU:
14798 mips32_op = OPC_DSUBU;
14799 check_insn(ctx, ISA_MIPS3);
14800 check_mips_64(ctx);
14801 break;
14802 #endif
14803 default:
14804 generate_exception_end(ctx, EXCP_RI);
14805 goto done;
14808 gen_arith(ctx, mips32_op, rz, rx, ry);
14809 done:
14812 break;
14813 case M16_OPC_RR:
14814 switch (op1) {
14815 case RR_JR:
14817 int nd = (ctx->opcode >> 7) & 0x1;
14818 int link = (ctx->opcode >> 6) & 0x1;
14819 int ra = (ctx->opcode >> 5) & 0x1;
14821 if (nd) {
14822 check_insn(ctx, ISA_MIPS32);
14825 if (link) {
14826 op = OPC_JALR;
14827 } else {
14828 op = OPC_JR;
14831 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
14832 (nd ? 0 : 2));
14834 break;
14835 case RR_SDBBP:
14836 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
14837 gen_helper_do_semihosting(cpu_env);
14838 } else {
14840 * XXX: not clear which exception should be raised
14841 * when in debug mode...
14843 check_insn(ctx, ISA_MIPS32);
14844 generate_exception_end(ctx, EXCP_DBp);
14846 break;
14847 case RR_SLT:
14848 gen_slt(ctx, OPC_SLT, 24, rx, ry);
14849 break;
14850 case RR_SLTU:
14851 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
14852 break;
14853 case RR_BREAK:
14854 generate_exception_end(ctx, EXCP_BREAK);
14855 break;
14856 case RR_SLLV:
14857 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
14858 break;
14859 case RR_SRLV:
14860 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
14861 break;
14862 case RR_SRAV:
14863 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
14864 break;
14865 #if defined(TARGET_MIPS64)
14866 case RR_DSRL:
14867 check_insn(ctx, ISA_MIPS3);
14868 check_mips_64(ctx);
14869 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
14870 break;
14871 #endif
14872 case RR_CMP:
14873 gen_logic(ctx, OPC_XOR, 24, rx, ry);
14874 break;
14875 case RR_NEG:
14876 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
14877 break;
14878 case RR_AND:
14879 gen_logic(ctx, OPC_AND, rx, rx, ry);
14880 break;
14881 case RR_OR:
14882 gen_logic(ctx, OPC_OR, rx, rx, ry);
14883 break;
14884 case RR_XOR:
14885 gen_logic(ctx, OPC_XOR, rx, rx, ry);
14886 break;
14887 case RR_NOT:
14888 gen_logic(ctx, OPC_NOR, rx, ry, 0);
14889 break;
14890 case RR_MFHI:
14891 gen_HILO(ctx, OPC_MFHI, 0, rx);
14892 break;
14893 case RR_CNVT:
14894 check_insn(ctx, ISA_MIPS32);
14895 switch (cnvt_op) {
14896 case RR_RY_CNVT_ZEB:
14897 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14898 break;
14899 case RR_RY_CNVT_ZEH:
14900 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14901 break;
14902 case RR_RY_CNVT_SEB:
14903 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14904 break;
14905 case RR_RY_CNVT_SEH:
14906 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14907 break;
14908 #if defined(TARGET_MIPS64)
14909 case RR_RY_CNVT_ZEW:
14910 check_insn(ctx, ISA_MIPS32);
14911 check_mips_64(ctx);
14912 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
14913 break;
14914 case RR_RY_CNVT_SEW:
14915 check_insn(ctx, ISA_MIPS32);
14916 check_mips_64(ctx);
14917 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
14918 break;
14919 #endif
14920 default:
14921 generate_exception_end(ctx, EXCP_RI);
14922 break;
14924 break;
14925 case RR_MFLO:
14926 gen_HILO(ctx, OPC_MFLO, 0, rx);
14927 break;
14928 #if defined(TARGET_MIPS64)
14929 case RR_DSRA:
14930 check_insn(ctx, ISA_MIPS3);
14931 check_mips_64(ctx);
14932 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
14933 break;
14934 case RR_DSLLV:
14935 check_insn(ctx, ISA_MIPS3);
14936 check_mips_64(ctx);
14937 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
14938 break;
14939 case RR_DSRLV:
14940 check_insn(ctx, ISA_MIPS3);
14941 check_mips_64(ctx);
14942 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
14943 break;
14944 case RR_DSRAV:
14945 check_insn(ctx, ISA_MIPS3);
14946 check_mips_64(ctx);
14947 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
14948 break;
14949 #endif
14950 case RR_MULT:
14951 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
14952 break;
14953 case RR_MULTU:
14954 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
14955 break;
14956 case RR_DIV:
14957 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
14958 break;
14959 case RR_DIVU:
14960 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
14961 break;
14962 #if defined(TARGET_MIPS64)
14963 case RR_DMULT:
14964 check_insn(ctx, ISA_MIPS3);
14965 check_mips_64(ctx);
14966 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
14967 break;
14968 case RR_DMULTU:
14969 check_insn(ctx, ISA_MIPS3);
14970 check_mips_64(ctx);
14971 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
14972 break;
14973 case RR_DDIV:
14974 check_insn(ctx, ISA_MIPS3);
14975 check_mips_64(ctx);
14976 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
14977 break;
14978 case RR_DDIVU:
14979 check_insn(ctx, ISA_MIPS3);
14980 check_mips_64(ctx);
14981 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
14982 break;
14983 #endif
14984 default:
14985 generate_exception_end(ctx, EXCP_RI);
14986 break;
14988 break;
14989 case M16_OPC_EXTEND:
14990 decode_extended_mips16_opc(env, ctx);
14991 n_bytes = 4;
14992 break;
14993 #if defined(TARGET_MIPS64)
14994 case M16_OPC_I64:
14995 funct = (ctx->opcode >> 8) & 0x7;
14996 decode_i64_mips16(ctx, ry, funct, offset, 0);
14997 break;
14998 #endif
14999 default:
15000 generate_exception_end(ctx, EXCP_RI);
15001 break;
15004 return n_bytes;
15007 /* microMIPS extension to MIPS32/MIPS64 */
15010 * microMIPS32/microMIPS64 major opcodes
15012 * 1. MIPS Architecture for Programmers Volume II-B:
15013 * The microMIPS32 Instruction Set (Revision 3.05)
15015 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
15017 * 2. MIPS Architecture For Programmers Volume II-A:
15018 * The MIPS64 Instruction Set (Revision 3.51)
15021 enum {
15022 POOL32A = 0x00,
15023 POOL16A = 0x01,
15024 LBU16 = 0x02,
15025 MOVE16 = 0x03,
15026 ADDI32 = 0x04,
15027 R6_LUI = 0x04,
15028 AUI = 0x04,
15029 LBU32 = 0x05,
15030 SB32 = 0x06,
15031 LB32 = 0x07,
15033 POOL32B = 0x08,
15034 POOL16B = 0x09,
15035 LHU16 = 0x0a,
15036 ANDI16 = 0x0b,
15037 ADDIU32 = 0x0c,
15038 LHU32 = 0x0d,
15039 SH32 = 0x0e,
15040 LH32 = 0x0f,
15042 POOL32I = 0x10,
15043 POOL16C = 0x11,
15044 LWSP16 = 0x12,
15045 POOL16D = 0x13,
15046 ORI32 = 0x14,
15047 POOL32F = 0x15,
15048 POOL32S = 0x16, /* MIPS64 */
15049 DADDIU32 = 0x17, /* MIPS64 */
15051 POOL32C = 0x18,
15052 LWGP16 = 0x19,
15053 LW16 = 0x1a,
15054 POOL16E = 0x1b,
15055 XORI32 = 0x1c,
15056 JALS32 = 0x1d,
15057 BOVC = 0x1d,
15058 BEQC = 0x1d,
15059 BEQZALC = 0x1d,
15060 ADDIUPC = 0x1e,
15061 PCREL = 0x1e,
15062 BNVC = 0x1f,
15063 BNEC = 0x1f,
15064 BNEZALC = 0x1f,
15066 R6_BEQZC = 0x20,
15067 JIC = 0x20,
15068 POOL16F = 0x21,
15069 SB16 = 0x22,
15070 BEQZ16 = 0x23,
15071 BEQZC16 = 0x23,
15072 SLTI32 = 0x24,
15073 BEQ32 = 0x25,
15074 BC = 0x25,
15075 SWC132 = 0x26,
15076 LWC132 = 0x27,
15078 /* 0x29 is reserved */
15079 RES_29 = 0x29,
15080 R6_BNEZC = 0x28,
15081 JIALC = 0x28,
15082 SH16 = 0x2a,
15083 BNEZ16 = 0x2b,
15084 BNEZC16 = 0x2b,
15085 SLTIU32 = 0x2c,
15086 BNE32 = 0x2d,
15087 BALC = 0x2d,
15088 SDC132 = 0x2e,
15089 LDC132 = 0x2f,
15091 /* 0x31 is reserved */
15092 RES_31 = 0x31,
15093 BLEZALC = 0x30,
15094 BGEZALC = 0x30,
15095 BGEUC = 0x30,
15096 SWSP16 = 0x32,
15097 B16 = 0x33,
15098 BC16 = 0x33,
15099 ANDI32 = 0x34,
15100 J32 = 0x35,
15101 BGTZC = 0x35,
15102 BLTZC = 0x35,
15103 BLTC = 0x35,
15104 SD32 = 0x36, /* MIPS64 */
15105 LD32 = 0x37, /* MIPS64 */
15107 /* 0x39 is reserved */
15108 RES_39 = 0x39,
15109 BGTZALC = 0x38,
15110 BLTZALC = 0x38,
15111 BLTUC = 0x38,
15112 SW16 = 0x3a,
15113 LI16 = 0x3b,
15114 JALX32 = 0x3c,
15115 JAL32 = 0x3d,
15116 BLEZC = 0x3d,
15117 BGEZC = 0x3d,
15118 BGEC = 0x3d,
15119 SW32 = 0x3e,
15120 LW32 = 0x3f
15123 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
15124 enum {
15125 ADDIUPC_00 = 0x00,
15126 ADDIUPC_01 = 0x01,
15127 ADDIUPC_02 = 0x02,
15128 ADDIUPC_03 = 0x03,
15129 ADDIUPC_04 = 0x04,
15130 ADDIUPC_05 = 0x05,
15131 ADDIUPC_06 = 0x06,
15132 ADDIUPC_07 = 0x07,
15133 AUIPC = 0x1e,
15134 ALUIPC = 0x1f,
15135 LWPC_08 = 0x08,
15136 LWPC_09 = 0x09,
15137 LWPC_0A = 0x0A,
15138 LWPC_0B = 0x0B,
15139 LWPC_0C = 0x0C,
15140 LWPC_0D = 0x0D,
15141 LWPC_0E = 0x0E,
15142 LWPC_0F = 0x0F,
15145 /* POOL32A encoding of minor opcode field */
15147 enum {
15149 * These opcodes are distinguished only by bits 9..6; those bits are
15150 * what are recorded below.
15152 SLL32 = 0x0,
15153 SRL32 = 0x1,
15154 SRA = 0x2,
15155 ROTR = 0x3,
15156 SELEQZ = 0x5,
15157 SELNEZ = 0x6,
15158 R6_RDHWR = 0x7,
15160 SLLV = 0x0,
15161 SRLV = 0x1,
15162 SRAV = 0x2,
15163 ROTRV = 0x3,
15164 ADD = 0x4,
15165 ADDU32 = 0x5,
15166 SUB = 0x6,
15167 SUBU32 = 0x7,
15168 MUL = 0x8,
15169 AND = 0x9,
15170 OR32 = 0xa,
15171 NOR = 0xb,
15172 XOR32 = 0xc,
15173 SLT = 0xd,
15174 SLTU = 0xe,
15176 MOVN = 0x0,
15177 R6_MUL = 0x0,
15178 MOVZ = 0x1,
15179 MUH = 0x1,
15180 MULU = 0x2,
15181 MUHU = 0x3,
15182 LWXS = 0x4,
15183 R6_DIV = 0x4,
15184 MOD = 0x5,
15185 R6_DIVU = 0x6,
15186 MODU = 0x7,
15188 /* The following can be distinguished by their lower 6 bits. */
15189 BREAK32 = 0x07,
15190 INS = 0x0c,
15191 LSA = 0x0f,
15192 ALIGN = 0x1f,
15193 EXT = 0x2c,
15194 POOL32AXF = 0x3c,
15195 SIGRIE = 0x3f
15198 /* POOL32AXF encoding of minor opcode field extension */
15201 * 1. MIPS Architecture for Programmers Volume II-B:
15202 * The microMIPS32 Instruction Set (Revision 3.05)
15204 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
15206 * 2. MIPS Architecture for Programmers VolumeIV-e:
15207 * The MIPS DSP Application-Specific Extension
15208 * to the microMIPS32 Architecture (Revision 2.34)
15210 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
15213 enum {
15214 /* bits 11..6 */
15215 TEQ = 0x00,
15216 TGE = 0x08,
15217 TGEU = 0x10,
15218 TLT = 0x20,
15219 TLTU = 0x28,
15220 TNE = 0x30,
15222 MFC0 = 0x03,
15223 MTC0 = 0x0b,
15225 /* begin of microMIPS32 DSP */
15227 /* bits 13..12 for 0x01 */
15228 MFHI_ACC = 0x0,
15229 MFLO_ACC = 0x1,
15230 MTHI_ACC = 0x2,
15231 MTLO_ACC = 0x3,
15233 /* bits 13..12 for 0x2a */
15234 MADD_ACC = 0x0,
15235 MADDU_ACC = 0x1,
15236 MSUB_ACC = 0x2,
15237 MSUBU_ACC = 0x3,
15239 /* bits 13..12 for 0x32 */
15240 MULT_ACC = 0x0,
15241 MULTU_ACC = 0x1,
15243 /* end of microMIPS32 DSP */
15245 /* bits 15..12 for 0x2c */
15246 BITSWAP = 0x0,
15247 SEB = 0x2,
15248 SEH = 0x3,
15249 CLO = 0x4,
15250 CLZ = 0x5,
15251 RDHWR = 0x6,
15252 WSBH = 0x7,
15253 MULT = 0x8,
15254 MULTU = 0x9,
15255 DIV = 0xa,
15256 DIVU = 0xb,
15257 MADD = 0xc,
15258 MADDU = 0xd,
15259 MSUB = 0xe,
15260 MSUBU = 0xf,
15262 /* bits 15..12 for 0x34 */
15263 MFC2 = 0x4,
15264 MTC2 = 0x5,
15265 MFHC2 = 0x8,
15266 MTHC2 = 0x9,
15267 CFC2 = 0xc,
15268 CTC2 = 0xd,
15270 /* bits 15..12 for 0x3c */
15271 JALR = 0x0,
15272 JR = 0x0, /* alias */
15273 JALRC = 0x0,
15274 JRC = 0x0,
15275 JALR_HB = 0x1,
15276 JALRC_HB = 0x1,
15277 JALRS = 0x4,
15278 JALRS_HB = 0x5,
15280 /* bits 15..12 for 0x05 */
15281 RDPGPR = 0xe,
15282 WRPGPR = 0xf,
15284 /* bits 15..12 for 0x0d */
15285 TLBP = 0x0,
15286 TLBR = 0x1,
15287 TLBWI = 0x2,
15288 TLBWR = 0x3,
15289 TLBINV = 0x4,
15290 TLBINVF = 0x5,
15291 WAIT = 0x9,
15292 IRET = 0xd,
15293 DERET = 0xe,
15294 ERET = 0xf,
15296 /* bits 15..12 for 0x15 */
15297 DMT = 0x0,
15298 DVPE = 0x1,
15299 EMT = 0x2,
15300 EVPE = 0x3,
15302 /* bits 15..12 for 0x1d */
15303 DI = 0x4,
15304 EI = 0x5,
15306 /* bits 15..12 for 0x2d */
15307 SYNC = 0x6,
15308 SYSCALL = 0x8,
15309 SDBBP = 0xd,
15311 /* bits 15..12 for 0x35 */
15312 MFHI32 = 0x0,
15313 MFLO32 = 0x1,
15314 MTHI32 = 0x2,
15315 MTLO32 = 0x3,
15318 /* POOL32B encoding of minor opcode field (bits 15..12) */
15320 enum {
15321 LWC2 = 0x0,
15322 LWP = 0x1,
15323 LDP = 0x4,
15324 LWM32 = 0x5,
15325 CACHE = 0x6,
15326 LDM = 0x7,
15327 SWC2 = 0x8,
15328 SWP = 0x9,
15329 SDP = 0xc,
15330 SWM32 = 0xd,
15331 SDM = 0xf
15334 /* POOL32C encoding of minor opcode field (bits 15..12) */
15336 enum {
15337 LWL = 0x0,
15338 SWL = 0x8,
15339 LWR = 0x1,
15340 SWR = 0x9,
15341 PREF = 0x2,
15342 ST_EVA = 0xa,
15343 LL = 0x3,
15344 SC = 0xb,
15345 LDL = 0x4,
15346 SDL = 0xc,
15347 LDR = 0x5,
15348 SDR = 0xd,
15349 LD_EVA = 0x6,
15350 LWU = 0xe,
15351 LLD = 0x7,
15352 SCD = 0xf
15355 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
15357 enum {
15358 LBUE = 0x0,
15359 LHUE = 0x1,
15360 LWLE = 0x2,
15361 LWRE = 0x3,
15362 LBE = 0x4,
15363 LHE = 0x5,
15364 LLE = 0x6,
15365 LWE = 0x7,
15368 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
15370 enum {
15371 SWLE = 0x0,
15372 SWRE = 0x1,
15373 PREFE = 0x2,
15374 CACHEE = 0x3,
15375 SBE = 0x4,
15376 SHE = 0x5,
15377 SCE = 0x6,
15378 SWE = 0x7,
15381 /* POOL32F encoding of minor opcode field (bits 5..0) */
15383 enum {
15384 /* These are the bit 7..6 values */
15385 ADD_FMT = 0x0,
15387 SUB_FMT = 0x1,
15389 MUL_FMT = 0x2,
15391 DIV_FMT = 0x3,
15393 /* These are the bit 8..6 values */
15394 MOVN_FMT = 0x0,
15395 RSQRT2_FMT = 0x0,
15396 MOVF_FMT = 0x0,
15397 RINT_FMT = 0x0,
15398 SELNEZ_FMT = 0x0,
15400 MOVZ_FMT = 0x1,
15401 LWXC1 = 0x1,
15402 MOVT_FMT = 0x1,
15403 CLASS_FMT = 0x1,
15404 SELEQZ_FMT = 0x1,
15406 PLL_PS = 0x2,
15407 SWXC1 = 0x2,
15408 SEL_FMT = 0x2,
15410 PLU_PS = 0x3,
15411 LDXC1 = 0x3,
15413 MOVN_FMT_04 = 0x4,
15414 PUL_PS = 0x4,
15415 SDXC1 = 0x4,
15416 RECIP2_FMT = 0x4,
15418 MOVZ_FMT_05 = 0x05,
15419 PUU_PS = 0x5,
15420 LUXC1 = 0x5,
15422 CVT_PS_S = 0x6,
15423 SUXC1 = 0x6,
15424 ADDR_PS = 0x6,
15425 PREFX = 0x6,
15426 MADDF_FMT = 0x6,
15428 MULR_PS = 0x7,
15429 MSUBF_FMT = 0x7,
15431 MADD_S = 0x01,
15432 MADD_D = 0x09,
15433 MADD_PS = 0x11,
15434 ALNV_PS = 0x19,
15435 MSUB_S = 0x21,
15436 MSUB_D = 0x29,
15437 MSUB_PS = 0x31,
15439 NMADD_S = 0x02,
15440 NMADD_D = 0x0a,
15441 NMADD_PS = 0x12,
15442 NMSUB_S = 0x22,
15443 NMSUB_D = 0x2a,
15444 NMSUB_PS = 0x32,
15446 MIN_FMT = 0x3,
15447 MAX_FMT = 0xb,
15448 MINA_FMT = 0x23,
15449 MAXA_FMT = 0x2b,
15450 POOL32FXF = 0x3b,
15452 CABS_COND_FMT = 0x1c, /* MIPS3D */
15453 C_COND_FMT = 0x3c,
15455 CMP_CONDN_S = 0x5,
15456 CMP_CONDN_D = 0x15
15459 /* POOL32Fxf encoding of minor opcode extension field */
15461 enum {
15462 CVT_L = 0x04,
15463 RSQRT_FMT = 0x08,
15464 FLOOR_L = 0x0c,
15465 CVT_PW_PS = 0x1c,
15466 CVT_W = 0x24,
15467 SQRT_FMT = 0x28,
15468 FLOOR_W = 0x2c,
15469 CVT_PS_PW = 0x3c,
15470 CFC1 = 0x40,
15471 RECIP_FMT = 0x48,
15472 CEIL_L = 0x4c,
15473 CTC1 = 0x60,
15474 CEIL_W = 0x6c,
15475 MFC1 = 0x80,
15476 CVT_S_PL = 0x84,
15477 TRUNC_L = 0x8c,
15478 MTC1 = 0xa0,
15479 CVT_S_PU = 0xa4,
15480 TRUNC_W = 0xac,
15481 MFHC1 = 0xc0,
15482 ROUND_L = 0xcc,
15483 MTHC1 = 0xe0,
15484 ROUND_W = 0xec,
15486 MOV_FMT = 0x01,
15487 MOVF = 0x05,
15488 ABS_FMT = 0x0d,
15489 RSQRT1_FMT = 0x1d,
15490 MOVT = 0x25,
15491 NEG_FMT = 0x2d,
15492 CVT_D = 0x4d,
15493 RECIP1_FMT = 0x5d,
15494 CVT_S = 0x6d
15497 /* POOL32I encoding of minor opcode field (bits 25..21) */
15499 enum {
15500 BLTZ = 0x00,
15501 BLTZAL = 0x01,
15502 BGEZ = 0x02,
15503 BGEZAL = 0x03,
15504 BLEZ = 0x04,
15505 BNEZC = 0x05,
15506 BGTZ = 0x06,
15507 BEQZC = 0x07,
15508 TLTI = 0x08,
15509 BC1EQZC = 0x08,
15510 TGEI = 0x09,
15511 BC1NEZC = 0x09,
15512 TLTIU = 0x0a,
15513 BC2EQZC = 0x0a,
15514 TGEIU = 0x0b,
15515 BC2NEZC = 0x0a,
15516 TNEI = 0x0c,
15517 R6_SYNCI = 0x0c,
15518 LUI = 0x0d,
15519 TEQI = 0x0e,
15520 SYNCI = 0x10,
15521 BLTZALS = 0x11,
15522 BGEZALS = 0x13,
15523 BC2F = 0x14,
15524 BC2T = 0x15,
15525 BPOSGE64 = 0x1a,
15526 BPOSGE32 = 0x1b,
15527 /* These overlap and are distinguished by bit16 of the instruction */
15528 BC1F = 0x1c,
15529 BC1T = 0x1d,
15530 BC1ANY2F = 0x1c,
15531 BC1ANY2T = 0x1d,
15532 BC1ANY4F = 0x1e,
15533 BC1ANY4T = 0x1f
15536 /* POOL16A encoding of minor opcode field */
15538 enum {
15539 ADDU16 = 0x0,
15540 SUBU16 = 0x1
15543 /* POOL16B encoding of minor opcode field */
15545 enum {
15546 SLL16 = 0x0,
15547 SRL16 = 0x1
15550 /* POOL16C encoding of minor opcode field */
15552 enum {
15553 NOT16 = 0x00,
15554 XOR16 = 0x04,
15555 AND16 = 0x08,
15556 OR16 = 0x0c,
15557 LWM16 = 0x10,
15558 SWM16 = 0x14,
15559 JR16 = 0x18,
15560 JRC16 = 0x1a,
15561 JALR16 = 0x1c,
15562 JALR16S = 0x1e,
15563 MFHI16 = 0x20,
15564 MFLO16 = 0x24,
15565 BREAK16 = 0x28,
15566 SDBBP16 = 0x2c,
15567 JRADDIUSP = 0x30
15570 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
15572 enum {
15573 R6_NOT16 = 0x00,
15574 R6_AND16 = 0x01,
15575 R6_LWM16 = 0x02,
15576 R6_JRC16 = 0x03,
15577 MOVEP = 0x04,
15578 MOVEP_05 = 0x05,
15579 MOVEP_06 = 0x06,
15580 MOVEP_07 = 0x07,
15581 R6_XOR16 = 0x08,
15582 R6_OR16 = 0x09,
15583 R6_SWM16 = 0x0a,
15584 JALRC16 = 0x0b,
15585 MOVEP_0C = 0x0c,
15586 MOVEP_0D = 0x0d,
15587 MOVEP_0E = 0x0e,
15588 MOVEP_0F = 0x0f,
15589 JRCADDIUSP = 0x13,
15590 R6_BREAK16 = 0x1b,
15591 R6_SDBBP16 = 0x3b
15594 /* POOL16D encoding of minor opcode field */
15596 enum {
15597 ADDIUS5 = 0x0,
15598 ADDIUSP = 0x1
15601 /* POOL16E encoding of minor opcode field */
15603 enum {
15604 ADDIUR2 = 0x0,
15605 ADDIUR1SP = 0x1
15608 static int mmreg(int r)
15610 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
15612 return map[r];
15615 /* Used for 16-bit store instructions. */
15616 static int mmreg2(int r)
15618 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
15620 return map[r];
15623 #define uMIPS_RD(op) ((op >> 7) & 0x7)
15624 #define uMIPS_RS(op) ((op >> 4) & 0x7)
15625 #define uMIPS_RS2(op) uMIPS_RS(op)
15626 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
15627 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
15628 #define uMIPS_RS5(op) (op & 0x1f)
15630 /* Signed immediate */
15631 #define SIMM(op, start, width) \
15632 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
15633 << (32 - width)) \
15634 >> (32 - width))
15635 /* Zero-extended immediate */
15636 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
15638 static void gen_addiur1sp(DisasContext *ctx)
15640 int rd = mmreg(uMIPS_RD(ctx->opcode));
15642 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
15645 static void gen_addiur2(DisasContext *ctx)
15647 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
15648 int rd = mmreg(uMIPS_RD(ctx->opcode));
15649 int rs = mmreg(uMIPS_RS(ctx->opcode));
15651 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
15654 static void gen_addiusp(DisasContext *ctx)
15656 int encoded = ZIMM(ctx->opcode, 1, 9);
15657 int decoded;
15659 if (encoded <= 1) {
15660 decoded = 256 + encoded;
15661 } else if (encoded <= 255) {
15662 decoded = encoded;
15663 } else if (encoded <= 509) {
15664 decoded = encoded - 512;
15665 } else {
15666 decoded = encoded - 768;
15669 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
15672 static void gen_addius5(DisasContext *ctx)
15674 int imm = SIMM(ctx->opcode, 1, 4);
15675 int rd = (ctx->opcode >> 5) & 0x1f;
15677 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
15680 static void gen_andi16(DisasContext *ctx)
15682 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
15683 31, 32, 63, 64, 255, 32768, 65535 };
15684 int rd = mmreg(uMIPS_RD(ctx->opcode));
15685 int rs = mmreg(uMIPS_RS(ctx->opcode));
15686 int encoded = ZIMM(ctx->opcode, 0, 4);
15688 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
15691 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
15692 int base, int16_t offset)
15694 TCGv t0, t1;
15695 TCGv_i32 t2;
15697 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15698 generate_exception_end(ctx, EXCP_RI);
15699 return;
15702 t0 = tcg_temp_new();
15704 gen_base_offset_addr(ctx, t0, base, offset);
15706 t1 = tcg_const_tl(reglist);
15707 t2 = tcg_const_i32(ctx->mem_idx);
15709 save_cpu_state(ctx, 1);
15710 switch (opc) {
15711 case LWM32:
15712 gen_helper_lwm(cpu_env, t0, t1, t2);
15713 break;
15714 case SWM32:
15715 gen_helper_swm(cpu_env, t0, t1, t2);
15716 break;
15717 #ifdef TARGET_MIPS64
15718 case LDM:
15719 gen_helper_ldm(cpu_env, t0, t1, t2);
15720 break;
15721 case SDM:
15722 gen_helper_sdm(cpu_env, t0, t1, t2);
15723 break;
15724 #endif
15726 tcg_temp_free(t0);
15727 tcg_temp_free(t1);
15728 tcg_temp_free_i32(t2);
15732 static void gen_pool16c_insn(DisasContext *ctx)
15734 int rd = mmreg((ctx->opcode >> 3) & 0x7);
15735 int rs = mmreg(ctx->opcode & 0x7);
15737 switch (((ctx->opcode) >> 4) & 0x3f) {
15738 case NOT16 + 0:
15739 case NOT16 + 1:
15740 case NOT16 + 2:
15741 case NOT16 + 3:
15742 gen_logic(ctx, OPC_NOR, rd, rs, 0);
15743 break;
15744 case XOR16 + 0:
15745 case XOR16 + 1:
15746 case XOR16 + 2:
15747 case XOR16 + 3:
15748 gen_logic(ctx, OPC_XOR, rd, rd, rs);
15749 break;
15750 case AND16 + 0:
15751 case AND16 + 1:
15752 case AND16 + 2:
15753 case AND16 + 3:
15754 gen_logic(ctx, OPC_AND, rd, rd, rs);
15755 break;
15756 case OR16 + 0:
15757 case OR16 + 1:
15758 case OR16 + 2:
15759 case OR16 + 3:
15760 gen_logic(ctx, OPC_OR, rd, rd, rs);
15761 break;
15762 case LWM16 + 0:
15763 case LWM16 + 1:
15764 case LWM16 + 2:
15765 case LWM16 + 3:
15767 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15768 int offset = ZIMM(ctx->opcode, 0, 4);
15770 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
15771 29, offset << 2);
15773 break;
15774 case SWM16 + 0:
15775 case SWM16 + 1:
15776 case SWM16 + 2:
15777 case SWM16 + 3:
15779 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
15780 int offset = ZIMM(ctx->opcode, 0, 4);
15782 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
15783 29, offset << 2);
15785 break;
15786 case JR16 + 0:
15787 case JR16 + 1:
15789 int reg = ctx->opcode & 0x1f;
15791 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
15793 break;
15794 case JRC16 + 0:
15795 case JRC16 + 1:
15797 int reg = ctx->opcode & 0x1f;
15798 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
15800 * Let normal delay slot handling in our caller take us
15801 * to the branch target.
15804 break;
15805 case JALR16 + 0:
15806 case JALR16 + 1:
15807 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
15808 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15809 break;
15810 case JALR16S + 0:
15811 case JALR16S + 1:
15812 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
15813 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15814 break;
15815 case MFHI16 + 0:
15816 case MFHI16 + 1:
15817 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
15818 break;
15819 case MFLO16 + 0:
15820 case MFLO16 + 1:
15821 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
15822 break;
15823 case BREAK16:
15824 generate_exception_end(ctx, EXCP_BREAK);
15825 break;
15826 case SDBBP16:
15827 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
15828 gen_helper_do_semihosting(cpu_env);
15829 } else {
15831 * XXX: not clear which exception should be raised
15832 * when in debug mode...
15834 check_insn(ctx, ISA_MIPS32);
15835 generate_exception_end(ctx, EXCP_DBp);
15837 break;
15838 case JRADDIUSP + 0:
15839 case JRADDIUSP + 1:
15841 int imm = ZIMM(ctx->opcode, 0, 5);
15842 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15843 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15845 * Let normal delay slot handling in our caller take us
15846 * to the branch target.
15849 break;
15850 default:
15851 generate_exception_end(ctx, EXCP_RI);
15852 break;
15856 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
15857 int enc_rs)
15859 int rd, rs, re, rt;
15860 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
15861 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
15862 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
15863 rd = rd_enc[enc_dest];
15864 re = re_enc[enc_dest];
15865 rs = rs_rt_enc[enc_rs];
15866 rt = rs_rt_enc[enc_rt];
15867 if (rs) {
15868 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
15869 } else {
15870 tcg_gen_movi_tl(cpu_gpr[rd], 0);
15872 if (rt) {
15873 tcg_gen_mov_tl(cpu_gpr[re], cpu_gpr[rt]);
15874 } else {
15875 tcg_gen_movi_tl(cpu_gpr[re], 0);
15879 static void gen_pool16c_r6_insn(DisasContext *ctx)
15881 int rt = mmreg((ctx->opcode >> 7) & 0x7);
15882 int rs = mmreg((ctx->opcode >> 4) & 0x7);
15884 switch (ctx->opcode & 0xf) {
15885 case R6_NOT16:
15886 gen_logic(ctx, OPC_NOR, rt, rs, 0);
15887 break;
15888 case R6_AND16:
15889 gen_logic(ctx, OPC_AND, rt, rt, rs);
15890 break;
15891 case R6_LWM16:
15893 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15894 int offset = extract32(ctx->opcode, 4, 4);
15895 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
15897 break;
15898 case R6_JRC16: /* JRCADDIUSP */
15899 if ((ctx->opcode >> 4) & 1) {
15900 /* JRCADDIUSP */
15901 int imm = extract32(ctx->opcode, 5, 5);
15902 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
15903 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
15904 } else {
15905 /* JRC16 */
15906 rs = extract32(ctx->opcode, 5, 5);
15907 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
15909 break;
15910 case MOVEP:
15911 case MOVEP_05:
15912 case MOVEP_06:
15913 case MOVEP_07:
15914 case MOVEP_0C:
15915 case MOVEP_0D:
15916 case MOVEP_0E:
15917 case MOVEP_0F:
15919 int enc_dest = uMIPS_RD(ctx->opcode);
15920 int enc_rt = uMIPS_RS2(ctx->opcode);
15921 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
15922 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
15924 break;
15925 case R6_XOR16:
15926 gen_logic(ctx, OPC_XOR, rt, rt, rs);
15927 break;
15928 case R6_OR16:
15929 gen_logic(ctx, OPC_OR, rt, rt, rs);
15930 break;
15931 case R6_SWM16:
15933 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
15934 int offset = extract32(ctx->opcode, 4, 4);
15935 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
15937 break;
15938 case JALRC16: /* BREAK16, SDBBP16 */
15939 switch (ctx->opcode & 0x3f) {
15940 case JALRC16:
15941 case JALRC16 + 0x20:
15942 /* JALRC16 */
15943 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
15944 31, 0, 0);
15945 break;
15946 case R6_BREAK16:
15947 /* BREAK16 */
15948 generate_exception(ctx, EXCP_BREAK);
15949 break;
15950 case R6_SDBBP16:
15951 /* SDBBP16 */
15952 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
15953 gen_helper_do_semihosting(cpu_env);
15954 } else {
15955 if (ctx->hflags & MIPS_HFLAG_SBRI) {
15956 generate_exception(ctx, EXCP_RI);
15957 } else {
15958 generate_exception(ctx, EXCP_DBp);
15961 break;
15963 break;
15964 default:
15965 generate_exception(ctx, EXCP_RI);
15966 break;
15970 static void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
15972 TCGv t0 = tcg_temp_new();
15973 TCGv t1 = tcg_temp_new();
15975 gen_load_gpr(t0, base);
15977 if (index != 0) {
15978 gen_load_gpr(t1, index);
15979 tcg_gen_shli_tl(t1, t1, 2);
15980 gen_op_addr_add(ctx, t0, t1, t0);
15983 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
15984 gen_store_gpr(t1, rd);
15986 tcg_temp_free(t0);
15987 tcg_temp_free(t1);
15990 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
15991 int base, int16_t offset)
15993 TCGv t0, t1;
15995 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
15996 generate_exception_end(ctx, EXCP_RI);
15997 return;
16000 t0 = tcg_temp_new();
16001 t1 = tcg_temp_new();
16003 gen_base_offset_addr(ctx, t0, base, offset);
16005 switch (opc) {
16006 case LWP:
16007 if (rd == base) {
16008 generate_exception_end(ctx, EXCP_RI);
16009 return;
16011 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
16012 gen_store_gpr(t1, rd);
16013 tcg_gen_movi_tl(t1, 4);
16014 gen_op_addr_add(ctx, t0, t0, t1);
16015 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
16016 gen_store_gpr(t1, rd + 1);
16017 break;
16018 case SWP:
16019 gen_load_gpr(t1, rd);
16020 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
16021 tcg_gen_movi_tl(t1, 4);
16022 gen_op_addr_add(ctx, t0, t0, t1);
16023 gen_load_gpr(t1, rd + 1);
16024 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
16025 break;
16026 #ifdef TARGET_MIPS64
16027 case LDP:
16028 if (rd == base) {
16029 generate_exception_end(ctx, EXCP_RI);
16030 return;
16032 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16033 gen_store_gpr(t1, rd);
16034 tcg_gen_movi_tl(t1, 8);
16035 gen_op_addr_add(ctx, t0, t0, t1);
16036 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16037 gen_store_gpr(t1, rd + 1);
16038 break;
16039 case SDP:
16040 gen_load_gpr(t1, rd);
16041 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16042 tcg_gen_movi_tl(t1, 8);
16043 gen_op_addr_add(ctx, t0, t0, t1);
16044 gen_load_gpr(t1, rd + 1);
16045 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
16046 break;
16047 #endif
16049 tcg_temp_free(t0);
16050 tcg_temp_free(t1);
16053 static void gen_sync(int stype)
16055 TCGBar tcg_mo = TCG_BAR_SC;
16057 switch (stype) {
16058 case 0x4: /* SYNC_WMB */
16059 tcg_mo |= TCG_MO_ST_ST;
16060 break;
16061 case 0x10: /* SYNC_MB */
16062 tcg_mo |= TCG_MO_ALL;
16063 break;
16064 case 0x11: /* SYNC_ACQUIRE */
16065 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
16066 break;
16067 case 0x12: /* SYNC_RELEASE */
16068 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
16069 break;
16070 case 0x13: /* SYNC_RMB */
16071 tcg_mo |= TCG_MO_LD_LD;
16072 break;
16073 default:
16074 tcg_mo |= TCG_MO_ALL;
16075 break;
16078 tcg_gen_mb(tcg_mo);
16081 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
16083 int extension = (ctx->opcode >> 6) & 0x3f;
16084 int minor = (ctx->opcode >> 12) & 0xf;
16085 uint32_t mips32_op;
16087 switch (extension) {
16088 case TEQ:
16089 mips32_op = OPC_TEQ;
16090 goto do_trap;
16091 case TGE:
16092 mips32_op = OPC_TGE;
16093 goto do_trap;
16094 case TGEU:
16095 mips32_op = OPC_TGEU;
16096 goto do_trap;
16097 case TLT:
16098 mips32_op = OPC_TLT;
16099 goto do_trap;
16100 case TLTU:
16101 mips32_op = OPC_TLTU;
16102 goto do_trap;
16103 case TNE:
16104 mips32_op = OPC_TNE;
16105 do_trap:
16106 gen_trap(ctx, mips32_op, rs, rt, -1);
16107 break;
16108 #ifndef CONFIG_USER_ONLY
16109 case MFC0:
16110 case MFC0 + 32:
16111 check_cp0_enabled(ctx);
16112 if (rt == 0) {
16113 /* Treat as NOP. */
16114 break;
16116 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
16117 break;
16118 case MTC0:
16119 case MTC0 + 32:
16120 check_cp0_enabled(ctx);
16122 TCGv t0 = tcg_temp_new();
16124 gen_load_gpr(t0, rt);
16125 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
16126 tcg_temp_free(t0);
16128 break;
16129 #endif
16130 case 0x2a:
16131 switch (minor & 3) {
16132 case MADD_ACC:
16133 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
16134 break;
16135 case MADDU_ACC:
16136 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
16137 break;
16138 case MSUB_ACC:
16139 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
16140 break;
16141 case MSUBU_ACC:
16142 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
16143 break;
16144 default:
16145 goto pool32axf_invalid;
16147 break;
16148 case 0x32:
16149 switch (minor & 3) {
16150 case MULT_ACC:
16151 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
16152 break;
16153 case MULTU_ACC:
16154 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
16155 break;
16156 default:
16157 goto pool32axf_invalid;
16159 break;
16160 case 0x2c:
16161 switch (minor) {
16162 case BITSWAP:
16163 check_insn(ctx, ISA_MIPS32R6);
16164 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
16165 break;
16166 case SEB:
16167 gen_bshfl(ctx, OPC_SEB, rs, rt);
16168 break;
16169 case SEH:
16170 gen_bshfl(ctx, OPC_SEH, rs, rt);
16171 break;
16172 case CLO:
16173 mips32_op = OPC_CLO;
16174 goto do_cl;
16175 case CLZ:
16176 mips32_op = OPC_CLZ;
16177 do_cl:
16178 check_insn(ctx, ISA_MIPS32);
16179 gen_cl(ctx, mips32_op, rt, rs);
16180 break;
16181 case RDHWR:
16182 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16183 gen_rdhwr(ctx, rt, rs, 0);
16184 break;
16185 case WSBH:
16186 gen_bshfl(ctx, OPC_WSBH, rs, rt);
16187 break;
16188 case MULT:
16189 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16190 mips32_op = OPC_MULT;
16191 goto do_mul;
16192 case MULTU:
16193 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16194 mips32_op = OPC_MULTU;
16195 goto do_mul;
16196 case DIV:
16197 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16198 mips32_op = OPC_DIV;
16199 goto do_div;
16200 case DIVU:
16201 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16202 mips32_op = OPC_DIVU;
16203 goto do_div;
16204 do_div:
16205 check_insn(ctx, ISA_MIPS32);
16206 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16207 break;
16208 case MADD:
16209 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16210 mips32_op = OPC_MADD;
16211 goto do_mul;
16212 case MADDU:
16213 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16214 mips32_op = OPC_MADDU;
16215 goto do_mul;
16216 case MSUB:
16217 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16218 mips32_op = OPC_MSUB;
16219 goto do_mul;
16220 case MSUBU:
16221 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16222 mips32_op = OPC_MSUBU;
16223 do_mul:
16224 check_insn(ctx, ISA_MIPS32);
16225 gen_muldiv(ctx, mips32_op, 0, rs, rt);
16226 break;
16227 default:
16228 goto pool32axf_invalid;
16230 break;
16231 case 0x34:
16232 switch (minor) {
16233 case MFC2:
16234 case MTC2:
16235 case MFHC2:
16236 case MTHC2:
16237 case CFC2:
16238 case CTC2:
16239 generate_exception_err(ctx, EXCP_CpU, 2);
16240 break;
16241 default:
16242 goto pool32axf_invalid;
16244 break;
16245 case 0x3c:
16246 switch (minor) {
16247 case JALR: /* JALRC */
16248 case JALR_HB: /* JALRC_HB */
16249 if (ctx->insn_flags & ISA_MIPS32R6) {
16250 /* JALRC, JALRC_HB */
16251 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
16252 } else {
16253 /* JALR, JALR_HB */
16254 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
16255 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16257 break;
16258 case JALRS:
16259 case JALRS_HB:
16260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16261 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
16262 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16263 break;
16264 default:
16265 goto pool32axf_invalid;
16267 break;
16268 case 0x05:
16269 switch (minor) {
16270 case RDPGPR:
16271 check_cp0_enabled(ctx);
16272 check_insn(ctx, ISA_MIPS32R2);
16273 gen_load_srsgpr(rs, rt);
16274 break;
16275 case WRPGPR:
16276 check_cp0_enabled(ctx);
16277 check_insn(ctx, ISA_MIPS32R2);
16278 gen_store_srsgpr(rs, rt);
16279 break;
16280 default:
16281 goto pool32axf_invalid;
16283 break;
16284 #ifndef CONFIG_USER_ONLY
16285 case 0x0d:
16286 switch (minor) {
16287 case TLBP:
16288 mips32_op = OPC_TLBP;
16289 goto do_cp0;
16290 case TLBR:
16291 mips32_op = OPC_TLBR;
16292 goto do_cp0;
16293 case TLBWI:
16294 mips32_op = OPC_TLBWI;
16295 goto do_cp0;
16296 case TLBWR:
16297 mips32_op = OPC_TLBWR;
16298 goto do_cp0;
16299 case TLBINV:
16300 mips32_op = OPC_TLBINV;
16301 goto do_cp0;
16302 case TLBINVF:
16303 mips32_op = OPC_TLBINVF;
16304 goto do_cp0;
16305 case WAIT:
16306 mips32_op = OPC_WAIT;
16307 goto do_cp0;
16308 case DERET:
16309 mips32_op = OPC_DERET;
16310 goto do_cp0;
16311 case ERET:
16312 mips32_op = OPC_ERET;
16313 do_cp0:
16314 gen_cp0(env, ctx, mips32_op, rt, rs);
16315 break;
16316 default:
16317 goto pool32axf_invalid;
16319 break;
16320 case 0x1d:
16321 switch (minor) {
16322 case DI:
16323 check_cp0_enabled(ctx);
16325 TCGv t0 = tcg_temp_new();
16327 save_cpu_state(ctx, 1);
16328 gen_helper_di(t0, cpu_env);
16329 gen_store_gpr(t0, rs);
16331 * Stop translation as we may have switched the execution
16332 * mode.
16334 ctx->base.is_jmp = DISAS_STOP;
16335 tcg_temp_free(t0);
16337 break;
16338 case EI:
16339 check_cp0_enabled(ctx);
16341 TCGv t0 = tcg_temp_new();
16343 save_cpu_state(ctx, 1);
16344 gen_helper_ei(t0, cpu_env);
16345 gen_store_gpr(t0, rs);
16347 * DISAS_STOP isn't sufficient, we need to ensure we break out
16348 * of translated code to check for pending interrupts.
16350 gen_save_pc(ctx->base.pc_next + 4);
16351 ctx->base.is_jmp = DISAS_EXIT;
16352 tcg_temp_free(t0);
16354 break;
16355 default:
16356 goto pool32axf_invalid;
16358 break;
16359 #endif
16360 case 0x2d:
16361 switch (minor) {
16362 case SYNC:
16363 gen_sync(extract32(ctx->opcode, 16, 5));
16364 break;
16365 case SYSCALL:
16366 generate_exception_end(ctx, EXCP_SYSCALL);
16367 break;
16368 case SDBBP:
16369 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
16370 gen_helper_do_semihosting(cpu_env);
16371 } else {
16372 check_insn(ctx, ISA_MIPS32);
16373 if (ctx->hflags & MIPS_HFLAG_SBRI) {
16374 generate_exception_end(ctx, EXCP_RI);
16375 } else {
16376 generate_exception_end(ctx, EXCP_DBp);
16379 break;
16380 default:
16381 goto pool32axf_invalid;
16383 break;
16384 case 0x01:
16385 switch (minor & 3) {
16386 case MFHI_ACC:
16387 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
16388 break;
16389 case MFLO_ACC:
16390 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
16391 break;
16392 case MTHI_ACC:
16393 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
16394 break;
16395 case MTLO_ACC:
16396 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
16397 break;
16398 default:
16399 goto pool32axf_invalid;
16401 break;
16402 case 0x35:
16403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16404 switch (minor) {
16405 case MFHI32:
16406 gen_HILO(ctx, OPC_MFHI, 0, rs);
16407 break;
16408 case MFLO32:
16409 gen_HILO(ctx, OPC_MFLO, 0, rs);
16410 break;
16411 case MTHI32:
16412 gen_HILO(ctx, OPC_MTHI, 0, rs);
16413 break;
16414 case MTLO32:
16415 gen_HILO(ctx, OPC_MTLO, 0, rs);
16416 break;
16417 default:
16418 goto pool32axf_invalid;
16420 break;
16421 default:
16422 pool32axf_invalid:
16423 MIPS_INVAL("pool32axf");
16424 generate_exception_end(ctx, EXCP_RI);
16425 break;
16430 * Values for microMIPS fmt field. Variable-width, depending on which
16431 * formats the instruction supports.
16433 enum {
16434 FMT_SD_S = 0,
16435 FMT_SD_D = 1,
16437 FMT_SDPS_S = 0,
16438 FMT_SDPS_D = 1,
16439 FMT_SDPS_PS = 2,
16441 FMT_SWL_S = 0,
16442 FMT_SWL_W = 1,
16443 FMT_SWL_L = 2,
16445 FMT_DWL_D = 0,
16446 FMT_DWL_W = 1,
16447 FMT_DWL_L = 2
16450 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
16452 int extension = (ctx->opcode >> 6) & 0x3ff;
16453 uint32_t mips32_op;
16455 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
16456 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
16457 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
16459 switch (extension) {
16460 case FLOAT_1BIT_FMT(CFC1, 0):
16461 mips32_op = OPC_CFC1;
16462 goto do_cp1;
16463 case FLOAT_1BIT_FMT(CTC1, 0):
16464 mips32_op = OPC_CTC1;
16465 goto do_cp1;
16466 case FLOAT_1BIT_FMT(MFC1, 0):
16467 mips32_op = OPC_MFC1;
16468 goto do_cp1;
16469 case FLOAT_1BIT_FMT(MTC1, 0):
16470 mips32_op = OPC_MTC1;
16471 goto do_cp1;
16472 case FLOAT_1BIT_FMT(MFHC1, 0):
16473 mips32_op = OPC_MFHC1;
16474 goto do_cp1;
16475 case FLOAT_1BIT_FMT(MTHC1, 0):
16476 mips32_op = OPC_MTHC1;
16477 do_cp1:
16478 gen_cp1(ctx, mips32_op, rt, rs);
16479 break;
16481 /* Reciprocal square root */
16482 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
16483 mips32_op = OPC_RSQRT_S;
16484 goto do_unaryfp;
16485 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
16486 mips32_op = OPC_RSQRT_D;
16487 goto do_unaryfp;
16489 /* Square root */
16490 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
16491 mips32_op = OPC_SQRT_S;
16492 goto do_unaryfp;
16493 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
16494 mips32_op = OPC_SQRT_D;
16495 goto do_unaryfp;
16497 /* Reciprocal */
16498 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
16499 mips32_op = OPC_RECIP_S;
16500 goto do_unaryfp;
16501 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
16502 mips32_op = OPC_RECIP_D;
16503 goto do_unaryfp;
16505 /* Floor */
16506 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
16507 mips32_op = OPC_FLOOR_L_S;
16508 goto do_unaryfp;
16509 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
16510 mips32_op = OPC_FLOOR_L_D;
16511 goto do_unaryfp;
16512 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
16513 mips32_op = OPC_FLOOR_W_S;
16514 goto do_unaryfp;
16515 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
16516 mips32_op = OPC_FLOOR_W_D;
16517 goto do_unaryfp;
16519 /* Ceiling */
16520 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
16521 mips32_op = OPC_CEIL_L_S;
16522 goto do_unaryfp;
16523 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
16524 mips32_op = OPC_CEIL_L_D;
16525 goto do_unaryfp;
16526 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
16527 mips32_op = OPC_CEIL_W_S;
16528 goto do_unaryfp;
16529 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
16530 mips32_op = OPC_CEIL_W_D;
16531 goto do_unaryfp;
16533 /* Truncation */
16534 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
16535 mips32_op = OPC_TRUNC_L_S;
16536 goto do_unaryfp;
16537 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
16538 mips32_op = OPC_TRUNC_L_D;
16539 goto do_unaryfp;
16540 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
16541 mips32_op = OPC_TRUNC_W_S;
16542 goto do_unaryfp;
16543 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
16544 mips32_op = OPC_TRUNC_W_D;
16545 goto do_unaryfp;
16547 /* Round */
16548 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
16549 mips32_op = OPC_ROUND_L_S;
16550 goto do_unaryfp;
16551 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
16552 mips32_op = OPC_ROUND_L_D;
16553 goto do_unaryfp;
16554 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
16555 mips32_op = OPC_ROUND_W_S;
16556 goto do_unaryfp;
16557 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
16558 mips32_op = OPC_ROUND_W_D;
16559 goto do_unaryfp;
16561 /* Integer to floating-point conversion */
16562 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
16563 mips32_op = OPC_CVT_L_S;
16564 goto do_unaryfp;
16565 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
16566 mips32_op = OPC_CVT_L_D;
16567 goto do_unaryfp;
16568 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
16569 mips32_op = OPC_CVT_W_S;
16570 goto do_unaryfp;
16571 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
16572 mips32_op = OPC_CVT_W_D;
16573 goto do_unaryfp;
16575 /* Paired-foo conversions */
16576 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
16577 mips32_op = OPC_CVT_S_PL;
16578 goto do_unaryfp;
16579 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
16580 mips32_op = OPC_CVT_S_PU;
16581 goto do_unaryfp;
16582 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
16583 mips32_op = OPC_CVT_PW_PS;
16584 goto do_unaryfp;
16585 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
16586 mips32_op = OPC_CVT_PS_PW;
16587 goto do_unaryfp;
16589 /* Floating-point moves */
16590 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
16591 mips32_op = OPC_MOV_S;
16592 goto do_unaryfp;
16593 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
16594 mips32_op = OPC_MOV_D;
16595 goto do_unaryfp;
16596 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
16597 mips32_op = OPC_MOV_PS;
16598 goto do_unaryfp;
16600 /* Absolute value */
16601 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
16602 mips32_op = OPC_ABS_S;
16603 goto do_unaryfp;
16604 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
16605 mips32_op = OPC_ABS_D;
16606 goto do_unaryfp;
16607 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
16608 mips32_op = OPC_ABS_PS;
16609 goto do_unaryfp;
16611 /* Negation */
16612 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
16613 mips32_op = OPC_NEG_S;
16614 goto do_unaryfp;
16615 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
16616 mips32_op = OPC_NEG_D;
16617 goto do_unaryfp;
16618 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
16619 mips32_op = OPC_NEG_PS;
16620 goto do_unaryfp;
16622 /* Reciprocal square root step */
16623 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
16624 mips32_op = OPC_RSQRT1_S;
16625 goto do_unaryfp;
16626 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
16627 mips32_op = OPC_RSQRT1_D;
16628 goto do_unaryfp;
16629 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
16630 mips32_op = OPC_RSQRT1_PS;
16631 goto do_unaryfp;
16633 /* Reciprocal step */
16634 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
16635 mips32_op = OPC_RECIP1_S;
16636 goto do_unaryfp;
16637 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
16638 mips32_op = OPC_RECIP1_S;
16639 goto do_unaryfp;
16640 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
16641 mips32_op = OPC_RECIP1_PS;
16642 goto do_unaryfp;
16644 /* Conversions from double */
16645 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
16646 mips32_op = OPC_CVT_D_S;
16647 goto do_unaryfp;
16648 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
16649 mips32_op = OPC_CVT_D_W;
16650 goto do_unaryfp;
16651 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
16652 mips32_op = OPC_CVT_D_L;
16653 goto do_unaryfp;
16655 /* Conversions from single */
16656 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
16657 mips32_op = OPC_CVT_S_D;
16658 goto do_unaryfp;
16659 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
16660 mips32_op = OPC_CVT_S_W;
16661 goto do_unaryfp;
16662 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
16663 mips32_op = OPC_CVT_S_L;
16664 do_unaryfp:
16665 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
16666 break;
16668 /* Conditional moves on floating-point codes */
16669 case COND_FLOAT_MOV(MOVT, 0):
16670 case COND_FLOAT_MOV(MOVT, 1):
16671 case COND_FLOAT_MOV(MOVT, 2):
16672 case COND_FLOAT_MOV(MOVT, 3):
16673 case COND_FLOAT_MOV(MOVT, 4):
16674 case COND_FLOAT_MOV(MOVT, 5):
16675 case COND_FLOAT_MOV(MOVT, 6):
16676 case COND_FLOAT_MOV(MOVT, 7):
16677 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16678 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
16679 break;
16680 case COND_FLOAT_MOV(MOVF, 0):
16681 case COND_FLOAT_MOV(MOVF, 1):
16682 case COND_FLOAT_MOV(MOVF, 2):
16683 case COND_FLOAT_MOV(MOVF, 3):
16684 case COND_FLOAT_MOV(MOVF, 4):
16685 case COND_FLOAT_MOV(MOVF, 5):
16686 case COND_FLOAT_MOV(MOVF, 6):
16687 case COND_FLOAT_MOV(MOVF, 7):
16688 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16689 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
16690 break;
16691 default:
16692 MIPS_INVAL("pool32fxf");
16693 generate_exception_end(ctx, EXCP_RI);
16694 break;
16698 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
16700 int32_t offset;
16701 uint16_t insn;
16702 int rt, rs, rd, rr;
16703 int16_t imm;
16704 uint32_t op, minor, minor2, mips32_op;
16705 uint32_t cond, fmt, cc;
16707 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
16708 ctx->opcode = (ctx->opcode << 16) | insn;
16710 rt = (ctx->opcode >> 21) & 0x1f;
16711 rs = (ctx->opcode >> 16) & 0x1f;
16712 rd = (ctx->opcode >> 11) & 0x1f;
16713 rr = (ctx->opcode >> 6) & 0x1f;
16714 imm = (int16_t) ctx->opcode;
16716 op = (ctx->opcode >> 26) & 0x3f;
16717 switch (op) {
16718 case POOL32A:
16719 minor = ctx->opcode & 0x3f;
16720 switch (minor) {
16721 case 0x00:
16722 minor = (ctx->opcode >> 6) & 0xf;
16723 switch (minor) {
16724 case SLL32:
16725 mips32_op = OPC_SLL;
16726 goto do_shifti;
16727 case SRA:
16728 mips32_op = OPC_SRA;
16729 goto do_shifti;
16730 case SRL32:
16731 mips32_op = OPC_SRL;
16732 goto do_shifti;
16733 case ROTR:
16734 mips32_op = OPC_ROTR;
16735 do_shifti:
16736 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
16737 break;
16738 case SELEQZ:
16739 check_insn(ctx, ISA_MIPS32R6);
16740 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
16741 break;
16742 case SELNEZ:
16743 check_insn(ctx, ISA_MIPS32R6);
16744 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
16745 break;
16746 case R6_RDHWR:
16747 check_insn(ctx, ISA_MIPS32R6);
16748 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
16749 break;
16750 default:
16751 goto pool32a_invalid;
16753 break;
16754 case 0x10:
16755 minor = (ctx->opcode >> 6) & 0xf;
16756 switch (minor) {
16757 /* Arithmetic */
16758 case ADD:
16759 mips32_op = OPC_ADD;
16760 goto do_arith;
16761 case ADDU32:
16762 mips32_op = OPC_ADDU;
16763 goto do_arith;
16764 case SUB:
16765 mips32_op = OPC_SUB;
16766 goto do_arith;
16767 case SUBU32:
16768 mips32_op = OPC_SUBU;
16769 goto do_arith;
16770 case MUL:
16771 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16772 mips32_op = OPC_MUL;
16773 do_arith:
16774 gen_arith(ctx, mips32_op, rd, rs, rt);
16775 break;
16776 /* Shifts */
16777 case SLLV:
16778 mips32_op = OPC_SLLV;
16779 goto do_shift;
16780 case SRLV:
16781 mips32_op = OPC_SRLV;
16782 goto do_shift;
16783 case SRAV:
16784 mips32_op = OPC_SRAV;
16785 goto do_shift;
16786 case ROTRV:
16787 mips32_op = OPC_ROTRV;
16788 do_shift:
16789 gen_shift(ctx, mips32_op, rd, rs, rt);
16790 break;
16791 /* Logical operations */
16792 case AND:
16793 mips32_op = OPC_AND;
16794 goto do_logic;
16795 case OR32:
16796 mips32_op = OPC_OR;
16797 goto do_logic;
16798 case NOR:
16799 mips32_op = OPC_NOR;
16800 goto do_logic;
16801 case XOR32:
16802 mips32_op = OPC_XOR;
16803 do_logic:
16804 gen_logic(ctx, mips32_op, rd, rs, rt);
16805 break;
16806 /* Set less than */
16807 case SLT:
16808 mips32_op = OPC_SLT;
16809 goto do_slt;
16810 case SLTU:
16811 mips32_op = OPC_SLTU;
16812 do_slt:
16813 gen_slt(ctx, mips32_op, rd, rs, rt);
16814 break;
16815 default:
16816 goto pool32a_invalid;
16818 break;
16819 case 0x18:
16820 minor = (ctx->opcode >> 6) & 0xf;
16821 switch (minor) {
16822 /* Conditional moves */
16823 case MOVN: /* MUL */
16824 if (ctx->insn_flags & ISA_MIPS32R6) {
16825 /* MUL */
16826 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
16827 } else {
16828 /* MOVN */
16829 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
16831 break;
16832 case MOVZ: /* MUH */
16833 if (ctx->insn_flags & ISA_MIPS32R6) {
16834 /* MUH */
16835 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
16836 } else {
16837 /* MOVZ */
16838 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
16840 break;
16841 case MULU:
16842 check_insn(ctx, ISA_MIPS32R6);
16843 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
16844 break;
16845 case MUHU:
16846 check_insn(ctx, ISA_MIPS32R6);
16847 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
16848 break;
16849 case LWXS: /* DIV */
16850 if (ctx->insn_flags & ISA_MIPS32R6) {
16851 /* DIV */
16852 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
16853 } else {
16854 /* LWXS */
16855 gen_ldxs(ctx, rs, rt, rd);
16857 break;
16858 case MOD:
16859 check_insn(ctx, ISA_MIPS32R6);
16860 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
16861 break;
16862 case R6_DIVU:
16863 check_insn(ctx, ISA_MIPS32R6);
16864 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
16865 break;
16866 case MODU:
16867 check_insn(ctx, ISA_MIPS32R6);
16868 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
16869 break;
16870 default:
16871 goto pool32a_invalid;
16873 break;
16874 case INS:
16875 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
16876 return;
16877 case LSA:
16878 check_insn(ctx, ISA_MIPS32R6);
16879 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
16880 extract32(ctx->opcode, 9, 2));
16881 break;
16882 case ALIGN:
16883 check_insn(ctx, ISA_MIPS32R6);
16884 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
16885 break;
16886 case EXT:
16887 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
16888 return;
16889 case POOL32AXF:
16890 gen_pool32axf(env, ctx, rt, rs);
16891 break;
16892 case BREAK32:
16893 generate_exception_end(ctx, EXCP_BREAK);
16894 break;
16895 case SIGRIE:
16896 check_insn(ctx, ISA_MIPS32R6);
16897 generate_exception_end(ctx, EXCP_RI);
16898 break;
16899 default:
16900 pool32a_invalid:
16901 MIPS_INVAL("pool32a");
16902 generate_exception_end(ctx, EXCP_RI);
16903 break;
16905 break;
16906 case POOL32B:
16907 minor = (ctx->opcode >> 12) & 0xf;
16908 switch (minor) {
16909 case CACHE:
16910 check_cp0_enabled(ctx);
16911 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16912 gen_cache_operation(ctx, rt, rs, imm);
16914 break;
16915 case LWC2:
16916 case SWC2:
16917 /* COP2: Not implemented. */
16918 generate_exception_err(ctx, EXCP_CpU, 2);
16919 break;
16920 #ifdef TARGET_MIPS64
16921 case LDP:
16922 case SDP:
16923 check_insn(ctx, ISA_MIPS3);
16924 check_mips_64(ctx);
16925 #endif
16926 /* fall through */
16927 case LWP:
16928 case SWP:
16929 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16930 break;
16931 #ifdef TARGET_MIPS64
16932 case LDM:
16933 case SDM:
16934 check_insn(ctx, ISA_MIPS3);
16935 check_mips_64(ctx);
16936 #endif
16937 /* fall through */
16938 case LWM32:
16939 case SWM32:
16940 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
16941 break;
16942 default:
16943 MIPS_INVAL("pool32b");
16944 generate_exception_end(ctx, EXCP_RI);
16945 break;
16947 break;
16948 case POOL32F:
16949 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
16950 minor = ctx->opcode & 0x3f;
16951 check_cp1_enabled(ctx);
16952 switch (minor) {
16953 case ALNV_PS:
16954 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16955 mips32_op = OPC_ALNV_PS;
16956 goto do_madd;
16957 case MADD_S:
16958 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16959 mips32_op = OPC_MADD_S;
16960 goto do_madd;
16961 case MADD_D:
16962 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16963 mips32_op = OPC_MADD_D;
16964 goto do_madd;
16965 case MADD_PS:
16966 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16967 mips32_op = OPC_MADD_PS;
16968 goto do_madd;
16969 case MSUB_S:
16970 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16971 mips32_op = OPC_MSUB_S;
16972 goto do_madd;
16973 case MSUB_D:
16974 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16975 mips32_op = OPC_MSUB_D;
16976 goto do_madd;
16977 case MSUB_PS:
16978 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16979 mips32_op = OPC_MSUB_PS;
16980 goto do_madd;
16981 case NMADD_S:
16982 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16983 mips32_op = OPC_NMADD_S;
16984 goto do_madd;
16985 case NMADD_D:
16986 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16987 mips32_op = OPC_NMADD_D;
16988 goto do_madd;
16989 case NMADD_PS:
16990 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16991 mips32_op = OPC_NMADD_PS;
16992 goto do_madd;
16993 case NMSUB_S:
16994 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16995 mips32_op = OPC_NMSUB_S;
16996 goto do_madd;
16997 case NMSUB_D:
16998 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16999 mips32_op = OPC_NMSUB_D;
17000 goto do_madd;
17001 case NMSUB_PS:
17002 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17003 mips32_op = OPC_NMSUB_PS;
17004 do_madd:
17005 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
17006 break;
17007 case CABS_COND_FMT:
17008 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17009 cond = (ctx->opcode >> 6) & 0xf;
17010 cc = (ctx->opcode >> 13) & 0x7;
17011 fmt = (ctx->opcode >> 10) & 0x3;
17012 switch (fmt) {
17013 case 0x0:
17014 gen_cmpabs_s(ctx, cond, rt, rs, cc);
17015 break;
17016 case 0x1:
17017 gen_cmpabs_d(ctx, cond, rt, rs, cc);
17018 break;
17019 case 0x2:
17020 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
17021 break;
17022 default:
17023 goto pool32f_invalid;
17025 break;
17026 case C_COND_FMT:
17027 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17028 cond = (ctx->opcode >> 6) & 0xf;
17029 cc = (ctx->opcode >> 13) & 0x7;
17030 fmt = (ctx->opcode >> 10) & 0x3;
17031 switch (fmt) {
17032 case 0x0:
17033 gen_cmp_s(ctx, cond, rt, rs, cc);
17034 break;
17035 case 0x1:
17036 gen_cmp_d(ctx, cond, rt, rs, cc);
17037 break;
17038 case 0x2:
17039 gen_cmp_ps(ctx, cond, rt, rs, cc);
17040 break;
17041 default:
17042 goto pool32f_invalid;
17044 break;
17045 case CMP_CONDN_S:
17046 check_insn(ctx, ISA_MIPS32R6);
17047 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
17048 break;
17049 case CMP_CONDN_D:
17050 check_insn(ctx, ISA_MIPS32R6);
17051 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
17052 break;
17053 case POOL32FXF:
17054 gen_pool32fxf(ctx, rt, rs);
17055 break;
17056 case 0x00:
17057 /* PLL foo */
17058 switch ((ctx->opcode >> 6) & 0x7) {
17059 case PLL_PS:
17060 mips32_op = OPC_PLL_PS;
17061 goto do_ps;
17062 case PLU_PS:
17063 mips32_op = OPC_PLU_PS;
17064 goto do_ps;
17065 case PUL_PS:
17066 mips32_op = OPC_PUL_PS;
17067 goto do_ps;
17068 case PUU_PS:
17069 mips32_op = OPC_PUU_PS;
17070 goto do_ps;
17071 case CVT_PS_S:
17072 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17073 mips32_op = OPC_CVT_PS_S;
17074 do_ps:
17075 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17076 break;
17077 default:
17078 goto pool32f_invalid;
17080 break;
17081 case MIN_FMT:
17082 check_insn(ctx, ISA_MIPS32R6);
17083 switch ((ctx->opcode >> 9) & 0x3) {
17084 case FMT_SDPS_S:
17085 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
17086 break;
17087 case FMT_SDPS_D:
17088 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
17089 break;
17090 default:
17091 goto pool32f_invalid;
17093 break;
17094 case 0x08:
17095 /* [LS][WDU]XC1 */
17096 switch ((ctx->opcode >> 6) & 0x7) {
17097 case LWXC1:
17098 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17099 mips32_op = OPC_LWXC1;
17100 goto do_ldst_cp1;
17101 case SWXC1:
17102 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17103 mips32_op = OPC_SWXC1;
17104 goto do_ldst_cp1;
17105 case LDXC1:
17106 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17107 mips32_op = OPC_LDXC1;
17108 goto do_ldst_cp1;
17109 case SDXC1:
17110 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17111 mips32_op = OPC_SDXC1;
17112 goto do_ldst_cp1;
17113 case LUXC1:
17114 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17115 mips32_op = OPC_LUXC1;
17116 goto do_ldst_cp1;
17117 case SUXC1:
17118 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17119 mips32_op = OPC_SUXC1;
17120 do_ldst_cp1:
17121 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
17122 break;
17123 default:
17124 goto pool32f_invalid;
17126 break;
17127 case MAX_FMT:
17128 check_insn(ctx, ISA_MIPS32R6);
17129 switch ((ctx->opcode >> 9) & 0x3) {
17130 case FMT_SDPS_S:
17131 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
17132 break;
17133 case FMT_SDPS_D:
17134 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
17135 break;
17136 default:
17137 goto pool32f_invalid;
17139 break;
17140 case 0x18:
17141 /* 3D insns */
17142 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17143 fmt = (ctx->opcode >> 9) & 0x3;
17144 switch ((ctx->opcode >> 6) & 0x7) {
17145 case RSQRT2_FMT:
17146 switch (fmt) {
17147 case FMT_SDPS_S:
17148 mips32_op = OPC_RSQRT2_S;
17149 goto do_3d;
17150 case FMT_SDPS_D:
17151 mips32_op = OPC_RSQRT2_D;
17152 goto do_3d;
17153 case FMT_SDPS_PS:
17154 mips32_op = OPC_RSQRT2_PS;
17155 goto do_3d;
17156 default:
17157 goto pool32f_invalid;
17159 break;
17160 case RECIP2_FMT:
17161 switch (fmt) {
17162 case FMT_SDPS_S:
17163 mips32_op = OPC_RECIP2_S;
17164 goto do_3d;
17165 case FMT_SDPS_D:
17166 mips32_op = OPC_RECIP2_D;
17167 goto do_3d;
17168 case FMT_SDPS_PS:
17169 mips32_op = OPC_RECIP2_PS;
17170 goto do_3d;
17171 default:
17172 goto pool32f_invalid;
17174 break;
17175 case ADDR_PS:
17176 mips32_op = OPC_ADDR_PS;
17177 goto do_3d;
17178 case MULR_PS:
17179 mips32_op = OPC_MULR_PS;
17180 do_3d:
17181 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17182 break;
17183 default:
17184 goto pool32f_invalid;
17186 break;
17187 case 0x20:
17188 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
17189 cc = (ctx->opcode >> 13) & 0x7;
17190 fmt = (ctx->opcode >> 9) & 0x3;
17191 switch ((ctx->opcode >> 6) & 0x7) {
17192 case MOVF_FMT: /* RINT_FMT */
17193 if (ctx->insn_flags & ISA_MIPS32R6) {
17194 /* RINT_FMT */
17195 switch (fmt) {
17196 case FMT_SDPS_S:
17197 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
17198 break;
17199 case FMT_SDPS_D:
17200 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
17201 break;
17202 default:
17203 goto pool32f_invalid;
17205 } else {
17206 /* MOVF_FMT */
17207 switch (fmt) {
17208 case FMT_SDPS_S:
17209 gen_movcf_s(ctx, rs, rt, cc, 0);
17210 break;
17211 case FMT_SDPS_D:
17212 gen_movcf_d(ctx, rs, rt, cc, 0);
17213 break;
17214 case FMT_SDPS_PS:
17215 check_ps(ctx);
17216 gen_movcf_ps(ctx, rs, rt, cc, 0);
17217 break;
17218 default:
17219 goto pool32f_invalid;
17222 break;
17223 case MOVT_FMT: /* CLASS_FMT */
17224 if (ctx->insn_flags & ISA_MIPS32R6) {
17225 /* CLASS_FMT */
17226 switch (fmt) {
17227 case FMT_SDPS_S:
17228 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
17229 break;
17230 case FMT_SDPS_D:
17231 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
17232 break;
17233 default:
17234 goto pool32f_invalid;
17236 } else {
17237 /* MOVT_FMT */
17238 switch (fmt) {
17239 case FMT_SDPS_S:
17240 gen_movcf_s(ctx, rs, rt, cc, 1);
17241 break;
17242 case FMT_SDPS_D:
17243 gen_movcf_d(ctx, rs, rt, cc, 1);
17244 break;
17245 case FMT_SDPS_PS:
17246 check_ps(ctx);
17247 gen_movcf_ps(ctx, rs, rt, cc, 1);
17248 break;
17249 default:
17250 goto pool32f_invalid;
17253 break;
17254 case PREFX:
17255 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17256 break;
17257 default:
17258 goto pool32f_invalid;
17260 break;
17261 #define FINSN_3ARG_SDPS(prfx) \
17262 switch ((ctx->opcode >> 8) & 0x3) { \
17263 case FMT_SDPS_S: \
17264 mips32_op = OPC_##prfx##_S; \
17265 goto do_fpop; \
17266 case FMT_SDPS_D: \
17267 mips32_op = OPC_##prfx##_D; \
17268 goto do_fpop; \
17269 case FMT_SDPS_PS: \
17270 check_ps(ctx); \
17271 mips32_op = OPC_##prfx##_PS; \
17272 goto do_fpop; \
17273 default: \
17274 goto pool32f_invalid; \
17276 case MINA_FMT:
17277 check_insn(ctx, ISA_MIPS32R6);
17278 switch ((ctx->opcode >> 9) & 0x3) {
17279 case FMT_SDPS_S:
17280 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
17281 break;
17282 case FMT_SDPS_D:
17283 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
17284 break;
17285 default:
17286 goto pool32f_invalid;
17288 break;
17289 case MAXA_FMT:
17290 check_insn(ctx, ISA_MIPS32R6);
17291 switch ((ctx->opcode >> 9) & 0x3) {
17292 case FMT_SDPS_S:
17293 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
17294 break;
17295 case FMT_SDPS_D:
17296 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
17297 break;
17298 default:
17299 goto pool32f_invalid;
17301 break;
17302 case 0x30:
17303 /* regular FP ops */
17304 switch ((ctx->opcode >> 6) & 0x3) {
17305 case ADD_FMT:
17306 FINSN_3ARG_SDPS(ADD);
17307 break;
17308 case SUB_FMT:
17309 FINSN_3ARG_SDPS(SUB);
17310 break;
17311 case MUL_FMT:
17312 FINSN_3ARG_SDPS(MUL);
17313 break;
17314 case DIV_FMT:
17315 fmt = (ctx->opcode >> 8) & 0x3;
17316 if (fmt == 1) {
17317 mips32_op = OPC_DIV_D;
17318 } else if (fmt == 0) {
17319 mips32_op = OPC_DIV_S;
17320 } else {
17321 goto pool32f_invalid;
17323 goto do_fpop;
17324 default:
17325 goto pool32f_invalid;
17327 break;
17328 case 0x38:
17329 /* cmovs */
17330 switch ((ctx->opcode >> 6) & 0x7) {
17331 case MOVN_FMT: /* SELEQZ_FMT */
17332 if (ctx->insn_flags & ISA_MIPS32R6) {
17333 /* SELEQZ_FMT */
17334 switch ((ctx->opcode >> 9) & 0x3) {
17335 case FMT_SDPS_S:
17336 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
17337 break;
17338 case FMT_SDPS_D:
17339 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
17340 break;
17341 default:
17342 goto pool32f_invalid;
17344 } else {
17345 /* MOVN_FMT */
17346 FINSN_3ARG_SDPS(MOVN);
17348 break;
17349 case MOVN_FMT_04:
17350 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17351 FINSN_3ARG_SDPS(MOVN);
17352 break;
17353 case MOVZ_FMT: /* SELNEZ_FMT */
17354 if (ctx->insn_flags & ISA_MIPS32R6) {
17355 /* SELNEZ_FMT */
17356 switch ((ctx->opcode >> 9) & 0x3) {
17357 case FMT_SDPS_S:
17358 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
17359 break;
17360 case FMT_SDPS_D:
17361 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
17362 break;
17363 default:
17364 goto pool32f_invalid;
17366 } else {
17367 /* MOVZ_FMT */
17368 FINSN_3ARG_SDPS(MOVZ);
17370 break;
17371 case MOVZ_FMT_05:
17372 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17373 FINSN_3ARG_SDPS(MOVZ);
17374 break;
17375 case SEL_FMT:
17376 check_insn(ctx, ISA_MIPS32R6);
17377 switch ((ctx->opcode >> 9) & 0x3) {
17378 case FMT_SDPS_S:
17379 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
17380 break;
17381 case FMT_SDPS_D:
17382 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
17383 break;
17384 default:
17385 goto pool32f_invalid;
17387 break;
17388 case MADDF_FMT:
17389 check_insn(ctx, ISA_MIPS32R6);
17390 switch ((ctx->opcode >> 9) & 0x3) {
17391 case FMT_SDPS_S:
17392 mips32_op = OPC_MADDF_S;
17393 goto do_fpop;
17394 case FMT_SDPS_D:
17395 mips32_op = OPC_MADDF_D;
17396 goto do_fpop;
17397 default:
17398 goto pool32f_invalid;
17400 break;
17401 case MSUBF_FMT:
17402 check_insn(ctx, ISA_MIPS32R6);
17403 switch ((ctx->opcode >> 9) & 0x3) {
17404 case FMT_SDPS_S:
17405 mips32_op = OPC_MSUBF_S;
17406 goto do_fpop;
17407 case FMT_SDPS_D:
17408 mips32_op = OPC_MSUBF_D;
17409 goto do_fpop;
17410 default:
17411 goto pool32f_invalid;
17413 break;
17414 default:
17415 goto pool32f_invalid;
17417 break;
17418 do_fpop:
17419 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
17420 break;
17421 default:
17422 pool32f_invalid:
17423 MIPS_INVAL("pool32f");
17424 generate_exception_end(ctx, EXCP_RI);
17425 break;
17427 } else {
17428 generate_exception_err(ctx, EXCP_CpU, 1);
17430 break;
17431 case POOL32I:
17432 minor = (ctx->opcode >> 21) & 0x1f;
17433 switch (minor) {
17434 case BLTZ:
17435 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17436 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
17437 break;
17438 case BLTZAL:
17439 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17440 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
17441 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17442 break;
17443 case BLTZALS:
17444 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17445 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
17446 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17447 break;
17448 case BGEZ:
17449 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17450 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
17451 break;
17452 case BGEZAL:
17453 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17454 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
17455 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17456 break;
17457 case BGEZALS:
17458 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17459 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
17460 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17461 break;
17462 case BLEZ:
17463 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17464 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
17465 break;
17466 case BGTZ:
17467 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17468 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
17469 break;
17471 /* Traps */
17472 case TLTI: /* BC1EQZC */
17473 if (ctx->insn_flags & ISA_MIPS32R6) {
17474 /* BC1EQZC */
17475 check_cp1_enabled(ctx);
17476 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
17477 } else {
17478 /* TLTI */
17479 mips32_op = OPC_TLTI;
17480 goto do_trapi;
17482 break;
17483 case TGEI: /* BC1NEZC */
17484 if (ctx->insn_flags & ISA_MIPS32R6) {
17485 /* BC1NEZC */
17486 check_cp1_enabled(ctx);
17487 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
17488 } else {
17489 /* TGEI */
17490 mips32_op = OPC_TGEI;
17491 goto do_trapi;
17493 break;
17494 case TLTIU:
17495 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17496 mips32_op = OPC_TLTIU;
17497 goto do_trapi;
17498 case TGEIU:
17499 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17500 mips32_op = OPC_TGEIU;
17501 goto do_trapi;
17502 case TNEI: /* SYNCI */
17503 if (ctx->insn_flags & ISA_MIPS32R6) {
17504 /* SYNCI */
17506 * Break the TB to be able to sync copied instructions
17507 * immediately.
17509 ctx->base.is_jmp = DISAS_STOP;
17510 } else {
17511 /* TNEI */
17512 mips32_op = OPC_TNEI;
17513 goto do_trapi;
17515 break;
17516 case TEQI:
17517 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17518 mips32_op = OPC_TEQI;
17519 do_trapi:
17520 gen_trap(ctx, mips32_op, rs, -1, imm);
17521 break;
17523 case BNEZC:
17524 case BEQZC:
17525 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17526 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
17527 4, rs, 0, imm << 1, 0);
17529 * Compact branches don't have a delay slot, so just let
17530 * the normal delay slot handling take us to the branch
17531 * target.
17533 break;
17534 case LUI:
17535 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17536 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
17537 break;
17538 case SYNCI:
17539 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17541 * Break the TB to be able to sync copied instructions
17542 * immediately.
17544 ctx->base.is_jmp = DISAS_STOP;
17545 break;
17546 case BC2F:
17547 case BC2T:
17548 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17549 /* COP2: Not implemented. */
17550 generate_exception_err(ctx, EXCP_CpU, 2);
17551 break;
17552 case BC1F:
17553 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17554 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
17555 goto do_cp1branch;
17556 case BC1T:
17557 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17558 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
17559 goto do_cp1branch;
17560 case BC1ANY4F:
17561 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17562 mips32_op = OPC_BC1FANY4;
17563 goto do_cp1mips3d;
17564 case BC1ANY4T:
17565 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17566 mips32_op = OPC_BC1TANY4;
17567 do_cp1mips3d:
17568 check_cop1x(ctx);
17569 check_insn(ctx, ASE_MIPS3D);
17570 /* Fall through */
17571 do_cp1branch:
17572 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17573 check_cp1_enabled(ctx);
17574 gen_compute_branch1(ctx, mips32_op,
17575 (ctx->opcode >> 18) & 0x7, imm << 1);
17576 } else {
17577 generate_exception_err(ctx, EXCP_CpU, 1);
17579 break;
17580 case BPOSGE64:
17581 case BPOSGE32:
17582 /* MIPS DSP: not implemented */
17583 /* Fall through */
17584 default:
17585 MIPS_INVAL("pool32i");
17586 generate_exception_end(ctx, EXCP_RI);
17587 break;
17589 break;
17590 case POOL32C:
17591 minor = (ctx->opcode >> 12) & 0xf;
17592 offset = sextract32(ctx->opcode, 0,
17593 (ctx->insn_flags & ISA_MIPS32R6) ? 9 : 12);
17594 switch (minor) {
17595 case LWL:
17596 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17597 mips32_op = OPC_LWL;
17598 goto do_ld_lr;
17599 case SWL:
17600 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17601 mips32_op = OPC_SWL;
17602 goto do_st_lr;
17603 case LWR:
17604 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17605 mips32_op = OPC_LWR;
17606 goto do_ld_lr;
17607 case SWR:
17608 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17609 mips32_op = OPC_SWR;
17610 goto do_st_lr;
17611 #if defined(TARGET_MIPS64)
17612 case LDL:
17613 check_insn(ctx, ISA_MIPS3);
17614 check_mips_64(ctx);
17615 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17616 mips32_op = OPC_LDL;
17617 goto do_ld_lr;
17618 case SDL:
17619 check_insn(ctx, ISA_MIPS3);
17620 check_mips_64(ctx);
17621 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17622 mips32_op = OPC_SDL;
17623 goto do_st_lr;
17624 case LDR:
17625 check_insn(ctx, ISA_MIPS3);
17626 check_mips_64(ctx);
17627 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17628 mips32_op = OPC_LDR;
17629 goto do_ld_lr;
17630 case SDR:
17631 check_insn(ctx, ISA_MIPS3);
17632 check_mips_64(ctx);
17633 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17634 mips32_op = OPC_SDR;
17635 goto do_st_lr;
17636 case LWU:
17637 check_insn(ctx, ISA_MIPS3);
17638 check_mips_64(ctx);
17639 mips32_op = OPC_LWU;
17640 goto do_ld_lr;
17641 case LLD:
17642 check_insn(ctx, ISA_MIPS3);
17643 check_mips_64(ctx);
17644 mips32_op = OPC_LLD;
17645 goto do_ld_lr;
17646 #endif
17647 case LL:
17648 mips32_op = OPC_LL;
17649 goto do_ld_lr;
17650 do_ld_lr:
17651 gen_ld(ctx, mips32_op, rt, rs, offset);
17652 break;
17653 do_st_lr:
17654 gen_st(ctx, mips32_op, rt, rs, offset);
17655 break;
17656 case SC:
17657 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
17658 break;
17659 #if defined(TARGET_MIPS64)
17660 case SCD:
17661 check_insn(ctx, ISA_MIPS3);
17662 check_mips_64(ctx);
17663 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
17664 break;
17665 #endif
17666 case LD_EVA:
17667 if (!ctx->eva) {
17668 MIPS_INVAL("pool32c ld-eva");
17669 generate_exception_end(ctx, EXCP_RI);
17670 break;
17672 check_cp0_enabled(ctx);
17674 minor2 = (ctx->opcode >> 9) & 0x7;
17675 offset = sextract32(ctx->opcode, 0, 9);
17676 switch (minor2) {
17677 case LBUE:
17678 mips32_op = OPC_LBUE;
17679 goto do_ld_lr;
17680 case LHUE:
17681 mips32_op = OPC_LHUE;
17682 goto do_ld_lr;
17683 case LWLE:
17684 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17685 mips32_op = OPC_LWLE;
17686 goto do_ld_lr;
17687 case LWRE:
17688 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17689 mips32_op = OPC_LWRE;
17690 goto do_ld_lr;
17691 case LBE:
17692 mips32_op = OPC_LBE;
17693 goto do_ld_lr;
17694 case LHE:
17695 mips32_op = OPC_LHE;
17696 goto do_ld_lr;
17697 case LLE:
17698 mips32_op = OPC_LLE;
17699 goto do_ld_lr;
17700 case LWE:
17701 mips32_op = OPC_LWE;
17702 goto do_ld_lr;
17704 break;
17705 case ST_EVA:
17706 if (!ctx->eva) {
17707 MIPS_INVAL("pool32c st-eva");
17708 generate_exception_end(ctx, EXCP_RI);
17709 break;
17711 check_cp0_enabled(ctx);
17713 minor2 = (ctx->opcode >> 9) & 0x7;
17714 offset = sextract32(ctx->opcode, 0, 9);
17715 switch (minor2) {
17716 case SWLE:
17717 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17718 mips32_op = OPC_SWLE;
17719 goto do_st_lr;
17720 case SWRE:
17721 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17722 mips32_op = OPC_SWRE;
17723 goto do_st_lr;
17724 case PREFE:
17725 /* Treat as no-op */
17726 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17727 /* hint codes 24-31 are reserved and signal RI */
17728 generate_exception(ctx, EXCP_RI);
17730 break;
17731 case CACHEE:
17732 /* Treat as no-op */
17733 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
17734 gen_cache_operation(ctx, rt, rs, offset);
17736 break;
17737 case SBE:
17738 mips32_op = OPC_SBE;
17739 goto do_st_lr;
17740 case SHE:
17741 mips32_op = OPC_SHE;
17742 goto do_st_lr;
17743 case SCE:
17744 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
17745 break;
17746 case SWE:
17747 mips32_op = OPC_SWE;
17748 goto do_st_lr;
17750 break;
17751 case PREF:
17752 /* Treat as no-op */
17753 if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
17754 /* hint codes 24-31 are reserved and signal RI */
17755 generate_exception(ctx, EXCP_RI);
17757 break;
17758 default:
17759 MIPS_INVAL("pool32c");
17760 generate_exception_end(ctx, EXCP_RI);
17761 break;
17763 break;
17764 case ADDI32: /* AUI, LUI */
17765 if (ctx->insn_flags & ISA_MIPS32R6) {
17766 /* AUI, LUI */
17767 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
17768 } else {
17769 /* ADDI32 */
17770 mips32_op = OPC_ADDI;
17771 goto do_addi;
17773 break;
17774 case ADDIU32:
17775 mips32_op = OPC_ADDIU;
17776 do_addi:
17777 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
17778 break;
17780 /* Logical operations */
17781 case ORI32:
17782 mips32_op = OPC_ORI;
17783 goto do_logici;
17784 case XORI32:
17785 mips32_op = OPC_XORI;
17786 goto do_logici;
17787 case ANDI32:
17788 mips32_op = OPC_ANDI;
17789 do_logici:
17790 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
17791 break;
17793 /* Set less than immediate */
17794 case SLTI32:
17795 mips32_op = OPC_SLTI;
17796 goto do_slti;
17797 case SLTIU32:
17798 mips32_op = OPC_SLTIU;
17799 do_slti:
17800 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
17801 break;
17802 case JALX32:
17803 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17804 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17805 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
17806 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17807 break;
17808 case JALS32: /* BOVC, BEQC, BEQZALC */
17809 if (ctx->insn_flags & ISA_MIPS32R6) {
17810 if (rs >= rt) {
17811 /* BOVC */
17812 mips32_op = OPC_BOVC;
17813 } else if (rs < rt && rs == 0) {
17814 /* BEQZALC */
17815 mips32_op = OPC_BEQZALC;
17816 } else {
17817 /* BEQC */
17818 mips32_op = OPC_BEQC;
17820 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17821 } else {
17822 /* JALS32 */
17823 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
17824 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
17825 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17827 break;
17828 case BEQ32: /* BC */
17829 if (ctx->insn_flags & ISA_MIPS32R6) {
17830 /* BC */
17831 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
17832 sextract32(ctx->opcode << 1, 0, 27));
17833 } else {
17834 /* BEQ32 */
17835 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
17837 break;
17838 case BNE32: /* BALC */
17839 if (ctx->insn_flags & ISA_MIPS32R6) {
17840 /* BALC */
17841 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
17842 sextract32(ctx->opcode << 1, 0, 27));
17843 } else {
17844 /* BNE32 */
17845 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
17847 break;
17848 case J32: /* BGTZC, BLTZC, BLTC */
17849 if (ctx->insn_flags & ISA_MIPS32R6) {
17850 if (rs == 0 && rt != 0) {
17851 /* BGTZC */
17852 mips32_op = OPC_BGTZC;
17853 } else if (rs != 0 && rt != 0 && rs == rt) {
17854 /* BLTZC */
17855 mips32_op = OPC_BLTZC;
17856 } else {
17857 /* BLTC */
17858 mips32_op = OPC_BLTC;
17860 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17861 } else {
17862 /* J32 */
17863 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
17864 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17866 break;
17867 case JAL32: /* BLEZC, BGEZC, BGEC */
17868 if (ctx->insn_flags & ISA_MIPS32R6) {
17869 if (rs == 0 && rt != 0) {
17870 /* BLEZC */
17871 mips32_op = OPC_BLEZC;
17872 } else if (rs != 0 && rt != 0 && rs == rt) {
17873 /* BGEZC */
17874 mips32_op = OPC_BGEZC;
17875 } else {
17876 /* BGEC */
17877 mips32_op = OPC_BGEC;
17879 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17880 } else {
17881 /* JAL32 */
17882 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
17883 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
17884 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
17886 break;
17887 /* Floating point (COP1) */
17888 case LWC132:
17889 mips32_op = OPC_LWC1;
17890 goto do_cop1;
17891 case LDC132:
17892 mips32_op = OPC_LDC1;
17893 goto do_cop1;
17894 case SWC132:
17895 mips32_op = OPC_SWC1;
17896 goto do_cop1;
17897 case SDC132:
17898 mips32_op = OPC_SDC1;
17899 do_cop1:
17900 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
17901 break;
17902 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17903 if (ctx->insn_flags & ISA_MIPS32R6) {
17904 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
17905 switch ((ctx->opcode >> 16) & 0x1f) {
17906 case ADDIUPC_00:
17907 case ADDIUPC_01:
17908 case ADDIUPC_02:
17909 case ADDIUPC_03:
17910 case ADDIUPC_04:
17911 case ADDIUPC_05:
17912 case ADDIUPC_06:
17913 case ADDIUPC_07:
17914 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
17915 break;
17916 case AUIPC:
17917 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
17918 break;
17919 case ALUIPC:
17920 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
17921 break;
17922 case LWPC_08:
17923 case LWPC_09:
17924 case LWPC_0A:
17925 case LWPC_0B:
17926 case LWPC_0C:
17927 case LWPC_0D:
17928 case LWPC_0E:
17929 case LWPC_0F:
17930 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
17931 break;
17932 default:
17933 generate_exception(ctx, EXCP_RI);
17934 break;
17936 } else {
17937 /* ADDIUPC */
17938 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
17939 offset = SIMM(ctx->opcode, 0, 23) << 2;
17941 gen_addiupc(ctx, reg, offset, 0, 0);
17943 break;
17944 case BNVC: /* BNEC, BNEZALC */
17945 check_insn(ctx, ISA_MIPS32R6);
17946 if (rs >= rt) {
17947 /* BNVC */
17948 mips32_op = OPC_BNVC;
17949 } else if (rs < rt && rs == 0) {
17950 /* BNEZALC */
17951 mips32_op = OPC_BNEZALC;
17952 } else {
17953 /* BNEC */
17954 mips32_op = OPC_BNEC;
17956 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17957 break;
17958 case R6_BNEZC: /* JIALC */
17959 check_insn(ctx, ISA_MIPS32R6);
17960 if (rt != 0) {
17961 /* BNEZC */
17962 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
17963 sextract32(ctx->opcode << 1, 0, 22));
17964 } else {
17965 /* JIALC */
17966 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
17968 break;
17969 case R6_BEQZC: /* JIC */
17970 check_insn(ctx, ISA_MIPS32R6);
17971 if (rt != 0) {
17972 /* BEQZC */
17973 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
17974 sextract32(ctx->opcode << 1, 0, 22));
17975 } else {
17976 /* JIC */
17977 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
17979 break;
17980 case BLEZALC: /* BGEZALC, BGEUC */
17981 check_insn(ctx, ISA_MIPS32R6);
17982 if (rs == 0 && rt != 0) {
17983 /* BLEZALC */
17984 mips32_op = OPC_BLEZALC;
17985 } else if (rs != 0 && rt != 0 && rs == rt) {
17986 /* BGEZALC */
17987 mips32_op = OPC_BGEZALC;
17988 } else {
17989 /* BGEUC */
17990 mips32_op = OPC_BGEUC;
17992 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
17993 break;
17994 case BGTZALC: /* BLTZALC, BLTUC */
17995 check_insn(ctx, ISA_MIPS32R6);
17996 if (rs == 0 && rt != 0) {
17997 /* BGTZALC */
17998 mips32_op = OPC_BGTZALC;
17999 } else if (rs != 0 && rt != 0 && rs == rt) {
18000 /* BLTZALC */
18001 mips32_op = OPC_BLTZALC;
18002 } else {
18003 /* BLTUC */
18004 mips32_op = OPC_BLTUC;
18006 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
18007 break;
18008 /* Loads and stores */
18009 case LB32:
18010 mips32_op = OPC_LB;
18011 goto do_ld;
18012 case LBU32:
18013 mips32_op = OPC_LBU;
18014 goto do_ld;
18015 case LH32:
18016 mips32_op = OPC_LH;
18017 goto do_ld;
18018 case LHU32:
18019 mips32_op = OPC_LHU;
18020 goto do_ld;
18021 case LW32:
18022 mips32_op = OPC_LW;
18023 goto do_ld;
18024 #ifdef TARGET_MIPS64
18025 case LD32:
18026 check_insn(ctx, ISA_MIPS3);
18027 check_mips_64(ctx);
18028 mips32_op = OPC_LD;
18029 goto do_ld;
18030 case SD32:
18031 check_insn(ctx, ISA_MIPS3);
18032 check_mips_64(ctx);
18033 mips32_op = OPC_SD;
18034 goto do_st;
18035 #endif
18036 case SB32:
18037 mips32_op = OPC_SB;
18038 goto do_st;
18039 case SH32:
18040 mips32_op = OPC_SH;
18041 goto do_st;
18042 case SW32:
18043 mips32_op = OPC_SW;
18044 goto do_st;
18045 do_ld:
18046 gen_ld(ctx, mips32_op, rt, rs, imm);
18047 break;
18048 do_st:
18049 gen_st(ctx, mips32_op, rt, rs, imm);
18050 break;
18051 default:
18052 generate_exception_end(ctx, EXCP_RI);
18053 break;
18057 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
18059 uint32_t op;
18061 /* make sure instructions are on a halfword boundary */
18062 if (ctx->base.pc_next & 0x1) {
18063 env->CP0_BadVAddr = ctx->base.pc_next;
18064 generate_exception_end(ctx, EXCP_AdEL);
18065 return 2;
18068 op = (ctx->opcode >> 10) & 0x3f;
18069 /* Enforce properly-sized instructions in a delay slot */
18070 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
18071 switch (op & 0x7) { /* MSB-3..MSB-5 */
18072 case 0:
18073 /* POOL32A, POOL32B, POOL32I, POOL32C */
18074 case 4:
18075 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
18076 case 5:
18077 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
18078 case 6:
18079 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
18080 case 7:
18081 /* LB32, LH32, LWC132, LDC132, LW32 */
18082 if (ctx->hflags & MIPS_HFLAG_BDS16) {
18083 generate_exception_end(ctx, EXCP_RI);
18084 return 2;
18086 break;
18087 case 1:
18088 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
18089 case 2:
18090 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
18091 case 3:
18092 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
18093 if (ctx->hflags & MIPS_HFLAG_BDS32) {
18094 generate_exception_end(ctx, EXCP_RI);
18095 return 2;
18097 break;
18101 switch (op) {
18102 case POOL16A:
18104 int rd = mmreg(uMIPS_RD(ctx->opcode));
18105 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
18106 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
18107 uint32_t opc = 0;
18109 switch (ctx->opcode & 0x1) {
18110 case ADDU16:
18111 opc = OPC_ADDU;
18112 break;
18113 case SUBU16:
18114 opc = OPC_SUBU;
18115 break;
18117 if (ctx->insn_flags & ISA_MIPS32R6) {
18119 * In the Release 6, the register number location in
18120 * the instruction encoding has changed.
18122 gen_arith(ctx, opc, rs1, rd, rs2);
18123 } else {
18124 gen_arith(ctx, opc, rd, rs1, rs2);
18127 break;
18128 case POOL16B:
18130 int rd = mmreg(uMIPS_RD(ctx->opcode));
18131 int rs = mmreg(uMIPS_RS(ctx->opcode));
18132 int amount = (ctx->opcode >> 1) & 0x7;
18133 uint32_t opc = 0;
18134 amount = amount == 0 ? 8 : amount;
18136 switch (ctx->opcode & 0x1) {
18137 case SLL16:
18138 opc = OPC_SLL;
18139 break;
18140 case SRL16:
18141 opc = OPC_SRL;
18142 break;
18145 gen_shift_imm(ctx, opc, rd, rs, amount);
18147 break;
18148 case POOL16C:
18149 if (ctx->insn_flags & ISA_MIPS32R6) {
18150 gen_pool16c_r6_insn(ctx);
18151 } else {
18152 gen_pool16c_insn(ctx);
18154 break;
18155 case LWGP16:
18157 int rd = mmreg(uMIPS_RD(ctx->opcode));
18158 int rb = 28; /* GP */
18159 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
18161 gen_ld(ctx, OPC_LW, rd, rb, offset);
18163 break;
18164 case POOL16F:
18165 check_insn_opc_removed(ctx, ISA_MIPS32R6);
18166 if (ctx->opcode & 1) {
18167 generate_exception_end(ctx, EXCP_RI);
18168 } else {
18169 /* MOVEP */
18170 int enc_dest = uMIPS_RD(ctx->opcode);
18171 int enc_rt = uMIPS_RS2(ctx->opcode);
18172 int enc_rs = uMIPS_RS1(ctx->opcode);
18173 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
18175 break;
18176 case LBU16:
18178 int rd = mmreg(uMIPS_RD(ctx->opcode));
18179 int rb = mmreg(uMIPS_RS(ctx->opcode));
18180 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18181 offset = (offset == 0xf ? -1 : offset);
18183 gen_ld(ctx, OPC_LBU, rd, rb, offset);
18185 break;
18186 case LHU16:
18188 int rd = mmreg(uMIPS_RD(ctx->opcode));
18189 int rb = mmreg(uMIPS_RS(ctx->opcode));
18190 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18192 gen_ld(ctx, OPC_LHU, rd, rb, offset);
18194 break;
18195 case LWSP16:
18197 int rd = (ctx->opcode >> 5) & 0x1f;
18198 int rb = 29; /* SP */
18199 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18201 gen_ld(ctx, OPC_LW, rd, rb, offset);
18203 break;
18204 case LW16:
18206 int rd = mmreg(uMIPS_RD(ctx->opcode));
18207 int rb = mmreg(uMIPS_RS(ctx->opcode));
18208 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18210 gen_ld(ctx, OPC_LW, rd, rb, offset);
18212 break;
18213 case SB16:
18215 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18216 int rb = mmreg(uMIPS_RS(ctx->opcode));
18217 int16_t offset = ZIMM(ctx->opcode, 0, 4);
18219 gen_st(ctx, OPC_SB, rd, rb, offset);
18221 break;
18222 case SH16:
18224 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18225 int rb = mmreg(uMIPS_RS(ctx->opcode));
18226 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
18228 gen_st(ctx, OPC_SH, rd, rb, offset);
18230 break;
18231 case SWSP16:
18233 int rd = (ctx->opcode >> 5) & 0x1f;
18234 int rb = 29; /* SP */
18235 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
18237 gen_st(ctx, OPC_SW, rd, rb, offset);
18239 break;
18240 case SW16:
18242 int rd = mmreg2(uMIPS_RD(ctx->opcode));
18243 int rb = mmreg(uMIPS_RS(ctx->opcode));
18244 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
18246 gen_st(ctx, OPC_SW, rd, rb, offset);
18248 break;
18249 case MOVE16:
18251 int rd = uMIPS_RD5(ctx->opcode);
18252 int rs = uMIPS_RS5(ctx->opcode);
18254 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
18256 break;
18257 case ANDI16:
18258 gen_andi16(ctx);
18259 break;
18260 case POOL16D:
18261 switch (ctx->opcode & 0x1) {
18262 case ADDIUS5:
18263 gen_addius5(ctx);
18264 break;
18265 case ADDIUSP:
18266 gen_addiusp(ctx);
18267 break;
18269 break;
18270 case POOL16E:
18271 switch (ctx->opcode & 0x1) {
18272 case ADDIUR2:
18273 gen_addiur2(ctx);
18274 break;
18275 case ADDIUR1SP:
18276 gen_addiur1sp(ctx);
18277 break;
18279 break;
18280 case B16: /* BC16 */
18281 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
18282 sextract32(ctx->opcode, 0, 10) << 1,
18283 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
18284 break;
18285 case BNEZ16: /* BNEZC16 */
18286 case BEQZ16: /* BEQZC16 */
18287 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
18288 mmreg(uMIPS_RD(ctx->opcode)),
18289 0, sextract32(ctx->opcode, 0, 7) << 1,
18290 (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
18292 break;
18293 case LI16:
18295 int reg = mmreg(uMIPS_RD(ctx->opcode));
18296 int imm = ZIMM(ctx->opcode, 0, 7);
18298 imm = (imm == 0x7f ? -1 : imm);
18299 tcg_gen_movi_tl(cpu_gpr[reg], imm);
18301 break;
18302 case RES_29:
18303 case RES_31:
18304 case RES_39:
18305 generate_exception_end(ctx, EXCP_RI);
18306 break;
18307 default:
18308 decode_micromips32_opc(env, ctx);
18309 return 4;
18312 return 2;
18317 * nanoMIPS opcodes
18321 /* MAJOR, P16, and P32 pools opcodes */
18322 enum {
18323 NM_P_ADDIU = 0x00,
18324 NM_ADDIUPC = 0x01,
18325 NM_MOVE_BALC = 0x02,
18326 NM_P16_MV = 0x04,
18327 NM_LW16 = 0x05,
18328 NM_BC16 = 0x06,
18329 NM_P16_SR = 0x07,
18331 NM_POOL32A = 0x08,
18332 NM_P_BAL = 0x0a,
18333 NM_P16_SHIFT = 0x0c,
18334 NM_LWSP16 = 0x0d,
18335 NM_BALC16 = 0x0e,
18336 NM_P16_4X4 = 0x0f,
18338 NM_P_GP_W = 0x10,
18339 NM_P_GP_BH = 0x11,
18340 NM_P_J = 0x12,
18341 NM_P16C = 0x14,
18342 NM_LWGP16 = 0x15,
18343 NM_P16_LB = 0x17,
18345 NM_P48I = 0x18,
18346 NM_P16_A1 = 0x1c,
18347 NM_LW4X4 = 0x1d,
18348 NM_P16_LH = 0x1f,
18350 NM_P_U12 = 0x20,
18351 NM_P_LS_U12 = 0x21,
18352 NM_P_BR1 = 0x22,
18353 NM_P16_A2 = 0x24,
18354 NM_SW16 = 0x25,
18355 NM_BEQZC16 = 0x26,
18357 NM_POOL32F = 0x28,
18358 NM_P_LS_S9 = 0x29,
18359 NM_P_BR2 = 0x2a,
18361 NM_P16_ADDU = 0x2c,
18362 NM_SWSP16 = 0x2d,
18363 NM_BNEZC16 = 0x2e,
18364 NM_MOVEP = 0x2f,
18366 NM_POOL32S = 0x30,
18367 NM_P_BRI = 0x32,
18368 NM_LI16 = 0x34,
18369 NM_SWGP16 = 0x35,
18370 NM_P16_BR = 0x36,
18372 NM_P_LUI = 0x38,
18373 NM_ANDI16 = 0x3c,
18374 NM_SW4X4 = 0x3d,
18375 NM_MOVEPREV = 0x3f,
18378 /* POOL32A instruction pool */
18379 enum {
18380 NM_POOL32A0 = 0x00,
18381 NM_SPECIAL2 = 0x01,
18382 NM_COP2_1 = 0x02,
18383 NM_UDI = 0x03,
18384 NM_POOL32A5 = 0x05,
18385 NM_POOL32A7 = 0x07,
18388 /* P.GP.W instruction pool */
18389 enum {
18390 NM_ADDIUGP_W = 0x00,
18391 NM_LWGP = 0x02,
18392 NM_SWGP = 0x03,
18395 /* P48I instruction pool */
18396 enum {
18397 NM_LI48 = 0x00,
18398 NM_ADDIU48 = 0x01,
18399 NM_ADDIUGP48 = 0x02,
18400 NM_ADDIUPC48 = 0x03,
18401 NM_LWPC48 = 0x0b,
18402 NM_SWPC48 = 0x0f,
18405 /* P.U12 instruction pool */
18406 enum {
18407 NM_ORI = 0x00,
18408 NM_XORI = 0x01,
18409 NM_ANDI = 0x02,
18410 NM_P_SR = 0x03,
18411 NM_SLTI = 0x04,
18412 NM_SLTIU = 0x05,
18413 NM_SEQI = 0x06,
18414 NM_ADDIUNEG = 0x08,
18415 NM_P_SHIFT = 0x0c,
18416 NM_P_ROTX = 0x0d,
18417 NM_P_INS = 0x0e,
18418 NM_P_EXT = 0x0f,
18421 /* POOL32F instruction pool */
18422 enum {
18423 NM_POOL32F_0 = 0x00,
18424 NM_POOL32F_3 = 0x03,
18425 NM_POOL32F_5 = 0x05,
18428 /* POOL32S instruction pool */
18429 enum {
18430 NM_POOL32S_0 = 0x00,
18431 NM_POOL32S_4 = 0x04,
18434 /* P.LUI instruction pool */
18435 enum {
18436 NM_LUI = 0x00,
18437 NM_ALUIPC = 0x01,
18440 /* P.GP.BH instruction pool */
18441 enum {
18442 NM_LBGP = 0x00,
18443 NM_SBGP = 0x01,
18444 NM_LBUGP = 0x02,
18445 NM_ADDIUGP_B = 0x03,
18446 NM_P_GP_LH = 0x04,
18447 NM_P_GP_SH = 0x05,
18448 NM_P_GP_CP1 = 0x06,
18451 /* P.LS.U12 instruction pool */
18452 enum {
18453 NM_LB = 0x00,
18454 NM_SB = 0x01,
18455 NM_LBU = 0x02,
18456 NM_P_PREFU12 = 0x03,
18457 NM_LH = 0x04,
18458 NM_SH = 0x05,
18459 NM_LHU = 0x06,
18460 NM_LWU = 0x07,
18461 NM_LW = 0x08,
18462 NM_SW = 0x09,
18463 NM_LWC1 = 0x0a,
18464 NM_SWC1 = 0x0b,
18465 NM_LDC1 = 0x0e,
18466 NM_SDC1 = 0x0f,
18469 /* P.LS.S9 instruction pool */
18470 enum {
18471 NM_P_LS_S0 = 0x00,
18472 NM_P_LS_S1 = 0x01,
18473 NM_P_LS_E0 = 0x02,
18474 NM_P_LS_WM = 0x04,
18475 NM_P_LS_UAWM = 0x05,
18478 /* P.BAL instruction pool */
18479 enum {
18480 NM_BC = 0x00,
18481 NM_BALC = 0x01,
18484 /* P.J instruction pool */
18485 enum {
18486 NM_JALRC = 0x00,
18487 NM_JALRC_HB = 0x01,
18488 NM_P_BALRSC = 0x08,
18491 /* P.BR1 instruction pool */
18492 enum {
18493 NM_BEQC = 0x00,
18494 NM_P_BR3A = 0x01,
18495 NM_BGEC = 0x02,
18496 NM_BGEUC = 0x03,
18499 /* P.BR2 instruction pool */
18500 enum {
18501 NM_BNEC = 0x00,
18502 NM_BLTC = 0x02,
18503 NM_BLTUC = 0x03,
18506 /* P.BRI instruction pool */
18507 enum {
18508 NM_BEQIC = 0x00,
18509 NM_BBEQZC = 0x01,
18510 NM_BGEIC = 0x02,
18511 NM_BGEIUC = 0x03,
18512 NM_BNEIC = 0x04,
18513 NM_BBNEZC = 0x05,
18514 NM_BLTIC = 0x06,
18515 NM_BLTIUC = 0x07,
18518 /* P16.SHIFT instruction pool */
18519 enum {
18520 NM_SLL16 = 0x00,
18521 NM_SRL16 = 0x01,
18524 /* POOL16C instruction pool */
18525 enum {
18526 NM_POOL16C_0 = 0x00,
18527 NM_LWXS16 = 0x01,
18530 /* P16.A1 instruction pool */
18531 enum {
18532 NM_ADDIUR1SP = 0x01,
18535 /* P16.A2 instruction pool */
18536 enum {
18537 NM_ADDIUR2 = 0x00,
18538 NM_P_ADDIURS5 = 0x01,
18541 /* P16.ADDU instruction pool */
18542 enum {
18543 NM_ADDU16 = 0x00,
18544 NM_SUBU16 = 0x01,
18547 /* P16.SR instruction pool */
18548 enum {
18549 NM_SAVE16 = 0x00,
18550 NM_RESTORE_JRC16 = 0x01,
18553 /* P16.4X4 instruction pool */
18554 enum {
18555 NM_ADDU4X4 = 0x00,
18556 NM_MUL4X4 = 0x01,
18559 /* P16.LB instruction pool */
18560 enum {
18561 NM_LB16 = 0x00,
18562 NM_SB16 = 0x01,
18563 NM_LBU16 = 0x02,
18566 /* P16.LH instruction pool */
18567 enum {
18568 NM_LH16 = 0x00,
18569 NM_SH16 = 0x01,
18570 NM_LHU16 = 0x02,
18573 /* P.RI instruction pool */
18574 enum {
18575 NM_SIGRIE = 0x00,
18576 NM_P_SYSCALL = 0x01,
18577 NM_BREAK = 0x02,
18578 NM_SDBBP = 0x03,
18581 /* POOL32A0 instruction pool */
18582 enum {
18583 NM_P_TRAP = 0x00,
18584 NM_SEB = 0x01,
18585 NM_SLLV = 0x02,
18586 NM_MUL = 0x03,
18587 NM_MFC0 = 0x06,
18588 NM_MFHC0 = 0x07,
18589 NM_SEH = 0x09,
18590 NM_SRLV = 0x0a,
18591 NM_MUH = 0x0b,
18592 NM_MTC0 = 0x0e,
18593 NM_MTHC0 = 0x0f,
18594 NM_SRAV = 0x12,
18595 NM_MULU = 0x13,
18596 NM_ROTRV = 0x1a,
18597 NM_MUHU = 0x1b,
18598 NM_ADD = 0x22,
18599 NM_DIV = 0x23,
18600 NM_ADDU = 0x2a,
18601 NM_MOD = 0x2b,
18602 NM_SUB = 0x32,
18603 NM_DIVU = 0x33,
18604 NM_RDHWR = 0x38,
18605 NM_SUBU = 0x3a,
18606 NM_MODU = 0x3b,
18607 NM_P_CMOVE = 0x42,
18608 NM_FORK = 0x45,
18609 NM_MFTR = 0x46,
18610 NM_MFHTR = 0x47,
18611 NM_AND = 0x4a,
18612 NM_YIELD = 0x4d,
18613 NM_MTTR = 0x4e,
18614 NM_MTHTR = 0x4f,
18615 NM_OR = 0x52,
18616 NM_D_E_MT_VPE = 0x56,
18617 NM_NOR = 0x5a,
18618 NM_XOR = 0x62,
18619 NM_SLT = 0x6a,
18620 NM_P_SLTU = 0x72,
18621 NM_SOV = 0x7a,
18624 /* CRC32 instruction pool */
18625 enum {
18626 NM_CRC32B = 0x00,
18627 NM_CRC32H = 0x01,
18628 NM_CRC32W = 0x02,
18629 NM_CRC32CB = 0x04,
18630 NM_CRC32CH = 0x05,
18631 NM_CRC32CW = 0x06,
18634 /* POOL32A5 instruction pool */
18635 enum {
18636 NM_CMP_EQ_PH = 0x00,
18637 NM_CMP_LT_PH = 0x08,
18638 NM_CMP_LE_PH = 0x10,
18639 NM_CMPGU_EQ_QB = 0x18,
18640 NM_CMPGU_LT_QB = 0x20,
18641 NM_CMPGU_LE_QB = 0x28,
18642 NM_CMPGDU_EQ_QB = 0x30,
18643 NM_CMPGDU_LT_QB = 0x38,
18644 NM_CMPGDU_LE_QB = 0x40,
18645 NM_CMPU_EQ_QB = 0x48,
18646 NM_CMPU_LT_QB = 0x50,
18647 NM_CMPU_LE_QB = 0x58,
18648 NM_ADDQ_S_W = 0x60,
18649 NM_SUBQ_S_W = 0x68,
18650 NM_ADDSC = 0x70,
18651 NM_ADDWC = 0x78,
18653 NM_ADDQ_S_PH = 0x01,
18654 NM_ADDQH_R_PH = 0x09,
18655 NM_ADDQH_R_W = 0x11,
18656 NM_ADDU_S_QB = 0x19,
18657 NM_ADDU_S_PH = 0x21,
18658 NM_ADDUH_R_QB = 0x29,
18659 NM_SHRAV_R_PH = 0x31,
18660 NM_SHRAV_R_QB = 0x39,
18661 NM_SUBQ_S_PH = 0x41,
18662 NM_SUBQH_R_PH = 0x49,
18663 NM_SUBQH_R_W = 0x51,
18664 NM_SUBU_S_QB = 0x59,
18665 NM_SUBU_S_PH = 0x61,
18666 NM_SUBUH_R_QB = 0x69,
18667 NM_SHLLV_S_PH = 0x71,
18668 NM_PRECR_SRA_R_PH_W = 0x79,
18670 NM_MULEU_S_PH_QBL = 0x12,
18671 NM_MULEU_S_PH_QBR = 0x1a,
18672 NM_MULQ_RS_PH = 0x22,
18673 NM_MULQ_S_PH = 0x2a,
18674 NM_MULQ_RS_W = 0x32,
18675 NM_MULQ_S_W = 0x3a,
18676 NM_APPEND = 0x42,
18677 NM_MODSUB = 0x52,
18678 NM_SHRAV_R_W = 0x5a,
18679 NM_SHRLV_PH = 0x62,
18680 NM_SHRLV_QB = 0x6a,
18681 NM_SHLLV_QB = 0x72,
18682 NM_SHLLV_S_W = 0x7a,
18684 NM_SHILO = 0x03,
18686 NM_MULEQ_S_W_PHL = 0x04,
18687 NM_MULEQ_S_W_PHR = 0x0c,
18689 NM_MUL_S_PH = 0x05,
18690 NM_PRECR_QB_PH = 0x0d,
18691 NM_PRECRQ_QB_PH = 0x15,
18692 NM_PRECRQ_PH_W = 0x1d,
18693 NM_PRECRQ_RS_PH_W = 0x25,
18694 NM_PRECRQU_S_QB_PH = 0x2d,
18695 NM_PACKRL_PH = 0x35,
18696 NM_PICK_QB = 0x3d,
18697 NM_PICK_PH = 0x45,
18699 NM_SHRA_R_W = 0x5e,
18700 NM_SHRA_R_PH = 0x66,
18701 NM_SHLL_S_PH = 0x76,
18702 NM_SHLL_S_W = 0x7e,
18704 NM_REPL_PH = 0x07
18707 /* POOL32A7 instruction pool */
18708 enum {
18709 NM_P_LSX = 0x00,
18710 NM_LSA = 0x01,
18711 NM_EXTW = 0x03,
18712 NM_POOL32AXF = 0x07,
18715 /* P.SR instruction pool */
18716 enum {
18717 NM_PP_SR = 0x00,
18718 NM_P_SR_F = 0x01,
18721 /* P.SHIFT instruction pool */
18722 enum {
18723 NM_P_SLL = 0x00,
18724 NM_SRL = 0x02,
18725 NM_SRA = 0x04,
18726 NM_ROTR = 0x06,
18729 /* P.ROTX instruction pool */
18730 enum {
18731 NM_ROTX = 0x00,
18734 /* P.INS instruction pool */
18735 enum {
18736 NM_INS = 0x00,
18739 /* P.EXT instruction pool */
18740 enum {
18741 NM_EXT = 0x00,
18744 /* POOL32F_0 (fmt) instruction pool */
18745 enum {
18746 NM_RINT_S = 0x04,
18747 NM_RINT_D = 0x44,
18748 NM_ADD_S = 0x06,
18749 NM_SELEQZ_S = 0x07,
18750 NM_SELEQZ_D = 0x47,
18751 NM_CLASS_S = 0x0c,
18752 NM_CLASS_D = 0x4c,
18753 NM_SUB_S = 0x0e,
18754 NM_SELNEZ_S = 0x0f,
18755 NM_SELNEZ_D = 0x4f,
18756 NM_MUL_S = 0x16,
18757 NM_SEL_S = 0x17,
18758 NM_SEL_D = 0x57,
18759 NM_DIV_S = 0x1e,
18760 NM_ADD_D = 0x26,
18761 NM_SUB_D = 0x2e,
18762 NM_MUL_D = 0x36,
18763 NM_MADDF_S = 0x37,
18764 NM_MADDF_D = 0x77,
18765 NM_DIV_D = 0x3e,
18766 NM_MSUBF_S = 0x3f,
18767 NM_MSUBF_D = 0x7f,
18770 /* POOL32F_3 instruction pool */
18771 enum {
18772 NM_MIN_FMT = 0x00,
18773 NM_MAX_FMT = 0x01,
18774 NM_MINA_FMT = 0x04,
18775 NM_MAXA_FMT = 0x05,
18776 NM_POOL32FXF = 0x07,
18779 /* POOL32F_5 instruction pool */
18780 enum {
18781 NM_CMP_CONDN_S = 0x00,
18782 NM_CMP_CONDN_D = 0x02,
18785 /* P.GP.LH instruction pool */
18786 enum {
18787 NM_LHGP = 0x00,
18788 NM_LHUGP = 0x01,
18791 /* P.GP.SH instruction pool */
18792 enum {
18793 NM_SHGP = 0x00,
18796 /* P.GP.CP1 instruction pool */
18797 enum {
18798 NM_LWC1GP = 0x00,
18799 NM_SWC1GP = 0x01,
18800 NM_LDC1GP = 0x02,
18801 NM_SDC1GP = 0x03,
18804 /* P.LS.S0 instruction pool */
18805 enum {
18806 NM_LBS9 = 0x00,
18807 NM_LHS9 = 0x04,
18808 NM_LWS9 = 0x08,
18809 NM_LDS9 = 0x0c,
18811 NM_SBS9 = 0x01,
18812 NM_SHS9 = 0x05,
18813 NM_SWS9 = 0x09,
18814 NM_SDS9 = 0x0d,
18816 NM_LBUS9 = 0x02,
18817 NM_LHUS9 = 0x06,
18818 NM_LWC1S9 = 0x0a,
18819 NM_LDC1S9 = 0x0e,
18821 NM_P_PREFS9 = 0x03,
18822 NM_LWUS9 = 0x07,
18823 NM_SWC1S9 = 0x0b,
18824 NM_SDC1S9 = 0x0f,
18827 /* P.LS.S1 instruction pool */
18828 enum {
18829 NM_ASET_ACLR = 0x02,
18830 NM_UALH = 0x04,
18831 NM_UASH = 0x05,
18832 NM_CACHE = 0x07,
18833 NM_P_LL = 0x0a,
18834 NM_P_SC = 0x0b,
18837 /* P.LS.E0 instruction pool */
18838 enum {
18839 NM_LBE = 0x00,
18840 NM_SBE = 0x01,
18841 NM_LBUE = 0x02,
18842 NM_P_PREFE = 0x03,
18843 NM_LHE = 0x04,
18844 NM_SHE = 0x05,
18845 NM_LHUE = 0x06,
18846 NM_CACHEE = 0x07,
18847 NM_LWE = 0x08,
18848 NM_SWE = 0x09,
18849 NM_P_LLE = 0x0a,
18850 NM_P_SCE = 0x0b,
18853 /* P.PREFE instruction pool */
18854 enum {
18855 NM_SYNCIE = 0x00,
18856 NM_PREFE = 0x01,
18859 /* P.LLE instruction pool */
18860 enum {
18861 NM_LLE = 0x00,
18862 NM_LLWPE = 0x01,
18865 /* P.SCE instruction pool */
18866 enum {
18867 NM_SCE = 0x00,
18868 NM_SCWPE = 0x01,
18871 /* P.LS.WM instruction pool */
18872 enum {
18873 NM_LWM = 0x00,
18874 NM_SWM = 0x01,
18877 /* P.LS.UAWM instruction pool */
18878 enum {
18879 NM_UALWM = 0x00,
18880 NM_UASWM = 0x01,
18883 /* P.BR3A instruction pool */
18884 enum {
18885 NM_BC1EQZC = 0x00,
18886 NM_BC1NEZC = 0x01,
18887 NM_BC2EQZC = 0x02,
18888 NM_BC2NEZC = 0x03,
18889 NM_BPOSGE32C = 0x04,
18892 /* P16.RI instruction pool */
18893 enum {
18894 NM_P16_SYSCALL = 0x01,
18895 NM_BREAK16 = 0x02,
18896 NM_SDBBP16 = 0x03,
18899 /* POOL16C_0 instruction pool */
18900 enum {
18901 NM_POOL16C_00 = 0x00,
18904 /* P16.JRC instruction pool */
18905 enum {
18906 NM_JRC = 0x00,
18907 NM_JALRC16 = 0x01,
18910 /* P.SYSCALL instruction pool */
18911 enum {
18912 NM_SYSCALL = 0x00,
18913 NM_HYPCALL = 0x01,
18916 /* P.TRAP instruction pool */
18917 enum {
18918 NM_TEQ = 0x00,
18919 NM_TNE = 0x01,
18922 /* P.CMOVE instruction pool */
18923 enum {
18924 NM_MOVZ = 0x00,
18925 NM_MOVN = 0x01,
18928 /* POOL32Axf instruction pool */
18929 enum {
18930 NM_POOL32AXF_1 = 0x01,
18931 NM_POOL32AXF_2 = 0x02,
18932 NM_POOL32AXF_4 = 0x04,
18933 NM_POOL32AXF_5 = 0x05,
18934 NM_POOL32AXF_7 = 0x07,
18937 /* POOL32Axf_1 instruction pool */
18938 enum {
18939 NM_POOL32AXF_1_0 = 0x00,
18940 NM_POOL32AXF_1_1 = 0x01,
18941 NM_POOL32AXF_1_3 = 0x03,
18942 NM_POOL32AXF_1_4 = 0x04,
18943 NM_POOL32AXF_1_5 = 0x05,
18944 NM_POOL32AXF_1_7 = 0x07,
18947 /* POOL32Axf_2 instruction pool */
18948 enum {
18949 NM_POOL32AXF_2_0_7 = 0x00,
18950 NM_POOL32AXF_2_8_15 = 0x01,
18951 NM_POOL32AXF_2_16_23 = 0x02,
18952 NM_POOL32AXF_2_24_31 = 0x03,
18955 /* POOL32Axf_7 instruction pool */
18956 enum {
18957 NM_SHRA_R_QB = 0x0,
18958 NM_SHRL_PH = 0x1,
18959 NM_REPL_QB = 0x2,
18962 /* POOL32Axf_1_0 instruction pool */
18963 enum {
18964 NM_MFHI = 0x0,
18965 NM_MFLO = 0x1,
18966 NM_MTHI = 0x2,
18967 NM_MTLO = 0x3,
18970 /* POOL32Axf_1_1 instruction pool */
18971 enum {
18972 NM_MTHLIP = 0x0,
18973 NM_SHILOV = 0x1,
18976 /* POOL32Axf_1_3 instruction pool */
18977 enum {
18978 NM_RDDSP = 0x0,
18979 NM_WRDSP = 0x1,
18980 NM_EXTP = 0x2,
18981 NM_EXTPDP = 0x3,
18984 /* POOL32Axf_1_4 instruction pool */
18985 enum {
18986 NM_SHLL_QB = 0x0,
18987 NM_SHRL_QB = 0x1,
18990 /* POOL32Axf_1_5 instruction pool */
18991 enum {
18992 NM_MAQ_S_W_PHR = 0x0,
18993 NM_MAQ_S_W_PHL = 0x1,
18994 NM_MAQ_SA_W_PHR = 0x2,
18995 NM_MAQ_SA_W_PHL = 0x3,
18998 /* POOL32Axf_1_7 instruction pool */
18999 enum {
19000 NM_EXTR_W = 0x0,
19001 NM_EXTR_R_W = 0x1,
19002 NM_EXTR_RS_W = 0x2,
19003 NM_EXTR_S_H = 0x3,
19006 /* POOL32Axf_2_0_7 instruction pool */
19007 enum {
19008 NM_DPA_W_PH = 0x0,
19009 NM_DPAQ_S_W_PH = 0x1,
19010 NM_DPS_W_PH = 0x2,
19011 NM_DPSQ_S_W_PH = 0x3,
19012 NM_BALIGN = 0x4,
19013 NM_MADD = 0x5,
19014 NM_MULT = 0x6,
19015 NM_EXTRV_W = 0x7,
19018 /* POOL32Axf_2_8_15 instruction pool */
19019 enum {
19020 NM_DPAX_W_PH = 0x0,
19021 NM_DPAQ_SA_L_W = 0x1,
19022 NM_DPSX_W_PH = 0x2,
19023 NM_DPSQ_SA_L_W = 0x3,
19024 NM_MADDU = 0x5,
19025 NM_MULTU = 0x6,
19026 NM_EXTRV_R_W = 0x7,
19029 /* POOL32Axf_2_16_23 instruction pool */
19030 enum {
19031 NM_DPAU_H_QBL = 0x0,
19032 NM_DPAQX_S_W_PH = 0x1,
19033 NM_DPSU_H_QBL = 0x2,
19034 NM_DPSQX_S_W_PH = 0x3,
19035 NM_EXTPV = 0x4,
19036 NM_MSUB = 0x5,
19037 NM_MULSA_W_PH = 0x6,
19038 NM_EXTRV_RS_W = 0x7,
19041 /* POOL32Axf_2_24_31 instruction pool */
19042 enum {
19043 NM_DPAU_H_QBR = 0x0,
19044 NM_DPAQX_SA_W_PH = 0x1,
19045 NM_DPSU_H_QBR = 0x2,
19046 NM_DPSQX_SA_W_PH = 0x3,
19047 NM_EXTPDPV = 0x4,
19048 NM_MSUBU = 0x5,
19049 NM_MULSAQ_S_W_PH = 0x6,
19050 NM_EXTRV_S_H = 0x7,
19053 /* POOL32Axf_{4, 5} instruction pool */
19054 enum {
19055 NM_CLO = 0x25,
19056 NM_CLZ = 0x2d,
19058 NM_TLBP = 0x01,
19059 NM_TLBR = 0x09,
19060 NM_TLBWI = 0x11,
19061 NM_TLBWR = 0x19,
19062 NM_TLBINV = 0x03,
19063 NM_TLBINVF = 0x0b,
19064 NM_DI = 0x23,
19065 NM_EI = 0x2b,
19066 NM_RDPGPR = 0x70,
19067 NM_WRPGPR = 0x78,
19068 NM_WAIT = 0x61,
19069 NM_DERET = 0x71,
19070 NM_ERETX = 0x79,
19072 /* nanoMIPS DSP instructions */
19073 NM_ABSQ_S_QB = 0x00,
19074 NM_ABSQ_S_PH = 0x08,
19075 NM_ABSQ_S_W = 0x10,
19076 NM_PRECEQ_W_PHL = 0x28,
19077 NM_PRECEQ_W_PHR = 0x30,
19078 NM_PRECEQU_PH_QBL = 0x38,
19079 NM_PRECEQU_PH_QBR = 0x48,
19080 NM_PRECEU_PH_QBL = 0x58,
19081 NM_PRECEU_PH_QBR = 0x68,
19082 NM_PRECEQU_PH_QBLA = 0x39,
19083 NM_PRECEQU_PH_QBRA = 0x49,
19084 NM_PRECEU_PH_QBLA = 0x59,
19085 NM_PRECEU_PH_QBRA = 0x69,
19086 NM_REPLV_PH = 0x01,
19087 NM_REPLV_QB = 0x09,
19088 NM_BITREV = 0x18,
19089 NM_INSV = 0x20,
19090 NM_RADDU_W_QB = 0x78,
19092 NM_BITSWAP = 0x05,
19093 NM_WSBH = 0x3d,
19096 /* PP.SR instruction pool */
19097 enum {
19098 NM_SAVE = 0x00,
19099 NM_RESTORE = 0x02,
19100 NM_RESTORE_JRC = 0x03,
19103 /* P.SR.F instruction pool */
19104 enum {
19105 NM_SAVEF = 0x00,
19106 NM_RESTOREF = 0x01,
19109 /* P16.SYSCALL instruction pool */
19110 enum {
19111 NM_SYSCALL16 = 0x00,
19112 NM_HYPCALL16 = 0x01,
19115 /* POOL16C_00 instruction pool */
19116 enum {
19117 NM_NOT16 = 0x00,
19118 NM_XOR16 = 0x01,
19119 NM_AND16 = 0x02,
19120 NM_OR16 = 0x03,
19123 /* PP.LSX and PP.LSXS instruction pool */
19124 enum {
19125 NM_LBX = 0x00,
19126 NM_LHX = 0x04,
19127 NM_LWX = 0x08,
19128 NM_LDX = 0x0c,
19130 NM_SBX = 0x01,
19131 NM_SHX = 0x05,
19132 NM_SWX = 0x09,
19133 NM_SDX = 0x0d,
19135 NM_LBUX = 0x02,
19136 NM_LHUX = 0x06,
19137 NM_LWC1X = 0x0a,
19138 NM_LDC1X = 0x0e,
19140 NM_LWUX = 0x07,
19141 NM_SWC1X = 0x0b,
19142 NM_SDC1X = 0x0f,
19144 NM_LHXS = 0x04,
19145 NM_LWXS = 0x08,
19146 NM_LDXS = 0x0c,
19148 NM_SHXS = 0x05,
19149 NM_SWXS = 0x09,
19150 NM_SDXS = 0x0d,
19152 NM_LHUXS = 0x06,
19153 NM_LWC1XS = 0x0a,
19154 NM_LDC1XS = 0x0e,
19156 NM_LWUXS = 0x07,
19157 NM_SWC1XS = 0x0b,
19158 NM_SDC1XS = 0x0f,
19161 /* ERETx instruction pool */
19162 enum {
19163 NM_ERET = 0x00,
19164 NM_ERETNC = 0x01,
19167 /* POOL32FxF_{0, 1} insturction pool */
19168 enum {
19169 NM_CFC1 = 0x40,
19170 NM_CTC1 = 0x60,
19171 NM_MFC1 = 0x80,
19172 NM_MTC1 = 0xa0,
19173 NM_MFHC1 = 0xc0,
19174 NM_MTHC1 = 0xe0,
19176 NM_CVT_S_PL = 0x84,
19177 NM_CVT_S_PU = 0xa4,
19179 NM_CVT_L_S = 0x004,
19180 NM_CVT_L_D = 0x104,
19181 NM_CVT_W_S = 0x024,
19182 NM_CVT_W_D = 0x124,
19184 NM_RSQRT_S = 0x008,
19185 NM_RSQRT_D = 0x108,
19187 NM_SQRT_S = 0x028,
19188 NM_SQRT_D = 0x128,
19190 NM_RECIP_S = 0x048,
19191 NM_RECIP_D = 0x148,
19193 NM_FLOOR_L_S = 0x00c,
19194 NM_FLOOR_L_D = 0x10c,
19196 NM_FLOOR_W_S = 0x02c,
19197 NM_FLOOR_W_D = 0x12c,
19199 NM_CEIL_L_S = 0x04c,
19200 NM_CEIL_L_D = 0x14c,
19201 NM_CEIL_W_S = 0x06c,
19202 NM_CEIL_W_D = 0x16c,
19203 NM_TRUNC_L_S = 0x08c,
19204 NM_TRUNC_L_D = 0x18c,
19205 NM_TRUNC_W_S = 0x0ac,
19206 NM_TRUNC_W_D = 0x1ac,
19207 NM_ROUND_L_S = 0x0cc,
19208 NM_ROUND_L_D = 0x1cc,
19209 NM_ROUND_W_S = 0x0ec,
19210 NM_ROUND_W_D = 0x1ec,
19212 NM_MOV_S = 0x01,
19213 NM_MOV_D = 0x81,
19214 NM_ABS_S = 0x0d,
19215 NM_ABS_D = 0x8d,
19216 NM_NEG_S = 0x2d,
19217 NM_NEG_D = 0xad,
19218 NM_CVT_D_S = 0x04d,
19219 NM_CVT_D_W = 0x0cd,
19220 NM_CVT_D_L = 0x14d,
19221 NM_CVT_S_D = 0x06d,
19222 NM_CVT_S_W = 0x0ed,
19223 NM_CVT_S_L = 0x16d,
19226 /* P.LL instruction pool */
19227 enum {
19228 NM_LL = 0x00,
19229 NM_LLWP = 0x01,
19232 /* P.SC instruction pool */
19233 enum {
19234 NM_SC = 0x00,
19235 NM_SCWP = 0x01,
19238 /* P.DVP instruction pool */
19239 enum {
19240 NM_DVP = 0x00,
19241 NM_EVP = 0x01,
19247 * nanoMIPS decoding engine
19252 /* extraction utilities */
19254 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
19255 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
19256 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
19257 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
19258 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
19260 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
19261 static inline int decode_gpr_gpr3(int r)
19263 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
19265 return map[r & 0x7];
19268 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
19269 static inline int decode_gpr_gpr3_src_store(int r)
19271 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
19273 return map[r & 0x7];
19276 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
19277 static inline int decode_gpr_gpr4(int r)
19279 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
19280 16, 17, 18, 19, 20, 21, 22, 23 };
19282 return map[r & 0xf];
19285 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
19286 static inline int decode_gpr_gpr4_zero(int r)
19288 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
19289 16, 17, 18, 19, 20, 21, 22, 23 };
19291 return map[r & 0xf];
19295 static void gen_adjust_sp(DisasContext *ctx, int u)
19297 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
19300 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
19301 uint8_t gp, uint16_t u)
19303 int counter = 0;
19304 TCGv va = tcg_temp_new();
19305 TCGv t0 = tcg_temp_new();
19307 while (counter != count) {
19308 bool use_gp = gp && (counter == count - 1);
19309 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19310 int this_offset = -((counter + 1) << 2);
19311 gen_base_offset_addr(ctx, va, 29, this_offset);
19312 gen_load_gpr(t0, this_rt);
19313 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
19314 (MO_TEUL | ctx->default_tcg_memop_mask));
19315 counter++;
19318 /* adjust stack pointer */
19319 gen_adjust_sp(ctx, -u);
19321 tcg_temp_free(t0);
19322 tcg_temp_free(va);
19325 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
19326 uint8_t gp, uint16_t u)
19328 int counter = 0;
19329 TCGv va = tcg_temp_new();
19330 TCGv t0 = tcg_temp_new();
19332 while (counter != count) {
19333 bool use_gp = gp && (counter == count - 1);
19334 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
19335 int this_offset = u - ((counter + 1) << 2);
19336 gen_base_offset_addr(ctx, va, 29, this_offset);
19337 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
19338 ctx->default_tcg_memop_mask);
19339 tcg_gen_ext32s_tl(t0, t0);
19340 gen_store_gpr(t0, this_rt);
19341 counter++;
19344 /* adjust stack pointer */
19345 gen_adjust_sp(ctx, u);
19347 tcg_temp_free(t0);
19348 tcg_temp_free(va);
19351 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
19353 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
19354 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
19356 switch (extract32(ctx->opcode, 2, 2)) {
19357 case NM_NOT16:
19358 gen_logic(ctx, OPC_NOR, rt, rs, 0);
19359 break;
19360 case NM_AND16:
19361 gen_logic(ctx, OPC_AND, rt, rt, rs);
19362 break;
19363 case NM_XOR16:
19364 gen_logic(ctx, OPC_XOR, rt, rt, rs);
19365 break;
19366 case NM_OR16:
19367 gen_logic(ctx, OPC_OR, rt, rt, rs);
19368 break;
19372 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
19374 int rt = extract32(ctx->opcode, 21, 5);
19375 int rs = extract32(ctx->opcode, 16, 5);
19376 int rd = extract32(ctx->opcode, 11, 5);
19378 switch (extract32(ctx->opcode, 3, 7)) {
19379 case NM_P_TRAP:
19380 switch (extract32(ctx->opcode, 10, 1)) {
19381 case NM_TEQ:
19382 check_nms(ctx);
19383 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
19384 break;
19385 case NM_TNE:
19386 check_nms(ctx);
19387 gen_trap(ctx, OPC_TNE, rs, rt, -1);
19388 break;
19390 break;
19391 case NM_RDHWR:
19392 check_nms(ctx);
19393 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
19394 break;
19395 case NM_SEB:
19396 check_nms(ctx);
19397 gen_bshfl(ctx, OPC_SEB, rs, rt);
19398 break;
19399 case NM_SEH:
19400 gen_bshfl(ctx, OPC_SEH, rs, rt);
19401 break;
19402 case NM_SLLV:
19403 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
19404 break;
19405 case NM_SRLV:
19406 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
19407 break;
19408 case NM_SRAV:
19409 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
19410 break;
19411 case NM_ROTRV:
19412 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
19413 break;
19414 case NM_ADD:
19415 gen_arith(ctx, OPC_ADD, rd, rs, rt);
19416 break;
19417 case NM_ADDU:
19418 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
19419 break;
19420 case NM_SUB:
19421 check_nms(ctx);
19422 gen_arith(ctx, OPC_SUB, rd, rs, rt);
19423 break;
19424 case NM_SUBU:
19425 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
19426 break;
19427 case NM_P_CMOVE:
19428 switch (extract32(ctx->opcode, 10, 1)) {
19429 case NM_MOVZ:
19430 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
19431 break;
19432 case NM_MOVN:
19433 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
19434 break;
19436 break;
19437 case NM_AND:
19438 gen_logic(ctx, OPC_AND, rd, rs, rt);
19439 break;
19440 case NM_OR:
19441 gen_logic(ctx, OPC_OR, rd, rs, rt);
19442 break;
19443 case NM_NOR:
19444 gen_logic(ctx, OPC_NOR, rd, rs, rt);
19445 break;
19446 case NM_XOR:
19447 gen_logic(ctx, OPC_XOR, rd, rs, rt);
19448 break;
19449 case NM_SLT:
19450 gen_slt(ctx, OPC_SLT, rd, rs, rt);
19451 break;
19452 case NM_P_SLTU:
19453 if (rd == 0) {
19454 /* P_DVP */
19455 #ifndef CONFIG_USER_ONLY
19456 TCGv t0 = tcg_temp_new();
19457 switch (extract32(ctx->opcode, 10, 1)) {
19458 case NM_DVP:
19459 if (ctx->vp) {
19460 check_cp0_enabled(ctx);
19461 gen_helper_dvp(t0, cpu_env);
19462 gen_store_gpr(t0, rt);
19464 break;
19465 case NM_EVP:
19466 if (ctx->vp) {
19467 check_cp0_enabled(ctx);
19468 gen_helper_evp(t0, cpu_env);
19469 gen_store_gpr(t0, rt);
19471 break;
19473 tcg_temp_free(t0);
19474 #endif
19475 } else {
19476 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
19478 break;
19479 case NM_SOV:
19481 TCGv t0 = tcg_temp_new();
19482 TCGv t1 = tcg_temp_new();
19483 TCGv t2 = tcg_temp_new();
19485 gen_load_gpr(t1, rs);
19486 gen_load_gpr(t2, rt);
19487 tcg_gen_add_tl(t0, t1, t2);
19488 tcg_gen_ext32s_tl(t0, t0);
19489 tcg_gen_xor_tl(t1, t1, t2);
19490 tcg_gen_xor_tl(t2, t0, t2);
19491 tcg_gen_andc_tl(t1, t2, t1);
19493 /* operands of same sign, result different sign */
19494 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
19495 gen_store_gpr(t0, rd);
19497 tcg_temp_free(t0);
19498 tcg_temp_free(t1);
19499 tcg_temp_free(t2);
19501 break;
19502 case NM_MUL:
19503 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
19504 break;
19505 case NM_MUH:
19506 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
19507 break;
19508 case NM_MULU:
19509 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
19510 break;
19511 case NM_MUHU:
19512 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
19513 break;
19514 case NM_DIV:
19515 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
19516 break;
19517 case NM_MOD:
19518 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
19519 break;
19520 case NM_DIVU:
19521 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
19522 break;
19523 case NM_MODU:
19524 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
19525 break;
19526 #ifndef CONFIG_USER_ONLY
19527 case NM_MFC0:
19528 check_cp0_enabled(ctx);
19529 if (rt == 0) {
19530 /* Treat as NOP. */
19531 break;
19533 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
19534 break;
19535 case NM_MTC0:
19536 check_cp0_enabled(ctx);
19538 TCGv t0 = tcg_temp_new();
19540 gen_load_gpr(t0, rt);
19541 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
19542 tcg_temp_free(t0);
19544 break;
19545 case NM_D_E_MT_VPE:
19547 uint8_t sc = extract32(ctx->opcode, 10, 1);
19548 TCGv t0 = tcg_temp_new();
19550 switch (sc) {
19551 case 0:
19552 if (rs == 1) {
19553 /* DMT */
19554 check_cp0_mt(ctx);
19555 gen_helper_dmt(t0);
19556 gen_store_gpr(t0, rt);
19557 } else if (rs == 0) {
19558 /* DVPE */
19559 check_cp0_mt(ctx);
19560 gen_helper_dvpe(t0, cpu_env);
19561 gen_store_gpr(t0, rt);
19562 } else {
19563 generate_exception_end(ctx, EXCP_RI);
19565 break;
19566 case 1:
19567 if (rs == 1) {
19568 /* EMT */
19569 check_cp0_mt(ctx);
19570 gen_helper_emt(t0);
19571 gen_store_gpr(t0, rt);
19572 } else if (rs == 0) {
19573 /* EVPE */
19574 check_cp0_mt(ctx);
19575 gen_helper_evpe(t0, cpu_env);
19576 gen_store_gpr(t0, rt);
19577 } else {
19578 generate_exception_end(ctx, EXCP_RI);
19580 break;
19583 tcg_temp_free(t0);
19585 break;
19586 case NM_FORK:
19587 check_mt(ctx);
19589 TCGv t0 = tcg_temp_new();
19590 TCGv t1 = tcg_temp_new();
19592 gen_load_gpr(t0, rt);
19593 gen_load_gpr(t1, rs);
19594 gen_helper_fork(t0, t1);
19595 tcg_temp_free(t0);
19596 tcg_temp_free(t1);
19598 break;
19599 case NM_MFTR:
19600 case NM_MFHTR:
19601 check_cp0_enabled(ctx);
19602 if (rd == 0) {
19603 /* Treat as NOP. */
19604 return;
19606 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19607 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19608 break;
19609 case NM_MTTR:
19610 case NM_MTHTR:
19611 check_cp0_enabled(ctx);
19612 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
19613 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
19614 break;
19615 case NM_YIELD:
19616 check_mt(ctx);
19618 TCGv t0 = tcg_temp_new();
19620 gen_load_gpr(t0, rs);
19621 gen_helper_yield(t0, cpu_env, t0);
19622 gen_store_gpr(t0, rt);
19623 tcg_temp_free(t0);
19625 break;
19626 #endif
19627 default:
19628 generate_exception_end(ctx, EXCP_RI);
19629 break;
19633 /* dsp */
19634 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
19635 int ret, int v1, int v2)
19637 TCGv_i32 t0;
19638 TCGv v0_t;
19639 TCGv v1_t;
19641 t0 = tcg_temp_new_i32();
19643 v0_t = tcg_temp_new();
19644 v1_t = tcg_temp_new();
19646 tcg_gen_movi_i32(t0, v2 >> 3);
19648 gen_load_gpr(v0_t, ret);
19649 gen_load_gpr(v1_t, v1);
19651 switch (opc) {
19652 case NM_MAQ_S_W_PHR:
19653 check_dsp(ctx);
19654 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
19655 break;
19656 case NM_MAQ_S_W_PHL:
19657 check_dsp(ctx);
19658 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
19659 break;
19660 case NM_MAQ_SA_W_PHR:
19661 check_dsp(ctx);
19662 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
19663 break;
19664 case NM_MAQ_SA_W_PHL:
19665 check_dsp(ctx);
19666 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
19667 break;
19668 default:
19669 generate_exception_end(ctx, EXCP_RI);
19670 break;
19673 tcg_temp_free_i32(t0);
19675 tcg_temp_free(v0_t);
19676 tcg_temp_free(v1_t);
19680 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
19681 int ret, int v1, int v2)
19683 int16_t imm;
19684 TCGv t0 = tcg_temp_new();
19685 TCGv t1 = tcg_temp_new();
19686 TCGv v0_t = tcg_temp_new();
19688 gen_load_gpr(v0_t, v1);
19690 switch (opc) {
19691 case NM_POOL32AXF_1_0:
19692 check_dsp(ctx);
19693 switch (extract32(ctx->opcode, 12, 2)) {
19694 case NM_MFHI:
19695 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
19696 break;
19697 case NM_MFLO:
19698 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
19699 break;
19700 case NM_MTHI:
19701 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
19702 break;
19703 case NM_MTLO:
19704 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
19705 break;
19707 break;
19708 case NM_POOL32AXF_1_1:
19709 check_dsp(ctx);
19710 switch (extract32(ctx->opcode, 12, 2)) {
19711 case NM_MTHLIP:
19712 tcg_gen_movi_tl(t0, v2);
19713 gen_helper_mthlip(t0, v0_t, cpu_env);
19714 break;
19715 case NM_SHILOV:
19716 tcg_gen_movi_tl(t0, v2 >> 3);
19717 gen_helper_shilo(t0, v0_t, cpu_env);
19718 break;
19719 default:
19720 generate_exception_end(ctx, EXCP_RI);
19721 break;
19723 break;
19724 case NM_POOL32AXF_1_3:
19725 check_dsp(ctx);
19726 imm = extract32(ctx->opcode, 14, 7);
19727 switch (extract32(ctx->opcode, 12, 2)) {
19728 case NM_RDDSP:
19729 tcg_gen_movi_tl(t0, imm);
19730 gen_helper_rddsp(t0, t0, cpu_env);
19731 gen_store_gpr(t0, ret);
19732 break;
19733 case NM_WRDSP:
19734 gen_load_gpr(t0, ret);
19735 tcg_gen_movi_tl(t1, imm);
19736 gen_helper_wrdsp(t0, t1, cpu_env);
19737 break;
19738 case NM_EXTP:
19739 tcg_gen_movi_tl(t0, v2 >> 3);
19740 tcg_gen_movi_tl(t1, v1);
19741 gen_helper_extp(t0, t0, t1, cpu_env);
19742 gen_store_gpr(t0, ret);
19743 break;
19744 case NM_EXTPDP:
19745 tcg_gen_movi_tl(t0, v2 >> 3);
19746 tcg_gen_movi_tl(t1, v1);
19747 gen_helper_extpdp(t0, t0, t1, cpu_env);
19748 gen_store_gpr(t0, ret);
19749 break;
19751 break;
19752 case NM_POOL32AXF_1_4:
19753 check_dsp(ctx);
19754 tcg_gen_movi_tl(t0, v2 >> 2);
19755 switch (extract32(ctx->opcode, 12, 1)) {
19756 case NM_SHLL_QB:
19757 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
19758 gen_store_gpr(t0, ret);
19759 break;
19760 case NM_SHRL_QB:
19761 gen_helper_shrl_qb(t0, t0, v0_t);
19762 gen_store_gpr(t0, ret);
19763 break;
19765 break;
19766 case NM_POOL32AXF_1_5:
19767 opc = extract32(ctx->opcode, 12, 2);
19768 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
19769 break;
19770 case NM_POOL32AXF_1_7:
19771 check_dsp(ctx);
19772 tcg_gen_movi_tl(t0, v2 >> 3);
19773 tcg_gen_movi_tl(t1, v1);
19774 switch (extract32(ctx->opcode, 12, 2)) {
19775 case NM_EXTR_W:
19776 gen_helper_extr_w(t0, t0, t1, cpu_env);
19777 gen_store_gpr(t0, ret);
19778 break;
19779 case NM_EXTR_R_W:
19780 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
19781 gen_store_gpr(t0, ret);
19782 break;
19783 case NM_EXTR_RS_W:
19784 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
19785 gen_store_gpr(t0, ret);
19786 break;
19787 case NM_EXTR_S_H:
19788 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
19789 gen_store_gpr(t0, ret);
19790 break;
19792 break;
19793 default:
19794 generate_exception_end(ctx, EXCP_RI);
19795 break;
19798 tcg_temp_free(t0);
19799 tcg_temp_free(t1);
19800 tcg_temp_free(v0_t);
19803 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
19804 TCGv v0, TCGv v1, int rd)
19806 TCGv_i32 t0;
19808 t0 = tcg_temp_new_i32();
19810 tcg_gen_movi_i32(t0, rd >> 3);
19812 switch (opc) {
19813 case NM_POOL32AXF_2_0_7:
19814 switch (extract32(ctx->opcode, 9, 3)) {
19815 case NM_DPA_W_PH:
19816 check_dsp_r2(ctx);
19817 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
19818 break;
19819 case NM_DPAQ_S_W_PH:
19820 check_dsp(ctx);
19821 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
19822 break;
19823 case NM_DPS_W_PH:
19824 check_dsp_r2(ctx);
19825 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
19826 break;
19827 case NM_DPSQ_S_W_PH:
19828 check_dsp(ctx);
19829 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
19830 break;
19831 default:
19832 generate_exception_end(ctx, EXCP_RI);
19833 break;
19835 break;
19836 case NM_POOL32AXF_2_8_15:
19837 switch (extract32(ctx->opcode, 9, 3)) {
19838 case NM_DPAX_W_PH:
19839 check_dsp_r2(ctx);
19840 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
19841 break;
19842 case NM_DPAQ_SA_L_W:
19843 check_dsp(ctx);
19844 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
19845 break;
19846 case NM_DPSX_W_PH:
19847 check_dsp_r2(ctx);
19848 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
19849 break;
19850 case NM_DPSQ_SA_L_W:
19851 check_dsp(ctx);
19852 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
19853 break;
19854 default:
19855 generate_exception_end(ctx, EXCP_RI);
19856 break;
19858 break;
19859 case NM_POOL32AXF_2_16_23:
19860 switch (extract32(ctx->opcode, 9, 3)) {
19861 case NM_DPAU_H_QBL:
19862 check_dsp(ctx);
19863 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
19864 break;
19865 case NM_DPAQX_S_W_PH:
19866 check_dsp_r2(ctx);
19867 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
19868 break;
19869 case NM_DPSU_H_QBL:
19870 check_dsp(ctx);
19871 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
19872 break;
19873 case NM_DPSQX_S_W_PH:
19874 check_dsp_r2(ctx);
19875 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
19876 break;
19877 case NM_MULSA_W_PH:
19878 check_dsp_r2(ctx);
19879 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
19880 break;
19881 default:
19882 generate_exception_end(ctx, EXCP_RI);
19883 break;
19885 break;
19886 case NM_POOL32AXF_2_24_31:
19887 switch (extract32(ctx->opcode, 9, 3)) {
19888 case NM_DPAU_H_QBR:
19889 check_dsp(ctx);
19890 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
19891 break;
19892 case NM_DPAQX_SA_W_PH:
19893 check_dsp_r2(ctx);
19894 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
19895 break;
19896 case NM_DPSU_H_QBR:
19897 check_dsp(ctx);
19898 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
19899 break;
19900 case NM_DPSQX_SA_W_PH:
19901 check_dsp_r2(ctx);
19902 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
19903 break;
19904 case NM_MULSAQ_S_W_PH:
19905 check_dsp(ctx);
19906 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
19907 break;
19908 default:
19909 generate_exception_end(ctx, EXCP_RI);
19910 break;
19912 break;
19913 default:
19914 generate_exception_end(ctx, EXCP_RI);
19915 break;
19918 tcg_temp_free_i32(t0);
19921 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
19922 int rt, int rs, int rd)
19924 int ret = rt;
19925 TCGv t0 = tcg_temp_new();
19926 TCGv t1 = tcg_temp_new();
19927 TCGv v0_t = tcg_temp_new();
19928 TCGv v1_t = tcg_temp_new();
19930 gen_load_gpr(v0_t, rt);
19931 gen_load_gpr(v1_t, rs);
19933 switch (opc) {
19934 case NM_POOL32AXF_2_0_7:
19935 switch (extract32(ctx->opcode, 9, 3)) {
19936 case NM_DPA_W_PH:
19937 case NM_DPAQ_S_W_PH:
19938 case NM_DPS_W_PH:
19939 case NM_DPSQ_S_W_PH:
19940 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
19941 break;
19942 case NM_BALIGN:
19943 check_dsp_r2(ctx);
19944 if (rt != 0) {
19945 gen_load_gpr(t0, rs);
19946 rd &= 3;
19947 if (rd != 0 && rd != 2) {
19948 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
19949 tcg_gen_ext32u_tl(t0, t0);
19950 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
19951 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
19953 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
19955 break;
19956 case NM_MADD:
19957 check_dsp(ctx);
19959 int acc = extract32(ctx->opcode, 14, 2);
19960 TCGv_i64 t2 = tcg_temp_new_i64();
19961 TCGv_i64 t3 = tcg_temp_new_i64();
19963 gen_load_gpr(t0, rt);
19964 gen_load_gpr(t1, rs);
19965 tcg_gen_ext_tl_i64(t2, t0);
19966 tcg_gen_ext_tl_i64(t3, t1);
19967 tcg_gen_mul_i64(t2, t2, t3);
19968 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
19969 tcg_gen_add_i64(t2, t2, t3);
19970 tcg_temp_free_i64(t3);
19971 gen_move_low32(cpu_LO[acc], t2);
19972 gen_move_high32(cpu_HI[acc], t2);
19973 tcg_temp_free_i64(t2);
19975 break;
19976 case NM_MULT:
19977 check_dsp(ctx);
19979 int acc = extract32(ctx->opcode, 14, 2);
19980 TCGv_i32 t2 = tcg_temp_new_i32();
19981 TCGv_i32 t3 = tcg_temp_new_i32();
19983 gen_load_gpr(t0, rs);
19984 gen_load_gpr(t1, rt);
19985 tcg_gen_trunc_tl_i32(t2, t0);
19986 tcg_gen_trunc_tl_i32(t3, t1);
19987 tcg_gen_muls2_i32(t2, t3, t2, t3);
19988 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
19989 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
19990 tcg_temp_free_i32(t2);
19991 tcg_temp_free_i32(t3);
19993 break;
19994 case NM_EXTRV_W:
19995 check_dsp(ctx);
19996 gen_load_gpr(v1_t, rs);
19997 tcg_gen_movi_tl(t0, rd >> 3);
19998 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
19999 gen_store_gpr(t0, ret);
20000 break;
20002 break;
20003 case NM_POOL32AXF_2_8_15:
20004 switch (extract32(ctx->opcode, 9, 3)) {
20005 case NM_DPAX_W_PH:
20006 case NM_DPAQ_SA_L_W:
20007 case NM_DPSX_W_PH:
20008 case NM_DPSQ_SA_L_W:
20009 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20010 break;
20011 case NM_MADDU:
20012 check_dsp(ctx);
20014 int acc = extract32(ctx->opcode, 14, 2);
20015 TCGv_i64 t2 = tcg_temp_new_i64();
20016 TCGv_i64 t3 = tcg_temp_new_i64();
20018 gen_load_gpr(t0, rs);
20019 gen_load_gpr(t1, rt);
20020 tcg_gen_ext32u_tl(t0, t0);
20021 tcg_gen_ext32u_tl(t1, t1);
20022 tcg_gen_extu_tl_i64(t2, t0);
20023 tcg_gen_extu_tl_i64(t3, t1);
20024 tcg_gen_mul_i64(t2, t2, t3);
20025 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20026 tcg_gen_add_i64(t2, t2, t3);
20027 tcg_temp_free_i64(t3);
20028 gen_move_low32(cpu_LO[acc], t2);
20029 gen_move_high32(cpu_HI[acc], t2);
20030 tcg_temp_free_i64(t2);
20032 break;
20033 case NM_MULTU:
20034 check_dsp(ctx);
20036 int acc = extract32(ctx->opcode, 14, 2);
20037 TCGv_i32 t2 = tcg_temp_new_i32();
20038 TCGv_i32 t3 = tcg_temp_new_i32();
20040 gen_load_gpr(t0, rs);
20041 gen_load_gpr(t1, rt);
20042 tcg_gen_trunc_tl_i32(t2, t0);
20043 tcg_gen_trunc_tl_i32(t3, t1);
20044 tcg_gen_mulu2_i32(t2, t3, t2, t3);
20045 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
20046 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
20047 tcg_temp_free_i32(t2);
20048 tcg_temp_free_i32(t3);
20050 break;
20051 case NM_EXTRV_R_W:
20052 check_dsp(ctx);
20053 tcg_gen_movi_tl(t0, rd >> 3);
20054 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
20055 gen_store_gpr(t0, ret);
20056 break;
20057 default:
20058 generate_exception_end(ctx, EXCP_RI);
20059 break;
20061 break;
20062 case NM_POOL32AXF_2_16_23:
20063 switch (extract32(ctx->opcode, 9, 3)) {
20064 case NM_DPAU_H_QBL:
20065 case NM_DPAQX_S_W_PH:
20066 case NM_DPSU_H_QBL:
20067 case NM_DPSQX_S_W_PH:
20068 case NM_MULSA_W_PH:
20069 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20070 break;
20071 case NM_EXTPV:
20072 check_dsp(ctx);
20073 tcg_gen_movi_tl(t0, rd >> 3);
20074 gen_helper_extp(t0, t0, v1_t, cpu_env);
20075 gen_store_gpr(t0, ret);
20076 break;
20077 case NM_MSUB:
20078 check_dsp(ctx);
20080 int acc = extract32(ctx->opcode, 14, 2);
20081 TCGv_i64 t2 = tcg_temp_new_i64();
20082 TCGv_i64 t3 = tcg_temp_new_i64();
20084 gen_load_gpr(t0, rs);
20085 gen_load_gpr(t1, rt);
20086 tcg_gen_ext_tl_i64(t2, t0);
20087 tcg_gen_ext_tl_i64(t3, t1);
20088 tcg_gen_mul_i64(t2, t2, t3);
20089 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20090 tcg_gen_sub_i64(t2, t3, t2);
20091 tcg_temp_free_i64(t3);
20092 gen_move_low32(cpu_LO[acc], t2);
20093 gen_move_high32(cpu_HI[acc], t2);
20094 tcg_temp_free_i64(t2);
20096 break;
20097 case NM_EXTRV_RS_W:
20098 check_dsp(ctx);
20099 tcg_gen_movi_tl(t0, rd >> 3);
20100 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
20101 gen_store_gpr(t0, ret);
20102 break;
20104 break;
20105 case NM_POOL32AXF_2_24_31:
20106 switch (extract32(ctx->opcode, 9, 3)) {
20107 case NM_DPAU_H_QBR:
20108 case NM_DPAQX_SA_W_PH:
20109 case NM_DPSU_H_QBR:
20110 case NM_DPSQX_SA_W_PH:
20111 case NM_MULSAQ_S_W_PH:
20112 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
20113 break;
20114 case NM_EXTPDPV:
20115 check_dsp(ctx);
20116 tcg_gen_movi_tl(t0, rd >> 3);
20117 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
20118 gen_store_gpr(t0, ret);
20119 break;
20120 case NM_MSUBU:
20121 check_dsp(ctx);
20123 int acc = extract32(ctx->opcode, 14, 2);
20124 TCGv_i64 t2 = tcg_temp_new_i64();
20125 TCGv_i64 t3 = tcg_temp_new_i64();
20127 gen_load_gpr(t0, rs);
20128 gen_load_gpr(t1, rt);
20129 tcg_gen_ext32u_tl(t0, t0);
20130 tcg_gen_ext32u_tl(t1, t1);
20131 tcg_gen_extu_tl_i64(t2, t0);
20132 tcg_gen_extu_tl_i64(t3, t1);
20133 tcg_gen_mul_i64(t2, t2, t3);
20134 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
20135 tcg_gen_sub_i64(t2, t3, t2);
20136 tcg_temp_free_i64(t3);
20137 gen_move_low32(cpu_LO[acc], t2);
20138 gen_move_high32(cpu_HI[acc], t2);
20139 tcg_temp_free_i64(t2);
20141 break;
20142 case NM_EXTRV_S_H:
20143 check_dsp(ctx);
20144 tcg_gen_movi_tl(t0, rd >> 3);
20145 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
20146 gen_store_gpr(t0, ret);
20147 break;
20149 break;
20150 default:
20151 generate_exception_end(ctx, EXCP_RI);
20152 break;
20155 tcg_temp_free(t0);
20156 tcg_temp_free(t1);
20158 tcg_temp_free(v0_t);
20159 tcg_temp_free(v1_t);
20162 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
20163 int rt, int rs)
20165 int ret = rt;
20166 TCGv t0 = tcg_temp_new();
20167 TCGv v0_t = tcg_temp_new();
20169 gen_load_gpr(v0_t, rs);
20171 switch (opc) {
20172 case NM_ABSQ_S_QB:
20173 check_dsp_r2(ctx);
20174 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
20175 gen_store_gpr(v0_t, ret);
20176 break;
20177 case NM_ABSQ_S_PH:
20178 check_dsp(ctx);
20179 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
20180 gen_store_gpr(v0_t, ret);
20181 break;
20182 case NM_ABSQ_S_W:
20183 check_dsp(ctx);
20184 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
20185 gen_store_gpr(v0_t, ret);
20186 break;
20187 case NM_PRECEQ_W_PHL:
20188 check_dsp(ctx);
20189 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
20190 tcg_gen_ext32s_tl(v0_t, v0_t);
20191 gen_store_gpr(v0_t, ret);
20192 break;
20193 case NM_PRECEQ_W_PHR:
20194 check_dsp(ctx);
20195 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
20196 tcg_gen_shli_tl(v0_t, v0_t, 16);
20197 tcg_gen_ext32s_tl(v0_t, v0_t);
20198 gen_store_gpr(v0_t, ret);
20199 break;
20200 case NM_PRECEQU_PH_QBL:
20201 check_dsp(ctx);
20202 gen_helper_precequ_ph_qbl(v0_t, v0_t);
20203 gen_store_gpr(v0_t, ret);
20204 break;
20205 case NM_PRECEQU_PH_QBR:
20206 check_dsp(ctx);
20207 gen_helper_precequ_ph_qbr(v0_t, v0_t);
20208 gen_store_gpr(v0_t, ret);
20209 break;
20210 case NM_PRECEQU_PH_QBLA:
20211 check_dsp(ctx);
20212 gen_helper_precequ_ph_qbla(v0_t, v0_t);
20213 gen_store_gpr(v0_t, ret);
20214 break;
20215 case NM_PRECEQU_PH_QBRA:
20216 check_dsp(ctx);
20217 gen_helper_precequ_ph_qbra(v0_t, v0_t);
20218 gen_store_gpr(v0_t, ret);
20219 break;
20220 case NM_PRECEU_PH_QBL:
20221 check_dsp(ctx);
20222 gen_helper_preceu_ph_qbl(v0_t, v0_t);
20223 gen_store_gpr(v0_t, ret);
20224 break;
20225 case NM_PRECEU_PH_QBR:
20226 check_dsp(ctx);
20227 gen_helper_preceu_ph_qbr(v0_t, v0_t);
20228 gen_store_gpr(v0_t, ret);
20229 break;
20230 case NM_PRECEU_PH_QBLA:
20231 check_dsp(ctx);
20232 gen_helper_preceu_ph_qbla(v0_t, v0_t);
20233 gen_store_gpr(v0_t, ret);
20234 break;
20235 case NM_PRECEU_PH_QBRA:
20236 check_dsp(ctx);
20237 gen_helper_preceu_ph_qbra(v0_t, v0_t);
20238 gen_store_gpr(v0_t, ret);
20239 break;
20240 case NM_REPLV_PH:
20241 check_dsp(ctx);
20242 tcg_gen_ext16u_tl(v0_t, v0_t);
20243 tcg_gen_shli_tl(t0, v0_t, 16);
20244 tcg_gen_or_tl(v0_t, v0_t, t0);
20245 tcg_gen_ext32s_tl(v0_t, v0_t);
20246 gen_store_gpr(v0_t, ret);
20247 break;
20248 case NM_REPLV_QB:
20249 check_dsp(ctx);
20250 tcg_gen_ext8u_tl(v0_t, v0_t);
20251 tcg_gen_shli_tl(t0, v0_t, 8);
20252 tcg_gen_or_tl(v0_t, v0_t, t0);
20253 tcg_gen_shli_tl(t0, v0_t, 16);
20254 tcg_gen_or_tl(v0_t, v0_t, t0);
20255 tcg_gen_ext32s_tl(v0_t, v0_t);
20256 gen_store_gpr(v0_t, ret);
20257 break;
20258 case NM_BITREV:
20259 check_dsp(ctx);
20260 gen_helper_bitrev(v0_t, v0_t);
20261 gen_store_gpr(v0_t, ret);
20262 break;
20263 case NM_INSV:
20264 check_dsp(ctx);
20266 TCGv tv0 = tcg_temp_new();
20268 gen_load_gpr(tv0, rt);
20269 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
20270 gen_store_gpr(v0_t, ret);
20271 tcg_temp_free(tv0);
20273 break;
20274 case NM_RADDU_W_QB:
20275 check_dsp(ctx);
20276 gen_helper_raddu_w_qb(v0_t, v0_t);
20277 gen_store_gpr(v0_t, ret);
20278 break;
20279 case NM_BITSWAP:
20280 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
20281 break;
20282 case NM_CLO:
20283 check_nms(ctx);
20284 gen_cl(ctx, OPC_CLO, ret, rs);
20285 break;
20286 case NM_CLZ:
20287 check_nms(ctx);
20288 gen_cl(ctx, OPC_CLZ, ret, rs);
20289 break;
20290 case NM_WSBH:
20291 gen_bshfl(ctx, OPC_WSBH, ret, rs);
20292 break;
20293 default:
20294 generate_exception_end(ctx, EXCP_RI);
20295 break;
20298 tcg_temp_free(v0_t);
20299 tcg_temp_free(t0);
20302 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
20303 int rt, int rs, int rd)
20305 TCGv t0 = tcg_temp_new();
20306 TCGv rs_t = tcg_temp_new();
20308 gen_load_gpr(rs_t, rs);
20310 switch (opc) {
20311 case NM_SHRA_R_QB:
20312 check_dsp_r2(ctx);
20313 tcg_gen_movi_tl(t0, rd >> 2);
20314 switch (extract32(ctx->opcode, 12, 1)) {
20315 case 0:
20316 /* NM_SHRA_QB */
20317 gen_helper_shra_qb(t0, t0, rs_t);
20318 gen_store_gpr(t0, rt);
20319 break;
20320 case 1:
20321 /* NM_SHRA_R_QB */
20322 gen_helper_shra_r_qb(t0, t0, rs_t);
20323 gen_store_gpr(t0, rt);
20324 break;
20326 break;
20327 case NM_SHRL_PH:
20328 check_dsp_r2(ctx);
20329 tcg_gen_movi_tl(t0, rd >> 1);
20330 gen_helper_shrl_ph(t0, t0, rs_t);
20331 gen_store_gpr(t0, rt);
20332 break;
20333 case NM_REPL_QB:
20334 check_dsp(ctx);
20336 int16_t imm;
20337 target_long result;
20338 imm = extract32(ctx->opcode, 13, 8);
20339 result = (uint32_t)imm << 24 |
20340 (uint32_t)imm << 16 |
20341 (uint32_t)imm << 8 |
20342 (uint32_t)imm;
20343 result = (int32_t)result;
20344 tcg_gen_movi_tl(t0, result);
20345 gen_store_gpr(t0, rt);
20347 break;
20348 default:
20349 generate_exception_end(ctx, EXCP_RI);
20350 break;
20352 tcg_temp_free(t0);
20353 tcg_temp_free(rs_t);
20357 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
20359 int rt = extract32(ctx->opcode, 21, 5);
20360 int rs = extract32(ctx->opcode, 16, 5);
20361 int rd = extract32(ctx->opcode, 11, 5);
20363 switch (extract32(ctx->opcode, 6, 3)) {
20364 case NM_POOL32AXF_1:
20366 int32_t op1 = extract32(ctx->opcode, 9, 3);
20367 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
20369 break;
20370 case NM_POOL32AXF_2:
20372 int32_t op1 = extract32(ctx->opcode, 12, 2);
20373 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
20375 break;
20376 case NM_POOL32AXF_4:
20378 int32_t op1 = extract32(ctx->opcode, 9, 7);
20379 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
20381 break;
20382 case NM_POOL32AXF_5:
20383 switch (extract32(ctx->opcode, 9, 7)) {
20384 #ifndef CONFIG_USER_ONLY
20385 case NM_TLBP:
20386 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
20387 break;
20388 case NM_TLBR:
20389 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
20390 break;
20391 case NM_TLBWI:
20392 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
20393 break;
20394 case NM_TLBWR:
20395 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
20396 break;
20397 case NM_TLBINV:
20398 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
20399 break;
20400 case NM_TLBINVF:
20401 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
20402 break;
20403 case NM_DI:
20404 check_cp0_enabled(ctx);
20406 TCGv t0 = tcg_temp_new();
20408 save_cpu_state(ctx, 1);
20409 gen_helper_di(t0, cpu_env);
20410 gen_store_gpr(t0, rt);
20411 /* Stop translation as we may have switched the execution mode */
20412 ctx->base.is_jmp = DISAS_STOP;
20413 tcg_temp_free(t0);
20415 break;
20416 case NM_EI:
20417 check_cp0_enabled(ctx);
20419 TCGv t0 = tcg_temp_new();
20421 save_cpu_state(ctx, 1);
20422 gen_helper_ei(t0, cpu_env);
20423 gen_store_gpr(t0, rt);
20424 /* Stop translation as we may have switched the execution mode */
20425 ctx->base.is_jmp = DISAS_STOP;
20426 tcg_temp_free(t0);
20428 break;
20429 case NM_RDPGPR:
20430 gen_load_srsgpr(rs, rt);
20431 break;
20432 case NM_WRPGPR:
20433 gen_store_srsgpr(rs, rt);
20434 break;
20435 case NM_WAIT:
20436 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
20437 break;
20438 case NM_DERET:
20439 gen_cp0(env, ctx, OPC_DERET, 0, 0);
20440 break;
20441 case NM_ERETX:
20442 gen_cp0(env, ctx, OPC_ERET, 0, 0);
20443 break;
20444 #endif
20445 default:
20446 generate_exception_end(ctx, EXCP_RI);
20447 break;
20449 break;
20450 case NM_POOL32AXF_7:
20452 int32_t op1 = extract32(ctx->opcode, 9, 3);
20453 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
20455 break;
20456 default:
20457 generate_exception_end(ctx, EXCP_RI);
20458 break;
20462 /* Immediate Value Compact Branches */
20463 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
20464 int rt, int32_t imm, int32_t offset)
20466 TCGCond cond = TCG_COND_ALWAYS;
20467 TCGv t0 = tcg_temp_new();
20468 TCGv t1 = tcg_temp_new();
20470 gen_load_gpr(t0, rt);
20471 tcg_gen_movi_tl(t1, imm);
20472 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20474 /* Load needed operands and calculate btarget */
20475 switch (opc) {
20476 case NM_BEQIC:
20477 if (rt == 0 && imm == 0) {
20478 /* Unconditional branch */
20479 } else if (rt == 0 && imm != 0) {
20480 /* Treat as NOP */
20481 goto out;
20482 } else {
20483 cond = TCG_COND_EQ;
20485 break;
20486 case NM_BBEQZC:
20487 case NM_BBNEZC:
20488 check_nms(ctx);
20489 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
20490 generate_exception_end(ctx, EXCP_RI);
20491 goto out;
20492 } else if (rt == 0 && opc == NM_BBEQZC) {
20493 /* Unconditional branch */
20494 } else if (rt == 0 && opc == NM_BBNEZC) {
20495 /* Treat as NOP */
20496 goto out;
20497 } else {
20498 tcg_gen_shri_tl(t0, t0, imm);
20499 tcg_gen_andi_tl(t0, t0, 1);
20500 tcg_gen_movi_tl(t1, 0);
20501 if (opc == NM_BBEQZC) {
20502 cond = TCG_COND_EQ;
20503 } else {
20504 cond = TCG_COND_NE;
20507 break;
20508 case NM_BNEIC:
20509 if (rt == 0 && imm == 0) {
20510 /* Treat as NOP */
20511 goto out;
20512 } else if (rt == 0 && imm != 0) {
20513 /* Unconditional branch */
20514 } else {
20515 cond = TCG_COND_NE;
20517 break;
20518 case NM_BGEIC:
20519 if (rt == 0 && imm == 0) {
20520 /* Unconditional branch */
20521 } else {
20522 cond = TCG_COND_GE;
20524 break;
20525 case NM_BLTIC:
20526 cond = TCG_COND_LT;
20527 break;
20528 case NM_BGEIUC:
20529 if (rt == 0 && imm == 0) {
20530 /* Unconditional branch */
20531 } else {
20532 cond = TCG_COND_GEU;
20534 break;
20535 case NM_BLTIUC:
20536 cond = TCG_COND_LTU;
20537 break;
20538 default:
20539 MIPS_INVAL("Immediate Value Compact branch");
20540 generate_exception_end(ctx, EXCP_RI);
20541 goto out;
20544 /* branch completion */
20545 clear_branch_hflags(ctx);
20546 ctx->base.is_jmp = DISAS_NORETURN;
20548 if (cond == TCG_COND_ALWAYS) {
20549 /* Uncoditional compact branch */
20550 gen_goto_tb(ctx, 0, ctx->btarget);
20551 } else {
20552 /* Conditional compact branch */
20553 TCGLabel *fs = gen_new_label();
20555 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
20557 gen_goto_tb(ctx, 1, ctx->btarget);
20558 gen_set_label(fs);
20560 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20563 out:
20564 tcg_temp_free(t0);
20565 tcg_temp_free(t1);
20568 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
20569 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
20570 int rt)
20572 TCGv t0 = tcg_temp_new();
20573 TCGv t1 = tcg_temp_new();
20575 /* load rs */
20576 gen_load_gpr(t0, rs);
20578 /* link */
20579 if (rt != 0) {
20580 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
20583 /* calculate btarget */
20584 tcg_gen_shli_tl(t0, t0, 1);
20585 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
20586 gen_op_addr_add(ctx, btarget, t1, t0);
20588 /* branch completion */
20589 clear_branch_hflags(ctx);
20590 ctx->base.is_jmp = DISAS_NORETURN;
20592 /* unconditional branch to register */
20593 tcg_gen_mov_tl(cpu_PC, btarget);
20594 tcg_gen_lookup_and_goto_ptr();
20596 tcg_temp_free(t0);
20597 tcg_temp_free(t1);
20600 /* nanoMIPS Branches */
20601 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
20602 int rs, int rt, int32_t offset)
20604 int bcond_compute = 0;
20605 TCGv t0 = tcg_temp_new();
20606 TCGv t1 = tcg_temp_new();
20608 /* Load needed operands and calculate btarget */
20609 switch (opc) {
20610 /* compact branch */
20611 case OPC_BGEC:
20612 case OPC_BLTC:
20613 gen_load_gpr(t0, rs);
20614 gen_load_gpr(t1, rt);
20615 bcond_compute = 1;
20616 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20617 break;
20618 case OPC_BGEUC:
20619 case OPC_BLTUC:
20620 if (rs == 0 || rs == rt) {
20621 /* OPC_BLEZALC, OPC_BGEZALC */
20622 /* OPC_BGTZALC, OPC_BLTZALC */
20623 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
20625 gen_load_gpr(t0, rs);
20626 gen_load_gpr(t1, rt);
20627 bcond_compute = 1;
20628 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20629 break;
20630 case OPC_BC:
20631 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20632 break;
20633 case OPC_BEQZC:
20634 if (rs != 0) {
20635 /* OPC_BEQZC, OPC_BNEZC */
20636 gen_load_gpr(t0, rs);
20637 bcond_compute = 1;
20638 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20639 } else {
20640 /* OPC_JIC, OPC_JIALC */
20641 TCGv tbase = tcg_temp_new();
20642 TCGv toffset = tcg_temp_new();
20644 gen_load_gpr(tbase, rt);
20645 tcg_gen_movi_tl(toffset, offset);
20646 gen_op_addr_add(ctx, btarget, tbase, toffset);
20647 tcg_temp_free(tbase);
20648 tcg_temp_free(toffset);
20650 break;
20651 default:
20652 MIPS_INVAL("Compact branch/jump");
20653 generate_exception_end(ctx, EXCP_RI);
20654 goto out;
20657 if (bcond_compute == 0) {
20658 /* Uncoditional compact branch */
20659 switch (opc) {
20660 case OPC_BC:
20661 gen_goto_tb(ctx, 0, ctx->btarget);
20662 break;
20663 default:
20664 MIPS_INVAL("Compact branch/jump");
20665 generate_exception_end(ctx, EXCP_RI);
20666 goto out;
20668 } else {
20669 /* Conditional compact branch */
20670 TCGLabel *fs = gen_new_label();
20672 switch (opc) {
20673 case OPC_BGEUC:
20674 if (rs == 0 && rt != 0) {
20675 /* OPC_BLEZALC */
20676 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20677 } else if (rs != 0 && rt != 0 && rs == rt) {
20678 /* OPC_BGEZALC */
20679 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20680 } else {
20681 /* OPC_BGEUC */
20682 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
20684 break;
20685 case OPC_BLTUC:
20686 if (rs == 0 && rt != 0) {
20687 /* OPC_BGTZALC */
20688 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20689 } else if (rs != 0 && rt != 0 && rs == rt) {
20690 /* OPC_BLTZALC */
20691 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20692 } else {
20693 /* OPC_BLTUC */
20694 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
20696 break;
20697 case OPC_BGEC:
20698 if (rs == 0 && rt != 0) {
20699 /* OPC_BLEZC */
20700 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
20701 } else if (rs != 0 && rt != 0 && rs == rt) {
20702 /* OPC_BGEZC */
20703 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
20704 } else {
20705 /* OPC_BGEC */
20706 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
20708 break;
20709 case OPC_BLTC:
20710 if (rs == 0 && rt != 0) {
20711 /* OPC_BGTZC */
20712 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
20713 } else if (rs != 0 && rt != 0 && rs == rt) {
20714 /* OPC_BLTZC */
20715 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
20716 } else {
20717 /* OPC_BLTC */
20718 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
20720 break;
20721 case OPC_BEQZC:
20722 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
20723 break;
20724 default:
20725 MIPS_INVAL("Compact conditional branch/jump");
20726 generate_exception_end(ctx, EXCP_RI);
20727 goto out;
20730 /* branch completion */
20731 clear_branch_hflags(ctx);
20732 ctx->base.is_jmp = DISAS_NORETURN;
20734 /* Generating branch here as compact branches don't have delay slot */
20735 gen_goto_tb(ctx, 1, ctx->btarget);
20736 gen_set_label(fs);
20738 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
20741 out:
20742 tcg_temp_free(t0);
20743 tcg_temp_free(t1);
20747 /* nanoMIPS CP1 Branches */
20748 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
20749 int32_t ft, int32_t offset)
20751 target_ulong btarget;
20752 TCGv_i64 t0 = tcg_temp_new_i64();
20754 gen_load_fpr64(ctx, t0, ft);
20755 tcg_gen_andi_i64(t0, t0, 1);
20757 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
20759 switch (op) {
20760 case NM_BC1EQZC:
20761 tcg_gen_xori_i64(t0, t0, 1);
20762 ctx->hflags |= MIPS_HFLAG_BC;
20763 break;
20764 case NM_BC1NEZC:
20765 /* t0 already set */
20766 ctx->hflags |= MIPS_HFLAG_BC;
20767 break;
20768 default:
20769 MIPS_INVAL("cp1 cond branch");
20770 generate_exception_end(ctx, EXCP_RI);
20771 goto out;
20774 tcg_gen_trunc_i64_tl(bcond, t0);
20776 ctx->btarget = btarget;
20778 out:
20779 tcg_temp_free_i64(t0);
20783 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
20785 TCGv t0, t1;
20786 t0 = tcg_temp_new();
20787 t1 = tcg_temp_new();
20789 gen_load_gpr(t0, rs);
20790 gen_load_gpr(t1, rt);
20792 if ((extract32(ctx->opcode, 6, 1)) == 1) {
20793 /* PP.LSXS instructions require shifting */
20794 switch (extract32(ctx->opcode, 7, 4)) {
20795 case NM_SHXS:
20796 check_nms(ctx);
20797 /* fall through */
20798 case NM_LHXS:
20799 case NM_LHUXS:
20800 tcg_gen_shli_tl(t0, t0, 1);
20801 break;
20802 case NM_SWXS:
20803 check_nms(ctx);
20804 /* fall through */
20805 case NM_LWXS:
20806 case NM_LWC1XS:
20807 case NM_SWC1XS:
20808 tcg_gen_shli_tl(t0, t0, 2);
20809 break;
20810 case NM_LDC1XS:
20811 case NM_SDC1XS:
20812 tcg_gen_shli_tl(t0, t0, 3);
20813 break;
20816 gen_op_addr_add(ctx, t0, t0, t1);
20818 switch (extract32(ctx->opcode, 7, 4)) {
20819 case NM_LBX:
20820 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20821 MO_SB);
20822 gen_store_gpr(t0, rd);
20823 break;
20824 case NM_LHX:
20825 /*case NM_LHXS:*/
20826 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20827 MO_TESW);
20828 gen_store_gpr(t0, rd);
20829 break;
20830 case NM_LWX:
20831 /*case NM_LWXS:*/
20832 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20833 MO_TESL);
20834 gen_store_gpr(t0, rd);
20835 break;
20836 case NM_LBUX:
20837 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20838 MO_UB);
20839 gen_store_gpr(t0, rd);
20840 break;
20841 case NM_LHUX:
20842 /*case NM_LHUXS:*/
20843 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
20844 MO_TEUW);
20845 gen_store_gpr(t0, rd);
20846 break;
20847 case NM_SBX:
20848 check_nms(ctx);
20849 gen_load_gpr(t1, rd);
20850 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20851 MO_8);
20852 break;
20853 case NM_SHX:
20854 /*case NM_SHXS:*/
20855 check_nms(ctx);
20856 gen_load_gpr(t1, rd);
20857 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20858 MO_TEUW);
20859 break;
20860 case NM_SWX:
20861 /*case NM_SWXS:*/
20862 check_nms(ctx);
20863 gen_load_gpr(t1, rd);
20864 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
20865 MO_TEUL);
20866 break;
20867 case NM_LWC1X:
20868 /*case NM_LWC1XS:*/
20869 case NM_LDC1X:
20870 /*case NM_LDC1XS:*/
20871 case NM_SWC1X:
20872 /*case NM_SWC1XS:*/
20873 case NM_SDC1X:
20874 /*case NM_SDC1XS:*/
20875 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
20876 check_cp1_enabled(ctx);
20877 switch (extract32(ctx->opcode, 7, 4)) {
20878 case NM_LWC1X:
20879 /*case NM_LWC1XS:*/
20880 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
20881 break;
20882 case NM_LDC1X:
20883 /*case NM_LDC1XS:*/
20884 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
20885 break;
20886 case NM_SWC1X:
20887 /*case NM_SWC1XS:*/
20888 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
20889 break;
20890 case NM_SDC1X:
20891 /*case NM_SDC1XS:*/
20892 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
20893 break;
20895 } else {
20896 generate_exception_err(ctx, EXCP_CpU, 1);
20898 break;
20899 default:
20900 generate_exception_end(ctx, EXCP_RI);
20901 break;
20904 tcg_temp_free(t0);
20905 tcg_temp_free(t1);
20908 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
20910 int rt, rs, rd;
20912 rt = extract32(ctx->opcode, 21, 5);
20913 rs = extract32(ctx->opcode, 16, 5);
20914 rd = extract32(ctx->opcode, 11, 5);
20916 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
20917 generate_exception_end(ctx, EXCP_RI);
20918 return;
20920 check_cp1_enabled(ctx);
20921 switch (extract32(ctx->opcode, 0, 3)) {
20922 case NM_POOL32F_0:
20923 switch (extract32(ctx->opcode, 3, 7)) {
20924 case NM_RINT_S:
20925 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
20926 break;
20927 case NM_RINT_D:
20928 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
20929 break;
20930 case NM_CLASS_S:
20931 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
20932 break;
20933 case NM_CLASS_D:
20934 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
20935 break;
20936 case NM_ADD_S:
20937 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
20938 break;
20939 case NM_ADD_D:
20940 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
20941 break;
20942 case NM_SUB_S:
20943 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
20944 break;
20945 case NM_SUB_D:
20946 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
20947 break;
20948 case NM_MUL_S:
20949 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
20950 break;
20951 case NM_MUL_D:
20952 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
20953 break;
20954 case NM_DIV_S:
20955 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
20956 break;
20957 case NM_DIV_D:
20958 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
20959 break;
20960 case NM_SELEQZ_S:
20961 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
20962 break;
20963 case NM_SELEQZ_D:
20964 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
20965 break;
20966 case NM_SELNEZ_S:
20967 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
20968 break;
20969 case NM_SELNEZ_D:
20970 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
20971 break;
20972 case NM_SEL_S:
20973 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
20974 break;
20975 case NM_SEL_D:
20976 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
20977 break;
20978 case NM_MADDF_S:
20979 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
20980 break;
20981 case NM_MADDF_D:
20982 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
20983 break;
20984 case NM_MSUBF_S:
20985 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
20986 break;
20987 case NM_MSUBF_D:
20988 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
20989 break;
20990 default:
20991 generate_exception_end(ctx, EXCP_RI);
20992 break;
20994 break;
20995 case NM_POOL32F_3:
20996 switch (extract32(ctx->opcode, 3, 3)) {
20997 case NM_MIN_FMT:
20998 switch (extract32(ctx->opcode, 9, 1)) {
20999 case FMT_SDPS_S:
21000 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
21001 break;
21002 case FMT_SDPS_D:
21003 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
21004 break;
21006 break;
21007 case NM_MAX_FMT:
21008 switch (extract32(ctx->opcode, 9, 1)) {
21009 case FMT_SDPS_S:
21010 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
21011 break;
21012 case FMT_SDPS_D:
21013 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
21014 break;
21016 break;
21017 case NM_MINA_FMT:
21018 switch (extract32(ctx->opcode, 9, 1)) {
21019 case FMT_SDPS_S:
21020 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
21021 break;
21022 case FMT_SDPS_D:
21023 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
21024 break;
21026 break;
21027 case NM_MAXA_FMT:
21028 switch (extract32(ctx->opcode, 9, 1)) {
21029 case FMT_SDPS_S:
21030 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
21031 break;
21032 case FMT_SDPS_D:
21033 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
21034 break;
21036 break;
21037 case NM_POOL32FXF:
21038 switch (extract32(ctx->opcode, 6, 8)) {
21039 case NM_CFC1:
21040 gen_cp1(ctx, OPC_CFC1, rt, rs);
21041 break;
21042 case NM_CTC1:
21043 gen_cp1(ctx, OPC_CTC1, rt, rs);
21044 break;
21045 case NM_MFC1:
21046 gen_cp1(ctx, OPC_MFC1, rt, rs);
21047 break;
21048 case NM_MTC1:
21049 gen_cp1(ctx, OPC_MTC1, rt, rs);
21050 break;
21051 case NM_MFHC1:
21052 gen_cp1(ctx, OPC_MFHC1, rt, rs);
21053 break;
21054 case NM_MTHC1:
21055 gen_cp1(ctx, OPC_MTHC1, rt, rs);
21056 break;
21057 case NM_CVT_S_PL:
21058 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
21059 break;
21060 case NM_CVT_S_PU:
21061 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
21062 break;
21063 default:
21064 switch (extract32(ctx->opcode, 6, 9)) {
21065 case NM_CVT_L_S:
21066 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
21067 break;
21068 case NM_CVT_L_D:
21069 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
21070 break;
21071 case NM_CVT_W_S:
21072 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
21073 break;
21074 case NM_CVT_W_D:
21075 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
21076 break;
21077 case NM_RSQRT_S:
21078 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
21079 break;
21080 case NM_RSQRT_D:
21081 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
21082 break;
21083 case NM_SQRT_S:
21084 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
21085 break;
21086 case NM_SQRT_D:
21087 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
21088 break;
21089 case NM_RECIP_S:
21090 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
21091 break;
21092 case NM_RECIP_D:
21093 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
21094 break;
21095 case NM_FLOOR_L_S:
21096 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
21097 break;
21098 case NM_FLOOR_L_D:
21099 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
21100 break;
21101 case NM_FLOOR_W_S:
21102 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
21103 break;
21104 case NM_FLOOR_W_D:
21105 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
21106 break;
21107 case NM_CEIL_L_S:
21108 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
21109 break;
21110 case NM_CEIL_L_D:
21111 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
21112 break;
21113 case NM_CEIL_W_S:
21114 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
21115 break;
21116 case NM_CEIL_W_D:
21117 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
21118 break;
21119 case NM_TRUNC_L_S:
21120 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
21121 break;
21122 case NM_TRUNC_L_D:
21123 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
21124 break;
21125 case NM_TRUNC_W_S:
21126 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
21127 break;
21128 case NM_TRUNC_W_D:
21129 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
21130 break;
21131 case NM_ROUND_L_S:
21132 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
21133 break;
21134 case NM_ROUND_L_D:
21135 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
21136 break;
21137 case NM_ROUND_W_S:
21138 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
21139 break;
21140 case NM_ROUND_W_D:
21141 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
21142 break;
21143 case NM_MOV_S:
21144 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
21145 break;
21146 case NM_MOV_D:
21147 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
21148 break;
21149 case NM_ABS_S:
21150 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
21151 break;
21152 case NM_ABS_D:
21153 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
21154 break;
21155 case NM_NEG_S:
21156 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
21157 break;
21158 case NM_NEG_D:
21159 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
21160 break;
21161 case NM_CVT_D_S:
21162 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
21163 break;
21164 case NM_CVT_D_W:
21165 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
21166 break;
21167 case NM_CVT_D_L:
21168 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
21169 break;
21170 case NM_CVT_S_D:
21171 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
21172 break;
21173 case NM_CVT_S_W:
21174 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
21175 break;
21176 case NM_CVT_S_L:
21177 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
21178 break;
21179 default:
21180 generate_exception_end(ctx, EXCP_RI);
21181 break;
21183 break;
21185 break;
21187 break;
21188 case NM_POOL32F_5:
21189 switch (extract32(ctx->opcode, 3, 3)) {
21190 case NM_CMP_CONDN_S:
21191 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21192 break;
21193 case NM_CMP_CONDN_D:
21194 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
21195 break;
21196 default:
21197 generate_exception_end(ctx, EXCP_RI);
21198 break;
21200 break;
21201 default:
21202 generate_exception_end(ctx, EXCP_RI);
21203 break;
21207 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
21208 int rd, int rs, int rt)
21210 int ret = rd;
21211 TCGv t0 = tcg_temp_new();
21212 TCGv v1_t = tcg_temp_new();
21213 TCGv v2_t = tcg_temp_new();
21215 gen_load_gpr(v1_t, rs);
21216 gen_load_gpr(v2_t, rt);
21218 switch (opc) {
21219 case NM_CMP_EQ_PH:
21220 check_dsp(ctx);
21221 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
21222 break;
21223 case NM_CMP_LT_PH:
21224 check_dsp(ctx);
21225 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
21226 break;
21227 case NM_CMP_LE_PH:
21228 check_dsp(ctx);
21229 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
21230 break;
21231 case NM_CMPU_EQ_QB:
21232 check_dsp(ctx);
21233 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
21234 break;
21235 case NM_CMPU_LT_QB:
21236 check_dsp(ctx);
21237 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
21238 break;
21239 case NM_CMPU_LE_QB:
21240 check_dsp(ctx);
21241 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
21242 break;
21243 case NM_CMPGU_EQ_QB:
21244 check_dsp(ctx);
21245 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21246 gen_store_gpr(v1_t, ret);
21247 break;
21248 case NM_CMPGU_LT_QB:
21249 check_dsp(ctx);
21250 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21251 gen_store_gpr(v1_t, ret);
21252 break;
21253 case NM_CMPGU_LE_QB:
21254 check_dsp(ctx);
21255 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21256 gen_store_gpr(v1_t, ret);
21257 break;
21258 case NM_CMPGDU_EQ_QB:
21259 check_dsp_r2(ctx);
21260 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
21261 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21262 gen_store_gpr(v1_t, ret);
21263 break;
21264 case NM_CMPGDU_LT_QB:
21265 check_dsp_r2(ctx);
21266 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
21267 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21268 gen_store_gpr(v1_t, ret);
21269 break;
21270 case NM_CMPGDU_LE_QB:
21271 check_dsp_r2(ctx);
21272 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
21273 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
21274 gen_store_gpr(v1_t, ret);
21275 break;
21276 case NM_PACKRL_PH:
21277 check_dsp(ctx);
21278 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
21279 gen_store_gpr(v1_t, ret);
21280 break;
21281 case NM_PICK_QB:
21282 check_dsp(ctx);
21283 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
21284 gen_store_gpr(v1_t, ret);
21285 break;
21286 case NM_PICK_PH:
21287 check_dsp(ctx);
21288 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
21289 gen_store_gpr(v1_t, ret);
21290 break;
21291 case NM_ADDQ_S_W:
21292 check_dsp(ctx);
21293 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
21294 gen_store_gpr(v1_t, ret);
21295 break;
21296 case NM_SUBQ_S_W:
21297 check_dsp(ctx);
21298 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
21299 gen_store_gpr(v1_t, ret);
21300 break;
21301 case NM_ADDSC:
21302 check_dsp(ctx);
21303 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
21304 gen_store_gpr(v1_t, ret);
21305 break;
21306 case NM_ADDWC:
21307 check_dsp(ctx);
21308 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
21309 gen_store_gpr(v1_t, ret);
21310 break;
21311 case NM_ADDQ_S_PH:
21312 check_dsp(ctx);
21313 switch (extract32(ctx->opcode, 10, 1)) {
21314 case 0:
21315 /* ADDQ_PH */
21316 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
21317 gen_store_gpr(v1_t, ret);
21318 break;
21319 case 1:
21320 /* ADDQ_S_PH */
21321 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21322 gen_store_gpr(v1_t, ret);
21323 break;
21325 break;
21326 case NM_ADDQH_R_PH:
21327 check_dsp_r2(ctx);
21328 switch (extract32(ctx->opcode, 10, 1)) {
21329 case 0:
21330 /* ADDQH_PH */
21331 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
21332 gen_store_gpr(v1_t, ret);
21333 break;
21334 case 1:
21335 /* ADDQH_R_PH */
21336 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
21337 gen_store_gpr(v1_t, ret);
21338 break;
21340 break;
21341 case NM_ADDQH_R_W:
21342 check_dsp_r2(ctx);
21343 switch (extract32(ctx->opcode, 10, 1)) {
21344 case 0:
21345 /* ADDQH_W */
21346 gen_helper_addqh_w(v1_t, v1_t, v2_t);
21347 gen_store_gpr(v1_t, ret);
21348 break;
21349 case 1:
21350 /* ADDQH_R_W */
21351 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
21352 gen_store_gpr(v1_t, ret);
21353 break;
21355 break;
21356 case NM_ADDU_S_QB:
21357 check_dsp(ctx);
21358 switch (extract32(ctx->opcode, 10, 1)) {
21359 case 0:
21360 /* ADDU_QB */
21361 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
21362 gen_store_gpr(v1_t, ret);
21363 break;
21364 case 1:
21365 /* ADDU_S_QB */
21366 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21367 gen_store_gpr(v1_t, ret);
21368 break;
21370 break;
21371 case NM_ADDU_S_PH:
21372 check_dsp_r2(ctx);
21373 switch (extract32(ctx->opcode, 10, 1)) {
21374 case 0:
21375 /* ADDU_PH */
21376 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
21377 gen_store_gpr(v1_t, ret);
21378 break;
21379 case 1:
21380 /* ADDU_S_PH */
21381 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21382 gen_store_gpr(v1_t, ret);
21383 break;
21385 break;
21386 case NM_ADDUH_R_QB:
21387 check_dsp_r2(ctx);
21388 switch (extract32(ctx->opcode, 10, 1)) {
21389 case 0:
21390 /* ADDUH_QB */
21391 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
21392 gen_store_gpr(v1_t, ret);
21393 break;
21394 case 1:
21395 /* ADDUH_R_QB */
21396 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
21397 gen_store_gpr(v1_t, ret);
21398 break;
21400 break;
21401 case NM_SHRAV_R_PH:
21402 check_dsp(ctx);
21403 switch (extract32(ctx->opcode, 10, 1)) {
21404 case 0:
21405 /* SHRAV_PH */
21406 gen_helper_shra_ph(v1_t, v1_t, v2_t);
21407 gen_store_gpr(v1_t, ret);
21408 break;
21409 case 1:
21410 /* SHRAV_R_PH */
21411 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
21412 gen_store_gpr(v1_t, ret);
21413 break;
21415 break;
21416 case NM_SHRAV_R_QB:
21417 check_dsp_r2(ctx);
21418 switch (extract32(ctx->opcode, 10, 1)) {
21419 case 0:
21420 /* SHRAV_QB */
21421 gen_helper_shra_qb(v1_t, v1_t, v2_t);
21422 gen_store_gpr(v1_t, ret);
21423 break;
21424 case 1:
21425 /* SHRAV_R_QB */
21426 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
21427 gen_store_gpr(v1_t, ret);
21428 break;
21430 break;
21431 case NM_SUBQ_S_PH:
21432 check_dsp(ctx);
21433 switch (extract32(ctx->opcode, 10, 1)) {
21434 case 0:
21435 /* SUBQ_PH */
21436 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
21437 gen_store_gpr(v1_t, ret);
21438 break;
21439 case 1:
21440 /* SUBQ_S_PH */
21441 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21442 gen_store_gpr(v1_t, ret);
21443 break;
21445 break;
21446 case NM_SUBQH_R_PH:
21447 check_dsp_r2(ctx);
21448 switch (extract32(ctx->opcode, 10, 1)) {
21449 case 0:
21450 /* SUBQH_PH */
21451 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
21452 gen_store_gpr(v1_t, ret);
21453 break;
21454 case 1:
21455 /* SUBQH_R_PH */
21456 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
21457 gen_store_gpr(v1_t, ret);
21458 break;
21460 break;
21461 case NM_SUBQH_R_W:
21462 check_dsp_r2(ctx);
21463 switch (extract32(ctx->opcode, 10, 1)) {
21464 case 0:
21465 /* SUBQH_W */
21466 gen_helper_subqh_w(v1_t, v1_t, v2_t);
21467 gen_store_gpr(v1_t, ret);
21468 break;
21469 case 1:
21470 /* SUBQH_R_W */
21471 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
21472 gen_store_gpr(v1_t, ret);
21473 break;
21475 break;
21476 case NM_SUBU_S_QB:
21477 check_dsp(ctx);
21478 switch (extract32(ctx->opcode, 10, 1)) {
21479 case 0:
21480 /* SUBU_QB */
21481 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
21482 gen_store_gpr(v1_t, ret);
21483 break;
21484 case 1:
21485 /* SUBU_S_QB */
21486 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
21487 gen_store_gpr(v1_t, ret);
21488 break;
21490 break;
21491 case NM_SUBU_S_PH:
21492 check_dsp_r2(ctx);
21493 switch (extract32(ctx->opcode, 10, 1)) {
21494 case 0:
21495 /* SUBU_PH */
21496 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
21497 gen_store_gpr(v1_t, ret);
21498 break;
21499 case 1:
21500 /* SUBU_S_PH */
21501 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
21502 gen_store_gpr(v1_t, ret);
21503 break;
21505 break;
21506 case NM_SUBUH_R_QB:
21507 check_dsp_r2(ctx);
21508 switch (extract32(ctx->opcode, 10, 1)) {
21509 case 0:
21510 /* SUBUH_QB */
21511 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
21512 gen_store_gpr(v1_t, ret);
21513 break;
21514 case 1:
21515 /* SUBUH_R_QB */
21516 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
21517 gen_store_gpr(v1_t, ret);
21518 break;
21520 break;
21521 case NM_SHLLV_S_PH:
21522 check_dsp(ctx);
21523 switch (extract32(ctx->opcode, 10, 1)) {
21524 case 0:
21525 /* SHLLV_PH */
21526 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
21527 gen_store_gpr(v1_t, ret);
21528 break;
21529 case 1:
21530 /* SHLLV_S_PH */
21531 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
21532 gen_store_gpr(v1_t, ret);
21533 break;
21535 break;
21536 case NM_PRECR_SRA_R_PH_W:
21537 check_dsp_r2(ctx);
21538 switch (extract32(ctx->opcode, 10, 1)) {
21539 case 0:
21540 /* PRECR_SRA_PH_W */
21542 TCGv_i32 sa_t = tcg_const_i32(rd);
21543 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
21544 cpu_gpr[rt]);
21545 gen_store_gpr(v1_t, rt);
21546 tcg_temp_free_i32(sa_t);
21548 break;
21549 case 1:
21550 /* PRECR_SRA_R_PH_W */
21552 TCGv_i32 sa_t = tcg_const_i32(rd);
21553 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
21554 cpu_gpr[rt]);
21555 gen_store_gpr(v1_t, rt);
21556 tcg_temp_free_i32(sa_t);
21558 break;
21560 break;
21561 case NM_MULEU_S_PH_QBL:
21562 check_dsp(ctx);
21563 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
21564 gen_store_gpr(v1_t, ret);
21565 break;
21566 case NM_MULEU_S_PH_QBR:
21567 check_dsp(ctx);
21568 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
21569 gen_store_gpr(v1_t, ret);
21570 break;
21571 case NM_MULQ_RS_PH:
21572 check_dsp(ctx);
21573 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
21574 gen_store_gpr(v1_t, ret);
21575 break;
21576 case NM_MULQ_S_PH:
21577 check_dsp_r2(ctx);
21578 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
21579 gen_store_gpr(v1_t, ret);
21580 break;
21581 case NM_MULQ_RS_W:
21582 check_dsp_r2(ctx);
21583 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
21584 gen_store_gpr(v1_t, ret);
21585 break;
21586 case NM_MULQ_S_W:
21587 check_dsp_r2(ctx);
21588 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
21589 gen_store_gpr(v1_t, ret);
21590 break;
21591 case NM_APPEND:
21592 check_dsp_r2(ctx);
21593 gen_load_gpr(t0, rs);
21594 if (rd != 0) {
21595 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
21597 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21598 break;
21599 case NM_MODSUB:
21600 check_dsp(ctx);
21601 gen_helper_modsub(v1_t, v1_t, v2_t);
21602 gen_store_gpr(v1_t, ret);
21603 break;
21604 case NM_SHRAV_R_W:
21605 check_dsp(ctx);
21606 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
21607 gen_store_gpr(v1_t, ret);
21608 break;
21609 case NM_SHRLV_PH:
21610 check_dsp_r2(ctx);
21611 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
21612 gen_store_gpr(v1_t, ret);
21613 break;
21614 case NM_SHRLV_QB:
21615 check_dsp(ctx);
21616 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
21617 gen_store_gpr(v1_t, ret);
21618 break;
21619 case NM_SHLLV_QB:
21620 check_dsp(ctx);
21621 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
21622 gen_store_gpr(v1_t, ret);
21623 break;
21624 case NM_SHLLV_S_W:
21625 check_dsp(ctx);
21626 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
21627 gen_store_gpr(v1_t, ret);
21628 break;
21629 case NM_SHILO:
21630 check_dsp(ctx);
21632 TCGv tv0 = tcg_temp_new();
21633 TCGv tv1 = tcg_temp_new();
21634 int16_t imm = extract32(ctx->opcode, 16, 7);
21636 tcg_gen_movi_tl(tv0, rd >> 3);
21637 tcg_gen_movi_tl(tv1, imm);
21638 gen_helper_shilo(tv0, tv1, cpu_env);
21640 break;
21641 case NM_MULEQ_S_W_PHL:
21642 check_dsp(ctx);
21643 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
21644 gen_store_gpr(v1_t, ret);
21645 break;
21646 case NM_MULEQ_S_W_PHR:
21647 check_dsp(ctx);
21648 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
21649 gen_store_gpr(v1_t, ret);
21650 break;
21651 case NM_MUL_S_PH:
21652 check_dsp_r2(ctx);
21653 switch (extract32(ctx->opcode, 10, 1)) {
21654 case 0:
21655 /* MUL_PH */
21656 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
21657 gen_store_gpr(v1_t, ret);
21658 break;
21659 case 1:
21660 /* MUL_S_PH */
21661 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
21662 gen_store_gpr(v1_t, ret);
21663 break;
21665 break;
21666 case NM_PRECR_QB_PH:
21667 check_dsp_r2(ctx);
21668 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
21669 gen_store_gpr(v1_t, ret);
21670 break;
21671 case NM_PRECRQ_QB_PH:
21672 check_dsp(ctx);
21673 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
21674 gen_store_gpr(v1_t, ret);
21675 break;
21676 case NM_PRECRQ_PH_W:
21677 check_dsp(ctx);
21678 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
21679 gen_store_gpr(v1_t, ret);
21680 break;
21681 case NM_PRECRQ_RS_PH_W:
21682 check_dsp(ctx);
21683 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
21684 gen_store_gpr(v1_t, ret);
21685 break;
21686 case NM_PRECRQU_S_QB_PH:
21687 check_dsp(ctx);
21688 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
21689 gen_store_gpr(v1_t, ret);
21690 break;
21691 case NM_SHRA_R_W:
21692 check_dsp(ctx);
21693 tcg_gen_movi_tl(t0, rd);
21694 gen_helper_shra_r_w(v1_t, t0, v1_t);
21695 gen_store_gpr(v1_t, rt);
21696 break;
21697 case NM_SHRA_R_PH:
21698 check_dsp(ctx);
21699 tcg_gen_movi_tl(t0, rd >> 1);
21700 switch (extract32(ctx->opcode, 10, 1)) {
21701 case 0:
21702 /* SHRA_PH */
21703 gen_helper_shra_ph(v1_t, t0, v1_t);
21704 gen_store_gpr(v1_t, rt);
21705 break;
21706 case 1:
21707 /* SHRA_R_PH */
21708 gen_helper_shra_r_ph(v1_t, t0, v1_t);
21709 gen_store_gpr(v1_t, rt);
21710 break;
21712 break;
21713 case NM_SHLL_S_PH:
21714 check_dsp(ctx);
21715 tcg_gen_movi_tl(t0, rd >> 1);
21716 switch (extract32(ctx->opcode, 10, 2)) {
21717 case 0:
21718 /* SHLL_PH */
21719 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
21720 gen_store_gpr(v1_t, rt);
21721 break;
21722 case 2:
21723 /* SHLL_S_PH */
21724 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
21725 gen_store_gpr(v1_t, rt);
21726 break;
21727 default:
21728 generate_exception_end(ctx, EXCP_RI);
21729 break;
21731 break;
21732 case NM_SHLL_S_W:
21733 check_dsp(ctx);
21734 tcg_gen_movi_tl(t0, rd);
21735 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
21736 gen_store_gpr(v1_t, rt);
21737 break;
21738 case NM_REPL_PH:
21739 check_dsp(ctx);
21741 int16_t imm;
21742 imm = sextract32(ctx->opcode, 11, 11);
21743 imm = (int16_t)(imm << 6) >> 6;
21744 if (rt != 0) {
21745 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
21748 break;
21749 default:
21750 generate_exception_end(ctx, EXCP_RI);
21751 break;
21755 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
21757 uint16_t insn;
21758 uint32_t op;
21759 int rt, rs, rd;
21760 int offset;
21761 int imm;
21763 insn = cpu_lduw_code(env, ctx->base.pc_next + 2);
21764 ctx->opcode = (ctx->opcode << 16) | insn;
21766 rt = extract32(ctx->opcode, 21, 5);
21767 rs = extract32(ctx->opcode, 16, 5);
21768 rd = extract32(ctx->opcode, 11, 5);
21770 op = extract32(ctx->opcode, 26, 6);
21771 switch (op) {
21772 case NM_P_ADDIU:
21773 if (rt == 0) {
21774 /* P.RI */
21775 switch (extract32(ctx->opcode, 19, 2)) {
21776 case NM_SIGRIE:
21777 default:
21778 generate_exception_end(ctx, EXCP_RI);
21779 break;
21780 case NM_P_SYSCALL:
21781 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
21782 generate_exception_end(ctx, EXCP_SYSCALL);
21783 } else {
21784 generate_exception_end(ctx, EXCP_RI);
21786 break;
21787 case NM_BREAK:
21788 generate_exception_end(ctx, EXCP_BREAK);
21789 break;
21790 case NM_SDBBP:
21791 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
21792 gen_helper_do_semihosting(cpu_env);
21793 } else {
21794 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21795 generate_exception_end(ctx, EXCP_RI);
21796 } else {
21797 generate_exception_end(ctx, EXCP_DBp);
21800 break;
21802 } else {
21803 /* NM_ADDIU */
21804 imm = extract32(ctx->opcode, 0, 16);
21805 if (rs != 0) {
21806 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
21807 } else {
21808 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21810 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21812 break;
21813 case NM_ADDIUPC:
21814 if (rt != 0) {
21815 offset = sextract32(ctx->opcode, 0, 1) << 21 |
21816 extract32(ctx->opcode, 1, 20) << 1;
21817 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
21818 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21820 break;
21821 case NM_POOL32A:
21822 switch (ctx->opcode & 0x07) {
21823 case NM_POOL32A0:
21824 gen_pool32a0_nanomips_insn(env, ctx);
21825 break;
21826 case NM_POOL32A5:
21828 int32_t op1 = extract32(ctx->opcode, 3, 7);
21829 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
21831 break;
21832 case NM_POOL32A7:
21833 switch (extract32(ctx->opcode, 3, 3)) {
21834 case NM_P_LSX:
21835 gen_p_lsx(ctx, rd, rs, rt);
21836 break;
21837 case NM_LSA:
21839 * In nanoMIPS, the shift field directly encodes the shift
21840 * amount, meaning that the supported shift values are in
21841 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
21843 gen_lsa(ctx, OPC_LSA, rd, rs, rt,
21844 extract32(ctx->opcode, 9, 2) - 1);
21845 break;
21846 case NM_EXTW:
21847 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
21848 break;
21849 case NM_POOL32AXF:
21850 gen_pool32axf_nanomips_insn(env, ctx);
21851 break;
21852 default:
21853 generate_exception_end(ctx, EXCP_RI);
21854 break;
21856 break;
21857 default:
21858 generate_exception_end(ctx, EXCP_RI);
21859 break;
21861 break;
21862 case NM_P_GP_W:
21863 switch (ctx->opcode & 0x03) {
21864 case NM_ADDIUGP_W:
21865 if (rt != 0) {
21866 offset = extract32(ctx->opcode, 0, 21);
21867 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
21869 break;
21870 case NM_LWGP:
21871 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21872 break;
21873 case NM_SWGP:
21874 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
21875 break;
21876 default:
21877 generate_exception_end(ctx, EXCP_RI);
21878 break;
21880 break;
21881 case NM_P48I:
21883 insn = cpu_lduw_code(env, ctx->base.pc_next + 4);
21884 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
21885 switch (extract32(ctx->opcode, 16, 5)) {
21886 case NM_LI48:
21887 check_nms(ctx);
21888 if (rt != 0) {
21889 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
21891 break;
21892 case NM_ADDIU48:
21893 check_nms(ctx);
21894 if (rt != 0) {
21895 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
21896 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
21898 break;
21899 case NM_ADDIUGP48:
21900 check_nms(ctx);
21901 if (rt != 0) {
21902 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
21904 break;
21905 case NM_ADDIUPC48:
21906 check_nms(ctx);
21907 if (rt != 0) {
21908 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21909 addr_off);
21911 tcg_gen_movi_tl(cpu_gpr[rt], addr);
21913 break;
21914 case NM_LWPC48:
21915 check_nms(ctx);
21916 if (rt != 0) {
21917 TCGv t0;
21918 t0 = tcg_temp_new();
21920 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21921 addr_off);
21923 tcg_gen_movi_tl(t0, addr);
21924 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
21925 tcg_temp_free(t0);
21927 break;
21928 case NM_SWPC48:
21929 check_nms(ctx);
21931 TCGv t0, t1;
21932 t0 = tcg_temp_new();
21933 t1 = tcg_temp_new();
21935 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
21936 addr_off);
21938 tcg_gen_movi_tl(t0, addr);
21939 gen_load_gpr(t1, rt);
21941 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
21943 tcg_temp_free(t0);
21944 tcg_temp_free(t1);
21946 break;
21947 default:
21948 generate_exception_end(ctx, EXCP_RI);
21949 break;
21951 return 6;
21953 case NM_P_U12:
21954 switch (extract32(ctx->opcode, 12, 4)) {
21955 case NM_ORI:
21956 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
21957 break;
21958 case NM_XORI:
21959 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
21960 break;
21961 case NM_ANDI:
21962 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
21963 break;
21964 case NM_P_SR:
21965 switch (extract32(ctx->opcode, 20, 1)) {
21966 case NM_PP_SR:
21967 switch (ctx->opcode & 3) {
21968 case NM_SAVE:
21969 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
21970 extract32(ctx->opcode, 2, 1),
21971 extract32(ctx->opcode, 3, 9) << 3);
21972 break;
21973 case NM_RESTORE:
21974 case NM_RESTORE_JRC:
21975 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
21976 extract32(ctx->opcode, 2, 1),
21977 extract32(ctx->opcode, 3, 9) << 3);
21978 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
21979 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21981 break;
21982 default:
21983 generate_exception_end(ctx, EXCP_RI);
21984 break;
21986 break;
21987 case NM_P_SR_F:
21988 generate_exception_end(ctx, EXCP_RI);
21989 break;
21991 break;
21992 case NM_SLTI:
21993 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
21994 break;
21995 case NM_SLTIU:
21996 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
21997 break;
21998 case NM_SEQI:
22000 TCGv t0 = tcg_temp_new();
22002 imm = extract32(ctx->opcode, 0, 12);
22003 gen_load_gpr(t0, rs);
22004 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
22005 gen_store_gpr(t0, rt);
22007 tcg_temp_free(t0);
22009 break;
22010 case NM_ADDIUNEG:
22011 imm = (int16_t) extract32(ctx->opcode, 0, 12);
22012 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
22013 break;
22014 case NM_P_SHIFT:
22016 int shift = extract32(ctx->opcode, 0, 5);
22017 switch (extract32(ctx->opcode, 5, 4)) {
22018 case NM_P_SLL:
22019 if (rt == 0 && shift == 0) {
22020 /* NOP */
22021 } else if (rt == 0 && shift == 3) {
22022 /* EHB - treat as NOP */
22023 } else if (rt == 0 && shift == 5) {
22024 /* PAUSE - treat as NOP */
22025 } else if (rt == 0 && shift == 6) {
22026 /* SYNC */
22027 gen_sync(extract32(ctx->opcode, 16, 5));
22028 } else {
22029 /* SLL */
22030 gen_shift_imm(ctx, OPC_SLL, rt, rs,
22031 extract32(ctx->opcode, 0, 5));
22033 break;
22034 case NM_SRL:
22035 gen_shift_imm(ctx, OPC_SRL, rt, rs,
22036 extract32(ctx->opcode, 0, 5));
22037 break;
22038 case NM_SRA:
22039 gen_shift_imm(ctx, OPC_SRA, rt, rs,
22040 extract32(ctx->opcode, 0, 5));
22041 break;
22042 case NM_ROTR:
22043 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
22044 extract32(ctx->opcode, 0, 5));
22045 break;
22048 break;
22049 case NM_P_ROTX:
22050 check_nms(ctx);
22051 if (rt != 0) {
22052 TCGv t0 = tcg_temp_new();
22053 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
22054 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
22055 << 1);
22056 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
22058 gen_load_gpr(t0, rs);
22059 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
22060 tcg_temp_free(t0);
22062 tcg_temp_free_i32(shift);
22063 tcg_temp_free_i32(shiftx);
22064 tcg_temp_free_i32(stripe);
22066 break;
22067 case NM_P_INS:
22068 switch (((ctx->opcode >> 10) & 2) |
22069 (extract32(ctx->opcode, 5, 1))) {
22070 case NM_INS:
22071 check_nms(ctx);
22072 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
22073 extract32(ctx->opcode, 6, 5));
22074 break;
22075 default:
22076 generate_exception_end(ctx, EXCP_RI);
22077 break;
22079 break;
22080 case NM_P_EXT:
22081 switch (((ctx->opcode >> 10) & 2) |
22082 (extract32(ctx->opcode, 5, 1))) {
22083 case NM_EXT:
22084 check_nms(ctx);
22085 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
22086 extract32(ctx->opcode, 6, 5));
22087 break;
22088 default:
22089 generate_exception_end(ctx, EXCP_RI);
22090 break;
22092 break;
22093 default:
22094 generate_exception_end(ctx, EXCP_RI);
22095 break;
22097 break;
22098 case NM_POOL32F:
22099 gen_pool32f_nanomips_insn(ctx);
22100 break;
22101 case NM_POOL32S:
22102 break;
22103 case NM_P_LUI:
22104 switch (extract32(ctx->opcode, 1, 1)) {
22105 case NM_LUI:
22106 if (rt != 0) {
22107 tcg_gen_movi_tl(cpu_gpr[rt],
22108 sextract32(ctx->opcode, 0, 1) << 31 |
22109 extract32(ctx->opcode, 2, 10) << 21 |
22110 extract32(ctx->opcode, 12, 9) << 12);
22112 break;
22113 case NM_ALUIPC:
22114 if (rt != 0) {
22115 offset = sextract32(ctx->opcode, 0, 1) << 31 |
22116 extract32(ctx->opcode, 2, 10) << 21 |
22117 extract32(ctx->opcode, 12, 9) << 12;
22118 target_long addr;
22119 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
22120 tcg_gen_movi_tl(cpu_gpr[rt], addr);
22122 break;
22124 break;
22125 case NM_P_GP_BH:
22127 uint32_t u = extract32(ctx->opcode, 0, 18);
22129 switch (extract32(ctx->opcode, 18, 3)) {
22130 case NM_LBGP:
22131 gen_ld(ctx, OPC_LB, rt, 28, u);
22132 break;
22133 case NM_SBGP:
22134 gen_st(ctx, OPC_SB, rt, 28, u);
22135 break;
22136 case NM_LBUGP:
22137 gen_ld(ctx, OPC_LBU, rt, 28, u);
22138 break;
22139 case NM_ADDIUGP_B:
22140 if (rt != 0) {
22141 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
22143 break;
22144 case NM_P_GP_LH:
22145 u &= ~1;
22146 switch (ctx->opcode & 1) {
22147 case NM_LHGP:
22148 gen_ld(ctx, OPC_LH, rt, 28, u);
22149 break;
22150 case NM_LHUGP:
22151 gen_ld(ctx, OPC_LHU, rt, 28, u);
22152 break;
22154 break;
22155 case NM_P_GP_SH:
22156 u &= ~1;
22157 switch (ctx->opcode & 1) {
22158 case NM_SHGP:
22159 gen_st(ctx, OPC_SH, rt, 28, u);
22160 break;
22161 default:
22162 generate_exception_end(ctx, EXCP_RI);
22163 break;
22165 break;
22166 case NM_P_GP_CP1:
22167 u &= ~0x3;
22168 switch (ctx->opcode & 0x3) {
22169 case NM_LWC1GP:
22170 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
22171 break;
22172 case NM_LDC1GP:
22173 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
22174 break;
22175 case NM_SWC1GP:
22176 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
22177 break;
22178 case NM_SDC1GP:
22179 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
22180 break;
22182 break;
22183 default:
22184 generate_exception_end(ctx, EXCP_RI);
22185 break;
22188 break;
22189 case NM_P_LS_U12:
22191 uint32_t u = extract32(ctx->opcode, 0, 12);
22193 switch (extract32(ctx->opcode, 12, 4)) {
22194 case NM_P_PREFU12:
22195 if (rt == 31) {
22196 /* SYNCI */
22198 * Break the TB to be able to sync copied instructions
22199 * immediately.
22201 ctx->base.is_jmp = DISAS_STOP;
22202 } else {
22203 /* PREF */
22204 /* Treat as NOP. */
22206 break;
22207 case NM_LB:
22208 gen_ld(ctx, OPC_LB, rt, rs, u);
22209 break;
22210 case NM_LH:
22211 gen_ld(ctx, OPC_LH, rt, rs, u);
22212 break;
22213 case NM_LW:
22214 gen_ld(ctx, OPC_LW, rt, rs, u);
22215 break;
22216 case NM_LBU:
22217 gen_ld(ctx, OPC_LBU, rt, rs, u);
22218 break;
22219 case NM_LHU:
22220 gen_ld(ctx, OPC_LHU, rt, rs, u);
22221 break;
22222 case NM_SB:
22223 gen_st(ctx, OPC_SB, rt, rs, u);
22224 break;
22225 case NM_SH:
22226 gen_st(ctx, OPC_SH, rt, rs, u);
22227 break;
22228 case NM_SW:
22229 gen_st(ctx, OPC_SW, rt, rs, u);
22230 break;
22231 case NM_LWC1:
22232 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
22233 break;
22234 case NM_LDC1:
22235 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
22236 break;
22237 case NM_SWC1:
22238 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
22239 break;
22240 case NM_SDC1:
22241 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
22242 break;
22243 default:
22244 generate_exception_end(ctx, EXCP_RI);
22245 break;
22248 break;
22249 case NM_P_LS_S9:
22251 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
22252 extract32(ctx->opcode, 0, 8);
22254 switch (extract32(ctx->opcode, 8, 3)) {
22255 case NM_P_LS_S0:
22256 switch (extract32(ctx->opcode, 11, 4)) {
22257 case NM_LBS9:
22258 gen_ld(ctx, OPC_LB, rt, rs, s);
22259 break;
22260 case NM_LHS9:
22261 gen_ld(ctx, OPC_LH, rt, rs, s);
22262 break;
22263 case NM_LWS9:
22264 gen_ld(ctx, OPC_LW, rt, rs, s);
22265 break;
22266 case NM_LBUS9:
22267 gen_ld(ctx, OPC_LBU, rt, rs, s);
22268 break;
22269 case NM_LHUS9:
22270 gen_ld(ctx, OPC_LHU, rt, rs, s);
22271 break;
22272 case NM_SBS9:
22273 gen_st(ctx, OPC_SB, rt, rs, s);
22274 break;
22275 case NM_SHS9:
22276 gen_st(ctx, OPC_SH, rt, rs, s);
22277 break;
22278 case NM_SWS9:
22279 gen_st(ctx, OPC_SW, rt, rs, s);
22280 break;
22281 case NM_LWC1S9:
22282 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
22283 break;
22284 case NM_LDC1S9:
22285 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
22286 break;
22287 case NM_SWC1S9:
22288 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
22289 break;
22290 case NM_SDC1S9:
22291 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
22292 break;
22293 case NM_P_PREFS9:
22294 if (rt == 31) {
22295 /* SYNCI */
22297 * Break the TB to be able to sync copied instructions
22298 * immediately.
22300 ctx->base.is_jmp = DISAS_STOP;
22301 } else {
22302 /* PREF */
22303 /* Treat as NOP. */
22305 break;
22306 default:
22307 generate_exception_end(ctx, EXCP_RI);
22308 break;
22310 break;
22311 case NM_P_LS_S1:
22312 switch (extract32(ctx->opcode, 11, 4)) {
22313 case NM_UALH:
22314 case NM_UASH:
22315 check_nms(ctx);
22317 TCGv t0 = tcg_temp_new();
22318 TCGv t1 = tcg_temp_new();
22320 gen_base_offset_addr(ctx, t0, rs, s);
22322 switch (extract32(ctx->opcode, 11, 4)) {
22323 case NM_UALH:
22324 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
22325 MO_UNALN);
22326 gen_store_gpr(t0, rt);
22327 break;
22328 case NM_UASH:
22329 gen_load_gpr(t1, rt);
22330 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
22331 MO_UNALN);
22332 break;
22334 tcg_temp_free(t0);
22335 tcg_temp_free(t1);
22337 break;
22338 case NM_P_LL:
22339 switch (ctx->opcode & 0x03) {
22340 case NM_LL:
22341 gen_ld(ctx, OPC_LL, rt, rs, s);
22342 break;
22343 case NM_LLWP:
22344 check_xnp(ctx);
22345 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22346 break;
22348 break;
22349 case NM_P_SC:
22350 switch (ctx->opcode & 0x03) {
22351 case NM_SC:
22352 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
22353 break;
22354 case NM_SCWP:
22355 check_xnp(ctx);
22356 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22357 false);
22358 break;
22360 break;
22361 case NM_CACHE:
22362 check_cp0_enabled(ctx);
22363 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
22364 gen_cache_operation(ctx, rt, rs, s);
22366 break;
22368 break;
22369 case NM_P_LS_E0:
22370 switch (extract32(ctx->opcode, 11, 4)) {
22371 case NM_LBE:
22372 check_eva(ctx);
22373 check_cp0_enabled(ctx);
22374 gen_ld(ctx, OPC_LBE, rt, rs, s);
22375 break;
22376 case NM_SBE:
22377 check_eva(ctx);
22378 check_cp0_enabled(ctx);
22379 gen_st(ctx, OPC_SBE, rt, rs, s);
22380 break;
22381 case NM_LBUE:
22382 check_eva(ctx);
22383 check_cp0_enabled(ctx);
22384 gen_ld(ctx, OPC_LBUE, rt, rs, s);
22385 break;
22386 case NM_P_PREFE:
22387 if (rt == 31) {
22388 /* case NM_SYNCIE */
22389 check_eva(ctx);
22390 check_cp0_enabled(ctx);
22392 * Break the TB to be able to sync copied instructions
22393 * immediately.
22395 ctx->base.is_jmp = DISAS_STOP;
22396 } else {
22397 /* case NM_PREFE */
22398 check_eva(ctx);
22399 check_cp0_enabled(ctx);
22400 /* Treat as NOP. */
22402 break;
22403 case NM_LHE:
22404 check_eva(ctx);
22405 check_cp0_enabled(ctx);
22406 gen_ld(ctx, OPC_LHE, rt, rs, s);
22407 break;
22408 case NM_SHE:
22409 check_eva(ctx);
22410 check_cp0_enabled(ctx);
22411 gen_st(ctx, OPC_SHE, rt, rs, s);
22412 break;
22413 case NM_LHUE:
22414 check_eva(ctx);
22415 check_cp0_enabled(ctx);
22416 gen_ld(ctx, OPC_LHUE, rt, rs, s);
22417 break;
22418 case NM_CACHEE:
22419 check_nms_dl_il_sl_tl_l2c(ctx);
22420 gen_cache_operation(ctx, rt, rs, s);
22421 break;
22422 case NM_LWE:
22423 check_eva(ctx);
22424 check_cp0_enabled(ctx);
22425 gen_ld(ctx, OPC_LWE, rt, rs, s);
22426 break;
22427 case NM_SWE:
22428 check_eva(ctx);
22429 check_cp0_enabled(ctx);
22430 gen_st(ctx, OPC_SWE, rt, rs, s);
22431 break;
22432 case NM_P_LLE:
22433 switch (extract32(ctx->opcode, 2, 2)) {
22434 case NM_LLE:
22435 check_xnp(ctx);
22436 check_eva(ctx);
22437 check_cp0_enabled(ctx);
22438 gen_ld(ctx, OPC_LLE, rt, rs, s);
22439 break;
22440 case NM_LLWPE:
22441 check_xnp(ctx);
22442 check_eva(ctx);
22443 check_cp0_enabled(ctx);
22444 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
22445 break;
22446 default:
22447 generate_exception_end(ctx, EXCP_RI);
22448 break;
22450 break;
22451 case NM_P_SCE:
22452 switch (extract32(ctx->opcode, 2, 2)) {
22453 case NM_SCE:
22454 check_xnp(ctx);
22455 check_eva(ctx);
22456 check_cp0_enabled(ctx);
22457 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
22458 break;
22459 case NM_SCWPE:
22460 check_xnp(ctx);
22461 check_eva(ctx);
22462 check_cp0_enabled(ctx);
22463 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
22464 true);
22465 break;
22466 default:
22467 generate_exception_end(ctx, EXCP_RI);
22468 break;
22470 break;
22472 break;
22473 case NM_P_LS_WM:
22474 case NM_P_LS_UAWM:
22475 check_nms(ctx);
22477 int count = extract32(ctx->opcode, 12, 3);
22478 int counter = 0;
22480 offset = sextract32(ctx->opcode, 15, 1) << 8 |
22481 extract32(ctx->opcode, 0, 8);
22482 TCGv va = tcg_temp_new();
22483 TCGv t1 = tcg_temp_new();
22484 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
22485 NM_P_LS_UAWM ? MO_UNALN : 0;
22487 count = (count == 0) ? 8 : count;
22488 while (counter != count) {
22489 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
22490 int this_offset = offset + (counter << 2);
22492 gen_base_offset_addr(ctx, va, rs, this_offset);
22494 switch (extract32(ctx->opcode, 11, 1)) {
22495 case NM_LWM:
22496 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
22497 memop | MO_TESL);
22498 gen_store_gpr(t1, this_rt);
22499 if ((this_rt == rs) &&
22500 (counter != (count - 1))) {
22501 /* UNPREDICTABLE */
22503 break;
22504 case NM_SWM:
22505 this_rt = (rt == 0) ? 0 : this_rt;
22506 gen_load_gpr(t1, this_rt);
22507 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
22508 memop | MO_TEUL);
22509 break;
22511 counter++;
22513 tcg_temp_free(va);
22514 tcg_temp_free(t1);
22516 break;
22517 default:
22518 generate_exception_end(ctx, EXCP_RI);
22519 break;
22522 break;
22523 case NM_MOVE_BALC:
22524 check_nms(ctx);
22526 TCGv t0 = tcg_temp_new();
22527 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
22528 extract32(ctx->opcode, 1, 20) << 1;
22529 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
22530 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
22531 extract32(ctx->opcode, 21, 3));
22532 gen_load_gpr(t0, rt);
22533 tcg_gen_mov_tl(cpu_gpr[rd], t0);
22534 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22535 tcg_temp_free(t0);
22537 break;
22538 case NM_P_BAL:
22540 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
22541 extract32(ctx->opcode, 1, 24) << 1;
22543 if ((extract32(ctx->opcode, 25, 1)) == 0) {
22544 /* BC */
22545 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
22546 } else {
22547 /* BALC */
22548 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
22551 break;
22552 case NM_P_J:
22553 switch (extract32(ctx->opcode, 12, 4)) {
22554 case NM_JALRC:
22555 case NM_JALRC_HB:
22556 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
22557 break;
22558 case NM_P_BALRSC:
22559 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
22560 break;
22561 default:
22562 generate_exception_end(ctx, EXCP_RI);
22563 break;
22565 break;
22566 case NM_P_BR1:
22568 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22569 extract32(ctx->opcode, 1, 13) << 1;
22570 switch (extract32(ctx->opcode, 14, 2)) {
22571 case NM_BEQC:
22572 check_nms(ctx);
22573 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
22574 break;
22575 case NM_P_BR3A:
22576 s = sextract32(ctx->opcode, 0, 1) << 14 |
22577 extract32(ctx->opcode, 1, 13) << 1;
22578 check_cp1_enabled(ctx);
22579 switch (extract32(ctx->opcode, 16, 5)) {
22580 case NM_BC1EQZC:
22581 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
22582 break;
22583 case NM_BC1NEZC:
22584 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
22585 break;
22586 case NM_BPOSGE32C:
22587 check_dsp_r3(ctx);
22589 int32_t imm = extract32(ctx->opcode, 1, 13) |
22590 extract32(ctx->opcode, 0, 1) << 13;
22592 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
22593 imm);
22595 break;
22596 default:
22597 generate_exception_end(ctx, EXCP_RI);
22598 break;
22600 break;
22601 case NM_BGEC:
22602 if (rs == rt) {
22603 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
22604 } else {
22605 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
22607 break;
22608 case NM_BGEUC:
22609 if (rs == rt || rt == 0) {
22610 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
22611 } else if (rs == 0) {
22612 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
22613 } else {
22614 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
22616 break;
22619 break;
22620 case NM_P_BR2:
22622 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
22623 extract32(ctx->opcode, 1, 13) << 1;
22624 switch (extract32(ctx->opcode, 14, 2)) {
22625 case NM_BNEC:
22626 check_nms(ctx);
22627 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
22628 break;
22629 case NM_BLTC:
22630 if (rs != 0 && rt != 0 && rs == rt) {
22631 /* NOP */
22632 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22633 } else {
22634 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
22636 break;
22637 case NM_BLTUC:
22638 if (rs == 0 || rs == rt) {
22639 /* NOP */
22640 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
22641 } else {
22642 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
22644 break;
22645 default:
22646 generate_exception_end(ctx, EXCP_RI);
22647 break;
22650 break;
22651 case NM_P_BRI:
22653 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
22654 extract32(ctx->opcode, 1, 10) << 1;
22655 uint32_t u = extract32(ctx->opcode, 11, 7);
22657 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
22658 rt, u, s);
22660 break;
22661 default:
22662 generate_exception_end(ctx, EXCP_RI);
22663 break;
22665 return 4;
22668 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
22670 uint32_t op;
22671 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
22672 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22673 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
22674 int offset;
22675 int imm;
22677 /* make sure instructions are on a halfword boundary */
22678 if (ctx->base.pc_next & 0x1) {
22679 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
22680 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
22681 tcg_temp_free(tmp);
22682 generate_exception_end(ctx, EXCP_AdEL);
22683 return 2;
22686 op = extract32(ctx->opcode, 10, 6);
22687 switch (op) {
22688 case NM_P16_MV:
22689 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22690 if (rt != 0) {
22691 /* MOVE */
22692 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
22693 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
22694 } else {
22695 /* P16.RI */
22696 switch (extract32(ctx->opcode, 3, 2)) {
22697 case NM_P16_SYSCALL:
22698 if (extract32(ctx->opcode, 2, 1) == 0) {
22699 generate_exception_end(ctx, EXCP_SYSCALL);
22700 } else {
22701 generate_exception_end(ctx, EXCP_RI);
22703 break;
22704 case NM_BREAK16:
22705 generate_exception_end(ctx, EXCP_BREAK);
22706 break;
22707 case NM_SDBBP16:
22708 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
22709 gen_helper_do_semihosting(cpu_env);
22710 } else {
22711 if (ctx->hflags & MIPS_HFLAG_SBRI) {
22712 generate_exception_end(ctx, EXCP_RI);
22713 } else {
22714 generate_exception_end(ctx, EXCP_DBp);
22717 break;
22718 default:
22719 generate_exception_end(ctx, EXCP_RI);
22720 break;
22723 break;
22724 case NM_P16_SHIFT:
22726 int shift = extract32(ctx->opcode, 0, 3);
22727 uint32_t opc = 0;
22728 shift = (shift == 0) ? 8 : shift;
22730 switch (extract32(ctx->opcode, 3, 1)) {
22731 case NM_SLL16:
22732 opc = OPC_SLL;
22733 break;
22734 case NM_SRL16:
22735 opc = OPC_SRL;
22736 break;
22738 gen_shift_imm(ctx, opc, rt, rs, shift);
22740 break;
22741 case NM_P16C:
22742 switch (ctx->opcode & 1) {
22743 case NM_POOL16C_0:
22744 gen_pool16c_nanomips_insn(ctx);
22745 break;
22746 case NM_LWXS16:
22747 gen_ldxs(ctx, rt, rs, rd);
22748 break;
22750 break;
22751 case NM_P16_A1:
22752 switch (extract32(ctx->opcode, 6, 1)) {
22753 case NM_ADDIUR1SP:
22754 imm = extract32(ctx->opcode, 0, 6) << 2;
22755 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
22756 break;
22757 default:
22758 generate_exception_end(ctx, EXCP_RI);
22759 break;
22761 break;
22762 case NM_P16_A2:
22763 switch (extract32(ctx->opcode, 3, 1)) {
22764 case NM_ADDIUR2:
22765 imm = extract32(ctx->opcode, 0, 3) << 2;
22766 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
22767 break;
22768 case NM_P_ADDIURS5:
22769 rt = extract32(ctx->opcode, 5, 5);
22770 if (rt != 0) {
22771 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
22772 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
22773 (extract32(ctx->opcode, 0, 3));
22774 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
22776 break;
22778 break;
22779 case NM_P16_ADDU:
22780 switch (ctx->opcode & 0x1) {
22781 case NM_ADDU16:
22782 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
22783 break;
22784 case NM_SUBU16:
22785 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
22786 break;
22788 break;
22789 case NM_P16_4X4:
22790 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22791 extract32(ctx->opcode, 5, 3);
22792 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22793 extract32(ctx->opcode, 0, 3);
22794 rt = decode_gpr_gpr4(rt);
22795 rs = decode_gpr_gpr4(rs);
22796 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
22797 (extract32(ctx->opcode, 3, 1))) {
22798 case NM_ADDU4X4:
22799 check_nms(ctx);
22800 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
22801 break;
22802 case NM_MUL4X4:
22803 check_nms(ctx);
22804 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
22805 break;
22806 default:
22807 generate_exception_end(ctx, EXCP_RI);
22808 break;
22810 break;
22811 case NM_LI16:
22813 int imm = extract32(ctx->opcode, 0, 7);
22814 imm = (imm == 0x7f ? -1 : imm);
22815 if (rt != 0) {
22816 tcg_gen_movi_tl(cpu_gpr[rt], imm);
22819 break;
22820 case NM_ANDI16:
22822 uint32_t u = extract32(ctx->opcode, 0, 4);
22823 u = (u == 12) ? 0xff :
22824 (u == 13) ? 0xffff : u;
22825 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
22827 break;
22828 case NM_P16_LB:
22829 offset = extract32(ctx->opcode, 0, 2);
22830 switch (extract32(ctx->opcode, 2, 2)) {
22831 case NM_LB16:
22832 gen_ld(ctx, OPC_LB, rt, rs, offset);
22833 break;
22834 case NM_SB16:
22835 rt = decode_gpr_gpr3_src_store(
22836 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22837 gen_st(ctx, OPC_SB, rt, rs, offset);
22838 break;
22839 case NM_LBU16:
22840 gen_ld(ctx, OPC_LBU, rt, rs, offset);
22841 break;
22842 default:
22843 generate_exception_end(ctx, EXCP_RI);
22844 break;
22846 break;
22847 case NM_P16_LH:
22848 offset = extract32(ctx->opcode, 1, 2) << 1;
22849 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
22850 case NM_LH16:
22851 gen_ld(ctx, OPC_LH, rt, rs, offset);
22852 break;
22853 case NM_SH16:
22854 rt = decode_gpr_gpr3_src_store(
22855 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22856 gen_st(ctx, OPC_SH, rt, rs, offset);
22857 break;
22858 case NM_LHU16:
22859 gen_ld(ctx, OPC_LHU, rt, rs, offset);
22860 break;
22861 default:
22862 generate_exception_end(ctx, EXCP_RI);
22863 break;
22865 break;
22866 case NM_LW16:
22867 offset = extract32(ctx->opcode, 0, 4) << 2;
22868 gen_ld(ctx, OPC_LW, rt, rs, offset);
22869 break;
22870 case NM_LWSP16:
22871 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22872 offset = extract32(ctx->opcode, 0, 5) << 2;
22873 gen_ld(ctx, OPC_LW, rt, 29, offset);
22874 break;
22875 case NM_LW4X4:
22876 check_nms(ctx);
22877 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22878 extract32(ctx->opcode, 5, 3);
22879 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22880 extract32(ctx->opcode, 0, 3);
22881 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22882 (extract32(ctx->opcode, 8, 1) << 2);
22883 rt = decode_gpr_gpr4(rt);
22884 rs = decode_gpr_gpr4(rs);
22885 gen_ld(ctx, OPC_LW, rt, rs, offset);
22886 break;
22887 case NM_SW4X4:
22888 check_nms(ctx);
22889 rt = (extract32(ctx->opcode, 9, 1) << 3) |
22890 extract32(ctx->opcode, 5, 3);
22891 rs = (extract32(ctx->opcode, 4, 1) << 3) |
22892 extract32(ctx->opcode, 0, 3);
22893 offset = (extract32(ctx->opcode, 3, 1) << 3) |
22894 (extract32(ctx->opcode, 8, 1) << 2);
22895 rt = decode_gpr_gpr4_zero(rt);
22896 rs = decode_gpr_gpr4(rs);
22897 gen_st(ctx, OPC_SW, rt, rs, offset);
22898 break;
22899 case NM_LWGP16:
22900 offset = extract32(ctx->opcode, 0, 7) << 2;
22901 gen_ld(ctx, OPC_LW, rt, 28, offset);
22902 break;
22903 case NM_SWSP16:
22904 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
22905 offset = extract32(ctx->opcode, 0, 5) << 2;
22906 gen_st(ctx, OPC_SW, rt, 29, offset);
22907 break;
22908 case NM_SW16:
22909 rt = decode_gpr_gpr3_src_store(
22910 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22911 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
22912 offset = extract32(ctx->opcode, 0, 4) << 2;
22913 gen_st(ctx, OPC_SW, rt, rs, offset);
22914 break;
22915 case NM_SWGP16:
22916 rt = decode_gpr_gpr3_src_store(
22917 NANOMIPS_EXTRACT_RT3(ctx->opcode));
22918 offset = extract32(ctx->opcode, 0, 7) << 2;
22919 gen_st(ctx, OPC_SW, rt, 28, offset);
22920 break;
22921 case NM_BC16:
22922 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
22923 (sextract32(ctx->opcode, 0, 1) << 10) |
22924 (extract32(ctx->opcode, 1, 9) << 1));
22925 break;
22926 case NM_BALC16:
22927 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
22928 (sextract32(ctx->opcode, 0, 1) << 10) |
22929 (extract32(ctx->opcode, 1, 9) << 1));
22930 break;
22931 case NM_BEQZC16:
22932 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
22933 (sextract32(ctx->opcode, 0, 1) << 7) |
22934 (extract32(ctx->opcode, 1, 6) << 1));
22935 break;
22936 case NM_BNEZC16:
22937 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
22938 (sextract32(ctx->opcode, 0, 1) << 7) |
22939 (extract32(ctx->opcode, 1, 6) << 1));
22940 break;
22941 case NM_P16_BR:
22942 switch (ctx->opcode & 0xf) {
22943 case 0:
22944 /* P16.JRC */
22945 switch (extract32(ctx->opcode, 4, 1)) {
22946 case NM_JRC:
22947 gen_compute_branch_nm(ctx, OPC_JR, 2,
22948 extract32(ctx->opcode, 5, 5), 0, 0);
22949 break;
22950 case NM_JALRC16:
22951 gen_compute_branch_nm(ctx, OPC_JALR, 2,
22952 extract32(ctx->opcode, 5, 5), 31, 0);
22953 break;
22955 break;
22956 default:
22958 /* P16.BRI */
22959 uint32_t opc = extract32(ctx->opcode, 4, 3) <
22960 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
22961 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
22962 extract32(ctx->opcode, 0, 4) << 1);
22964 break;
22966 break;
22967 case NM_P16_SR:
22969 int count = extract32(ctx->opcode, 0, 4);
22970 int u = extract32(ctx->opcode, 4, 4) << 4;
22972 rt = 30 + extract32(ctx->opcode, 9, 1);
22973 switch (extract32(ctx->opcode, 8, 1)) {
22974 case NM_SAVE16:
22975 gen_save(ctx, rt, count, 0, u);
22976 break;
22977 case NM_RESTORE_JRC16:
22978 gen_restore(ctx, rt, count, 0, u);
22979 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
22980 break;
22983 break;
22984 case NM_MOVEP:
22985 case NM_MOVEPREV:
22986 check_nms(ctx);
22988 static const int gpr2reg1[] = {4, 5, 6, 7};
22989 static const int gpr2reg2[] = {5, 6, 7, 8};
22990 int re;
22991 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
22992 extract32(ctx->opcode, 8, 1);
22993 int r1 = gpr2reg1[rd2];
22994 int r2 = gpr2reg2[rd2];
22995 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
22996 extract32(ctx->opcode, 0, 3);
22997 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
22998 extract32(ctx->opcode, 5, 3);
22999 TCGv t0 = tcg_temp_new();
23000 TCGv t1 = tcg_temp_new();
23001 if (op == NM_MOVEP) {
23002 rd = r1;
23003 re = r2;
23004 rs = decode_gpr_gpr4_zero(r3);
23005 rt = decode_gpr_gpr4_zero(r4);
23006 } else {
23007 rd = decode_gpr_gpr4(r3);
23008 re = decode_gpr_gpr4(r4);
23009 rs = r1;
23010 rt = r2;
23012 gen_load_gpr(t0, rs);
23013 gen_load_gpr(t1, rt);
23014 tcg_gen_mov_tl(cpu_gpr[rd], t0);
23015 tcg_gen_mov_tl(cpu_gpr[re], t1);
23016 tcg_temp_free(t0);
23017 tcg_temp_free(t1);
23019 break;
23020 default:
23021 return decode_nanomips_32_48_opc(env, ctx);
23024 return 2;
23028 /* SmartMIPS extension to MIPS32 */
23030 #if defined(TARGET_MIPS64)
23032 /* MDMX extension to MIPS64 */
23034 #endif
23036 /* MIPSDSP functions. */
23037 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
23038 int rd, int base, int offset)
23040 TCGv t0;
23042 check_dsp(ctx);
23043 t0 = tcg_temp_new();
23045 if (base == 0) {
23046 gen_load_gpr(t0, offset);
23047 } else if (offset == 0) {
23048 gen_load_gpr(t0, base);
23049 } else {
23050 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
23053 switch (opc) {
23054 case OPC_LBUX:
23055 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
23056 gen_store_gpr(t0, rd);
23057 break;
23058 case OPC_LHX:
23059 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
23060 gen_store_gpr(t0, rd);
23061 break;
23062 case OPC_LWX:
23063 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
23064 gen_store_gpr(t0, rd);
23065 break;
23066 #if defined(TARGET_MIPS64)
23067 case OPC_LDX:
23068 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
23069 gen_store_gpr(t0, rd);
23070 break;
23071 #endif
23073 tcg_temp_free(t0);
23076 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
23077 int ret, int v1, int v2)
23079 TCGv v1_t;
23080 TCGv v2_t;
23082 if (ret == 0) {
23083 /* Treat as NOP. */
23084 return;
23087 v1_t = tcg_temp_new();
23088 v2_t = tcg_temp_new();
23090 gen_load_gpr(v1_t, v1);
23091 gen_load_gpr(v2_t, v2);
23093 switch (op1) {
23094 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
23095 case OPC_MULT_G_2E:
23096 check_dsp_r2(ctx);
23097 switch (op2) {
23098 case OPC_ADDUH_QB:
23099 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
23100 break;
23101 case OPC_ADDUH_R_QB:
23102 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23103 break;
23104 case OPC_ADDQH_PH:
23105 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
23106 break;
23107 case OPC_ADDQH_R_PH:
23108 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23109 break;
23110 case OPC_ADDQH_W:
23111 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
23112 break;
23113 case OPC_ADDQH_R_W:
23114 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23115 break;
23116 case OPC_SUBUH_QB:
23117 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
23118 break;
23119 case OPC_SUBUH_R_QB:
23120 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
23121 break;
23122 case OPC_SUBQH_PH:
23123 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
23124 break;
23125 case OPC_SUBQH_R_PH:
23126 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
23127 break;
23128 case OPC_SUBQH_W:
23129 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
23130 break;
23131 case OPC_SUBQH_R_W:
23132 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
23133 break;
23135 break;
23136 case OPC_ABSQ_S_PH_DSP:
23137 switch (op2) {
23138 case OPC_ABSQ_S_QB:
23139 check_dsp_r2(ctx);
23140 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
23141 break;
23142 case OPC_ABSQ_S_PH:
23143 check_dsp(ctx);
23144 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
23145 break;
23146 case OPC_ABSQ_S_W:
23147 check_dsp(ctx);
23148 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
23149 break;
23150 case OPC_PRECEQ_W_PHL:
23151 check_dsp(ctx);
23152 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
23153 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23154 break;
23155 case OPC_PRECEQ_W_PHR:
23156 check_dsp(ctx);
23157 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
23158 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
23159 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
23160 break;
23161 case OPC_PRECEQU_PH_QBL:
23162 check_dsp(ctx);
23163 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
23164 break;
23165 case OPC_PRECEQU_PH_QBR:
23166 check_dsp(ctx);
23167 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
23168 break;
23169 case OPC_PRECEQU_PH_QBLA:
23170 check_dsp(ctx);
23171 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
23172 break;
23173 case OPC_PRECEQU_PH_QBRA:
23174 check_dsp(ctx);
23175 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
23176 break;
23177 case OPC_PRECEU_PH_QBL:
23178 check_dsp(ctx);
23179 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
23180 break;
23181 case OPC_PRECEU_PH_QBR:
23182 check_dsp(ctx);
23183 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
23184 break;
23185 case OPC_PRECEU_PH_QBLA:
23186 check_dsp(ctx);
23187 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
23188 break;
23189 case OPC_PRECEU_PH_QBRA:
23190 check_dsp(ctx);
23191 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
23192 break;
23194 break;
23195 case OPC_ADDU_QB_DSP:
23196 switch (op2) {
23197 case OPC_ADDQ_PH:
23198 check_dsp(ctx);
23199 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23200 break;
23201 case OPC_ADDQ_S_PH:
23202 check_dsp(ctx);
23203 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23204 break;
23205 case OPC_ADDQ_S_W:
23206 check_dsp(ctx);
23207 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23208 break;
23209 case OPC_ADDU_QB:
23210 check_dsp(ctx);
23211 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23212 break;
23213 case OPC_ADDU_S_QB:
23214 check_dsp(ctx);
23215 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23216 break;
23217 case OPC_ADDU_PH:
23218 check_dsp_r2(ctx);
23219 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23220 break;
23221 case OPC_ADDU_S_PH:
23222 check_dsp_r2(ctx);
23223 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23224 break;
23225 case OPC_SUBQ_PH:
23226 check_dsp(ctx);
23227 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23228 break;
23229 case OPC_SUBQ_S_PH:
23230 check_dsp(ctx);
23231 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23232 break;
23233 case OPC_SUBQ_S_W:
23234 check_dsp(ctx);
23235 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23236 break;
23237 case OPC_SUBU_QB:
23238 check_dsp(ctx);
23239 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23240 break;
23241 case OPC_SUBU_S_QB:
23242 check_dsp(ctx);
23243 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23244 break;
23245 case OPC_SUBU_PH:
23246 check_dsp_r2(ctx);
23247 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23248 break;
23249 case OPC_SUBU_S_PH:
23250 check_dsp_r2(ctx);
23251 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23252 break;
23253 case OPC_ADDSC:
23254 check_dsp(ctx);
23255 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23256 break;
23257 case OPC_ADDWC:
23258 check_dsp(ctx);
23259 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23260 break;
23261 case OPC_MODSUB:
23262 check_dsp(ctx);
23263 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
23264 break;
23265 case OPC_RADDU_W_QB:
23266 check_dsp(ctx);
23267 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
23268 break;
23270 break;
23271 case OPC_CMPU_EQ_QB_DSP:
23272 switch (op2) {
23273 case OPC_PRECR_QB_PH:
23274 check_dsp_r2(ctx);
23275 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23276 break;
23277 case OPC_PRECRQ_QB_PH:
23278 check_dsp(ctx);
23279 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
23280 break;
23281 case OPC_PRECR_SRA_PH_W:
23282 check_dsp_r2(ctx);
23284 TCGv_i32 sa_t = tcg_const_i32(v2);
23285 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
23286 cpu_gpr[ret]);
23287 tcg_temp_free_i32(sa_t);
23288 break;
23290 case OPC_PRECR_SRA_R_PH_W:
23291 check_dsp_r2(ctx);
23293 TCGv_i32 sa_t = tcg_const_i32(v2);
23294 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
23295 cpu_gpr[ret]);
23296 tcg_temp_free_i32(sa_t);
23297 break;
23299 case OPC_PRECRQ_PH_W:
23300 check_dsp(ctx);
23301 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
23302 break;
23303 case OPC_PRECRQ_RS_PH_W:
23304 check_dsp(ctx);
23305 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23306 break;
23307 case OPC_PRECRQU_S_QB_PH:
23308 check_dsp(ctx);
23309 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23310 break;
23312 break;
23313 #ifdef TARGET_MIPS64
23314 case OPC_ABSQ_S_QH_DSP:
23315 switch (op2) {
23316 case OPC_PRECEQ_L_PWL:
23317 check_dsp(ctx);
23318 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
23319 break;
23320 case OPC_PRECEQ_L_PWR:
23321 check_dsp(ctx);
23322 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
23323 break;
23324 case OPC_PRECEQ_PW_QHL:
23325 check_dsp(ctx);
23326 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
23327 break;
23328 case OPC_PRECEQ_PW_QHR:
23329 check_dsp(ctx);
23330 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
23331 break;
23332 case OPC_PRECEQ_PW_QHLA:
23333 check_dsp(ctx);
23334 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
23335 break;
23336 case OPC_PRECEQ_PW_QHRA:
23337 check_dsp(ctx);
23338 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
23339 break;
23340 case OPC_PRECEQU_QH_OBL:
23341 check_dsp(ctx);
23342 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
23343 break;
23344 case OPC_PRECEQU_QH_OBR:
23345 check_dsp(ctx);
23346 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
23347 break;
23348 case OPC_PRECEQU_QH_OBLA:
23349 check_dsp(ctx);
23350 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
23351 break;
23352 case OPC_PRECEQU_QH_OBRA:
23353 check_dsp(ctx);
23354 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
23355 break;
23356 case OPC_PRECEU_QH_OBL:
23357 check_dsp(ctx);
23358 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
23359 break;
23360 case OPC_PRECEU_QH_OBR:
23361 check_dsp(ctx);
23362 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
23363 break;
23364 case OPC_PRECEU_QH_OBLA:
23365 check_dsp(ctx);
23366 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
23367 break;
23368 case OPC_PRECEU_QH_OBRA:
23369 check_dsp(ctx);
23370 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
23371 break;
23372 case OPC_ABSQ_S_OB:
23373 check_dsp_r2(ctx);
23374 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
23375 break;
23376 case OPC_ABSQ_S_PW:
23377 check_dsp(ctx);
23378 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
23379 break;
23380 case OPC_ABSQ_S_QH:
23381 check_dsp(ctx);
23382 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
23383 break;
23385 break;
23386 case OPC_ADDU_OB_DSP:
23387 switch (op2) {
23388 case OPC_RADDU_L_OB:
23389 check_dsp(ctx);
23390 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
23391 break;
23392 case OPC_SUBQ_PW:
23393 check_dsp(ctx);
23394 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23395 break;
23396 case OPC_SUBQ_S_PW:
23397 check_dsp(ctx);
23398 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23399 break;
23400 case OPC_SUBQ_QH:
23401 check_dsp(ctx);
23402 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23403 break;
23404 case OPC_SUBQ_S_QH:
23405 check_dsp(ctx);
23406 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23407 break;
23408 case OPC_SUBU_OB:
23409 check_dsp(ctx);
23410 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23411 break;
23412 case OPC_SUBU_S_OB:
23413 check_dsp(ctx);
23414 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23415 break;
23416 case OPC_SUBU_QH:
23417 check_dsp_r2(ctx);
23418 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23419 break;
23420 case OPC_SUBU_S_QH:
23421 check_dsp_r2(ctx);
23422 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23423 break;
23424 case OPC_SUBUH_OB:
23425 check_dsp_r2(ctx);
23426 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
23427 break;
23428 case OPC_SUBUH_R_OB:
23429 check_dsp_r2(ctx);
23430 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23431 break;
23432 case OPC_ADDQ_PW:
23433 check_dsp(ctx);
23434 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23435 break;
23436 case OPC_ADDQ_S_PW:
23437 check_dsp(ctx);
23438 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23439 break;
23440 case OPC_ADDQ_QH:
23441 check_dsp(ctx);
23442 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23443 break;
23444 case OPC_ADDQ_S_QH:
23445 check_dsp(ctx);
23446 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23447 break;
23448 case OPC_ADDU_OB:
23449 check_dsp(ctx);
23450 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23451 break;
23452 case OPC_ADDU_S_OB:
23453 check_dsp(ctx);
23454 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23455 break;
23456 case OPC_ADDU_QH:
23457 check_dsp_r2(ctx);
23458 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23459 break;
23460 case OPC_ADDU_S_QH:
23461 check_dsp_r2(ctx);
23462 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23463 break;
23464 case OPC_ADDUH_OB:
23465 check_dsp_r2(ctx);
23466 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
23467 break;
23468 case OPC_ADDUH_R_OB:
23469 check_dsp_r2(ctx);
23470 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
23471 break;
23473 break;
23474 case OPC_CMPU_EQ_OB_DSP:
23475 switch (op2) {
23476 case OPC_PRECR_OB_QH:
23477 check_dsp_r2(ctx);
23478 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23479 break;
23480 case OPC_PRECR_SRA_QH_PW:
23481 check_dsp_r2(ctx);
23483 TCGv_i32 ret_t = tcg_const_i32(ret);
23484 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
23485 tcg_temp_free_i32(ret_t);
23486 break;
23488 case OPC_PRECR_SRA_R_QH_PW:
23489 check_dsp_r2(ctx);
23491 TCGv_i32 sa_v = tcg_const_i32(ret);
23492 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
23493 tcg_temp_free_i32(sa_v);
23494 break;
23496 case OPC_PRECRQ_OB_QH:
23497 check_dsp(ctx);
23498 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
23499 break;
23500 case OPC_PRECRQ_PW_L:
23501 check_dsp(ctx);
23502 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
23503 break;
23504 case OPC_PRECRQ_QH_PW:
23505 check_dsp(ctx);
23506 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
23507 break;
23508 case OPC_PRECRQ_RS_QH_PW:
23509 check_dsp(ctx);
23510 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23511 break;
23512 case OPC_PRECRQU_S_OB_QH:
23513 check_dsp(ctx);
23514 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23515 break;
23517 break;
23518 #endif
23521 tcg_temp_free(v1_t);
23522 tcg_temp_free(v2_t);
23525 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
23526 int ret, int v1, int v2)
23528 uint32_t op2;
23529 TCGv t0;
23530 TCGv v1_t;
23531 TCGv v2_t;
23533 if (ret == 0) {
23534 /* Treat as NOP. */
23535 return;
23538 t0 = tcg_temp_new();
23539 v1_t = tcg_temp_new();
23540 v2_t = tcg_temp_new();
23542 tcg_gen_movi_tl(t0, v1);
23543 gen_load_gpr(v1_t, v1);
23544 gen_load_gpr(v2_t, v2);
23546 switch (opc) {
23547 case OPC_SHLL_QB_DSP:
23549 op2 = MASK_SHLL_QB(ctx->opcode);
23550 switch (op2) {
23551 case OPC_SHLL_QB:
23552 check_dsp(ctx);
23553 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
23554 break;
23555 case OPC_SHLLV_QB:
23556 check_dsp(ctx);
23557 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23558 break;
23559 case OPC_SHLL_PH:
23560 check_dsp(ctx);
23561 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23562 break;
23563 case OPC_SHLLV_PH:
23564 check_dsp(ctx);
23565 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23566 break;
23567 case OPC_SHLL_S_PH:
23568 check_dsp(ctx);
23569 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
23570 break;
23571 case OPC_SHLLV_S_PH:
23572 check_dsp(ctx);
23573 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23574 break;
23575 case OPC_SHLL_S_W:
23576 check_dsp(ctx);
23577 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
23578 break;
23579 case OPC_SHLLV_S_W:
23580 check_dsp(ctx);
23581 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23582 break;
23583 case OPC_SHRL_QB:
23584 check_dsp(ctx);
23585 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
23586 break;
23587 case OPC_SHRLV_QB:
23588 check_dsp(ctx);
23589 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
23590 break;
23591 case OPC_SHRL_PH:
23592 check_dsp_r2(ctx);
23593 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
23594 break;
23595 case OPC_SHRLV_PH:
23596 check_dsp_r2(ctx);
23597 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
23598 break;
23599 case OPC_SHRA_QB:
23600 check_dsp_r2(ctx);
23601 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
23602 break;
23603 case OPC_SHRA_R_QB:
23604 check_dsp_r2(ctx);
23605 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
23606 break;
23607 case OPC_SHRAV_QB:
23608 check_dsp_r2(ctx);
23609 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
23610 break;
23611 case OPC_SHRAV_R_QB:
23612 check_dsp_r2(ctx);
23613 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
23614 break;
23615 case OPC_SHRA_PH:
23616 check_dsp(ctx);
23617 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
23618 break;
23619 case OPC_SHRA_R_PH:
23620 check_dsp(ctx);
23621 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
23622 break;
23623 case OPC_SHRAV_PH:
23624 check_dsp(ctx);
23625 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
23626 break;
23627 case OPC_SHRAV_R_PH:
23628 check_dsp(ctx);
23629 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
23630 break;
23631 case OPC_SHRA_R_W:
23632 check_dsp(ctx);
23633 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
23634 break;
23635 case OPC_SHRAV_R_W:
23636 check_dsp(ctx);
23637 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
23638 break;
23639 default: /* Invalid */
23640 MIPS_INVAL("MASK SHLL.QB");
23641 generate_exception_end(ctx, EXCP_RI);
23642 break;
23644 break;
23646 #ifdef TARGET_MIPS64
23647 case OPC_SHLL_OB_DSP:
23648 op2 = MASK_SHLL_OB(ctx->opcode);
23649 switch (op2) {
23650 case OPC_SHLL_PW:
23651 check_dsp(ctx);
23652 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23653 break;
23654 case OPC_SHLLV_PW:
23655 check_dsp(ctx);
23656 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23657 break;
23658 case OPC_SHLL_S_PW:
23659 check_dsp(ctx);
23660 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
23661 break;
23662 case OPC_SHLLV_S_PW:
23663 check_dsp(ctx);
23664 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23665 break;
23666 case OPC_SHLL_OB:
23667 check_dsp(ctx);
23668 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
23669 break;
23670 case OPC_SHLLV_OB:
23671 check_dsp(ctx);
23672 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23673 break;
23674 case OPC_SHLL_QH:
23675 check_dsp(ctx);
23676 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23677 break;
23678 case OPC_SHLLV_QH:
23679 check_dsp(ctx);
23680 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23681 break;
23682 case OPC_SHLL_S_QH:
23683 check_dsp(ctx);
23684 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
23685 break;
23686 case OPC_SHLLV_S_QH:
23687 check_dsp(ctx);
23688 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
23689 break;
23690 case OPC_SHRA_OB:
23691 check_dsp_r2(ctx);
23692 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
23693 break;
23694 case OPC_SHRAV_OB:
23695 check_dsp_r2(ctx);
23696 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
23697 break;
23698 case OPC_SHRA_R_OB:
23699 check_dsp_r2(ctx);
23700 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
23701 break;
23702 case OPC_SHRAV_R_OB:
23703 check_dsp_r2(ctx);
23704 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
23705 break;
23706 case OPC_SHRA_PW:
23707 check_dsp(ctx);
23708 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
23709 break;
23710 case OPC_SHRAV_PW:
23711 check_dsp(ctx);
23712 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
23713 break;
23714 case OPC_SHRA_R_PW:
23715 check_dsp(ctx);
23716 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
23717 break;
23718 case OPC_SHRAV_R_PW:
23719 check_dsp(ctx);
23720 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
23721 break;
23722 case OPC_SHRA_QH:
23723 check_dsp(ctx);
23724 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
23725 break;
23726 case OPC_SHRAV_QH:
23727 check_dsp(ctx);
23728 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
23729 break;
23730 case OPC_SHRA_R_QH:
23731 check_dsp(ctx);
23732 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
23733 break;
23734 case OPC_SHRAV_R_QH:
23735 check_dsp(ctx);
23736 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
23737 break;
23738 case OPC_SHRL_OB:
23739 check_dsp(ctx);
23740 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
23741 break;
23742 case OPC_SHRLV_OB:
23743 check_dsp(ctx);
23744 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
23745 break;
23746 case OPC_SHRL_QH:
23747 check_dsp_r2(ctx);
23748 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
23749 break;
23750 case OPC_SHRLV_QH:
23751 check_dsp_r2(ctx);
23752 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
23753 break;
23754 default: /* Invalid */
23755 MIPS_INVAL("MASK SHLL.OB");
23756 generate_exception_end(ctx, EXCP_RI);
23757 break;
23759 break;
23760 #endif
23763 tcg_temp_free(t0);
23764 tcg_temp_free(v1_t);
23765 tcg_temp_free(v2_t);
23768 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
23769 int ret, int v1, int v2, int check_ret)
23771 TCGv_i32 t0;
23772 TCGv v1_t;
23773 TCGv v2_t;
23775 if ((ret == 0) && (check_ret == 1)) {
23776 /* Treat as NOP. */
23777 return;
23780 t0 = tcg_temp_new_i32();
23781 v1_t = tcg_temp_new();
23782 v2_t = tcg_temp_new();
23784 tcg_gen_movi_i32(t0, ret);
23785 gen_load_gpr(v1_t, v1);
23786 gen_load_gpr(v2_t, v2);
23788 switch (op1) {
23790 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23791 * the same mask and op1.
23793 case OPC_MULT_G_2E:
23794 check_dsp_r2(ctx);
23795 switch (op2) {
23796 case OPC_MUL_PH:
23797 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23798 break;
23799 case OPC_MUL_S_PH:
23800 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23801 break;
23802 case OPC_MULQ_S_W:
23803 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23804 break;
23805 case OPC_MULQ_RS_W:
23806 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
23807 break;
23809 break;
23810 case OPC_DPA_W_PH_DSP:
23811 switch (op2) {
23812 case OPC_DPAU_H_QBL:
23813 check_dsp(ctx);
23814 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
23815 break;
23816 case OPC_DPAU_H_QBR:
23817 check_dsp(ctx);
23818 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
23819 break;
23820 case OPC_DPSU_H_QBL:
23821 check_dsp(ctx);
23822 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
23823 break;
23824 case OPC_DPSU_H_QBR:
23825 check_dsp(ctx);
23826 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
23827 break;
23828 case OPC_DPA_W_PH:
23829 check_dsp_r2(ctx);
23830 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
23831 break;
23832 case OPC_DPAX_W_PH:
23833 check_dsp_r2(ctx);
23834 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
23835 break;
23836 case OPC_DPAQ_S_W_PH:
23837 check_dsp(ctx);
23838 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23839 break;
23840 case OPC_DPAQX_S_W_PH:
23841 check_dsp_r2(ctx);
23842 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23843 break;
23844 case OPC_DPAQX_SA_W_PH:
23845 check_dsp_r2(ctx);
23846 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23847 break;
23848 case OPC_DPS_W_PH:
23849 check_dsp_r2(ctx);
23850 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
23851 break;
23852 case OPC_DPSX_W_PH:
23853 check_dsp_r2(ctx);
23854 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
23855 break;
23856 case OPC_DPSQ_S_W_PH:
23857 check_dsp(ctx);
23858 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23859 break;
23860 case OPC_DPSQX_S_W_PH:
23861 check_dsp_r2(ctx);
23862 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
23863 break;
23864 case OPC_DPSQX_SA_W_PH:
23865 check_dsp_r2(ctx);
23866 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
23867 break;
23868 case OPC_MULSAQ_S_W_PH:
23869 check_dsp(ctx);
23870 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
23871 break;
23872 case OPC_DPAQ_SA_L_W:
23873 check_dsp(ctx);
23874 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23875 break;
23876 case OPC_DPSQ_SA_L_W:
23877 check_dsp(ctx);
23878 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
23879 break;
23880 case OPC_MAQ_S_W_PHL:
23881 check_dsp(ctx);
23882 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
23883 break;
23884 case OPC_MAQ_S_W_PHR:
23885 check_dsp(ctx);
23886 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
23887 break;
23888 case OPC_MAQ_SA_W_PHL:
23889 check_dsp(ctx);
23890 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
23891 break;
23892 case OPC_MAQ_SA_W_PHR:
23893 check_dsp(ctx);
23894 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
23895 break;
23896 case OPC_MULSA_W_PH:
23897 check_dsp_r2(ctx);
23898 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
23899 break;
23901 break;
23902 #ifdef TARGET_MIPS64
23903 case OPC_DPAQ_W_QH_DSP:
23905 int ac = ret & 0x03;
23906 tcg_gen_movi_i32(t0, ac);
23908 switch (op2) {
23909 case OPC_DMADD:
23910 check_dsp(ctx);
23911 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
23912 break;
23913 case OPC_DMADDU:
23914 check_dsp(ctx);
23915 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
23916 break;
23917 case OPC_DMSUB:
23918 check_dsp(ctx);
23919 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
23920 break;
23921 case OPC_DMSUBU:
23922 check_dsp(ctx);
23923 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
23924 break;
23925 case OPC_DPA_W_QH:
23926 check_dsp_r2(ctx);
23927 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
23928 break;
23929 case OPC_DPAQ_S_W_QH:
23930 check_dsp(ctx);
23931 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23932 break;
23933 case OPC_DPAQ_SA_L_PW:
23934 check_dsp(ctx);
23935 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23936 break;
23937 case OPC_DPAU_H_OBL:
23938 check_dsp(ctx);
23939 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
23940 break;
23941 case OPC_DPAU_H_OBR:
23942 check_dsp(ctx);
23943 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
23944 break;
23945 case OPC_DPS_W_QH:
23946 check_dsp_r2(ctx);
23947 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
23948 break;
23949 case OPC_DPSQ_S_W_QH:
23950 check_dsp(ctx);
23951 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
23952 break;
23953 case OPC_DPSQ_SA_L_PW:
23954 check_dsp(ctx);
23955 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
23956 break;
23957 case OPC_DPSU_H_OBL:
23958 check_dsp(ctx);
23959 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
23960 break;
23961 case OPC_DPSU_H_OBR:
23962 check_dsp(ctx);
23963 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
23964 break;
23965 case OPC_MAQ_S_L_PWL:
23966 check_dsp(ctx);
23967 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
23968 break;
23969 case OPC_MAQ_S_L_PWR:
23970 check_dsp(ctx);
23971 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
23972 break;
23973 case OPC_MAQ_S_W_QHLL:
23974 check_dsp(ctx);
23975 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
23976 break;
23977 case OPC_MAQ_SA_W_QHLL:
23978 check_dsp(ctx);
23979 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
23980 break;
23981 case OPC_MAQ_S_W_QHLR:
23982 check_dsp(ctx);
23983 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
23984 break;
23985 case OPC_MAQ_SA_W_QHLR:
23986 check_dsp(ctx);
23987 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
23988 break;
23989 case OPC_MAQ_S_W_QHRL:
23990 check_dsp(ctx);
23991 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
23992 break;
23993 case OPC_MAQ_SA_W_QHRL:
23994 check_dsp(ctx);
23995 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
23996 break;
23997 case OPC_MAQ_S_W_QHRR:
23998 check_dsp(ctx);
23999 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
24000 break;
24001 case OPC_MAQ_SA_W_QHRR:
24002 check_dsp(ctx);
24003 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
24004 break;
24005 case OPC_MULSAQ_S_L_PW:
24006 check_dsp(ctx);
24007 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
24008 break;
24009 case OPC_MULSAQ_S_W_QH:
24010 check_dsp(ctx);
24011 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
24012 break;
24015 break;
24016 #endif
24017 case OPC_ADDU_QB_DSP:
24018 switch (op2) {
24019 case OPC_MULEU_S_PH_QBL:
24020 check_dsp(ctx);
24021 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24022 break;
24023 case OPC_MULEU_S_PH_QBR:
24024 check_dsp(ctx);
24025 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24026 break;
24027 case OPC_MULQ_RS_PH:
24028 check_dsp(ctx);
24029 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24030 break;
24031 case OPC_MULEQ_S_W_PHL:
24032 check_dsp(ctx);
24033 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24034 break;
24035 case OPC_MULEQ_S_W_PHR:
24036 check_dsp(ctx);
24037 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24038 break;
24039 case OPC_MULQ_S_PH:
24040 check_dsp_r2(ctx);
24041 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24042 break;
24044 break;
24045 #ifdef TARGET_MIPS64
24046 case OPC_ADDU_OB_DSP:
24047 switch (op2) {
24048 case OPC_MULEQ_S_PW_QHL:
24049 check_dsp(ctx);
24050 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24051 break;
24052 case OPC_MULEQ_S_PW_QHR:
24053 check_dsp(ctx);
24054 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24055 break;
24056 case OPC_MULEU_S_QH_OBL:
24057 check_dsp(ctx);
24058 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24059 break;
24060 case OPC_MULEU_S_QH_OBR:
24061 check_dsp(ctx);
24062 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24063 break;
24064 case OPC_MULQ_RS_QH:
24065 check_dsp(ctx);
24066 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24067 break;
24069 break;
24070 #endif
24073 tcg_temp_free_i32(t0);
24074 tcg_temp_free(v1_t);
24075 tcg_temp_free(v2_t);
24078 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24079 int ret, int val)
24081 int16_t imm;
24082 TCGv t0;
24083 TCGv val_t;
24085 if (ret == 0) {
24086 /* Treat as NOP. */
24087 return;
24090 t0 = tcg_temp_new();
24091 val_t = tcg_temp_new();
24092 gen_load_gpr(val_t, val);
24094 switch (op1) {
24095 case OPC_ABSQ_S_PH_DSP:
24096 switch (op2) {
24097 case OPC_BITREV:
24098 check_dsp(ctx);
24099 gen_helper_bitrev(cpu_gpr[ret], val_t);
24100 break;
24101 case OPC_REPL_QB:
24102 check_dsp(ctx);
24104 target_long result;
24105 imm = (ctx->opcode >> 16) & 0xFF;
24106 result = (uint32_t)imm << 24 |
24107 (uint32_t)imm << 16 |
24108 (uint32_t)imm << 8 |
24109 (uint32_t)imm;
24110 result = (int32_t)result;
24111 tcg_gen_movi_tl(cpu_gpr[ret], result);
24113 break;
24114 case OPC_REPLV_QB:
24115 check_dsp(ctx);
24116 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24117 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24118 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24119 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24120 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24121 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24122 break;
24123 case OPC_REPL_PH:
24124 check_dsp(ctx);
24126 imm = (ctx->opcode >> 16) & 0x03FF;
24127 imm = (int16_t)(imm << 6) >> 6;
24128 tcg_gen_movi_tl(cpu_gpr[ret], \
24129 (target_long)((int32_t)imm << 16 | \
24130 (uint16_t)imm));
24132 break;
24133 case OPC_REPLV_PH:
24134 check_dsp(ctx);
24135 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24136 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24137 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24138 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
24139 break;
24141 break;
24142 #ifdef TARGET_MIPS64
24143 case OPC_ABSQ_S_QH_DSP:
24144 switch (op2) {
24145 case OPC_REPL_OB:
24146 check_dsp(ctx);
24148 target_long temp;
24150 imm = (ctx->opcode >> 16) & 0xFF;
24151 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
24152 temp = (temp << 16) | temp;
24153 temp = (temp << 32) | temp;
24154 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24155 break;
24157 case OPC_REPL_PW:
24158 check_dsp(ctx);
24160 target_long temp;
24162 imm = (ctx->opcode >> 16) & 0x03FF;
24163 imm = (int16_t)(imm << 6) >> 6;
24164 temp = ((target_long)imm << 32) \
24165 | ((target_long)imm & 0xFFFFFFFF);
24166 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24167 break;
24169 case OPC_REPL_QH:
24170 check_dsp(ctx);
24172 target_long temp;
24174 imm = (ctx->opcode >> 16) & 0x03FF;
24175 imm = (int16_t)(imm << 6) >> 6;
24177 temp = ((uint64_t)(uint16_t)imm << 48) |
24178 ((uint64_t)(uint16_t)imm << 32) |
24179 ((uint64_t)(uint16_t)imm << 16) |
24180 (uint64_t)(uint16_t)imm;
24181 tcg_gen_movi_tl(cpu_gpr[ret], temp);
24182 break;
24184 case OPC_REPLV_OB:
24185 check_dsp(ctx);
24186 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
24187 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
24188 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24189 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24190 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24191 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24192 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24193 break;
24194 case OPC_REPLV_PW:
24195 check_dsp(ctx);
24196 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
24197 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24198 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24199 break;
24200 case OPC_REPLV_QH:
24201 check_dsp(ctx);
24202 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
24203 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
24204 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24205 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
24206 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
24207 break;
24209 break;
24210 #endif
24212 tcg_temp_free(t0);
24213 tcg_temp_free(val_t);
24216 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
24217 uint32_t op1, uint32_t op2,
24218 int ret, int v1, int v2, int check_ret)
24220 TCGv t1;
24221 TCGv v1_t;
24222 TCGv v2_t;
24224 if ((ret == 0) && (check_ret == 1)) {
24225 /* Treat as NOP. */
24226 return;
24229 t1 = tcg_temp_new();
24230 v1_t = tcg_temp_new();
24231 v2_t = tcg_temp_new();
24233 gen_load_gpr(v1_t, v1);
24234 gen_load_gpr(v2_t, v2);
24236 switch (op1) {
24237 case OPC_CMPU_EQ_QB_DSP:
24238 switch (op2) {
24239 case OPC_CMPU_EQ_QB:
24240 check_dsp(ctx);
24241 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
24242 break;
24243 case OPC_CMPU_LT_QB:
24244 check_dsp(ctx);
24245 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
24246 break;
24247 case OPC_CMPU_LE_QB:
24248 check_dsp(ctx);
24249 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
24250 break;
24251 case OPC_CMPGU_EQ_QB:
24252 check_dsp(ctx);
24253 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
24254 break;
24255 case OPC_CMPGU_LT_QB:
24256 check_dsp(ctx);
24257 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
24258 break;
24259 case OPC_CMPGU_LE_QB:
24260 check_dsp(ctx);
24261 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
24262 break;
24263 case OPC_CMPGDU_EQ_QB:
24264 check_dsp_r2(ctx);
24265 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
24266 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24267 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24268 tcg_gen_shli_tl(t1, t1, 24);
24269 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24270 break;
24271 case OPC_CMPGDU_LT_QB:
24272 check_dsp_r2(ctx);
24273 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
24274 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24275 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24276 tcg_gen_shli_tl(t1, t1, 24);
24277 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24278 break;
24279 case OPC_CMPGDU_LE_QB:
24280 check_dsp_r2(ctx);
24281 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
24282 tcg_gen_mov_tl(cpu_gpr[ret], t1);
24283 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
24284 tcg_gen_shli_tl(t1, t1, 24);
24285 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
24286 break;
24287 case OPC_CMP_EQ_PH:
24288 check_dsp(ctx);
24289 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
24290 break;
24291 case OPC_CMP_LT_PH:
24292 check_dsp(ctx);
24293 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
24294 break;
24295 case OPC_CMP_LE_PH:
24296 check_dsp(ctx);
24297 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
24298 break;
24299 case OPC_PICK_QB:
24300 check_dsp(ctx);
24301 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24302 break;
24303 case OPC_PICK_PH:
24304 check_dsp(ctx);
24305 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24306 break;
24307 case OPC_PACKRL_PH:
24308 check_dsp(ctx);
24309 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
24310 break;
24312 break;
24313 #ifdef TARGET_MIPS64
24314 case OPC_CMPU_EQ_OB_DSP:
24315 switch (op2) {
24316 case OPC_CMP_EQ_PW:
24317 check_dsp(ctx);
24318 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
24319 break;
24320 case OPC_CMP_LT_PW:
24321 check_dsp(ctx);
24322 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
24323 break;
24324 case OPC_CMP_LE_PW:
24325 check_dsp(ctx);
24326 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
24327 break;
24328 case OPC_CMP_EQ_QH:
24329 check_dsp(ctx);
24330 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
24331 break;
24332 case OPC_CMP_LT_QH:
24333 check_dsp(ctx);
24334 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
24335 break;
24336 case OPC_CMP_LE_QH:
24337 check_dsp(ctx);
24338 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
24339 break;
24340 case OPC_CMPGDU_EQ_OB:
24341 check_dsp_r2(ctx);
24342 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24343 break;
24344 case OPC_CMPGDU_LT_OB:
24345 check_dsp_r2(ctx);
24346 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24347 break;
24348 case OPC_CMPGDU_LE_OB:
24349 check_dsp_r2(ctx);
24350 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24351 break;
24352 case OPC_CMPGU_EQ_OB:
24353 check_dsp(ctx);
24354 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
24355 break;
24356 case OPC_CMPGU_LT_OB:
24357 check_dsp(ctx);
24358 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
24359 break;
24360 case OPC_CMPGU_LE_OB:
24361 check_dsp(ctx);
24362 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
24363 break;
24364 case OPC_CMPU_EQ_OB:
24365 check_dsp(ctx);
24366 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
24367 break;
24368 case OPC_CMPU_LT_OB:
24369 check_dsp(ctx);
24370 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
24371 break;
24372 case OPC_CMPU_LE_OB:
24373 check_dsp(ctx);
24374 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
24375 break;
24376 case OPC_PACKRL_PW:
24377 check_dsp(ctx);
24378 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
24379 break;
24380 case OPC_PICK_OB:
24381 check_dsp(ctx);
24382 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24383 break;
24384 case OPC_PICK_PW:
24385 check_dsp(ctx);
24386 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24387 break;
24388 case OPC_PICK_QH:
24389 check_dsp(ctx);
24390 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
24391 break;
24393 break;
24394 #endif
24397 tcg_temp_free(t1);
24398 tcg_temp_free(v1_t);
24399 tcg_temp_free(v2_t);
24402 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
24403 uint32_t op1, int rt, int rs, int sa)
24405 TCGv t0;
24407 check_dsp_r2(ctx);
24409 if (rt == 0) {
24410 /* Treat as NOP. */
24411 return;
24414 t0 = tcg_temp_new();
24415 gen_load_gpr(t0, rs);
24417 switch (op1) {
24418 case OPC_APPEND_DSP:
24419 switch (MASK_APPEND(ctx->opcode)) {
24420 case OPC_APPEND:
24421 if (sa != 0) {
24422 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
24424 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24425 break;
24426 case OPC_PREPEND:
24427 if (sa != 0) {
24428 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
24429 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24430 tcg_gen_shli_tl(t0, t0, 32 - sa);
24431 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24433 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24434 break;
24435 case OPC_BALIGN:
24436 sa &= 3;
24437 if (sa != 0 && sa != 2) {
24438 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24439 tcg_gen_ext32u_tl(t0, t0);
24440 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
24441 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24443 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
24444 break;
24445 default: /* Invalid */
24446 MIPS_INVAL("MASK APPEND");
24447 generate_exception_end(ctx, EXCP_RI);
24448 break;
24450 break;
24451 #ifdef TARGET_MIPS64
24452 case OPC_DAPPEND_DSP:
24453 switch (MASK_DAPPEND(ctx->opcode)) {
24454 case OPC_DAPPEND:
24455 if (sa != 0) {
24456 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
24458 break;
24459 case OPC_PREPENDD:
24460 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
24461 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
24462 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
24463 break;
24464 case OPC_PREPENDW:
24465 if (sa != 0) {
24466 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
24467 tcg_gen_shli_tl(t0, t0, 64 - sa);
24468 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24470 break;
24471 case OPC_DBALIGN:
24472 sa &= 7;
24473 if (sa != 0 && sa != 2 && sa != 4) {
24474 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
24475 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
24476 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
24478 break;
24479 default: /* Invalid */
24480 MIPS_INVAL("MASK DAPPEND");
24481 generate_exception_end(ctx, EXCP_RI);
24482 break;
24484 break;
24485 #endif
24487 tcg_temp_free(t0);
24490 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
24491 int ret, int v1, int v2, int check_ret)
24494 TCGv t0;
24495 TCGv t1;
24496 TCGv v1_t;
24497 TCGv v2_t;
24498 int16_t imm;
24500 if ((ret == 0) && (check_ret == 1)) {
24501 /* Treat as NOP. */
24502 return;
24505 t0 = tcg_temp_new();
24506 t1 = tcg_temp_new();
24507 v1_t = tcg_temp_new();
24508 v2_t = tcg_temp_new();
24510 gen_load_gpr(v1_t, v1);
24511 gen_load_gpr(v2_t, v2);
24513 switch (op1) {
24514 case OPC_EXTR_W_DSP:
24515 check_dsp(ctx);
24516 switch (op2) {
24517 case OPC_EXTR_W:
24518 tcg_gen_movi_tl(t0, v2);
24519 tcg_gen_movi_tl(t1, v1);
24520 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
24521 break;
24522 case OPC_EXTR_R_W:
24523 tcg_gen_movi_tl(t0, v2);
24524 tcg_gen_movi_tl(t1, v1);
24525 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24526 break;
24527 case OPC_EXTR_RS_W:
24528 tcg_gen_movi_tl(t0, v2);
24529 tcg_gen_movi_tl(t1, v1);
24530 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24531 break;
24532 case OPC_EXTR_S_H:
24533 tcg_gen_movi_tl(t0, v2);
24534 tcg_gen_movi_tl(t1, v1);
24535 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24536 break;
24537 case OPC_EXTRV_S_H:
24538 tcg_gen_movi_tl(t0, v2);
24539 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
24540 break;
24541 case OPC_EXTRV_W:
24542 tcg_gen_movi_tl(t0, v2);
24543 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24544 break;
24545 case OPC_EXTRV_R_W:
24546 tcg_gen_movi_tl(t0, v2);
24547 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24548 break;
24549 case OPC_EXTRV_RS_W:
24550 tcg_gen_movi_tl(t0, v2);
24551 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24552 break;
24553 case OPC_EXTP:
24554 tcg_gen_movi_tl(t0, v2);
24555 tcg_gen_movi_tl(t1, v1);
24556 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
24557 break;
24558 case OPC_EXTPV:
24559 tcg_gen_movi_tl(t0, v2);
24560 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
24561 break;
24562 case OPC_EXTPDP:
24563 tcg_gen_movi_tl(t0, v2);
24564 tcg_gen_movi_tl(t1, v1);
24565 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
24566 break;
24567 case OPC_EXTPDPV:
24568 tcg_gen_movi_tl(t0, v2);
24569 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24570 break;
24571 case OPC_SHILO:
24572 imm = (ctx->opcode >> 20) & 0x3F;
24573 tcg_gen_movi_tl(t0, ret);
24574 tcg_gen_movi_tl(t1, imm);
24575 gen_helper_shilo(t0, t1, cpu_env);
24576 break;
24577 case OPC_SHILOV:
24578 tcg_gen_movi_tl(t0, ret);
24579 gen_helper_shilo(t0, v1_t, cpu_env);
24580 break;
24581 case OPC_MTHLIP:
24582 tcg_gen_movi_tl(t0, ret);
24583 gen_helper_mthlip(t0, v1_t, cpu_env);
24584 break;
24585 case OPC_WRDSP:
24586 imm = (ctx->opcode >> 11) & 0x3FF;
24587 tcg_gen_movi_tl(t0, imm);
24588 gen_helper_wrdsp(v1_t, t0, cpu_env);
24589 break;
24590 case OPC_RDDSP:
24591 imm = (ctx->opcode >> 16) & 0x03FF;
24592 tcg_gen_movi_tl(t0, imm);
24593 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
24594 break;
24596 break;
24597 #ifdef TARGET_MIPS64
24598 case OPC_DEXTR_W_DSP:
24599 check_dsp(ctx);
24600 switch (op2) {
24601 case OPC_DMTHLIP:
24602 tcg_gen_movi_tl(t0, ret);
24603 gen_helper_dmthlip(v1_t, t0, cpu_env);
24604 break;
24605 case OPC_DSHILO:
24607 int shift = (ctx->opcode >> 19) & 0x7F;
24608 int ac = (ctx->opcode >> 11) & 0x03;
24609 tcg_gen_movi_tl(t0, shift);
24610 tcg_gen_movi_tl(t1, ac);
24611 gen_helper_dshilo(t0, t1, cpu_env);
24612 break;
24614 case OPC_DSHILOV:
24616 int ac = (ctx->opcode >> 11) & 0x03;
24617 tcg_gen_movi_tl(t0, ac);
24618 gen_helper_dshilo(v1_t, t0, cpu_env);
24619 break;
24621 case OPC_DEXTP:
24622 tcg_gen_movi_tl(t0, v2);
24623 tcg_gen_movi_tl(t1, v1);
24625 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
24626 break;
24627 case OPC_DEXTPV:
24628 tcg_gen_movi_tl(t0, v2);
24629 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
24630 break;
24631 case OPC_DEXTPDP:
24632 tcg_gen_movi_tl(t0, v2);
24633 tcg_gen_movi_tl(t1, v1);
24634 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
24635 break;
24636 case OPC_DEXTPDPV:
24637 tcg_gen_movi_tl(t0, v2);
24638 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
24639 break;
24640 case OPC_DEXTR_L:
24641 tcg_gen_movi_tl(t0, v2);
24642 tcg_gen_movi_tl(t1, v1);
24643 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
24644 break;
24645 case OPC_DEXTR_R_L:
24646 tcg_gen_movi_tl(t0, v2);
24647 tcg_gen_movi_tl(t1, v1);
24648 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
24649 break;
24650 case OPC_DEXTR_RS_L:
24651 tcg_gen_movi_tl(t0, v2);
24652 tcg_gen_movi_tl(t1, v1);
24653 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
24654 break;
24655 case OPC_DEXTR_W:
24656 tcg_gen_movi_tl(t0, v2);
24657 tcg_gen_movi_tl(t1, v1);
24658 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
24659 break;
24660 case OPC_DEXTR_R_W:
24661 tcg_gen_movi_tl(t0, v2);
24662 tcg_gen_movi_tl(t1, v1);
24663 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
24664 break;
24665 case OPC_DEXTR_RS_W:
24666 tcg_gen_movi_tl(t0, v2);
24667 tcg_gen_movi_tl(t1, v1);
24668 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
24669 break;
24670 case OPC_DEXTR_S_H:
24671 tcg_gen_movi_tl(t0, v2);
24672 tcg_gen_movi_tl(t1, v1);
24673 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24674 break;
24675 case OPC_DEXTRV_S_H:
24676 tcg_gen_movi_tl(t0, v2);
24677 tcg_gen_movi_tl(t1, v1);
24678 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
24679 break;
24680 case OPC_DEXTRV_L:
24681 tcg_gen_movi_tl(t0, v2);
24682 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24683 break;
24684 case OPC_DEXTRV_R_L:
24685 tcg_gen_movi_tl(t0, v2);
24686 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24687 break;
24688 case OPC_DEXTRV_RS_L:
24689 tcg_gen_movi_tl(t0, v2);
24690 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
24691 break;
24692 case OPC_DEXTRV_W:
24693 tcg_gen_movi_tl(t0, v2);
24694 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24695 break;
24696 case OPC_DEXTRV_R_W:
24697 tcg_gen_movi_tl(t0, v2);
24698 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24699 break;
24700 case OPC_DEXTRV_RS_W:
24701 tcg_gen_movi_tl(t0, v2);
24702 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
24703 break;
24705 break;
24706 #endif
24709 tcg_temp_free(t0);
24710 tcg_temp_free(t1);
24711 tcg_temp_free(v1_t);
24712 tcg_temp_free(v2_t);
24715 /* End MIPSDSP functions. */
24717 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
24719 int rs, rt, rd, sa;
24720 uint32_t op1, op2;
24722 rs = (ctx->opcode >> 21) & 0x1f;
24723 rt = (ctx->opcode >> 16) & 0x1f;
24724 rd = (ctx->opcode >> 11) & 0x1f;
24725 sa = (ctx->opcode >> 6) & 0x1f;
24727 op1 = MASK_SPECIAL(ctx->opcode);
24728 switch (op1) {
24729 case OPC_LSA:
24730 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24731 break;
24732 case OPC_MULT:
24733 case OPC_MULTU:
24734 case OPC_DIV:
24735 case OPC_DIVU:
24736 op2 = MASK_R6_MULDIV(ctx->opcode);
24737 switch (op2) {
24738 case R6_OPC_MUL:
24739 case R6_OPC_MUH:
24740 case R6_OPC_MULU:
24741 case R6_OPC_MUHU:
24742 case R6_OPC_DIV:
24743 case R6_OPC_MOD:
24744 case R6_OPC_DIVU:
24745 case R6_OPC_MODU:
24746 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24747 break;
24748 default:
24749 MIPS_INVAL("special_r6 muldiv");
24750 generate_exception_end(ctx, EXCP_RI);
24751 break;
24753 break;
24754 case OPC_SELEQZ:
24755 case OPC_SELNEZ:
24756 gen_cond_move(ctx, op1, rd, rs, rt);
24757 break;
24758 case R6_OPC_CLO:
24759 case R6_OPC_CLZ:
24760 if (rt == 0 && sa == 1) {
24762 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24763 * We need additionally to check other fields.
24765 gen_cl(ctx, op1, rd, rs);
24766 } else {
24767 generate_exception_end(ctx, EXCP_RI);
24769 break;
24770 case R6_OPC_SDBBP:
24771 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
24772 gen_helper_do_semihosting(cpu_env);
24773 } else {
24774 if (ctx->hflags & MIPS_HFLAG_SBRI) {
24775 generate_exception_end(ctx, EXCP_RI);
24776 } else {
24777 generate_exception_end(ctx, EXCP_DBp);
24780 break;
24781 #if defined(TARGET_MIPS64)
24782 case OPC_DLSA:
24783 check_mips_64(ctx);
24784 gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
24785 break;
24786 case R6_OPC_DCLO:
24787 case R6_OPC_DCLZ:
24788 if (rt == 0 && sa == 1) {
24790 * Major opcode and function field is shared with preR6 MFHI/MTHI.
24791 * We need additionally to check other fields.
24793 check_mips_64(ctx);
24794 gen_cl(ctx, op1, rd, rs);
24795 } else {
24796 generate_exception_end(ctx, EXCP_RI);
24798 break;
24799 case OPC_DMULT:
24800 case OPC_DMULTU:
24801 case OPC_DDIV:
24802 case OPC_DDIVU:
24804 op2 = MASK_R6_MULDIV(ctx->opcode);
24805 switch (op2) {
24806 case R6_OPC_DMUL:
24807 case R6_OPC_DMUH:
24808 case R6_OPC_DMULU:
24809 case R6_OPC_DMUHU:
24810 case R6_OPC_DDIV:
24811 case R6_OPC_DMOD:
24812 case R6_OPC_DDIVU:
24813 case R6_OPC_DMODU:
24814 check_mips_64(ctx);
24815 gen_r6_muldiv(ctx, op2, rd, rs, rt);
24816 break;
24817 default:
24818 MIPS_INVAL("special_r6 muldiv");
24819 generate_exception_end(ctx, EXCP_RI);
24820 break;
24822 break;
24823 #endif
24824 default: /* Invalid */
24825 MIPS_INVAL("special_r6");
24826 generate_exception_end(ctx, EXCP_RI);
24827 break;
24831 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
24833 int rs = extract32(ctx->opcode, 21, 5);
24834 int rt = extract32(ctx->opcode, 16, 5);
24835 int rd = extract32(ctx->opcode, 11, 5);
24836 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
24838 switch (op1) {
24839 case OPC_MOVN: /* Conditional move */
24840 case OPC_MOVZ:
24841 gen_cond_move(ctx, op1, rd, rs, rt);
24842 break;
24843 case OPC_MFHI: /* Move from HI/LO */
24844 case OPC_MFLO:
24845 gen_HILO(ctx, op1, 0, rd);
24846 break;
24847 case OPC_MTHI:
24848 case OPC_MTLO: /* Move to HI/LO */
24849 gen_HILO(ctx, op1, 0, rs);
24850 break;
24851 case OPC_MULT:
24852 case OPC_MULTU:
24853 gen_mul_txx9(ctx, op1, rd, rs, rt);
24854 break;
24855 case OPC_DIV:
24856 case OPC_DIVU:
24857 gen_muldiv(ctx, op1, 0, rs, rt);
24858 break;
24859 #if defined(TARGET_MIPS64)
24860 case OPC_DMULT:
24861 case OPC_DMULTU:
24862 case OPC_DDIV:
24863 case OPC_DDIVU:
24864 check_insn_opc_user_only(ctx, INSN_R5900);
24865 gen_muldiv(ctx, op1, 0, rs, rt);
24866 break;
24867 #endif
24868 case OPC_JR:
24869 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
24870 break;
24871 default: /* Invalid */
24872 MIPS_INVAL("special_tx79");
24873 generate_exception_end(ctx, EXCP_RI);
24874 break;
24878 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
24880 int rs, rt, rd, sa;
24881 uint32_t op1;
24883 rs = (ctx->opcode >> 21) & 0x1f;
24884 rt = (ctx->opcode >> 16) & 0x1f;
24885 rd = (ctx->opcode >> 11) & 0x1f;
24886 sa = (ctx->opcode >> 6) & 0x1f;
24888 op1 = MASK_SPECIAL(ctx->opcode);
24889 switch (op1) {
24890 case OPC_MOVN: /* Conditional move */
24891 case OPC_MOVZ:
24892 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
24893 INSN_LOONGSON2E | INSN_LOONGSON2F);
24894 gen_cond_move(ctx, op1, rd, rs, rt);
24895 break;
24896 case OPC_MFHI: /* Move from HI/LO */
24897 case OPC_MFLO:
24898 gen_HILO(ctx, op1, rs & 3, rd);
24899 break;
24900 case OPC_MTHI:
24901 case OPC_MTLO: /* Move to HI/LO */
24902 gen_HILO(ctx, op1, rd & 3, rs);
24903 break;
24904 case OPC_MOVCI:
24905 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
24906 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
24907 check_cp1_enabled(ctx);
24908 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
24909 (ctx->opcode >> 16) & 1);
24910 } else {
24911 generate_exception_err(ctx, EXCP_CpU, 1);
24913 break;
24914 case OPC_MULT:
24915 case OPC_MULTU:
24916 if (sa) {
24917 check_insn(ctx, INSN_VR54XX);
24918 op1 = MASK_MUL_VR54XX(ctx->opcode);
24919 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
24920 } else {
24921 gen_muldiv(ctx, op1, rd & 3, rs, rt);
24923 break;
24924 case OPC_DIV:
24925 case OPC_DIVU:
24926 gen_muldiv(ctx, op1, 0, rs, rt);
24927 break;
24928 #if defined(TARGET_MIPS64)
24929 case OPC_DMULT:
24930 case OPC_DMULTU:
24931 case OPC_DDIV:
24932 case OPC_DDIVU:
24933 check_insn(ctx, ISA_MIPS3);
24934 check_mips_64(ctx);
24935 gen_muldiv(ctx, op1, 0, rs, rt);
24936 break;
24937 #endif
24938 case OPC_JR:
24939 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
24940 break;
24941 case OPC_SPIM:
24942 #ifdef MIPS_STRICT_STANDARD
24943 MIPS_INVAL("SPIM");
24944 generate_exception_end(ctx, EXCP_RI);
24945 #else
24946 /* Implemented as RI exception for now. */
24947 MIPS_INVAL("spim (unofficial)");
24948 generate_exception_end(ctx, EXCP_RI);
24949 #endif
24950 break;
24951 default: /* Invalid */
24952 MIPS_INVAL("special_legacy");
24953 generate_exception_end(ctx, EXCP_RI);
24954 break;
24958 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
24960 int rs, rt, rd, sa;
24961 uint32_t op1;
24963 rs = (ctx->opcode >> 21) & 0x1f;
24964 rt = (ctx->opcode >> 16) & 0x1f;
24965 rd = (ctx->opcode >> 11) & 0x1f;
24966 sa = (ctx->opcode >> 6) & 0x1f;
24968 op1 = MASK_SPECIAL(ctx->opcode);
24969 switch (op1) {
24970 case OPC_SLL: /* Shift with immediate */
24971 if (sa == 5 && rd == 0 &&
24972 rs == 0 && rt == 0) { /* PAUSE */
24973 if ((ctx->insn_flags & ISA_MIPS32R6) &&
24974 (ctx->hflags & MIPS_HFLAG_BMASK)) {
24975 generate_exception_end(ctx, EXCP_RI);
24976 break;
24979 /* Fallthrough */
24980 case OPC_SRA:
24981 gen_shift_imm(ctx, op1, rd, rt, sa);
24982 break;
24983 case OPC_SRL:
24984 switch ((ctx->opcode >> 21) & 0x1f) {
24985 case 1:
24986 /* rotr is decoded as srl on non-R2 CPUs */
24987 if (ctx->insn_flags & ISA_MIPS32R2) {
24988 op1 = OPC_ROTR;
24990 /* Fallthrough */
24991 case 0:
24992 gen_shift_imm(ctx, op1, rd, rt, sa);
24993 break;
24994 default:
24995 generate_exception_end(ctx, EXCP_RI);
24996 break;
24998 break;
24999 case OPC_ADD:
25000 case OPC_ADDU:
25001 case OPC_SUB:
25002 case OPC_SUBU:
25003 gen_arith(ctx, op1, rd, rs, rt);
25004 break;
25005 case OPC_SLLV: /* Shifts */
25006 case OPC_SRAV:
25007 gen_shift(ctx, op1, rd, rs, rt);
25008 break;
25009 case OPC_SRLV:
25010 switch ((ctx->opcode >> 6) & 0x1f) {
25011 case 1:
25012 /* rotrv is decoded as srlv on non-R2 CPUs */
25013 if (ctx->insn_flags & ISA_MIPS32R2) {
25014 op1 = OPC_ROTRV;
25016 /* Fallthrough */
25017 case 0:
25018 gen_shift(ctx, op1, rd, rs, rt);
25019 break;
25020 default:
25021 generate_exception_end(ctx, EXCP_RI);
25022 break;
25024 break;
25025 case OPC_SLT: /* Set on less than */
25026 case OPC_SLTU:
25027 gen_slt(ctx, op1, rd, rs, rt);
25028 break;
25029 case OPC_AND: /* Logic*/
25030 case OPC_OR:
25031 case OPC_NOR:
25032 case OPC_XOR:
25033 gen_logic(ctx, op1, rd, rs, rt);
25034 break;
25035 case OPC_JALR:
25036 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
25037 break;
25038 case OPC_TGE: /* Traps */
25039 case OPC_TGEU:
25040 case OPC_TLT:
25041 case OPC_TLTU:
25042 case OPC_TEQ:
25043 case OPC_TNE:
25044 check_insn(ctx, ISA_MIPS2);
25045 gen_trap(ctx, op1, rs, rt, -1);
25046 break;
25047 case OPC_LSA: /* OPC_PMON */
25048 if ((ctx->insn_flags & ISA_MIPS32R6) ||
25049 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
25050 decode_opc_special_r6(env, ctx);
25051 } else {
25052 /* Pmon entry point, also R4010 selsl */
25053 #ifdef MIPS_STRICT_STANDARD
25054 MIPS_INVAL("PMON / selsl");
25055 generate_exception_end(ctx, EXCP_RI);
25056 #else
25057 gen_helper_0e0i(pmon, sa);
25058 #endif
25060 break;
25061 case OPC_SYSCALL:
25062 generate_exception_end(ctx, EXCP_SYSCALL);
25063 break;
25064 case OPC_BREAK:
25065 generate_exception_end(ctx, EXCP_BREAK);
25066 break;
25067 case OPC_SYNC:
25068 check_insn(ctx, ISA_MIPS2);
25069 gen_sync(extract32(ctx->opcode, 6, 5));
25070 break;
25072 #if defined(TARGET_MIPS64)
25073 /* MIPS64 specific opcodes */
25074 case OPC_DSLL:
25075 case OPC_DSRA:
25076 case OPC_DSLL32:
25077 case OPC_DSRA32:
25078 check_insn(ctx, ISA_MIPS3);
25079 check_mips_64(ctx);
25080 gen_shift_imm(ctx, op1, rd, rt, sa);
25081 break;
25082 case OPC_DSRL:
25083 switch ((ctx->opcode >> 21) & 0x1f) {
25084 case 1:
25085 /* drotr is decoded as dsrl on non-R2 CPUs */
25086 if (ctx->insn_flags & ISA_MIPS32R2) {
25087 op1 = OPC_DROTR;
25089 /* Fallthrough */
25090 case 0:
25091 check_insn(ctx, ISA_MIPS3);
25092 check_mips_64(ctx);
25093 gen_shift_imm(ctx, op1, rd, rt, sa);
25094 break;
25095 default:
25096 generate_exception_end(ctx, EXCP_RI);
25097 break;
25099 break;
25100 case OPC_DSRL32:
25101 switch ((ctx->opcode >> 21) & 0x1f) {
25102 case 1:
25103 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
25104 if (ctx->insn_flags & ISA_MIPS32R2) {
25105 op1 = OPC_DROTR32;
25107 /* Fallthrough */
25108 case 0:
25109 check_insn(ctx, ISA_MIPS3);
25110 check_mips_64(ctx);
25111 gen_shift_imm(ctx, op1, rd, rt, sa);
25112 break;
25113 default:
25114 generate_exception_end(ctx, EXCP_RI);
25115 break;
25117 break;
25118 case OPC_DADD:
25119 case OPC_DADDU:
25120 case OPC_DSUB:
25121 case OPC_DSUBU:
25122 check_insn(ctx, ISA_MIPS3);
25123 check_mips_64(ctx);
25124 gen_arith(ctx, op1, rd, rs, rt);
25125 break;
25126 case OPC_DSLLV:
25127 case OPC_DSRAV:
25128 check_insn(ctx, ISA_MIPS3);
25129 check_mips_64(ctx);
25130 gen_shift(ctx, op1, rd, rs, rt);
25131 break;
25132 case OPC_DSRLV:
25133 switch ((ctx->opcode >> 6) & 0x1f) {
25134 case 1:
25135 /* drotrv is decoded as dsrlv on non-R2 CPUs */
25136 if (ctx->insn_flags & ISA_MIPS32R2) {
25137 op1 = OPC_DROTRV;
25139 /* Fallthrough */
25140 case 0:
25141 check_insn(ctx, ISA_MIPS3);
25142 check_mips_64(ctx);
25143 gen_shift(ctx, op1, rd, rs, rt);
25144 break;
25145 default:
25146 generate_exception_end(ctx, EXCP_RI);
25147 break;
25149 break;
25150 case OPC_DLSA:
25151 if ((ctx->insn_flags & ISA_MIPS32R6) ||
25152 (env->CP0_Config3 & (1 << CP0C3_MSAP))) {
25153 decode_opc_special_r6(env, ctx);
25155 break;
25156 #endif
25157 default:
25158 if (ctx->insn_flags & ISA_MIPS32R6) {
25159 decode_opc_special_r6(env, ctx);
25160 } else if (ctx->insn_flags & INSN_R5900) {
25161 decode_opc_special_tx79(env, ctx);
25162 } else {
25163 decode_opc_special_legacy(env, ctx);
25169 #if defined(TARGET_MIPS64)
25173 * MMI (MultiMedia Interface) ASE instructions
25174 * ===========================================
25178 * MMI instructions category: data communication
25179 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25181 * PCPYH PEXCH PEXTLB PINTH PPACB PEXT5 PREVH
25182 * PCPYLD PEXCW PEXTLH PINTEH PPACH PPAC5 PROT3W
25183 * PCPYUD PEXEH PEXTLW PPACW
25184 * PEXEW PEXTUB
25185 * PEXTUH
25186 * PEXTUW
25190 * PCPYH rd, rt
25192 * Parallel Copy Halfword
25194 * 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
25195 * +-----------+---------+---------+---------+---------+-----------+
25196 * | MMI |0 0 0 0 0| rt | rd | PCPYH | MMI3 |
25197 * +-----------+---------+---------+---------+---------+-----------+
25199 static void gen_mmi_pcpyh(DisasContext *ctx)
25201 uint32_t pd, rt, rd;
25202 uint32_t opcode;
25204 opcode = ctx->opcode;
25206 pd = extract32(opcode, 21, 5);
25207 rt = extract32(opcode, 16, 5);
25208 rd = extract32(opcode, 11, 5);
25210 if (unlikely(pd != 0)) {
25211 generate_exception_end(ctx, EXCP_RI);
25212 } else if (rd == 0) {
25213 /* nop */
25214 } else if (rt == 0) {
25215 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25216 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25217 } else {
25218 TCGv_i64 t0 = tcg_temp_new();
25219 TCGv_i64 t1 = tcg_temp_new();
25220 uint64_t mask = (1ULL << 16) - 1;
25222 tcg_gen_andi_i64(t0, cpu_gpr[rt], mask);
25223 tcg_gen_movi_i64(t1, 0);
25224 tcg_gen_or_i64(t1, t0, t1);
25225 tcg_gen_shli_i64(t0, t0, 16);
25226 tcg_gen_or_i64(t1, t0, t1);
25227 tcg_gen_shli_i64(t0, t0, 16);
25228 tcg_gen_or_i64(t1, t0, t1);
25229 tcg_gen_shli_i64(t0, t0, 16);
25230 tcg_gen_or_i64(t1, t0, t1);
25232 tcg_gen_mov_i64(cpu_gpr[rd], t1);
25234 tcg_gen_andi_i64(t0, cpu_mmr[rt], mask);
25235 tcg_gen_movi_i64(t1, 0);
25236 tcg_gen_or_i64(t1, t0, t1);
25237 tcg_gen_shli_i64(t0, t0, 16);
25238 tcg_gen_or_i64(t1, t0, t1);
25239 tcg_gen_shli_i64(t0, t0, 16);
25240 tcg_gen_or_i64(t1, t0, t1);
25241 tcg_gen_shli_i64(t0, t0, 16);
25242 tcg_gen_or_i64(t1, t0, t1);
25244 tcg_gen_mov_i64(cpu_mmr[rd], t1);
25246 tcg_temp_free(t0);
25247 tcg_temp_free(t1);
25252 * PCPYLD rd, rs, rt
25254 * Parallel Copy Lower Doubleword
25256 * 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
25257 * +-----------+---------+---------+---------+---------+-----------+
25258 * | MMI | rs | rt | rd | PCPYLD | MMI2 |
25259 * +-----------+---------+---------+---------+---------+-----------+
25261 static void gen_mmi_pcpyld(DisasContext *ctx)
25263 uint32_t rs, rt, rd;
25264 uint32_t opcode;
25266 opcode = ctx->opcode;
25268 rs = extract32(opcode, 21, 5);
25269 rt = extract32(opcode, 16, 5);
25270 rd = extract32(opcode, 11, 5);
25272 if (rd == 0) {
25273 /* nop */
25274 } else {
25275 if (rs == 0) {
25276 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25277 } else {
25278 tcg_gen_mov_i64(cpu_mmr[rd], cpu_gpr[rs]);
25280 if (rt == 0) {
25281 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25282 } else {
25283 if (rd != rt) {
25284 tcg_gen_mov_i64(cpu_gpr[rd], cpu_gpr[rt]);
25291 * PCPYUD rd, rs, rt
25293 * Parallel Copy Upper Doubleword
25295 * 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
25296 * +-----------+---------+---------+---------+---------+-----------+
25297 * | MMI | rs | rt | rd | PCPYUD | MMI3 |
25298 * +-----------+---------+---------+---------+---------+-----------+
25300 static void gen_mmi_pcpyud(DisasContext *ctx)
25302 uint32_t rs, rt, rd;
25303 uint32_t opcode;
25305 opcode = ctx->opcode;
25307 rs = extract32(opcode, 21, 5);
25308 rt = extract32(opcode, 16, 5);
25309 rd = extract32(opcode, 11, 5);
25311 if (rd == 0) {
25312 /* nop */
25313 } else {
25314 if (rs == 0) {
25315 tcg_gen_movi_i64(cpu_gpr[rd], 0);
25316 } else {
25317 tcg_gen_mov_i64(cpu_gpr[rd], cpu_mmr[rs]);
25319 if (rt == 0) {
25320 tcg_gen_movi_i64(cpu_mmr[rd], 0);
25321 } else {
25322 if (rd != rt) {
25323 tcg_gen_mov_i64(cpu_mmr[rd], cpu_mmr[rt]);
25329 #endif
25332 #if !defined(TARGET_MIPS64)
25334 /* MXU accumulate add/subtract 1-bit pattern 'aptn1' */
25335 #define MXU_APTN1_A 0
25336 #define MXU_APTN1_S 1
25338 /* MXU accumulate add/subtract 2-bit pattern 'aptn2' */
25339 #define MXU_APTN2_AA 0
25340 #define MXU_APTN2_AS 1
25341 #define MXU_APTN2_SA 2
25342 #define MXU_APTN2_SS 3
25344 /* MXU execute add/subtract 2-bit pattern 'eptn2' */
25345 #define MXU_EPTN2_AA 0
25346 #define MXU_EPTN2_AS 1
25347 #define MXU_EPTN2_SA 2
25348 #define MXU_EPTN2_SS 3
25350 /* MXU operand getting pattern 'optn2' */
25351 #define MXU_OPTN2_PTN0 0
25352 #define MXU_OPTN2_PTN1 1
25353 #define MXU_OPTN2_PTN2 2
25354 #define MXU_OPTN2_PTN3 3
25355 /* alternative naming scheme for 'optn2' */
25356 #define MXU_OPTN2_WW 0
25357 #define MXU_OPTN2_LW 1
25358 #define MXU_OPTN2_HW 2
25359 #define MXU_OPTN2_XW 3
25361 /* MXU operand getting pattern 'optn3' */
25362 #define MXU_OPTN3_PTN0 0
25363 #define MXU_OPTN3_PTN1 1
25364 #define MXU_OPTN3_PTN2 2
25365 #define MXU_OPTN3_PTN3 3
25366 #define MXU_OPTN3_PTN4 4
25367 #define MXU_OPTN3_PTN5 5
25368 #define MXU_OPTN3_PTN6 6
25369 #define MXU_OPTN3_PTN7 7
25373 * S32I2M XRa, rb - Register move from GRF to XRF
25375 static void gen_mxu_s32i2m(DisasContext *ctx)
25377 TCGv t0;
25378 uint32_t XRa, Rb;
25380 t0 = tcg_temp_new();
25382 XRa = extract32(ctx->opcode, 6, 5);
25383 Rb = extract32(ctx->opcode, 16, 5);
25385 gen_load_gpr(t0, Rb);
25386 if (XRa <= 15) {
25387 gen_store_mxu_gpr(t0, XRa);
25388 } else if (XRa == 16) {
25389 gen_store_mxu_cr(t0);
25392 tcg_temp_free(t0);
25396 * S32M2I XRa, rb - Register move from XRF to GRF
25398 static void gen_mxu_s32m2i(DisasContext *ctx)
25400 TCGv t0;
25401 uint32_t XRa, Rb;
25403 t0 = tcg_temp_new();
25405 XRa = extract32(ctx->opcode, 6, 5);
25406 Rb = extract32(ctx->opcode, 16, 5);
25408 if (XRa <= 15) {
25409 gen_load_mxu_gpr(t0, XRa);
25410 } else if (XRa == 16) {
25411 gen_load_mxu_cr(t0);
25414 gen_store_gpr(t0, Rb);
25416 tcg_temp_free(t0);
25420 * S8LDD XRa, Rb, s8, optn3 - Load a byte from memory to XRF
25422 static void gen_mxu_s8ldd(DisasContext *ctx)
25424 TCGv t0, t1;
25425 uint32_t XRa, Rb, s8, optn3;
25427 t0 = tcg_temp_new();
25428 t1 = tcg_temp_new();
25430 XRa = extract32(ctx->opcode, 6, 4);
25431 s8 = extract32(ctx->opcode, 10, 8);
25432 optn3 = extract32(ctx->opcode, 18, 3);
25433 Rb = extract32(ctx->opcode, 21, 5);
25435 gen_load_gpr(t0, Rb);
25436 tcg_gen_addi_tl(t0, t0, (int8_t)s8);
25438 switch (optn3) {
25439 /* XRa[7:0] = tmp8 */
25440 case MXU_OPTN3_PTN0:
25441 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25442 gen_load_mxu_gpr(t0, XRa);
25443 tcg_gen_deposit_tl(t0, t0, t1, 0, 8);
25444 break;
25445 /* XRa[15:8] = tmp8 */
25446 case MXU_OPTN3_PTN1:
25447 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25448 gen_load_mxu_gpr(t0, XRa);
25449 tcg_gen_deposit_tl(t0, t0, t1, 8, 8);
25450 break;
25451 /* XRa[23:16] = tmp8 */
25452 case MXU_OPTN3_PTN2:
25453 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25454 gen_load_mxu_gpr(t0, XRa);
25455 tcg_gen_deposit_tl(t0, t0, t1, 16, 8);
25456 break;
25457 /* XRa[31:24] = tmp8 */
25458 case MXU_OPTN3_PTN3:
25459 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25460 gen_load_mxu_gpr(t0, XRa);
25461 tcg_gen_deposit_tl(t0, t0, t1, 24, 8);
25462 break;
25463 /* XRa = {8'b0, tmp8, 8'b0, tmp8} */
25464 case MXU_OPTN3_PTN4:
25465 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25466 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25467 break;
25468 /* XRa = {tmp8, 8'b0, tmp8, 8'b0} */
25469 case MXU_OPTN3_PTN5:
25470 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25471 tcg_gen_shli_tl(t1, t1, 8);
25472 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25473 break;
25474 /* XRa = {{8{sign of tmp8}}, tmp8, {8{sign of tmp8}}, tmp8} */
25475 case MXU_OPTN3_PTN6:
25476 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_SB);
25477 tcg_gen_mov_tl(t0, t1);
25478 tcg_gen_andi_tl(t0, t0, 0xFF00FFFF);
25479 tcg_gen_shli_tl(t1, t1, 16);
25480 tcg_gen_or_tl(t0, t0, t1);
25481 break;
25482 /* XRa = {tmp8, tmp8, tmp8, tmp8} */
25483 case MXU_OPTN3_PTN7:
25484 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
25485 tcg_gen_deposit_tl(t1, t1, t1, 8, 8);
25486 tcg_gen_deposit_tl(t0, t1, t1, 16, 16);
25487 break;
25490 gen_store_mxu_gpr(t0, XRa);
25492 tcg_temp_free(t0);
25493 tcg_temp_free(t1);
25497 * D16MUL XRa, XRb, XRc, XRd, optn2 - Signed 16 bit pattern multiplication
25499 static void gen_mxu_d16mul(DisasContext *ctx)
25501 TCGv t0, t1, t2, t3;
25502 uint32_t XRa, XRb, XRc, XRd, optn2;
25504 t0 = tcg_temp_new();
25505 t1 = tcg_temp_new();
25506 t2 = tcg_temp_new();
25507 t3 = tcg_temp_new();
25509 XRa = extract32(ctx->opcode, 6, 4);
25510 XRb = extract32(ctx->opcode, 10, 4);
25511 XRc = extract32(ctx->opcode, 14, 4);
25512 XRd = extract32(ctx->opcode, 18, 4);
25513 optn2 = extract32(ctx->opcode, 22, 2);
25515 gen_load_mxu_gpr(t1, XRb);
25516 tcg_gen_sextract_tl(t0, t1, 0, 16);
25517 tcg_gen_sextract_tl(t1, t1, 16, 16);
25518 gen_load_mxu_gpr(t3, XRc);
25519 tcg_gen_sextract_tl(t2, t3, 0, 16);
25520 tcg_gen_sextract_tl(t3, t3, 16, 16);
25522 switch (optn2) {
25523 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25524 tcg_gen_mul_tl(t3, t1, t3);
25525 tcg_gen_mul_tl(t2, t0, t2);
25526 break;
25527 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25528 tcg_gen_mul_tl(t3, t0, t3);
25529 tcg_gen_mul_tl(t2, t0, t2);
25530 break;
25531 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25532 tcg_gen_mul_tl(t3, t1, t3);
25533 tcg_gen_mul_tl(t2, t1, t2);
25534 break;
25535 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25536 tcg_gen_mul_tl(t3, t0, t3);
25537 tcg_gen_mul_tl(t2, t1, t2);
25538 break;
25540 gen_store_mxu_gpr(t3, XRa);
25541 gen_store_mxu_gpr(t2, XRd);
25543 tcg_temp_free(t0);
25544 tcg_temp_free(t1);
25545 tcg_temp_free(t2);
25546 tcg_temp_free(t3);
25550 * D16MAC XRa, XRb, XRc, XRd, aptn2, optn2 - Signed 16 bit pattern multiply
25551 * and accumulate
25553 static void gen_mxu_d16mac(DisasContext *ctx)
25555 TCGv t0, t1, t2, t3;
25556 uint32_t XRa, XRb, XRc, XRd, optn2, aptn2;
25558 t0 = tcg_temp_new();
25559 t1 = tcg_temp_new();
25560 t2 = tcg_temp_new();
25561 t3 = tcg_temp_new();
25563 XRa = extract32(ctx->opcode, 6, 4);
25564 XRb = extract32(ctx->opcode, 10, 4);
25565 XRc = extract32(ctx->opcode, 14, 4);
25566 XRd = extract32(ctx->opcode, 18, 4);
25567 optn2 = extract32(ctx->opcode, 22, 2);
25568 aptn2 = extract32(ctx->opcode, 24, 2);
25570 gen_load_mxu_gpr(t1, XRb);
25571 tcg_gen_sextract_tl(t0, t1, 0, 16);
25572 tcg_gen_sextract_tl(t1, t1, 16, 16);
25574 gen_load_mxu_gpr(t3, XRc);
25575 tcg_gen_sextract_tl(t2, t3, 0, 16);
25576 tcg_gen_sextract_tl(t3, t3, 16, 16);
25578 switch (optn2) {
25579 case MXU_OPTN2_WW: /* XRB.H*XRC.H == lop, XRB.L*XRC.L == rop */
25580 tcg_gen_mul_tl(t3, t1, t3);
25581 tcg_gen_mul_tl(t2, t0, t2);
25582 break;
25583 case MXU_OPTN2_LW: /* XRB.L*XRC.H == lop, XRB.L*XRC.L == rop */
25584 tcg_gen_mul_tl(t3, t0, t3);
25585 tcg_gen_mul_tl(t2, t0, t2);
25586 break;
25587 case MXU_OPTN2_HW: /* XRB.H*XRC.H == lop, XRB.H*XRC.L == rop */
25588 tcg_gen_mul_tl(t3, t1, t3);
25589 tcg_gen_mul_tl(t2, t1, t2);
25590 break;
25591 case MXU_OPTN2_XW: /* XRB.L*XRC.H == lop, XRB.H*XRC.L == rop */
25592 tcg_gen_mul_tl(t3, t0, t3);
25593 tcg_gen_mul_tl(t2, t1, t2);
25594 break;
25596 gen_load_mxu_gpr(t0, XRa);
25597 gen_load_mxu_gpr(t1, XRd);
25599 switch (aptn2) {
25600 case MXU_APTN2_AA:
25601 tcg_gen_add_tl(t3, t0, t3);
25602 tcg_gen_add_tl(t2, t1, t2);
25603 break;
25604 case MXU_APTN2_AS:
25605 tcg_gen_add_tl(t3, t0, t3);
25606 tcg_gen_sub_tl(t2, t1, t2);
25607 break;
25608 case MXU_APTN2_SA:
25609 tcg_gen_sub_tl(t3, t0, t3);
25610 tcg_gen_add_tl(t2, t1, t2);
25611 break;
25612 case MXU_APTN2_SS:
25613 tcg_gen_sub_tl(t3, t0, t3);
25614 tcg_gen_sub_tl(t2, t1, t2);
25615 break;
25617 gen_store_mxu_gpr(t3, XRa);
25618 gen_store_mxu_gpr(t2, XRd);
25620 tcg_temp_free(t0);
25621 tcg_temp_free(t1);
25622 tcg_temp_free(t2);
25623 tcg_temp_free(t3);
25627 * Q8MUL XRa, XRb, XRc, XRd - Parallel unsigned 8 bit pattern multiply
25628 * Q8MULSU XRa, XRb, XRc, XRd - Parallel signed 8 bit pattern multiply
25630 static void gen_mxu_q8mul_q8mulsu(DisasContext *ctx)
25632 TCGv t0, t1, t2, t3, t4, t5, t6, t7;
25633 uint32_t XRa, XRb, XRc, XRd, sel;
25635 t0 = tcg_temp_new();
25636 t1 = tcg_temp_new();
25637 t2 = tcg_temp_new();
25638 t3 = tcg_temp_new();
25639 t4 = tcg_temp_new();
25640 t5 = tcg_temp_new();
25641 t6 = tcg_temp_new();
25642 t7 = tcg_temp_new();
25644 XRa = extract32(ctx->opcode, 6, 4);
25645 XRb = extract32(ctx->opcode, 10, 4);
25646 XRc = extract32(ctx->opcode, 14, 4);
25647 XRd = extract32(ctx->opcode, 18, 4);
25648 sel = extract32(ctx->opcode, 22, 2);
25650 gen_load_mxu_gpr(t3, XRb);
25651 gen_load_mxu_gpr(t7, XRc);
25653 if (sel == 0x2) {
25654 /* Q8MULSU */
25655 tcg_gen_ext8s_tl(t0, t3);
25656 tcg_gen_shri_tl(t3, t3, 8);
25657 tcg_gen_ext8s_tl(t1, t3);
25658 tcg_gen_shri_tl(t3, t3, 8);
25659 tcg_gen_ext8s_tl(t2, t3);
25660 tcg_gen_shri_tl(t3, t3, 8);
25661 tcg_gen_ext8s_tl(t3, t3);
25662 } else {
25663 /* Q8MUL */
25664 tcg_gen_ext8u_tl(t0, t3);
25665 tcg_gen_shri_tl(t3, t3, 8);
25666 tcg_gen_ext8u_tl(t1, t3);
25667 tcg_gen_shri_tl(t3, t3, 8);
25668 tcg_gen_ext8u_tl(t2, t3);
25669 tcg_gen_shri_tl(t3, t3, 8);
25670 tcg_gen_ext8u_tl(t3, t3);
25673 tcg_gen_ext8u_tl(t4, t7);
25674 tcg_gen_shri_tl(t7, t7, 8);
25675 tcg_gen_ext8u_tl(t5, t7);
25676 tcg_gen_shri_tl(t7, t7, 8);
25677 tcg_gen_ext8u_tl(t6, t7);
25678 tcg_gen_shri_tl(t7, t7, 8);
25679 tcg_gen_ext8u_tl(t7, t7);
25681 tcg_gen_mul_tl(t0, t0, t4);
25682 tcg_gen_mul_tl(t1, t1, t5);
25683 tcg_gen_mul_tl(t2, t2, t6);
25684 tcg_gen_mul_tl(t3, t3, t7);
25686 tcg_gen_andi_tl(t0, t0, 0xFFFF);
25687 tcg_gen_andi_tl(t1, t1, 0xFFFF);
25688 tcg_gen_andi_tl(t2, t2, 0xFFFF);
25689 tcg_gen_andi_tl(t3, t3, 0xFFFF);
25691 tcg_gen_shli_tl(t1, t1, 16);
25692 tcg_gen_shli_tl(t3, t3, 16);
25694 tcg_gen_or_tl(t0, t0, t1);
25695 tcg_gen_or_tl(t1, t2, t3);
25697 gen_store_mxu_gpr(t0, XRd);
25698 gen_store_mxu_gpr(t1, XRa);
25700 tcg_temp_free(t0);
25701 tcg_temp_free(t1);
25702 tcg_temp_free(t2);
25703 tcg_temp_free(t3);
25704 tcg_temp_free(t4);
25705 tcg_temp_free(t5);
25706 tcg_temp_free(t6);
25707 tcg_temp_free(t7);
25711 * S32LDD XRa, Rb, S12 - Load a word from memory to XRF
25712 * S32LDDR XRa, Rb, S12 - Load a word from memory to XRF, reversed byte seq.
25714 static void gen_mxu_s32ldd_s32lddr(DisasContext *ctx)
25716 TCGv t0, t1;
25717 uint32_t XRa, Rb, s12, sel;
25719 t0 = tcg_temp_new();
25720 t1 = tcg_temp_new();
25722 XRa = extract32(ctx->opcode, 6, 4);
25723 s12 = extract32(ctx->opcode, 10, 10);
25724 sel = extract32(ctx->opcode, 20, 1);
25725 Rb = extract32(ctx->opcode, 21, 5);
25727 gen_load_gpr(t0, Rb);
25729 tcg_gen_movi_tl(t1, s12);
25730 tcg_gen_shli_tl(t1, t1, 2);
25731 if (s12 & 0x200) {
25732 tcg_gen_ori_tl(t1, t1, 0xFFFFF000);
25734 tcg_gen_add_tl(t1, t0, t1);
25735 tcg_gen_qemu_ld_tl(t1, t1, ctx->mem_idx, MO_SL);
25737 if (sel == 1) {
25738 /* S32LDDR */
25739 tcg_gen_bswap32_tl(t1, t1);
25741 gen_store_mxu_gpr(t1, XRa);
25743 tcg_temp_free(t0);
25744 tcg_temp_free(t1);
25749 * MXU instruction category: logic
25750 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25752 * S32NOR S32AND S32OR S32XOR
25756 * S32NOR XRa, XRb, XRc
25757 * Update XRa with the result of logical bitwise 'nor' operation
25758 * applied to the content of XRb and XRc.
25760 * 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
25761 * +-----------+---------+-----+-------+-------+-------+-----------+
25762 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25763 * +-----------+---------+-----+-------+-------+-------+-----------+
25765 static void gen_mxu_S32NOR(DisasContext *ctx)
25767 uint32_t pad, XRc, XRb, XRa;
25769 pad = extract32(ctx->opcode, 21, 5);
25770 XRc = extract32(ctx->opcode, 14, 4);
25771 XRb = extract32(ctx->opcode, 10, 4);
25772 XRa = extract32(ctx->opcode, 6, 4);
25774 if (unlikely(pad != 0)) {
25775 /* opcode padding incorrect -> do nothing */
25776 } else if (unlikely(XRa == 0)) {
25777 /* destination is zero register -> do nothing */
25778 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25779 /* both operands zero registers -> just set destination to all 1s */
25780 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0xFFFFFFFF);
25781 } else if (unlikely(XRb == 0)) {
25782 /* XRb zero register -> just set destination to the negation of XRc */
25783 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25784 } else if (unlikely(XRc == 0)) {
25785 /* XRa zero register -> just set destination to the negation of XRb */
25786 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25787 } else if (unlikely(XRb == XRc)) {
25788 /* both operands same -> just set destination to the negation of XRb */
25789 tcg_gen_not_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25790 } else {
25791 /* the most general case */
25792 tcg_gen_nor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25797 * S32AND XRa, XRb, XRc
25798 * Update XRa with the result of logical bitwise 'and' operation
25799 * applied to the content of XRb and XRc.
25801 * 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
25802 * +-----------+---------+-----+-------+-------+-------+-----------+
25803 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25804 * +-----------+---------+-----+-------+-------+-------+-----------+
25806 static void gen_mxu_S32AND(DisasContext *ctx)
25808 uint32_t pad, XRc, XRb, XRa;
25810 pad = extract32(ctx->opcode, 21, 5);
25811 XRc = extract32(ctx->opcode, 14, 4);
25812 XRb = extract32(ctx->opcode, 10, 4);
25813 XRa = extract32(ctx->opcode, 6, 4);
25815 if (unlikely(pad != 0)) {
25816 /* opcode padding incorrect -> do nothing */
25817 } else if (unlikely(XRa == 0)) {
25818 /* destination is zero register -> do nothing */
25819 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25820 /* one of operands zero register -> just set destination to all 0s */
25821 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25822 } else if (unlikely(XRb == XRc)) {
25823 /* both operands same -> just set destination to one of them */
25824 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25825 } else {
25826 /* the most general case */
25827 tcg_gen_and_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25832 * S32OR XRa, XRb, XRc
25833 * Update XRa with the result of logical bitwise 'or' operation
25834 * applied to the content of XRb and XRc.
25836 * 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
25837 * +-----------+---------+-----+-------+-------+-------+-----------+
25838 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25839 * +-----------+---------+-----+-------+-------+-------+-----------+
25841 static void gen_mxu_S32OR(DisasContext *ctx)
25843 uint32_t pad, XRc, XRb, XRa;
25845 pad = extract32(ctx->opcode, 21, 5);
25846 XRc = extract32(ctx->opcode, 14, 4);
25847 XRb = extract32(ctx->opcode, 10, 4);
25848 XRa = extract32(ctx->opcode, 6, 4);
25850 if (unlikely(pad != 0)) {
25851 /* opcode padding incorrect -> do nothing */
25852 } else if (unlikely(XRa == 0)) {
25853 /* destination is zero register -> do nothing */
25854 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25855 /* both operands zero registers -> just set destination to all 0s */
25856 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25857 } else if (unlikely(XRb == 0)) {
25858 /* XRb zero register -> just set destination to the content of XRc */
25859 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25860 } else if (unlikely(XRc == 0)) {
25861 /* XRc zero register -> just set destination to the content of XRb */
25862 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25863 } else if (unlikely(XRb == XRc)) {
25864 /* both operands same -> just set destination to one of them */
25865 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25866 } else {
25867 /* the most general case */
25868 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25873 * S32XOR XRa, XRb, XRc
25874 * Update XRa with the result of logical bitwise 'xor' operation
25875 * applied to the content of XRb and XRc.
25877 * 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
25878 * +-----------+---------+-----+-------+-------+-------+-----------+
25879 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL16|
25880 * +-----------+---------+-----+-------+-------+-------+-----------+
25882 static void gen_mxu_S32XOR(DisasContext *ctx)
25884 uint32_t pad, XRc, XRb, XRa;
25886 pad = extract32(ctx->opcode, 21, 5);
25887 XRc = extract32(ctx->opcode, 14, 4);
25888 XRb = extract32(ctx->opcode, 10, 4);
25889 XRa = extract32(ctx->opcode, 6, 4);
25891 if (unlikely(pad != 0)) {
25892 /* opcode padding incorrect -> do nothing */
25893 } else if (unlikely(XRa == 0)) {
25894 /* destination is zero register -> do nothing */
25895 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25896 /* both operands zero registers -> just set destination to all 0s */
25897 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25898 } else if (unlikely(XRb == 0)) {
25899 /* XRb zero register -> just set destination to the content of XRc */
25900 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
25901 } else if (unlikely(XRc == 0)) {
25902 /* XRc zero register -> just set destination to the content of XRb */
25903 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25904 } else if (unlikely(XRb == XRc)) {
25905 /* both operands same -> just set destination to all 0s */
25906 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25907 } else {
25908 /* the most general case */
25909 tcg_gen_xor_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]);
25915 * MXU instruction category max/min
25916 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25918 * S32MAX D16MAX Q8MAX
25919 * S32MIN D16MIN Q8MIN
25923 * S32MAX XRa, XRb, XRc
25924 * Update XRa with the maximum of signed 32-bit integers contained
25925 * in XRb and XRc.
25927 * S32MIN XRa, XRb, XRc
25928 * Update XRa with the minimum of signed 32-bit integers contained
25929 * in XRb and XRc.
25931 * 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
25932 * +-----------+---------+-----+-------+-------+-------+-----------+
25933 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25934 * +-----------+---------+-----+-------+-------+-------+-----------+
25936 static void gen_mxu_S32MAX_S32MIN(DisasContext *ctx)
25938 uint32_t pad, opc, XRc, XRb, XRa;
25940 pad = extract32(ctx->opcode, 21, 5);
25941 opc = extract32(ctx->opcode, 18, 3);
25942 XRc = extract32(ctx->opcode, 14, 4);
25943 XRb = extract32(ctx->opcode, 10, 4);
25944 XRa = extract32(ctx->opcode, 6, 4);
25946 if (unlikely(pad != 0)) {
25947 /* opcode padding incorrect -> do nothing */
25948 } else if (unlikely(XRa == 0)) {
25949 /* destination is zero register -> do nothing */
25950 } else if (unlikely((XRb == 0) && (XRc == 0))) {
25951 /* both operands zero registers -> just set destination to zero */
25952 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
25953 } else if (unlikely((XRb == 0) || (XRc == 0))) {
25954 /* exactly one operand is zero register - find which one is not...*/
25955 uint32_t XRx = XRb ? XRb : XRc;
25956 /* ...and do max/min operation with one operand 0 */
25957 if (opc == OPC_MXU_S32MAX) {
25958 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25959 } else {
25960 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRx - 1], 0);
25962 } else if (unlikely(XRb == XRc)) {
25963 /* both operands same -> just set destination to one of them */
25964 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
25965 } else {
25966 /* the most general case */
25967 if (opc == OPC_MXU_S32MAX) {
25968 tcg_gen_smax_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25969 mxu_gpr[XRc - 1]);
25970 } else {
25971 tcg_gen_smin_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1],
25972 mxu_gpr[XRc - 1]);
25978 * D16MAX
25979 * Update XRa with the 16-bit-wise maximums of signed integers
25980 * contained in XRb and XRc.
25982 * D16MIN
25983 * Update XRa with the 16-bit-wise minimums of signed integers
25984 * contained in XRb and XRc.
25986 * 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
25987 * +-----------+---------+-----+-------+-------+-------+-----------+
25988 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
25989 * +-----------+---------+-----+-------+-------+-------+-----------+
25991 static void gen_mxu_D16MAX_D16MIN(DisasContext *ctx)
25993 uint32_t pad, opc, XRc, XRb, XRa;
25995 pad = extract32(ctx->opcode, 21, 5);
25996 opc = extract32(ctx->opcode, 18, 3);
25997 XRc = extract32(ctx->opcode, 14, 4);
25998 XRb = extract32(ctx->opcode, 10, 4);
25999 XRa = extract32(ctx->opcode, 6, 4);
26001 if (unlikely(pad != 0)) {
26002 /* opcode padding incorrect -> do nothing */
26003 } else if (unlikely(XRc == 0)) {
26004 /* destination is zero register -> do nothing */
26005 } else if (unlikely((XRb == 0) && (XRa == 0))) {
26006 /* both operands zero registers -> just set destination to zero */
26007 tcg_gen_movi_i32(mxu_gpr[XRc - 1], 0);
26008 } else if (unlikely((XRb == 0) || (XRa == 0))) {
26009 /* exactly one operand is zero register - find which one is not...*/
26010 uint32_t XRx = XRb ? XRb : XRc;
26011 /* ...and do half-word-wise max/min with one operand 0 */
26012 TCGv_i32 t0 = tcg_temp_new();
26013 TCGv_i32 t1 = tcg_const_i32(0);
26015 /* the left half-word first */
26016 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFFFF0000);
26017 if (opc == OPC_MXU_D16MAX) {
26018 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26019 } else {
26020 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26023 /* the right half-word */
26024 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0x0000FFFF);
26025 /* move half-words to the leftmost position */
26026 tcg_gen_shli_i32(t0, t0, 16);
26027 /* t0 will be max/min of t0 and t1 */
26028 if (opc == OPC_MXU_D16MAX) {
26029 tcg_gen_smax_i32(t0, t0, t1);
26030 } else {
26031 tcg_gen_smin_i32(t0, t0, t1);
26033 /* return resulting half-words to its original position */
26034 tcg_gen_shri_i32(t0, t0, 16);
26035 /* finally update the destination */
26036 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26038 tcg_temp_free(t1);
26039 tcg_temp_free(t0);
26040 } else if (unlikely(XRb == XRc)) {
26041 /* both operands same -> just set destination to one of them */
26042 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26043 } else {
26044 /* the most general case */
26045 TCGv_i32 t0 = tcg_temp_new();
26046 TCGv_i32 t1 = tcg_temp_new();
26048 /* the left half-word first */
26049 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFFFF0000);
26050 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26051 if (opc == OPC_MXU_D16MAX) {
26052 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26053 } else {
26054 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26057 /* the right half-word */
26058 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26059 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0x0000FFFF);
26060 /* move half-words to the leftmost position */
26061 tcg_gen_shli_i32(t0, t0, 16);
26062 tcg_gen_shli_i32(t1, t1, 16);
26063 /* t0 will be max/min of t0 and t1 */
26064 if (opc == OPC_MXU_D16MAX) {
26065 tcg_gen_smax_i32(t0, t0, t1);
26066 } else {
26067 tcg_gen_smin_i32(t0, t0, t1);
26069 /* return resulting half-words to its original position */
26070 tcg_gen_shri_i32(t0, t0, 16);
26071 /* finally update the destination */
26072 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26074 tcg_temp_free(t1);
26075 tcg_temp_free(t0);
26080 * Q8MAX
26081 * Update XRa with the 8-bit-wise maximums of signed integers
26082 * contained in XRb and XRc.
26084 * Q8MIN
26085 * Update XRa with the 8-bit-wise minimums of signed integers
26086 * contained in XRb and XRc.
26088 * 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
26089 * +-----------+---------+-----+-------+-------+-------+-----------+
26090 * | SPECIAL2 |0 0 0 0 0| opc | XRc | XRb | XRa |MXU__POOL00|
26091 * +-----------+---------+-----+-------+-------+-------+-----------+
26093 static void gen_mxu_Q8MAX_Q8MIN(DisasContext *ctx)
26095 uint32_t pad, opc, XRc, XRb, XRa;
26097 pad = extract32(ctx->opcode, 21, 5);
26098 opc = extract32(ctx->opcode, 18, 3);
26099 XRc = extract32(ctx->opcode, 14, 4);
26100 XRb = extract32(ctx->opcode, 10, 4);
26101 XRa = extract32(ctx->opcode, 6, 4);
26103 if (unlikely(pad != 0)) {
26104 /* opcode padding incorrect -> do nothing */
26105 } else if (unlikely(XRa == 0)) {
26106 /* destination is zero register -> do nothing */
26107 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26108 /* both operands zero registers -> just set destination to zero */
26109 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26110 } else if (unlikely((XRb == 0) || (XRc == 0))) {
26111 /* exactly one operand is zero register - make it be the first...*/
26112 uint32_t XRx = XRb ? XRb : XRc;
26113 /* ...and do byte-wise max/min with one operand 0 */
26114 TCGv_i32 t0 = tcg_temp_new();
26115 TCGv_i32 t1 = tcg_const_i32(0);
26116 int32_t i;
26118 /* the leftmost byte (byte 3) first */
26119 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF000000);
26120 if (opc == OPC_MXU_Q8MAX) {
26121 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26122 } else {
26123 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26126 /* bytes 2, 1, 0 */
26127 for (i = 2; i >= 0; i--) {
26128 /* extract the byte */
26129 tcg_gen_andi_i32(t0, mxu_gpr[XRx - 1], 0xFF << (8 * i));
26130 /* move the byte to the leftmost position */
26131 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26132 /* t0 will be max/min of t0 and t1 */
26133 if (opc == OPC_MXU_Q8MAX) {
26134 tcg_gen_smax_i32(t0, t0, t1);
26135 } else {
26136 tcg_gen_smin_i32(t0, t0, t1);
26138 /* return resulting byte to its original position */
26139 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26140 /* finally update the destination */
26141 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26144 tcg_temp_free(t1);
26145 tcg_temp_free(t0);
26146 } else if (unlikely(XRb == XRc)) {
26147 /* both operands same -> just set destination to one of them */
26148 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26149 } else {
26150 /* the most general case */
26151 TCGv_i32 t0 = tcg_temp_new();
26152 TCGv_i32 t1 = tcg_temp_new();
26153 int32_t i;
26155 /* the leftmost bytes (bytes 3) first */
26156 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF000000);
26157 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26158 if (opc == OPC_MXU_Q8MAX) {
26159 tcg_gen_smax_i32(mxu_gpr[XRa - 1], t0, t1);
26160 } else {
26161 tcg_gen_smin_i32(mxu_gpr[XRa - 1], t0, t1);
26164 /* bytes 2, 1, 0 */
26165 for (i = 2; i >= 0; i--) {
26166 /* extract corresponding bytes */
26167 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0xFF << (8 * i));
26168 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF << (8 * i));
26169 /* move the bytes to the leftmost position */
26170 tcg_gen_shli_i32(t0, t0, 8 * (3 - i));
26171 tcg_gen_shli_i32(t1, t1, 8 * (3 - i));
26172 /* t0 will be max/min of t0 and t1 */
26173 if (opc == OPC_MXU_Q8MAX) {
26174 tcg_gen_smax_i32(t0, t0, t1);
26175 } else {
26176 tcg_gen_smin_i32(t0, t0, t1);
26178 /* return resulting byte to its original position */
26179 tcg_gen_shri_i32(t0, t0, 8 * (3 - i));
26180 /* finally update the destination */
26181 tcg_gen_or_i32(mxu_gpr[XRa - 1], mxu_gpr[XRa - 1], t0);
26184 tcg_temp_free(t1);
26185 tcg_temp_free(t0);
26191 * MXU instruction category: align
26192 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26194 * S32ALN S32ALNI
26198 * S32ALNI XRc, XRb, XRa, optn3
26199 * Arrange bytes from XRb and XRc according to one of five sets of
26200 * rules determined by optn3, and place the result in XRa.
26202 * 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
26203 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26204 * | SPECIAL2 |optn3|0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
26205 * +-----------+-----+---+-----+-------+-------+-------+-----------+
26208 static void gen_mxu_S32ALNI(DisasContext *ctx)
26210 uint32_t optn3, pad, XRc, XRb, XRa;
26212 optn3 = extract32(ctx->opcode, 23, 3);
26213 pad = extract32(ctx->opcode, 21, 2);
26214 XRc = extract32(ctx->opcode, 14, 4);
26215 XRb = extract32(ctx->opcode, 10, 4);
26216 XRa = extract32(ctx->opcode, 6, 4);
26218 if (unlikely(pad != 0)) {
26219 /* opcode padding incorrect -> do nothing */
26220 } else if (unlikely(XRa == 0)) {
26221 /* destination is zero register -> do nothing */
26222 } else if (unlikely((XRb == 0) && (XRc == 0))) {
26223 /* both operands zero registers -> just set destination to all 0s */
26224 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26225 } else if (unlikely(XRb == 0)) {
26226 /* XRb zero register -> just appropriatelly shift XRc into XRa */
26227 switch (optn3) {
26228 case MXU_OPTN3_PTN0:
26229 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26230 break;
26231 case MXU_OPTN3_PTN1:
26232 case MXU_OPTN3_PTN2:
26233 case MXU_OPTN3_PTN3:
26234 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1],
26235 8 * (4 - optn3));
26236 break;
26237 case MXU_OPTN3_PTN4:
26238 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26239 break;
26241 } else if (unlikely(XRc == 0)) {
26242 /* XRc zero register -> just appropriatelly shift XRb into XRa */
26243 switch (optn3) {
26244 case MXU_OPTN3_PTN0:
26245 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26246 break;
26247 case MXU_OPTN3_PTN1:
26248 case MXU_OPTN3_PTN2:
26249 case MXU_OPTN3_PTN3:
26250 tcg_gen_shri_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26251 break;
26252 case MXU_OPTN3_PTN4:
26253 tcg_gen_movi_i32(mxu_gpr[XRa - 1], 0);
26254 break;
26256 } else if (unlikely(XRb == XRc)) {
26257 /* both operands same -> just rotation or moving from any of them */
26258 switch (optn3) {
26259 case MXU_OPTN3_PTN0:
26260 case MXU_OPTN3_PTN4:
26261 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26262 break;
26263 case MXU_OPTN3_PTN1:
26264 case MXU_OPTN3_PTN2:
26265 case MXU_OPTN3_PTN3:
26266 tcg_gen_rotli_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1], 8 * optn3);
26267 break;
26269 } else {
26270 /* the most general case */
26271 switch (optn3) {
26272 case MXU_OPTN3_PTN0:
26274 /* */
26275 /* XRb XRc */
26276 /* +---------------+ */
26277 /* | A B C D | E F G H */
26278 /* +-------+-------+ */
26279 /* | */
26280 /* XRa */
26281 /* */
26283 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRb - 1]);
26285 break;
26286 case MXU_OPTN3_PTN1:
26288 /* */
26289 /* XRb XRc */
26290 /* +-------------------+ */
26291 /* A | B C D E | F G H */
26292 /* +---------+---------+ */
26293 /* | */
26294 /* XRa */
26295 /* */
26297 TCGv_i32 t0 = tcg_temp_new();
26298 TCGv_i32 t1 = tcg_temp_new();
26300 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x00FFFFFF);
26301 tcg_gen_shli_i32(t0, t0, 8);
26303 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFF000000);
26304 tcg_gen_shri_i32(t1, t1, 24);
26306 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26308 tcg_temp_free(t1);
26309 tcg_temp_free(t0);
26311 break;
26312 case MXU_OPTN3_PTN2:
26314 /* */
26315 /* XRb XRc */
26316 /* +-------------------+ */
26317 /* A B | C D E F | G H */
26318 /* +---------+---------+ */
26319 /* | */
26320 /* XRa */
26321 /* */
26323 TCGv_i32 t0 = tcg_temp_new();
26324 TCGv_i32 t1 = tcg_temp_new();
26326 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x0000FFFF);
26327 tcg_gen_shli_i32(t0, t0, 16);
26329 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFF0000);
26330 tcg_gen_shri_i32(t1, t1, 16);
26332 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26334 tcg_temp_free(t1);
26335 tcg_temp_free(t0);
26337 break;
26338 case MXU_OPTN3_PTN3:
26340 /* */
26341 /* XRb XRc */
26342 /* +-------------------+ */
26343 /* A B C | D E F G | H */
26344 /* +---------+---------+ */
26345 /* | */
26346 /* XRa */
26347 /* */
26349 TCGv_i32 t0 = tcg_temp_new();
26350 TCGv_i32 t1 = tcg_temp_new();
26352 tcg_gen_andi_i32(t0, mxu_gpr[XRb - 1], 0x000000FF);
26353 tcg_gen_shli_i32(t0, t0, 24);
26355 tcg_gen_andi_i32(t1, mxu_gpr[XRc - 1], 0xFFFFFF00);
26356 tcg_gen_shri_i32(t1, t1, 8);
26358 tcg_gen_or_i32(mxu_gpr[XRa - 1], t0, t1);
26360 tcg_temp_free(t1);
26361 tcg_temp_free(t0);
26363 break;
26364 case MXU_OPTN3_PTN4:
26366 /* */
26367 /* XRb XRc */
26368 /* +---------------+ */
26369 /* A B C D | E F G H | */
26370 /* +-------+-------+ */
26371 /* | */
26372 /* XRa */
26373 /* */
26375 tcg_gen_mov_i32(mxu_gpr[XRa - 1], mxu_gpr[XRc - 1]);
26377 break;
26384 * Decoding engine for MXU
26385 * =======================
26390 * Decode MXU pool00
26392 * 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
26393 * +-----------+---------+-----+-------+-------+-------+-----------+
26394 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL00|
26395 * +-----------+---------+-----+-------+-------+-------+-----------+
26398 static void decode_opc_mxu__pool00(CPUMIPSState *env, DisasContext *ctx)
26400 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26402 switch (opcode) {
26403 case OPC_MXU_S32MAX:
26404 case OPC_MXU_S32MIN:
26405 gen_mxu_S32MAX_S32MIN(ctx);
26406 break;
26407 case OPC_MXU_D16MAX:
26408 case OPC_MXU_D16MIN:
26409 gen_mxu_D16MAX_D16MIN(ctx);
26410 break;
26411 case OPC_MXU_Q8MAX:
26412 case OPC_MXU_Q8MIN:
26413 gen_mxu_Q8MAX_Q8MIN(ctx);
26414 break;
26415 case OPC_MXU_Q8SLT:
26416 /* TODO: Implement emulation of Q8SLT instruction. */
26417 MIPS_INVAL("OPC_MXU_Q8SLT");
26418 generate_exception_end(ctx, EXCP_RI);
26419 break;
26420 case OPC_MXU_Q8SLTU:
26421 /* TODO: Implement emulation of Q8SLTU instruction. */
26422 MIPS_INVAL("OPC_MXU_Q8SLTU");
26423 generate_exception_end(ctx, EXCP_RI);
26424 break;
26425 default:
26426 MIPS_INVAL("decode_opc_mxu");
26427 generate_exception_end(ctx, EXCP_RI);
26428 break;
26434 * Decode MXU pool01
26436 * S32SLT, D16SLT, D16AVG, D16AVGR, Q8AVG, Q8AVGR:
26437 * 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
26438 * +-----------+---------+-----+-------+-------+-------+-----------+
26439 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26440 * +-----------+---------+-----+-------+-------+-------+-----------+
26442 * Q8ADD:
26443 * 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
26444 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26445 * | SPECIAL2 |en2|0 0 0|x x x| XRc | XRb | XRa |MXU__POOL01|
26446 * +-----------+---+-----+-----+-------+-------+-------+-----------+
26449 static void decode_opc_mxu__pool01(CPUMIPSState *env, DisasContext *ctx)
26451 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26453 switch (opcode) {
26454 case OPC_MXU_S32SLT:
26455 /* TODO: Implement emulation of S32SLT instruction. */
26456 MIPS_INVAL("OPC_MXU_S32SLT");
26457 generate_exception_end(ctx, EXCP_RI);
26458 break;
26459 case OPC_MXU_D16SLT:
26460 /* TODO: Implement emulation of D16SLT instruction. */
26461 MIPS_INVAL("OPC_MXU_D16SLT");
26462 generate_exception_end(ctx, EXCP_RI);
26463 break;
26464 case OPC_MXU_D16AVG:
26465 /* TODO: Implement emulation of D16AVG instruction. */
26466 MIPS_INVAL("OPC_MXU_D16AVG");
26467 generate_exception_end(ctx, EXCP_RI);
26468 break;
26469 case OPC_MXU_D16AVGR:
26470 /* TODO: Implement emulation of D16AVGR instruction. */
26471 MIPS_INVAL("OPC_MXU_D16AVGR");
26472 generate_exception_end(ctx, EXCP_RI);
26473 break;
26474 case OPC_MXU_Q8AVG:
26475 /* TODO: Implement emulation of Q8AVG instruction. */
26476 MIPS_INVAL("OPC_MXU_Q8AVG");
26477 generate_exception_end(ctx, EXCP_RI);
26478 break;
26479 case OPC_MXU_Q8AVGR:
26480 /* TODO: Implement emulation of Q8AVGR instruction. */
26481 MIPS_INVAL("OPC_MXU_Q8AVGR");
26482 generate_exception_end(ctx, EXCP_RI);
26483 break;
26484 case OPC_MXU_Q8ADD:
26485 /* TODO: Implement emulation of Q8ADD instruction. */
26486 MIPS_INVAL("OPC_MXU_Q8ADD");
26487 generate_exception_end(ctx, EXCP_RI);
26488 break;
26489 default:
26490 MIPS_INVAL("decode_opc_mxu");
26491 generate_exception_end(ctx, EXCP_RI);
26492 break;
26498 * Decode MXU pool02
26500 * 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
26501 * +-----------+---------+-----+-------+-------+-------+-----------+
26502 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL02|
26503 * +-----------+---------+-----+-------+-------+-------+-----------+
26506 static void decode_opc_mxu__pool02(CPUMIPSState *env, DisasContext *ctx)
26508 uint32_t opcode = extract32(ctx->opcode, 18, 3);
26510 switch (opcode) {
26511 case OPC_MXU_S32CPS:
26512 /* TODO: Implement emulation of S32CPS instruction. */
26513 MIPS_INVAL("OPC_MXU_S32CPS");
26514 generate_exception_end(ctx, EXCP_RI);
26515 break;
26516 case OPC_MXU_D16CPS:
26517 /* TODO: Implement emulation of D16CPS instruction. */
26518 MIPS_INVAL("OPC_MXU_D16CPS");
26519 generate_exception_end(ctx, EXCP_RI);
26520 break;
26521 case OPC_MXU_Q8ABD:
26522 /* TODO: Implement emulation of Q8ABD instruction. */
26523 MIPS_INVAL("OPC_MXU_Q8ABD");
26524 generate_exception_end(ctx, EXCP_RI);
26525 break;
26526 case OPC_MXU_Q16SAT:
26527 /* TODO: Implement emulation of Q16SAT instruction. */
26528 MIPS_INVAL("OPC_MXU_Q16SAT");
26529 generate_exception_end(ctx, EXCP_RI);
26530 break;
26531 default:
26532 MIPS_INVAL("decode_opc_mxu");
26533 generate_exception_end(ctx, EXCP_RI);
26534 break;
26540 * Decode MXU pool03
26542 * D16MULF:
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 |x x|on2|0 0 0 0| XRc | XRb | XRa |MXU__POOL03|
26546 * +-----------+---+---+-------+-------+-------+-------+-----------+
26548 * D16MULE:
26549 * 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
26550 * +-----------+---+---+-------+-------+-------+-------+-----------+
26551 * | SPECIAL2 |x x|on2| Xd | XRc | XRb | XRa |MXU__POOL03|
26552 * +-----------+---+---+-------+-------+-------+-------+-----------+
26555 static void decode_opc_mxu__pool03(CPUMIPSState *env, DisasContext *ctx)
26557 uint32_t opcode = extract32(ctx->opcode, 24, 2);
26559 switch (opcode) {
26560 case OPC_MXU_D16MULF:
26561 /* TODO: Implement emulation of D16MULF instruction. */
26562 MIPS_INVAL("OPC_MXU_D16MULF");
26563 generate_exception_end(ctx, EXCP_RI);
26564 break;
26565 case OPC_MXU_D16MULE:
26566 /* TODO: Implement emulation of D16MULE instruction. */
26567 MIPS_INVAL("OPC_MXU_D16MULE");
26568 generate_exception_end(ctx, EXCP_RI);
26569 break;
26570 default:
26571 MIPS_INVAL("decode_opc_mxu");
26572 generate_exception_end(ctx, EXCP_RI);
26573 break;
26579 * Decode MXU pool04
26581 * 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
26582 * +-----------+---------+-+-------------------+-------+-----------+
26583 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL04|
26584 * +-----------+---------+-+-------------------+-------+-----------+
26587 static void decode_opc_mxu__pool04(CPUMIPSState *env, DisasContext *ctx)
26589 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26591 switch (opcode) {
26592 case OPC_MXU_S32LDD:
26593 case OPC_MXU_S32LDDR:
26594 gen_mxu_s32ldd_s32lddr(ctx);
26595 break;
26596 default:
26597 MIPS_INVAL("decode_opc_mxu");
26598 generate_exception_end(ctx, EXCP_RI);
26599 break;
26605 * Decode MXU pool05
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__POOL05|
26610 * +-----------+---------+-+-------------------+-------+-----------+
26613 static void decode_opc_mxu__pool05(CPUMIPSState *env, DisasContext *ctx)
26615 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26617 switch (opcode) {
26618 case OPC_MXU_S32STD:
26619 /* TODO: Implement emulation of S32STD instruction. */
26620 MIPS_INVAL("OPC_MXU_S32STD");
26621 generate_exception_end(ctx, EXCP_RI);
26622 break;
26623 case OPC_MXU_S32STDR:
26624 /* TODO: Implement emulation of S32STDR instruction. */
26625 MIPS_INVAL("OPC_MXU_S32STDR");
26626 generate_exception_end(ctx, EXCP_RI);
26627 break;
26628 default:
26629 MIPS_INVAL("decode_opc_mxu");
26630 generate_exception_end(ctx, EXCP_RI);
26631 break;
26637 * Decode MXU pool06
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__POOL06|
26642 * +-----------+---------+---------+---+-------+-------+-----------+
26645 static void decode_opc_mxu__pool06(CPUMIPSState *env, DisasContext *ctx)
26647 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26649 switch (opcode) {
26650 case OPC_MXU_S32LDDV:
26651 /* TODO: Implement emulation of S32LDDV instruction. */
26652 MIPS_INVAL("OPC_MXU_S32LDDV");
26653 generate_exception_end(ctx, EXCP_RI);
26654 break;
26655 case OPC_MXU_S32LDDVR:
26656 /* TODO: Implement emulation of S32LDDVR instruction. */
26657 MIPS_INVAL("OPC_MXU_S32LDDVR");
26658 generate_exception_end(ctx, EXCP_RI);
26659 break;
26660 default:
26661 MIPS_INVAL("decode_opc_mxu");
26662 generate_exception_end(ctx, EXCP_RI);
26663 break;
26669 * Decode MXU pool07
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__POOL07|
26674 * +-----------+---------+---------+---+-------+-------+-----------+
26677 static void decode_opc_mxu__pool07(CPUMIPSState *env, DisasContext *ctx)
26679 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26681 switch (opcode) {
26682 case OPC_MXU_S32STDV:
26683 /* TODO: Implement emulation of S32TDV instruction. */
26684 MIPS_INVAL("OPC_MXU_S32TDV");
26685 generate_exception_end(ctx, EXCP_RI);
26686 break;
26687 case OPC_MXU_S32STDVR:
26688 /* TODO: Implement emulation of S32TDVR instruction. */
26689 MIPS_INVAL("OPC_MXU_S32TDVR");
26690 generate_exception_end(ctx, EXCP_RI);
26691 break;
26692 default:
26693 MIPS_INVAL("decode_opc_mxu");
26694 generate_exception_end(ctx, EXCP_RI);
26695 break;
26701 * Decode MXU pool08
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 | rb |x| s12 | XRa |MXU__POOL08|
26706 * +-----------+---------+-+-------------------+-------+-----------+
26709 static void decode_opc_mxu__pool08(CPUMIPSState *env, DisasContext *ctx)
26711 uint32_t opcode = extract32(ctx->opcode, 20, 1);
26713 switch (opcode) {
26714 case OPC_MXU_S32LDI:
26715 /* TODO: Implement emulation of S32LDI instruction. */
26716 MIPS_INVAL("OPC_MXU_S32LDI");
26717 generate_exception_end(ctx, EXCP_RI);
26718 break;
26719 case OPC_MXU_S32LDIR:
26720 /* TODO: Implement emulation of S32LDIR instruction. */
26721 MIPS_INVAL("OPC_MXU_S32LDIR");
26722 generate_exception_end(ctx, EXCP_RI);
26723 break;
26724 default:
26725 MIPS_INVAL("decode_opc_mxu");
26726 generate_exception_end(ctx, EXCP_RI);
26727 break;
26733 * Decode MXU pool09
26735 * 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
26736 * +-----------+---------+-+-------------------+-------+-----------+
26737 * | SPECIAL2 | rb |x| s12 | XRa |MXU__POOL09|
26738 * +-----------+---------+-+-------------------+-------+-----------+
26741 static void decode_opc_mxu__pool09(CPUMIPSState *env, DisasContext *ctx)
26743 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26745 switch (opcode) {
26746 case OPC_MXU_S32SDI:
26747 /* TODO: Implement emulation of S32SDI instruction. */
26748 MIPS_INVAL("OPC_MXU_S32SDI");
26749 generate_exception_end(ctx, EXCP_RI);
26750 break;
26751 case OPC_MXU_S32SDIR:
26752 /* TODO: Implement emulation of S32SDIR instruction. */
26753 MIPS_INVAL("OPC_MXU_S32SDIR");
26754 generate_exception_end(ctx, EXCP_RI);
26755 break;
26756 default:
26757 MIPS_INVAL("decode_opc_mxu");
26758 generate_exception_end(ctx, EXCP_RI);
26759 break;
26765 * Decode MXU pool10
26767 * 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
26768 * +-----------+---------+---------+---+-------+-------+-----------+
26769 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL10|
26770 * +-----------+---------+---------+---+-------+-------+-----------+
26773 static void decode_opc_mxu__pool10(CPUMIPSState *env, DisasContext *ctx)
26775 uint32_t opcode = extract32(ctx->opcode, 5, 0);
26777 switch (opcode) {
26778 case OPC_MXU_S32LDIV:
26779 /* TODO: Implement emulation of S32LDIV instruction. */
26780 MIPS_INVAL("OPC_MXU_S32LDIV");
26781 generate_exception_end(ctx, EXCP_RI);
26782 break;
26783 case OPC_MXU_S32LDIVR:
26784 /* TODO: Implement emulation of S32LDIVR instruction. */
26785 MIPS_INVAL("OPC_MXU_S32LDIVR");
26786 generate_exception_end(ctx, EXCP_RI);
26787 break;
26788 default:
26789 MIPS_INVAL("decode_opc_mxu");
26790 generate_exception_end(ctx, EXCP_RI);
26791 break;
26797 * Decode MXU pool11
26799 * 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
26800 * +-----------+---------+---------+---+-------+-------+-----------+
26801 * | SPECIAL2 | rb | rc |st2|x x x x| XRa |MXU__POOL11|
26802 * +-----------+---------+---------+---+-------+-------+-----------+
26805 static void decode_opc_mxu__pool11(CPUMIPSState *env, DisasContext *ctx)
26807 uint32_t opcode = extract32(ctx->opcode, 10, 4);
26809 switch (opcode) {
26810 case OPC_MXU_S32SDIV:
26811 /* TODO: Implement emulation of S32SDIV instruction. */
26812 MIPS_INVAL("OPC_MXU_S32SDIV");
26813 generate_exception_end(ctx, EXCP_RI);
26814 break;
26815 case OPC_MXU_S32SDIVR:
26816 /* TODO: Implement emulation of S32SDIVR instruction. */
26817 MIPS_INVAL("OPC_MXU_S32SDIVR");
26818 generate_exception_end(ctx, EXCP_RI);
26819 break;
26820 default:
26821 MIPS_INVAL("decode_opc_mxu");
26822 generate_exception_end(ctx, EXCP_RI);
26823 break;
26829 * Decode MXU pool12
26831 * 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
26832 * +-----------+---+---+-------+-------+-------+-------+-----------+
26833 * | SPECIAL2 |an2|x x| Xd | XRc | XRb | XRa |MXU__POOL12|
26834 * +-----------+---+---+-------+-------+-------+-------+-----------+
26837 static void decode_opc_mxu__pool12(CPUMIPSState *env, DisasContext *ctx)
26839 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26841 switch (opcode) {
26842 case OPC_MXU_D32ACC:
26843 /* TODO: Implement emulation of D32ACC instruction. */
26844 MIPS_INVAL("OPC_MXU_D32ACC");
26845 generate_exception_end(ctx, EXCP_RI);
26846 break;
26847 case OPC_MXU_D32ACCM:
26848 /* TODO: Implement emulation of D32ACCM instruction. */
26849 MIPS_INVAL("OPC_MXU_D32ACCM");
26850 generate_exception_end(ctx, EXCP_RI);
26851 break;
26852 case OPC_MXU_D32ASUM:
26853 /* TODO: Implement emulation of D32ASUM instruction. */
26854 MIPS_INVAL("OPC_MXU_D32ASUM");
26855 generate_exception_end(ctx, EXCP_RI);
26856 break;
26857 default:
26858 MIPS_INVAL("decode_opc_mxu");
26859 generate_exception_end(ctx, EXCP_RI);
26860 break;
26866 * Decode MXU pool13
26868 * 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
26869 * +-----------+---+---+-------+-------+-------+-------+-----------+
26870 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL13|
26871 * +-----------+---+---+-------+-------+-------+-------+-----------+
26874 static void decode_opc_mxu__pool13(CPUMIPSState *env, DisasContext *ctx)
26876 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26878 switch (opcode) {
26879 case OPC_MXU_Q16ACC:
26880 /* TODO: Implement emulation of Q16ACC instruction. */
26881 MIPS_INVAL("OPC_MXU_Q16ACC");
26882 generate_exception_end(ctx, EXCP_RI);
26883 break;
26884 case OPC_MXU_Q16ACCM:
26885 /* TODO: Implement emulation of Q16ACCM instruction. */
26886 MIPS_INVAL("OPC_MXU_Q16ACCM");
26887 generate_exception_end(ctx, EXCP_RI);
26888 break;
26889 case OPC_MXU_Q16ASUM:
26890 /* TODO: Implement emulation of Q16ASUM instruction. */
26891 MIPS_INVAL("OPC_MXU_Q16ASUM");
26892 generate_exception_end(ctx, EXCP_RI);
26893 break;
26894 default:
26895 MIPS_INVAL("decode_opc_mxu");
26896 generate_exception_end(ctx, EXCP_RI);
26897 break;
26903 * Decode MXU pool14
26905 * Q8ADDE, Q8ACCE:
26906 * 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
26907 * +-----------+---+---+-------+-------+-------+-------+-----------+
26908 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL14|
26909 * +-----------+---+---+-------+-------+-------+-------+-----------+
26911 * D8SUM, D8SUMC:
26912 * 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
26913 * +-----------+---+---+-------+-------+-------+-------+-----------+
26914 * | SPECIAL2 |en2|x x|0 0 0 0| XRc | XRb | XRa |MXU__POOL14|
26915 * +-----------+---+---+-------+-------+-------+-------+-----------+
26918 static void decode_opc_mxu__pool14(CPUMIPSState *env, DisasContext *ctx)
26920 uint32_t opcode = extract32(ctx->opcode, 22, 2);
26922 switch (opcode) {
26923 case OPC_MXU_Q8ADDE:
26924 /* TODO: Implement emulation of Q8ADDE instruction. */
26925 MIPS_INVAL("OPC_MXU_Q8ADDE");
26926 generate_exception_end(ctx, EXCP_RI);
26927 break;
26928 case OPC_MXU_D8SUM:
26929 /* TODO: Implement emulation of D8SUM instruction. */
26930 MIPS_INVAL("OPC_MXU_D8SUM");
26931 generate_exception_end(ctx, EXCP_RI);
26932 break;
26933 case OPC_MXU_D8SUMC:
26934 /* TODO: Implement emulation of D8SUMC instruction. */
26935 MIPS_INVAL("OPC_MXU_D8SUMC");
26936 generate_exception_end(ctx, EXCP_RI);
26937 break;
26938 default:
26939 MIPS_INVAL("decode_opc_mxu");
26940 generate_exception_end(ctx, EXCP_RI);
26941 break;
26947 * Decode MXU pool15
26949 * S32MUL, S32MULU, S32EXTRV:
26950 * 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
26951 * +-----------+---------+---------+---+-------+-------+-----------+
26952 * | SPECIAL2 | rs | rt |x x| XRd | XRa |MXU__POOL15|
26953 * +-----------+---------+---------+---+-------+-------+-----------+
26955 * S32EXTR:
26956 * 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
26957 * +-----------+---------+---------+---+-------+-------+-----------+
26958 * | SPECIAL2 | rb | sft5 |x x| XRd | XRa |MXU__POOL15|
26959 * +-----------+---------+---------+---+-------+-------+-----------+
26962 static void decode_opc_mxu__pool15(CPUMIPSState *env, DisasContext *ctx)
26964 uint32_t opcode = extract32(ctx->opcode, 14, 2);
26966 switch (opcode) {
26967 case OPC_MXU_S32MUL:
26968 /* TODO: Implement emulation of S32MUL instruction. */
26969 MIPS_INVAL("OPC_MXU_S32MUL");
26970 generate_exception_end(ctx, EXCP_RI);
26971 break;
26972 case OPC_MXU_S32MULU:
26973 /* TODO: Implement emulation of S32MULU instruction. */
26974 MIPS_INVAL("OPC_MXU_S32MULU");
26975 generate_exception_end(ctx, EXCP_RI);
26976 break;
26977 case OPC_MXU_S32EXTR:
26978 /* TODO: Implement emulation of S32EXTR instruction. */
26979 MIPS_INVAL("OPC_MXU_S32EXTR");
26980 generate_exception_end(ctx, EXCP_RI);
26981 break;
26982 case OPC_MXU_S32EXTRV:
26983 /* TODO: Implement emulation of S32EXTRV instruction. */
26984 MIPS_INVAL("OPC_MXU_S32EXTRV");
26985 generate_exception_end(ctx, EXCP_RI);
26986 break;
26987 default:
26988 MIPS_INVAL("decode_opc_mxu");
26989 generate_exception_end(ctx, EXCP_RI);
26990 break;
26996 * Decode MXU pool16
26998 * D32SARW:
26999 * 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
27000 * +-----------+---------+-----+-------+-------+-------+-----------+
27001 * | SPECIAL2 | rb |x x x| XRc | XRb | XRa |MXU__POOL16|
27002 * +-----------+---------+-----+-------+-------+-------+-----------+
27004 * S32ALN:
27005 * 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
27006 * +-----------+---------+-----+-------+-------+-------+-----------+
27007 * | SPECIAL2 | rs |x x x| XRc | XRb | XRa |MXU__POOL16|
27008 * +-----------+---------+-----+-------+-------+-------+-----------+
27010 * S32ALNI:
27011 * 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
27012 * +-----------+-----+---+-----+-------+-------+-------+-----------+
27013 * | SPECIAL2 | s3 |0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
27014 * +-----------+-----+---+-----+-------+-------+-------+-----------+
27016 * S32LUI:
27017 * 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
27018 * +-----------+-----+---+-----+-------+---------------+-----------+
27019 * | SPECIAL2 |optn3|0 0|x x x| XRc | s8 |MXU__POOL16|
27020 * +-----------+-----+---+-----+-------+---------------+-----------+
27022 * S32NOR, S32AND, S32OR, S32XOR:
27023 * 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
27024 * +-----------+---------+-----+-------+-------+-------+-----------+
27025 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL16|
27026 * +-----------+---------+-----+-------+-------+-------+-----------+
27029 static void decode_opc_mxu__pool16(CPUMIPSState *env, DisasContext *ctx)
27031 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27033 switch (opcode) {
27034 case OPC_MXU_D32SARW:
27035 /* TODO: Implement emulation of D32SARW instruction. */
27036 MIPS_INVAL("OPC_MXU_D32SARW");
27037 generate_exception_end(ctx, EXCP_RI);
27038 break;
27039 case OPC_MXU_S32ALN:
27040 /* TODO: Implement emulation of S32ALN instruction. */
27041 MIPS_INVAL("OPC_MXU_S32ALN");
27042 generate_exception_end(ctx, EXCP_RI);
27043 break;
27044 case OPC_MXU_S32ALNI:
27045 gen_mxu_S32ALNI(ctx);
27046 break;
27047 case OPC_MXU_S32LUI:
27048 /* TODO: Implement emulation of S32LUI instruction. */
27049 MIPS_INVAL("OPC_MXU_S32LUI");
27050 generate_exception_end(ctx, EXCP_RI);
27051 break;
27052 case OPC_MXU_S32NOR:
27053 gen_mxu_S32NOR(ctx);
27054 break;
27055 case OPC_MXU_S32AND:
27056 gen_mxu_S32AND(ctx);
27057 break;
27058 case OPC_MXU_S32OR:
27059 gen_mxu_S32OR(ctx);
27060 break;
27061 case OPC_MXU_S32XOR:
27062 gen_mxu_S32XOR(ctx);
27063 break;
27064 default:
27065 MIPS_INVAL("decode_opc_mxu");
27066 generate_exception_end(ctx, EXCP_RI);
27067 break;
27073 * Decode MXU pool17
27075 * 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
27076 * +-----------+---------+---------+---+---------+-----+-----------+
27077 * | SPECIAL2 | rs | rt |0 0| rd |x x x|MXU__POOL15|
27078 * +-----------+---------+---------+---+---------+-----+-----------+
27081 static void decode_opc_mxu__pool17(CPUMIPSState *env, DisasContext *ctx)
27083 uint32_t opcode = extract32(ctx->opcode, 6, 2);
27085 switch (opcode) {
27086 case OPC_MXU_LXW:
27087 /* TODO: Implement emulation of LXW instruction. */
27088 MIPS_INVAL("OPC_MXU_LXW");
27089 generate_exception_end(ctx, EXCP_RI);
27090 break;
27091 case OPC_MXU_LXH:
27092 /* TODO: Implement emulation of LXH instruction. */
27093 MIPS_INVAL("OPC_MXU_LXH");
27094 generate_exception_end(ctx, EXCP_RI);
27095 break;
27096 case OPC_MXU_LXHU:
27097 /* TODO: Implement emulation of LXHU instruction. */
27098 MIPS_INVAL("OPC_MXU_LXHU");
27099 generate_exception_end(ctx, EXCP_RI);
27100 break;
27101 case OPC_MXU_LXB:
27102 /* TODO: Implement emulation of LXB instruction. */
27103 MIPS_INVAL("OPC_MXU_LXB");
27104 generate_exception_end(ctx, EXCP_RI);
27105 break;
27106 case OPC_MXU_LXBU:
27107 /* TODO: Implement emulation of LXBU instruction. */
27108 MIPS_INVAL("OPC_MXU_LXBU");
27109 generate_exception_end(ctx, EXCP_RI);
27110 break;
27111 default:
27112 MIPS_INVAL("decode_opc_mxu");
27113 generate_exception_end(ctx, EXCP_RI);
27114 break;
27119 * Decode MXU pool18
27121 * 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
27122 * +-----------+---------+-----+-------+-------+-------+-----------+
27123 * | SPECIAL2 | rb |x x x| XRd | XRa |0 0 0 0|MXU__POOL18|
27124 * +-----------+---------+-----+-------+-------+-------+-----------+
27127 static void decode_opc_mxu__pool18(CPUMIPSState *env, DisasContext *ctx)
27129 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27131 switch (opcode) {
27132 case OPC_MXU_D32SLLV:
27133 /* TODO: Implement emulation of D32SLLV instruction. */
27134 MIPS_INVAL("OPC_MXU_D32SLLV");
27135 generate_exception_end(ctx, EXCP_RI);
27136 break;
27137 case OPC_MXU_D32SLRV:
27138 /* TODO: Implement emulation of D32SLRV instruction. */
27139 MIPS_INVAL("OPC_MXU_D32SLRV");
27140 generate_exception_end(ctx, EXCP_RI);
27141 break;
27142 case OPC_MXU_D32SARV:
27143 /* TODO: Implement emulation of D32SARV instruction. */
27144 MIPS_INVAL("OPC_MXU_D32SARV");
27145 generate_exception_end(ctx, EXCP_RI);
27146 break;
27147 case OPC_MXU_Q16SLLV:
27148 /* TODO: Implement emulation of Q16SLLV instruction. */
27149 MIPS_INVAL("OPC_MXU_Q16SLLV");
27150 generate_exception_end(ctx, EXCP_RI);
27151 break;
27152 case OPC_MXU_Q16SLRV:
27153 /* TODO: Implement emulation of Q16SLRV instruction. */
27154 MIPS_INVAL("OPC_MXU_Q16SLRV");
27155 generate_exception_end(ctx, EXCP_RI);
27156 break;
27157 case OPC_MXU_Q16SARV:
27158 /* TODO: Implement emulation of Q16SARV instruction. */
27159 MIPS_INVAL("OPC_MXU_Q16SARV");
27160 generate_exception_end(ctx, EXCP_RI);
27161 break;
27162 default:
27163 MIPS_INVAL("decode_opc_mxu");
27164 generate_exception_end(ctx, EXCP_RI);
27165 break;
27171 * Decode MXU pool19
27173 * 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
27174 * +-----------+---+---+-------+-------+-------+-------+-----------+
27175 * | SPECIAL2 |0 0|x x| XRd | XRc | XRb | XRa |MXU__POOL19|
27176 * +-----------+---+---+-------+-------+-------+-------+-----------+
27179 static void decode_opc_mxu__pool19(CPUMIPSState *env, DisasContext *ctx)
27181 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27183 switch (opcode) {
27184 case OPC_MXU_Q8MUL:
27185 case OPC_MXU_Q8MULSU:
27186 gen_mxu_q8mul_q8mulsu(ctx);
27187 break;
27188 default:
27189 MIPS_INVAL("decode_opc_mxu");
27190 generate_exception_end(ctx, EXCP_RI);
27191 break;
27197 * Decode MXU pool20
27199 * 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
27200 * +-----------+---------+-----+-------+-------+-------+-----------+
27201 * | SPECIAL2 |0 0 0 0 0|x x x| XRc | XRb | XRa |MXU__POOL20|
27202 * +-----------+---------+-----+-------+-------+-------+-----------+
27205 static void decode_opc_mxu__pool20(CPUMIPSState *env, DisasContext *ctx)
27207 uint32_t opcode = extract32(ctx->opcode, 18, 3);
27209 switch (opcode) {
27210 case OPC_MXU_Q8MOVZ:
27211 /* TODO: Implement emulation of Q8MOVZ instruction. */
27212 MIPS_INVAL("OPC_MXU_Q8MOVZ");
27213 generate_exception_end(ctx, EXCP_RI);
27214 break;
27215 case OPC_MXU_Q8MOVN:
27216 /* TODO: Implement emulation of Q8MOVN instruction. */
27217 MIPS_INVAL("OPC_MXU_Q8MOVN");
27218 generate_exception_end(ctx, EXCP_RI);
27219 break;
27220 case OPC_MXU_D16MOVZ:
27221 /* TODO: Implement emulation of D16MOVZ instruction. */
27222 MIPS_INVAL("OPC_MXU_D16MOVZ");
27223 generate_exception_end(ctx, EXCP_RI);
27224 break;
27225 case OPC_MXU_D16MOVN:
27226 /* TODO: Implement emulation of D16MOVN instruction. */
27227 MIPS_INVAL("OPC_MXU_D16MOVN");
27228 generate_exception_end(ctx, EXCP_RI);
27229 break;
27230 case OPC_MXU_S32MOVZ:
27231 /* TODO: Implement emulation of S32MOVZ instruction. */
27232 MIPS_INVAL("OPC_MXU_S32MOVZ");
27233 generate_exception_end(ctx, EXCP_RI);
27234 break;
27235 case OPC_MXU_S32MOVN:
27236 /* TODO: Implement emulation of S32MOVN instruction. */
27237 MIPS_INVAL("OPC_MXU_S32MOVN");
27238 generate_exception_end(ctx, EXCP_RI);
27239 break;
27240 default:
27241 MIPS_INVAL("decode_opc_mxu");
27242 generate_exception_end(ctx, EXCP_RI);
27243 break;
27249 * Decode MXU pool21
27251 * 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
27252 * +-----------+---+---+-------+-------+-------+-------+-----------+
27253 * | SPECIAL2 |an2|x x| XRd | XRc | XRb | XRa |MXU__POOL21|
27254 * +-----------+---+---+-------+-------+-------+-------+-----------+
27257 static void decode_opc_mxu__pool21(CPUMIPSState *env, DisasContext *ctx)
27259 uint32_t opcode = extract32(ctx->opcode, 22, 2);
27261 switch (opcode) {
27262 case OPC_MXU_Q8MAC:
27263 /* TODO: Implement emulation of Q8MAC instruction. */
27264 MIPS_INVAL("OPC_MXU_Q8MAC");
27265 generate_exception_end(ctx, EXCP_RI);
27266 break;
27267 case OPC_MXU_Q8MACSU:
27268 /* TODO: Implement emulation of Q8MACSU instruction. */
27269 MIPS_INVAL("OPC_MXU_Q8MACSU");
27270 generate_exception_end(ctx, EXCP_RI);
27271 break;
27272 default:
27273 MIPS_INVAL("decode_opc_mxu");
27274 generate_exception_end(ctx, EXCP_RI);
27275 break;
27281 * Main MXU decoding function
27283 * 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
27284 * +-----------+---------------------------------------+-----------+
27285 * | SPECIAL2 | |x x x x x x|
27286 * +-----------+---------------------------------------+-----------+
27289 static void decode_opc_mxu(CPUMIPSState *env, DisasContext *ctx)
27292 * TODO: Investigate necessity of including handling of
27293 * CLZ, CLO, SDBB in this function, as they belong to
27294 * SPECIAL2 opcode space for regular pre-R6 MIPS ISAs.
27296 uint32_t opcode = extract32(ctx->opcode, 0, 6);
27298 if (opcode == OPC__MXU_MUL) {
27299 uint32_t rs, rt, rd, op1;
27301 rs = extract32(ctx->opcode, 21, 5);
27302 rt = extract32(ctx->opcode, 16, 5);
27303 rd = extract32(ctx->opcode, 11, 5);
27304 op1 = MASK_SPECIAL2(ctx->opcode);
27306 gen_arith(ctx, op1, rd, rs, rt);
27308 return;
27311 if (opcode == OPC_MXU_S32M2I) {
27312 gen_mxu_s32m2i(ctx);
27313 return;
27316 if (opcode == OPC_MXU_S32I2M) {
27317 gen_mxu_s32i2m(ctx);
27318 return;
27322 TCGv t_mxu_cr = tcg_temp_new();
27323 TCGLabel *l_exit = gen_new_label();
27325 gen_load_mxu_cr(t_mxu_cr);
27326 tcg_gen_andi_tl(t_mxu_cr, t_mxu_cr, MXU_CR_MXU_EN);
27327 tcg_gen_brcondi_tl(TCG_COND_NE, t_mxu_cr, MXU_CR_MXU_EN, l_exit);
27329 switch (opcode) {
27330 case OPC_MXU_S32MADD:
27331 /* TODO: Implement emulation of S32MADD instruction. */
27332 MIPS_INVAL("OPC_MXU_S32MADD");
27333 generate_exception_end(ctx, EXCP_RI);
27334 break;
27335 case OPC_MXU_S32MADDU:
27336 /* TODO: Implement emulation of S32MADDU instruction. */
27337 MIPS_INVAL("OPC_MXU_S32MADDU");
27338 generate_exception_end(ctx, EXCP_RI);
27339 break;
27340 case OPC_MXU__POOL00:
27341 decode_opc_mxu__pool00(env, ctx);
27342 break;
27343 case OPC_MXU_S32MSUB:
27344 /* TODO: Implement emulation of S32MSUB instruction. */
27345 MIPS_INVAL("OPC_MXU_S32MSUB");
27346 generate_exception_end(ctx, EXCP_RI);
27347 break;
27348 case OPC_MXU_S32MSUBU:
27349 /* TODO: Implement emulation of S32MSUBU instruction. */
27350 MIPS_INVAL("OPC_MXU_S32MSUBU");
27351 generate_exception_end(ctx, EXCP_RI);
27352 break;
27353 case OPC_MXU__POOL01:
27354 decode_opc_mxu__pool01(env, ctx);
27355 break;
27356 case OPC_MXU__POOL02:
27357 decode_opc_mxu__pool02(env, ctx);
27358 break;
27359 case OPC_MXU_D16MUL:
27360 gen_mxu_d16mul(ctx);
27361 break;
27362 case OPC_MXU__POOL03:
27363 decode_opc_mxu__pool03(env, ctx);
27364 break;
27365 case OPC_MXU_D16MAC:
27366 gen_mxu_d16mac(ctx);
27367 break;
27368 case OPC_MXU_D16MACF:
27369 /* TODO: Implement emulation of D16MACF instruction. */
27370 MIPS_INVAL("OPC_MXU_D16MACF");
27371 generate_exception_end(ctx, EXCP_RI);
27372 break;
27373 case OPC_MXU_D16MADL:
27374 /* TODO: Implement emulation of D16MADL instruction. */
27375 MIPS_INVAL("OPC_MXU_D16MADL");
27376 generate_exception_end(ctx, EXCP_RI);
27377 break;
27378 case OPC_MXU_S16MAD:
27379 /* TODO: Implement emulation of S16MAD instruction. */
27380 MIPS_INVAL("OPC_MXU_S16MAD");
27381 generate_exception_end(ctx, EXCP_RI);
27382 break;
27383 case OPC_MXU_Q16ADD:
27384 /* TODO: Implement emulation of Q16ADD instruction. */
27385 MIPS_INVAL("OPC_MXU_Q16ADD");
27386 generate_exception_end(ctx, EXCP_RI);
27387 break;
27388 case OPC_MXU_D16MACE:
27389 /* TODO: Implement emulation of D16MACE instruction. */
27390 MIPS_INVAL("OPC_MXU_D16MACE");
27391 generate_exception_end(ctx, EXCP_RI);
27392 break;
27393 case OPC_MXU__POOL04:
27394 decode_opc_mxu__pool04(env, ctx);
27395 break;
27396 case OPC_MXU__POOL05:
27397 decode_opc_mxu__pool05(env, ctx);
27398 break;
27399 case OPC_MXU__POOL06:
27400 decode_opc_mxu__pool06(env, ctx);
27401 break;
27402 case OPC_MXU__POOL07:
27403 decode_opc_mxu__pool07(env, ctx);
27404 break;
27405 case OPC_MXU__POOL08:
27406 decode_opc_mxu__pool08(env, ctx);
27407 break;
27408 case OPC_MXU__POOL09:
27409 decode_opc_mxu__pool09(env, ctx);
27410 break;
27411 case OPC_MXU__POOL10:
27412 decode_opc_mxu__pool10(env, ctx);
27413 break;
27414 case OPC_MXU__POOL11:
27415 decode_opc_mxu__pool11(env, ctx);
27416 break;
27417 case OPC_MXU_D32ADD:
27418 /* TODO: Implement emulation of D32ADD instruction. */
27419 MIPS_INVAL("OPC_MXU_D32ADD");
27420 generate_exception_end(ctx, EXCP_RI);
27421 break;
27422 case OPC_MXU__POOL12:
27423 decode_opc_mxu__pool12(env, ctx);
27424 break;
27425 case OPC_MXU__POOL13:
27426 decode_opc_mxu__pool13(env, ctx);
27427 break;
27428 case OPC_MXU__POOL14:
27429 decode_opc_mxu__pool14(env, ctx);
27430 break;
27431 case OPC_MXU_Q8ACCE:
27432 /* TODO: Implement emulation of Q8ACCE instruction. */
27433 MIPS_INVAL("OPC_MXU_Q8ACCE");
27434 generate_exception_end(ctx, EXCP_RI);
27435 break;
27436 case OPC_MXU_S8LDD:
27437 gen_mxu_s8ldd(ctx);
27438 break;
27439 case OPC_MXU_S8STD:
27440 /* TODO: Implement emulation of S8STD instruction. */
27441 MIPS_INVAL("OPC_MXU_S8STD");
27442 generate_exception_end(ctx, EXCP_RI);
27443 break;
27444 case OPC_MXU_S8LDI:
27445 /* TODO: Implement emulation of S8LDI instruction. */
27446 MIPS_INVAL("OPC_MXU_S8LDI");
27447 generate_exception_end(ctx, EXCP_RI);
27448 break;
27449 case OPC_MXU_S8SDI:
27450 /* TODO: Implement emulation of S8SDI instruction. */
27451 MIPS_INVAL("OPC_MXU_S8SDI");
27452 generate_exception_end(ctx, EXCP_RI);
27453 break;
27454 case OPC_MXU__POOL15:
27455 decode_opc_mxu__pool15(env, ctx);
27456 break;
27457 case OPC_MXU__POOL16:
27458 decode_opc_mxu__pool16(env, ctx);
27459 break;
27460 case OPC_MXU__POOL17:
27461 decode_opc_mxu__pool17(env, ctx);
27462 break;
27463 case OPC_MXU_S16LDD:
27464 /* TODO: Implement emulation of S16LDD instruction. */
27465 MIPS_INVAL("OPC_MXU_S16LDD");
27466 generate_exception_end(ctx, EXCP_RI);
27467 break;
27468 case OPC_MXU_S16STD:
27469 /* TODO: Implement emulation of S16STD instruction. */
27470 MIPS_INVAL("OPC_MXU_S16STD");
27471 generate_exception_end(ctx, EXCP_RI);
27472 break;
27473 case OPC_MXU_S16LDI:
27474 /* TODO: Implement emulation of S16LDI instruction. */
27475 MIPS_INVAL("OPC_MXU_S16LDI");
27476 generate_exception_end(ctx, EXCP_RI);
27477 break;
27478 case OPC_MXU_S16SDI:
27479 /* TODO: Implement emulation of S16SDI instruction. */
27480 MIPS_INVAL("OPC_MXU_S16SDI");
27481 generate_exception_end(ctx, EXCP_RI);
27482 break;
27483 case OPC_MXU_D32SLL:
27484 /* TODO: Implement emulation of D32SLL instruction. */
27485 MIPS_INVAL("OPC_MXU_D32SLL");
27486 generate_exception_end(ctx, EXCP_RI);
27487 break;
27488 case OPC_MXU_D32SLR:
27489 /* TODO: Implement emulation of D32SLR instruction. */
27490 MIPS_INVAL("OPC_MXU_D32SLR");
27491 generate_exception_end(ctx, EXCP_RI);
27492 break;
27493 case OPC_MXU_D32SARL:
27494 /* TODO: Implement emulation of D32SARL instruction. */
27495 MIPS_INVAL("OPC_MXU_D32SARL");
27496 generate_exception_end(ctx, EXCP_RI);
27497 break;
27498 case OPC_MXU_D32SAR:
27499 /* TODO: Implement emulation of D32SAR instruction. */
27500 MIPS_INVAL("OPC_MXU_D32SAR");
27501 generate_exception_end(ctx, EXCP_RI);
27502 break;
27503 case OPC_MXU_Q16SLL:
27504 /* TODO: Implement emulation of Q16SLL instruction. */
27505 MIPS_INVAL("OPC_MXU_Q16SLL");
27506 generate_exception_end(ctx, EXCP_RI);
27507 break;
27508 case OPC_MXU_Q16SLR:
27509 /* TODO: Implement emulation of Q16SLR instruction. */
27510 MIPS_INVAL("OPC_MXU_Q16SLR");
27511 generate_exception_end(ctx, EXCP_RI);
27512 break;
27513 case OPC_MXU__POOL18:
27514 decode_opc_mxu__pool18(env, ctx);
27515 break;
27516 case OPC_MXU_Q16SAR:
27517 /* TODO: Implement emulation of Q16SAR instruction. */
27518 MIPS_INVAL("OPC_MXU_Q16SAR");
27519 generate_exception_end(ctx, EXCP_RI);
27520 break;
27521 case OPC_MXU__POOL19:
27522 decode_opc_mxu__pool19(env, ctx);
27523 break;
27524 case OPC_MXU__POOL20:
27525 decode_opc_mxu__pool20(env, ctx);
27526 break;
27527 case OPC_MXU__POOL21:
27528 decode_opc_mxu__pool21(env, ctx);
27529 break;
27530 case OPC_MXU_Q16SCOP:
27531 /* TODO: Implement emulation of Q16SCOP instruction. */
27532 MIPS_INVAL("OPC_MXU_Q16SCOP");
27533 generate_exception_end(ctx, EXCP_RI);
27534 break;
27535 case OPC_MXU_Q8MADL:
27536 /* TODO: Implement emulation of Q8MADL instruction. */
27537 MIPS_INVAL("OPC_MXU_Q8MADL");
27538 generate_exception_end(ctx, EXCP_RI);
27539 break;
27540 case OPC_MXU_S32SFL:
27541 /* TODO: Implement emulation of S32SFL instruction. */
27542 MIPS_INVAL("OPC_MXU_S32SFL");
27543 generate_exception_end(ctx, EXCP_RI);
27544 break;
27545 case OPC_MXU_Q8SAD:
27546 /* TODO: Implement emulation of Q8SAD instruction. */
27547 MIPS_INVAL("OPC_MXU_Q8SAD");
27548 generate_exception_end(ctx, EXCP_RI);
27549 break;
27550 default:
27551 MIPS_INVAL("decode_opc_mxu");
27552 generate_exception_end(ctx, EXCP_RI);
27555 gen_set_label(l_exit);
27556 tcg_temp_free(t_mxu_cr);
27560 #endif /* !defined(TARGET_MIPS64) */
27563 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
27565 int rs, rt, rd;
27566 uint32_t op1;
27568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
27570 rs = (ctx->opcode >> 21) & 0x1f;
27571 rt = (ctx->opcode >> 16) & 0x1f;
27572 rd = (ctx->opcode >> 11) & 0x1f;
27574 op1 = MASK_SPECIAL2(ctx->opcode);
27575 switch (op1) {
27576 case OPC_MADD: /* Multiply and add/sub */
27577 case OPC_MADDU:
27578 case OPC_MSUB:
27579 case OPC_MSUBU:
27580 check_insn(ctx, ISA_MIPS32);
27581 gen_muldiv(ctx, op1, rd & 3, rs, rt);
27582 break;
27583 case OPC_MUL:
27584 gen_arith(ctx, op1, rd, rs, rt);
27585 break;
27586 case OPC_DIV_G_2F:
27587 case OPC_DIVU_G_2F:
27588 case OPC_MULT_G_2F:
27589 case OPC_MULTU_G_2F:
27590 case OPC_MOD_G_2F:
27591 case OPC_MODU_G_2F:
27592 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27593 gen_loongson_integer(ctx, op1, rd, rs, rt);
27594 break;
27595 case OPC_CLO:
27596 case OPC_CLZ:
27597 check_insn(ctx, ISA_MIPS32);
27598 gen_cl(ctx, op1, rd, rs);
27599 break;
27600 case OPC_SDBBP:
27601 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
27602 gen_helper_do_semihosting(cpu_env);
27603 } else {
27605 * XXX: not clear which exception should be raised
27606 * when in debug mode...
27608 check_insn(ctx, ISA_MIPS32);
27609 generate_exception_end(ctx, EXCP_DBp);
27611 break;
27612 #if defined(TARGET_MIPS64)
27613 case OPC_DCLO:
27614 case OPC_DCLZ:
27615 check_insn(ctx, ISA_MIPS32);
27616 check_mips_64(ctx);
27617 gen_cl(ctx, op1, rd, rs);
27618 break;
27619 case OPC_DMULT_G_2F:
27620 case OPC_DMULTU_G_2F:
27621 case OPC_DDIV_G_2F:
27622 case OPC_DDIVU_G_2F:
27623 case OPC_DMOD_G_2F:
27624 case OPC_DMODU_G_2F:
27625 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
27626 gen_loongson_integer(ctx, op1, rd, rs, rt);
27627 break;
27628 #endif
27629 default: /* Invalid */
27630 MIPS_INVAL("special2_legacy");
27631 generate_exception_end(ctx, EXCP_RI);
27632 break;
27636 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
27638 int rs, rt, rd, sa;
27639 uint32_t op1, op2;
27640 int16_t imm;
27642 rs = (ctx->opcode >> 21) & 0x1f;
27643 rt = (ctx->opcode >> 16) & 0x1f;
27644 rd = (ctx->opcode >> 11) & 0x1f;
27645 sa = (ctx->opcode >> 6) & 0x1f;
27646 imm = (int16_t)ctx->opcode >> 7;
27648 op1 = MASK_SPECIAL3(ctx->opcode);
27649 switch (op1) {
27650 case R6_OPC_PREF:
27651 if (rt >= 24) {
27652 /* hint codes 24-31 are reserved and signal RI */
27653 generate_exception_end(ctx, EXCP_RI);
27655 /* Treat as NOP. */
27656 break;
27657 case R6_OPC_CACHE:
27658 check_cp0_enabled(ctx);
27659 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
27660 gen_cache_operation(ctx, rt, rs, imm);
27662 break;
27663 case R6_OPC_SC:
27664 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
27665 break;
27666 case R6_OPC_LL:
27667 gen_ld(ctx, op1, rt, rs, imm);
27668 break;
27669 case OPC_BSHFL:
27671 if (rd == 0) {
27672 /* Treat as NOP. */
27673 break;
27675 op2 = MASK_BSHFL(ctx->opcode);
27676 switch (op2) {
27677 case OPC_ALIGN:
27678 case OPC_ALIGN_1:
27679 case OPC_ALIGN_2:
27680 case OPC_ALIGN_3:
27681 gen_align(ctx, 32, rd, rs, rt, sa & 3);
27682 break;
27683 case OPC_BITSWAP:
27684 gen_bitswap(ctx, op2, rd, rt);
27685 break;
27688 break;
27689 #ifndef CONFIG_USER_ONLY
27690 case OPC_GINV:
27691 if (unlikely(ctx->gi <= 1)) {
27692 generate_exception_end(ctx, EXCP_RI);
27694 check_cp0_enabled(ctx);
27695 switch ((ctx->opcode >> 6) & 3) {
27696 case 0: /* GINVI */
27697 /* Treat as NOP. */
27698 break;
27699 case 2: /* GINVT */
27700 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
27701 break;
27702 default:
27703 generate_exception_end(ctx, EXCP_RI);
27704 break;
27706 break;
27707 #endif
27708 #if defined(TARGET_MIPS64)
27709 case R6_OPC_SCD:
27710 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
27711 break;
27712 case R6_OPC_LLD:
27713 gen_ld(ctx, op1, rt, rs, imm);
27714 break;
27715 case OPC_DBSHFL:
27716 check_mips_64(ctx);
27718 if (rd == 0) {
27719 /* Treat as NOP. */
27720 break;
27722 op2 = MASK_DBSHFL(ctx->opcode);
27723 switch (op2) {
27724 case OPC_DALIGN:
27725 case OPC_DALIGN_1:
27726 case OPC_DALIGN_2:
27727 case OPC_DALIGN_3:
27728 case OPC_DALIGN_4:
27729 case OPC_DALIGN_5:
27730 case OPC_DALIGN_6:
27731 case OPC_DALIGN_7:
27732 gen_align(ctx, 64, rd, rs, rt, sa & 7);
27733 break;
27734 case OPC_DBITSWAP:
27735 gen_bitswap(ctx, op2, rd, rt);
27736 break;
27740 break;
27741 #endif
27742 default: /* Invalid */
27743 MIPS_INVAL("special3_r6");
27744 generate_exception_end(ctx, EXCP_RI);
27745 break;
27749 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
27751 int rs, rt, rd;
27752 uint32_t op1, op2;
27754 rs = (ctx->opcode >> 21) & 0x1f;
27755 rt = (ctx->opcode >> 16) & 0x1f;
27756 rd = (ctx->opcode >> 11) & 0x1f;
27758 op1 = MASK_SPECIAL3(ctx->opcode);
27759 switch (op1) {
27760 case OPC_DIV_G_2E:
27761 case OPC_DIVU_G_2E:
27762 case OPC_MOD_G_2E:
27763 case OPC_MODU_G_2E:
27764 case OPC_MULT_G_2E:
27765 case OPC_MULTU_G_2E:
27767 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
27768 * the same mask and op1.
27770 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
27771 op2 = MASK_ADDUH_QB(ctx->opcode);
27772 switch (op2) {
27773 case OPC_ADDUH_QB:
27774 case OPC_ADDUH_R_QB:
27775 case OPC_ADDQH_PH:
27776 case OPC_ADDQH_R_PH:
27777 case OPC_ADDQH_W:
27778 case OPC_ADDQH_R_W:
27779 case OPC_SUBUH_QB:
27780 case OPC_SUBUH_R_QB:
27781 case OPC_SUBQH_PH:
27782 case OPC_SUBQH_R_PH:
27783 case OPC_SUBQH_W:
27784 case OPC_SUBQH_R_W:
27785 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27786 break;
27787 case OPC_MUL_PH:
27788 case OPC_MUL_S_PH:
27789 case OPC_MULQ_S_W:
27790 case OPC_MULQ_RS_W:
27791 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27792 break;
27793 default:
27794 MIPS_INVAL("MASK ADDUH.QB");
27795 generate_exception_end(ctx, EXCP_RI);
27796 break;
27798 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
27799 gen_loongson_integer(ctx, op1, rd, rs, rt);
27800 } else {
27801 generate_exception_end(ctx, EXCP_RI);
27803 break;
27804 case OPC_LX_DSP:
27805 op2 = MASK_LX(ctx->opcode);
27806 switch (op2) {
27807 #if defined(TARGET_MIPS64)
27808 case OPC_LDX:
27809 #endif
27810 case OPC_LBUX:
27811 case OPC_LHX:
27812 case OPC_LWX:
27813 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
27814 break;
27815 default: /* Invalid */
27816 MIPS_INVAL("MASK LX");
27817 generate_exception_end(ctx, EXCP_RI);
27818 break;
27820 break;
27821 case OPC_ABSQ_S_PH_DSP:
27822 op2 = MASK_ABSQ_S_PH(ctx->opcode);
27823 switch (op2) {
27824 case OPC_ABSQ_S_QB:
27825 case OPC_ABSQ_S_PH:
27826 case OPC_ABSQ_S_W:
27827 case OPC_PRECEQ_W_PHL:
27828 case OPC_PRECEQ_W_PHR:
27829 case OPC_PRECEQU_PH_QBL:
27830 case OPC_PRECEQU_PH_QBR:
27831 case OPC_PRECEQU_PH_QBLA:
27832 case OPC_PRECEQU_PH_QBRA:
27833 case OPC_PRECEU_PH_QBL:
27834 case OPC_PRECEU_PH_QBR:
27835 case OPC_PRECEU_PH_QBLA:
27836 case OPC_PRECEU_PH_QBRA:
27837 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27838 break;
27839 case OPC_BITREV:
27840 case OPC_REPL_QB:
27841 case OPC_REPLV_QB:
27842 case OPC_REPL_PH:
27843 case OPC_REPLV_PH:
27844 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
27845 break;
27846 default:
27847 MIPS_INVAL("MASK ABSQ_S.PH");
27848 generate_exception_end(ctx, EXCP_RI);
27849 break;
27851 break;
27852 case OPC_ADDU_QB_DSP:
27853 op2 = MASK_ADDU_QB(ctx->opcode);
27854 switch (op2) {
27855 case OPC_ADDQ_PH:
27856 case OPC_ADDQ_S_PH:
27857 case OPC_ADDQ_S_W:
27858 case OPC_ADDU_QB:
27859 case OPC_ADDU_S_QB:
27860 case OPC_ADDU_PH:
27861 case OPC_ADDU_S_PH:
27862 case OPC_SUBQ_PH:
27863 case OPC_SUBQ_S_PH:
27864 case OPC_SUBQ_S_W:
27865 case OPC_SUBU_QB:
27866 case OPC_SUBU_S_QB:
27867 case OPC_SUBU_PH:
27868 case OPC_SUBU_S_PH:
27869 case OPC_ADDSC:
27870 case OPC_ADDWC:
27871 case OPC_MODSUB:
27872 case OPC_RADDU_W_QB:
27873 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27874 break;
27875 case OPC_MULEU_S_PH_QBL:
27876 case OPC_MULEU_S_PH_QBR:
27877 case OPC_MULQ_RS_PH:
27878 case OPC_MULEQ_S_W_PHL:
27879 case OPC_MULEQ_S_W_PHR:
27880 case OPC_MULQ_S_PH:
27881 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
27882 break;
27883 default: /* Invalid */
27884 MIPS_INVAL("MASK ADDU.QB");
27885 generate_exception_end(ctx, EXCP_RI);
27886 break;
27889 break;
27890 case OPC_CMPU_EQ_QB_DSP:
27891 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
27892 switch (op2) {
27893 case OPC_PRECR_SRA_PH_W:
27894 case OPC_PRECR_SRA_R_PH_W:
27895 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
27896 break;
27897 case OPC_PRECR_QB_PH:
27898 case OPC_PRECRQ_QB_PH:
27899 case OPC_PRECRQ_PH_W:
27900 case OPC_PRECRQ_RS_PH_W:
27901 case OPC_PRECRQU_S_QB_PH:
27902 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
27903 break;
27904 case OPC_CMPU_EQ_QB:
27905 case OPC_CMPU_LT_QB:
27906 case OPC_CMPU_LE_QB:
27907 case OPC_CMP_EQ_PH:
27908 case OPC_CMP_LT_PH:
27909 case OPC_CMP_LE_PH:
27910 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
27911 break;
27912 case OPC_CMPGU_EQ_QB:
27913 case OPC_CMPGU_LT_QB:
27914 case OPC_CMPGU_LE_QB:
27915 case OPC_CMPGDU_EQ_QB:
27916 case OPC_CMPGDU_LT_QB:
27917 case OPC_CMPGDU_LE_QB:
27918 case OPC_PICK_QB:
27919 case OPC_PICK_PH:
27920 case OPC_PACKRL_PH:
27921 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
27922 break;
27923 default: /* Invalid */
27924 MIPS_INVAL("MASK CMPU.EQ.QB");
27925 generate_exception_end(ctx, EXCP_RI);
27926 break;
27928 break;
27929 case OPC_SHLL_QB_DSP:
27930 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
27931 break;
27932 case OPC_DPA_W_PH_DSP:
27933 op2 = MASK_DPA_W_PH(ctx->opcode);
27934 switch (op2) {
27935 case OPC_DPAU_H_QBL:
27936 case OPC_DPAU_H_QBR:
27937 case OPC_DPSU_H_QBL:
27938 case OPC_DPSU_H_QBR:
27939 case OPC_DPA_W_PH:
27940 case OPC_DPAX_W_PH:
27941 case OPC_DPAQ_S_W_PH:
27942 case OPC_DPAQX_S_W_PH:
27943 case OPC_DPAQX_SA_W_PH:
27944 case OPC_DPS_W_PH:
27945 case OPC_DPSX_W_PH:
27946 case OPC_DPSQ_S_W_PH:
27947 case OPC_DPSQX_S_W_PH:
27948 case OPC_DPSQX_SA_W_PH:
27949 case OPC_MULSAQ_S_W_PH:
27950 case OPC_DPAQ_SA_L_W:
27951 case OPC_DPSQ_SA_L_W:
27952 case OPC_MAQ_S_W_PHL:
27953 case OPC_MAQ_S_W_PHR:
27954 case OPC_MAQ_SA_W_PHL:
27955 case OPC_MAQ_SA_W_PHR:
27956 case OPC_MULSA_W_PH:
27957 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
27958 break;
27959 default: /* Invalid */
27960 MIPS_INVAL("MASK DPAW.PH");
27961 generate_exception_end(ctx, EXCP_RI);
27962 break;
27964 break;
27965 case OPC_INSV_DSP:
27966 op2 = MASK_INSV(ctx->opcode);
27967 switch (op2) {
27968 case OPC_INSV:
27969 check_dsp(ctx);
27971 TCGv t0, t1;
27973 if (rt == 0) {
27974 break;
27977 t0 = tcg_temp_new();
27978 t1 = tcg_temp_new();
27980 gen_load_gpr(t0, rt);
27981 gen_load_gpr(t1, rs);
27983 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
27985 tcg_temp_free(t0);
27986 tcg_temp_free(t1);
27987 break;
27989 default: /* Invalid */
27990 MIPS_INVAL("MASK INSV");
27991 generate_exception_end(ctx, EXCP_RI);
27992 break;
27994 break;
27995 case OPC_APPEND_DSP:
27996 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
27997 break;
27998 case OPC_EXTR_W_DSP:
27999 op2 = MASK_EXTR_W(ctx->opcode);
28000 switch (op2) {
28001 case OPC_EXTR_W:
28002 case OPC_EXTR_R_W:
28003 case OPC_EXTR_RS_W:
28004 case OPC_EXTR_S_H:
28005 case OPC_EXTRV_S_H:
28006 case OPC_EXTRV_W:
28007 case OPC_EXTRV_R_W:
28008 case OPC_EXTRV_RS_W:
28009 case OPC_EXTP:
28010 case OPC_EXTPV:
28011 case OPC_EXTPDP:
28012 case OPC_EXTPDPV:
28013 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28014 break;
28015 case OPC_RDDSP:
28016 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
28017 break;
28018 case OPC_SHILO:
28019 case OPC_SHILOV:
28020 case OPC_MTHLIP:
28021 case OPC_WRDSP:
28022 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28023 break;
28024 default: /* Invalid */
28025 MIPS_INVAL("MASK EXTR.W");
28026 generate_exception_end(ctx, EXCP_RI);
28027 break;
28029 break;
28030 #if defined(TARGET_MIPS64)
28031 case OPC_DDIV_G_2E:
28032 case OPC_DDIVU_G_2E:
28033 case OPC_DMULT_G_2E:
28034 case OPC_DMULTU_G_2E:
28035 case OPC_DMOD_G_2E:
28036 case OPC_DMODU_G_2E:
28037 check_insn(ctx, INSN_LOONGSON2E);
28038 gen_loongson_integer(ctx, op1, rd, rs, rt);
28039 break;
28040 case OPC_ABSQ_S_QH_DSP:
28041 op2 = MASK_ABSQ_S_QH(ctx->opcode);
28042 switch (op2) {
28043 case OPC_PRECEQ_L_PWL:
28044 case OPC_PRECEQ_L_PWR:
28045 case OPC_PRECEQ_PW_QHL:
28046 case OPC_PRECEQ_PW_QHR:
28047 case OPC_PRECEQ_PW_QHLA:
28048 case OPC_PRECEQ_PW_QHRA:
28049 case OPC_PRECEQU_QH_OBL:
28050 case OPC_PRECEQU_QH_OBR:
28051 case OPC_PRECEQU_QH_OBLA:
28052 case OPC_PRECEQU_QH_OBRA:
28053 case OPC_PRECEU_QH_OBL:
28054 case OPC_PRECEU_QH_OBR:
28055 case OPC_PRECEU_QH_OBLA:
28056 case OPC_PRECEU_QH_OBRA:
28057 case OPC_ABSQ_S_OB:
28058 case OPC_ABSQ_S_PW:
28059 case OPC_ABSQ_S_QH:
28060 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28061 break;
28062 case OPC_REPL_OB:
28063 case OPC_REPL_PW:
28064 case OPC_REPL_QH:
28065 case OPC_REPLV_OB:
28066 case OPC_REPLV_PW:
28067 case OPC_REPLV_QH:
28068 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
28069 break;
28070 default: /* Invalid */
28071 MIPS_INVAL("MASK ABSQ_S.QH");
28072 generate_exception_end(ctx, EXCP_RI);
28073 break;
28075 break;
28076 case OPC_ADDU_OB_DSP:
28077 op2 = MASK_ADDU_OB(ctx->opcode);
28078 switch (op2) {
28079 case OPC_RADDU_L_OB:
28080 case OPC_SUBQ_PW:
28081 case OPC_SUBQ_S_PW:
28082 case OPC_SUBQ_QH:
28083 case OPC_SUBQ_S_QH:
28084 case OPC_SUBU_OB:
28085 case OPC_SUBU_S_OB:
28086 case OPC_SUBU_QH:
28087 case OPC_SUBU_S_QH:
28088 case OPC_SUBUH_OB:
28089 case OPC_SUBUH_R_OB:
28090 case OPC_ADDQ_PW:
28091 case OPC_ADDQ_S_PW:
28092 case OPC_ADDQ_QH:
28093 case OPC_ADDQ_S_QH:
28094 case OPC_ADDU_OB:
28095 case OPC_ADDU_S_OB:
28096 case OPC_ADDU_QH:
28097 case OPC_ADDU_S_QH:
28098 case OPC_ADDUH_OB:
28099 case OPC_ADDUH_R_OB:
28100 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28101 break;
28102 case OPC_MULEQ_S_PW_QHL:
28103 case OPC_MULEQ_S_PW_QHR:
28104 case OPC_MULEU_S_QH_OBL:
28105 case OPC_MULEU_S_QH_OBR:
28106 case OPC_MULQ_RS_QH:
28107 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
28108 break;
28109 default: /* Invalid */
28110 MIPS_INVAL("MASK ADDU.OB");
28111 generate_exception_end(ctx, EXCP_RI);
28112 break;
28114 break;
28115 case OPC_CMPU_EQ_OB_DSP:
28116 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
28117 switch (op2) {
28118 case OPC_PRECR_SRA_QH_PW:
28119 case OPC_PRECR_SRA_R_QH_PW:
28120 /* Return value is rt. */
28121 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
28122 break;
28123 case OPC_PRECR_OB_QH:
28124 case OPC_PRECRQ_OB_QH:
28125 case OPC_PRECRQ_PW_L:
28126 case OPC_PRECRQ_QH_PW:
28127 case OPC_PRECRQ_RS_QH_PW:
28128 case OPC_PRECRQU_S_OB_QH:
28129 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
28130 break;
28131 case OPC_CMPU_EQ_OB:
28132 case OPC_CMPU_LT_OB:
28133 case OPC_CMPU_LE_OB:
28134 case OPC_CMP_EQ_QH:
28135 case OPC_CMP_LT_QH:
28136 case OPC_CMP_LE_QH:
28137 case OPC_CMP_EQ_PW:
28138 case OPC_CMP_LT_PW:
28139 case OPC_CMP_LE_PW:
28140 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
28141 break;
28142 case OPC_CMPGDU_EQ_OB:
28143 case OPC_CMPGDU_LT_OB:
28144 case OPC_CMPGDU_LE_OB:
28145 case OPC_CMPGU_EQ_OB:
28146 case OPC_CMPGU_LT_OB:
28147 case OPC_CMPGU_LE_OB:
28148 case OPC_PACKRL_PW:
28149 case OPC_PICK_OB:
28150 case OPC_PICK_PW:
28151 case OPC_PICK_QH:
28152 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
28153 break;
28154 default: /* Invalid */
28155 MIPS_INVAL("MASK CMPU_EQ.OB");
28156 generate_exception_end(ctx, EXCP_RI);
28157 break;
28159 break;
28160 case OPC_DAPPEND_DSP:
28161 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
28162 break;
28163 case OPC_DEXTR_W_DSP:
28164 op2 = MASK_DEXTR_W(ctx->opcode);
28165 switch (op2) {
28166 case OPC_DEXTP:
28167 case OPC_DEXTPDP:
28168 case OPC_DEXTPDPV:
28169 case OPC_DEXTPV:
28170 case OPC_DEXTR_L:
28171 case OPC_DEXTR_R_L:
28172 case OPC_DEXTR_RS_L:
28173 case OPC_DEXTR_W:
28174 case OPC_DEXTR_R_W:
28175 case OPC_DEXTR_RS_W:
28176 case OPC_DEXTR_S_H:
28177 case OPC_DEXTRV_L:
28178 case OPC_DEXTRV_R_L:
28179 case OPC_DEXTRV_RS_L:
28180 case OPC_DEXTRV_S_H:
28181 case OPC_DEXTRV_W:
28182 case OPC_DEXTRV_R_W:
28183 case OPC_DEXTRV_RS_W:
28184 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
28185 break;
28186 case OPC_DMTHLIP:
28187 case OPC_DSHILO:
28188 case OPC_DSHILOV:
28189 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
28190 break;
28191 default: /* Invalid */
28192 MIPS_INVAL("MASK EXTR.W");
28193 generate_exception_end(ctx, EXCP_RI);
28194 break;
28196 break;
28197 case OPC_DPAQ_W_QH_DSP:
28198 op2 = MASK_DPAQ_W_QH(ctx->opcode);
28199 switch (op2) {
28200 case OPC_DPAU_H_OBL:
28201 case OPC_DPAU_H_OBR:
28202 case OPC_DPSU_H_OBL:
28203 case OPC_DPSU_H_OBR:
28204 case OPC_DPA_W_QH:
28205 case OPC_DPAQ_S_W_QH:
28206 case OPC_DPS_W_QH:
28207 case OPC_DPSQ_S_W_QH:
28208 case OPC_MULSAQ_S_W_QH:
28209 case OPC_DPAQ_SA_L_PW:
28210 case OPC_DPSQ_SA_L_PW:
28211 case OPC_MULSAQ_S_L_PW:
28212 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28213 break;
28214 case OPC_MAQ_S_W_QHLL:
28215 case OPC_MAQ_S_W_QHLR:
28216 case OPC_MAQ_S_W_QHRL:
28217 case OPC_MAQ_S_W_QHRR:
28218 case OPC_MAQ_SA_W_QHLL:
28219 case OPC_MAQ_SA_W_QHLR:
28220 case OPC_MAQ_SA_W_QHRL:
28221 case OPC_MAQ_SA_W_QHRR:
28222 case OPC_MAQ_S_L_PWL:
28223 case OPC_MAQ_S_L_PWR:
28224 case OPC_DMADD:
28225 case OPC_DMADDU:
28226 case OPC_DMSUB:
28227 case OPC_DMSUBU:
28228 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
28229 break;
28230 default: /* Invalid */
28231 MIPS_INVAL("MASK DPAQ.W.QH");
28232 generate_exception_end(ctx, EXCP_RI);
28233 break;
28235 break;
28236 case OPC_DINSV_DSP:
28237 op2 = MASK_INSV(ctx->opcode);
28238 switch (op2) {
28239 case OPC_DINSV:
28241 TCGv t0, t1;
28243 if (rt == 0) {
28244 break;
28246 check_dsp(ctx);
28248 t0 = tcg_temp_new();
28249 t1 = tcg_temp_new();
28251 gen_load_gpr(t0, rt);
28252 gen_load_gpr(t1, rs);
28254 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
28256 tcg_temp_free(t0);
28257 tcg_temp_free(t1);
28258 break;
28260 default: /* Invalid */
28261 MIPS_INVAL("MASK DINSV");
28262 generate_exception_end(ctx, EXCP_RI);
28263 break;
28265 break;
28266 case OPC_SHLL_OB_DSP:
28267 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
28268 break;
28269 #endif
28270 default: /* Invalid */
28271 MIPS_INVAL("special3_legacy");
28272 generate_exception_end(ctx, EXCP_RI);
28273 break;
28278 #if defined(TARGET_MIPS64)
28280 static void decode_mmi0(CPUMIPSState *env, DisasContext *ctx)
28282 uint32_t opc = MASK_MMI0(ctx->opcode);
28284 switch (opc) {
28285 case MMI_OPC_0_PADDW: /* TODO: MMI_OPC_0_PADDW */
28286 case MMI_OPC_0_PSUBW: /* TODO: MMI_OPC_0_PSUBW */
28287 case MMI_OPC_0_PCGTW: /* TODO: MMI_OPC_0_PCGTW */
28288 case MMI_OPC_0_PMAXW: /* TODO: MMI_OPC_0_PMAXW */
28289 case MMI_OPC_0_PADDH: /* TODO: MMI_OPC_0_PADDH */
28290 case MMI_OPC_0_PSUBH: /* TODO: MMI_OPC_0_PSUBH */
28291 case MMI_OPC_0_PCGTH: /* TODO: MMI_OPC_0_PCGTH */
28292 case MMI_OPC_0_PMAXH: /* TODO: MMI_OPC_0_PMAXH */
28293 case MMI_OPC_0_PADDB: /* TODO: MMI_OPC_0_PADDB */
28294 case MMI_OPC_0_PSUBB: /* TODO: MMI_OPC_0_PSUBB */
28295 case MMI_OPC_0_PCGTB: /* TODO: MMI_OPC_0_PCGTB */
28296 case MMI_OPC_0_PADDSW: /* TODO: MMI_OPC_0_PADDSW */
28297 case MMI_OPC_0_PSUBSW: /* TODO: MMI_OPC_0_PSUBSW */
28298 case MMI_OPC_0_PEXTLW: /* TODO: MMI_OPC_0_PEXTLW */
28299 case MMI_OPC_0_PPACW: /* TODO: MMI_OPC_0_PPACW */
28300 case MMI_OPC_0_PADDSH: /* TODO: MMI_OPC_0_PADDSH */
28301 case MMI_OPC_0_PSUBSH: /* TODO: MMI_OPC_0_PSUBSH */
28302 case MMI_OPC_0_PEXTLH: /* TODO: MMI_OPC_0_PEXTLH */
28303 case MMI_OPC_0_PPACH: /* TODO: MMI_OPC_0_PPACH */
28304 case MMI_OPC_0_PADDSB: /* TODO: MMI_OPC_0_PADDSB */
28305 case MMI_OPC_0_PSUBSB: /* TODO: MMI_OPC_0_PSUBSB */
28306 case MMI_OPC_0_PEXTLB: /* TODO: MMI_OPC_0_PEXTLB */
28307 case MMI_OPC_0_PPACB: /* TODO: MMI_OPC_0_PPACB */
28308 case MMI_OPC_0_PEXT5: /* TODO: MMI_OPC_0_PEXT5 */
28309 case MMI_OPC_0_PPAC5: /* TODO: MMI_OPC_0_PPAC5 */
28310 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI0 */
28311 break;
28312 default:
28313 MIPS_INVAL("TX79 MMI class MMI0");
28314 generate_exception_end(ctx, EXCP_RI);
28315 break;
28319 static void decode_mmi1(CPUMIPSState *env, DisasContext *ctx)
28321 uint32_t opc = MASK_MMI1(ctx->opcode);
28323 switch (opc) {
28324 case MMI_OPC_1_PABSW: /* TODO: MMI_OPC_1_PABSW */
28325 case MMI_OPC_1_PCEQW: /* TODO: MMI_OPC_1_PCEQW */
28326 case MMI_OPC_1_PMINW: /* TODO: MMI_OPC_1_PMINW */
28327 case MMI_OPC_1_PADSBH: /* TODO: MMI_OPC_1_PADSBH */
28328 case MMI_OPC_1_PABSH: /* TODO: MMI_OPC_1_PABSH */
28329 case MMI_OPC_1_PCEQH: /* TODO: MMI_OPC_1_PCEQH */
28330 case MMI_OPC_1_PMINH: /* TODO: MMI_OPC_1_PMINH */
28331 case MMI_OPC_1_PCEQB: /* TODO: MMI_OPC_1_PCEQB */
28332 case MMI_OPC_1_PADDUW: /* TODO: MMI_OPC_1_PADDUW */
28333 case MMI_OPC_1_PSUBUW: /* TODO: MMI_OPC_1_PSUBUW */
28334 case MMI_OPC_1_PEXTUW: /* TODO: MMI_OPC_1_PEXTUW */
28335 case MMI_OPC_1_PADDUH: /* TODO: MMI_OPC_1_PADDUH */
28336 case MMI_OPC_1_PSUBUH: /* TODO: MMI_OPC_1_PSUBUH */
28337 case MMI_OPC_1_PEXTUH: /* TODO: MMI_OPC_1_PEXTUH */
28338 case MMI_OPC_1_PADDUB: /* TODO: MMI_OPC_1_PADDUB */
28339 case MMI_OPC_1_PSUBUB: /* TODO: MMI_OPC_1_PSUBUB */
28340 case MMI_OPC_1_PEXTUB: /* TODO: MMI_OPC_1_PEXTUB */
28341 case MMI_OPC_1_QFSRV: /* TODO: MMI_OPC_1_QFSRV */
28342 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI1 */
28343 break;
28344 default:
28345 MIPS_INVAL("TX79 MMI class MMI1");
28346 generate_exception_end(ctx, EXCP_RI);
28347 break;
28351 static void decode_mmi2(CPUMIPSState *env, DisasContext *ctx)
28353 uint32_t opc = MASK_MMI2(ctx->opcode);
28355 switch (opc) {
28356 case MMI_OPC_2_PMADDW: /* TODO: MMI_OPC_2_PMADDW */
28357 case MMI_OPC_2_PSLLVW: /* TODO: MMI_OPC_2_PSLLVW */
28358 case MMI_OPC_2_PSRLVW: /* TODO: MMI_OPC_2_PSRLVW */
28359 case MMI_OPC_2_PMSUBW: /* TODO: MMI_OPC_2_PMSUBW */
28360 case MMI_OPC_2_PMFHI: /* TODO: MMI_OPC_2_PMFHI */
28361 case MMI_OPC_2_PMFLO: /* TODO: MMI_OPC_2_PMFLO */
28362 case MMI_OPC_2_PINTH: /* TODO: MMI_OPC_2_PINTH */
28363 case MMI_OPC_2_PMULTW: /* TODO: MMI_OPC_2_PMULTW */
28364 case MMI_OPC_2_PDIVW: /* TODO: MMI_OPC_2_PDIVW */
28365 case MMI_OPC_2_PMADDH: /* TODO: MMI_OPC_2_PMADDH */
28366 case MMI_OPC_2_PHMADH: /* TODO: MMI_OPC_2_PHMADH */
28367 case MMI_OPC_2_PAND: /* TODO: MMI_OPC_2_PAND */
28368 case MMI_OPC_2_PXOR: /* TODO: MMI_OPC_2_PXOR */
28369 case MMI_OPC_2_PMSUBH: /* TODO: MMI_OPC_2_PMSUBH */
28370 case MMI_OPC_2_PHMSBH: /* TODO: MMI_OPC_2_PHMSBH */
28371 case MMI_OPC_2_PEXEH: /* TODO: MMI_OPC_2_PEXEH */
28372 case MMI_OPC_2_PREVH: /* TODO: MMI_OPC_2_PREVH */
28373 case MMI_OPC_2_PMULTH: /* TODO: MMI_OPC_2_PMULTH */
28374 case MMI_OPC_2_PDIVBW: /* TODO: MMI_OPC_2_PDIVBW */
28375 case MMI_OPC_2_PEXEW: /* TODO: MMI_OPC_2_PEXEW */
28376 case MMI_OPC_2_PROT3W: /* TODO: MMI_OPC_2_PROT3W */
28377 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI2 */
28378 break;
28379 case MMI_OPC_2_PCPYLD:
28380 gen_mmi_pcpyld(ctx);
28381 break;
28382 default:
28383 MIPS_INVAL("TX79 MMI class MMI2");
28384 generate_exception_end(ctx, EXCP_RI);
28385 break;
28389 static void decode_mmi3(CPUMIPSState *env, DisasContext *ctx)
28391 uint32_t opc = MASK_MMI3(ctx->opcode);
28393 switch (opc) {
28394 case MMI_OPC_3_PMADDUW: /* TODO: MMI_OPC_3_PMADDUW */
28395 case MMI_OPC_3_PSRAVW: /* TODO: MMI_OPC_3_PSRAVW */
28396 case MMI_OPC_3_PMTHI: /* TODO: MMI_OPC_3_PMTHI */
28397 case MMI_OPC_3_PMTLO: /* TODO: MMI_OPC_3_PMTLO */
28398 case MMI_OPC_3_PINTEH: /* TODO: MMI_OPC_3_PINTEH */
28399 case MMI_OPC_3_PMULTUW: /* TODO: MMI_OPC_3_PMULTUW */
28400 case MMI_OPC_3_PDIVUW: /* TODO: MMI_OPC_3_PDIVUW */
28401 case MMI_OPC_3_POR: /* TODO: MMI_OPC_3_POR */
28402 case MMI_OPC_3_PNOR: /* TODO: MMI_OPC_3_PNOR */
28403 case MMI_OPC_3_PEXCH: /* TODO: MMI_OPC_3_PEXCH */
28404 case MMI_OPC_3_PEXCW: /* TODO: MMI_OPC_3_PEXCW */
28405 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI3 */
28406 break;
28407 case MMI_OPC_3_PCPYH:
28408 gen_mmi_pcpyh(ctx);
28409 break;
28410 case MMI_OPC_3_PCPYUD:
28411 gen_mmi_pcpyud(ctx);
28412 break;
28413 default:
28414 MIPS_INVAL("TX79 MMI class MMI3");
28415 generate_exception_end(ctx, EXCP_RI);
28416 break;
28420 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
28422 uint32_t opc = MASK_MMI(ctx->opcode);
28423 int rs = extract32(ctx->opcode, 21, 5);
28424 int rt = extract32(ctx->opcode, 16, 5);
28425 int rd = extract32(ctx->opcode, 11, 5);
28427 switch (opc) {
28428 case MMI_OPC_CLASS_MMI0:
28429 decode_mmi0(env, ctx);
28430 break;
28431 case MMI_OPC_CLASS_MMI1:
28432 decode_mmi1(env, ctx);
28433 break;
28434 case MMI_OPC_CLASS_MMI2:
28435 decode_mmi2(env, ctx);
28436 break;
28437 case MMI_OPC_CLASS_MMI3:
28438 decode_mmi3(env, ctx);
28439 break;
28440 case MMI_OPC_MULT1:
28441 case MMI_OPC_MULTU1:
28442 case MMI_OPC_MADD:
28443 case MMI_OPC_MADDU:
28444 case MMI_OPC_MADD1:
28445 case MMI_OPC_MADDU1:
28446 gen_mul_txx9(ctx, opc, rd, rs, rt);
28447 break;
28448 case MMI_OPC_DIV1:
28449 case MMI_OPC_DIVU1:
28450 gen_div1_tx79(ctx, opc, rs, rt);
28451 break;
28452 case MMI_OPC_MTLO1:
28453 case MMI_OPC_MTHI1:
28454 gen_HILO1_tx79(ctx, opc, rs);
28455 break;
28456 case MMI_OPC_MFLO1:
28457 case MMI_OPC_MFHI1:
28458 gen_HILO1_tx79(ctx, opc, rd);
28459 break;
28460 case MMI_OPC_PLZCW: /* TODO: MMI_OPC_PLZCW */
28461 case MMI_OPC_PMFHL: /* TODO: MMI_OPC_PMFHL */
28462 case MMI_OPC_PMTHL: /* TODO: MMI_OPC_PMTHL */
28463 case MMI_OPC_PSLLH: /* TODO: MMI_OPC_PSLLH */
28464 case MMI_OPC_PSRLH: /* TODO: MMI_OPC_PSRLH */
28465 case MMI_OPC_PSRAH: /* TODO: MMI_OPC_PSRAH */
28466 case MMI_OPC_PSLLW: /* TODO: MMI_OPC_PSLLW */
28467 case MMI_OPC_PSRLW: /* TODO: MMI_OPC_PSRLW */
28468 case MMI_OPC_PSRAW: /* TODO: MMI_OPC_PSRAW */
28469 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_CLASS_MMI */
28470 break;
28471 default:
28472 MIPS_INVAL("TX79 MMI class");
28473 generate_exception_end(ctx, EXCP_RI);
28474 break;
28478 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
28480 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_LQ */
28483 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
28485 generate_exception_end(ctx, EXCP_RI); /* TODO: MMI_OPC_SQ */
28489 * The TX79-specific instruction Store Quadword
28491 * +--------+-------+-------+------------------------+
28492 * | 011111 | base | rt | offset | SQ
28493 * +--------+-------+-------+------------------------+
28494 * 6 5 5 16
28496 * has the same opcode as the Read Hardware Register instruction
28498 * +--------+-------+-------+-------+-------+--------+
28499 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
28500 * +--------+-------+-------+-------+-------+--------+
28501 * 6 5 5 5 5 6
28503 * that is required, trapped and emulated by the Linux kernel. However, all
28504 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
28505 * offset is odd. Therefore all valid SQ instructions can execute normally.
28506 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
28507 * between SQ and RDHWR, as the Linux kernel does.
28509 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
28511 int base = extract32(ctx->opcode, 21, 5);
28512 int rt = extract32(ctx->opcode, 16, 5);
28513 int offset = extract32(ctx->opcode, 0, 16);
28515 #ifdef CONFIG_USER_ONLY
28516 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
28517 uint32_t op2 = extract32(ctx->opcode, 6, 5);
28519 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
28520 int rd = extract32(ctx->opcode, 11, 5);
28522 gen_rdhwr(ctx, rt, rd, 0);
28523 return;
28525 #endif
28527 gen_mmi_sq(ctx, base, rt, offset);
28530 #endif
28532 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
28534 int rs, rt, rd, sa;
28535 uint32_t op1, op2;
28536 int16_t imm;
28538 rs = (ctx->opcode >> 21) & 0x1f;
28539 rt = (ctx->opcode >> 16) & 0x1f;
28540 rd = (ctx->opcode >> 11) & 0x1f;
28541 sa = (ctx->opcode >> 6) & 0x1f;
28542 imm = sextract32(ctx->opcode, 7, 9);
28544 op1 = MASK_SPECIAL3(ctx->opcode);
28547 * EVA loads and stores overlap Loongson 2E instructions decoded by
28548 * decode_opc_special3_legacy(), so be careful to allow their decoding when
28549 * EVA is absent.
28551 if (ctx->eva) {
28552 switch (op1) {
28553 case OPC_LWLE:
28554 case OPC_LWRE:
28555 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28556 /* fall through */
28557 case OPC_LBUE:
28558 case OPC_LHUE:
28559 case OPC_LBE:
28560 case OPC_LHE:
28561 case OPC_LLE:
28562 case OPC_LWE:
28563 check_cp0_enabled(ctx);
28564 gen_ld(ctx, op1, rt, rs, imm);
28565 return;
28566 case OPC_SWLE:
28567 case OPC_SWRE:
28568 check_insn_opc_removed(ctx, ISA_MIPS32R6);
28569 /* fall through */
28570 case OPC_SBE:
28571 case OPC_SHE:
28572 case OPC_SWE:
28573 check_cp0_enabled(ctx);
28574 gen_st(ctx, op1, rt, rs, imm);
28575 return;
28576 case OPC_SCE:
28577 check_cp0_enabled(ctx);
28578 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
28579 return;
28580 case OPC_CACHEE:
28581 check_cp0_enabled(ctx);
28582 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
28583 gen_cache_operation(ctx, rt, rs, imm);
28585 /* Treat as NOP. */
28586 return;
28587 case OPC_PREFE:
28588 check_cp0_enabled(ctx);
28589 /* Treat as NOP. */
28590 return;
28594 switch (op1) {
28595 case OPC_EXT:
28596 case OPC_INS:
28597 check_insn(ctx, ISA_MIPS32R2);
28598 gen_bitops(ctx, op1, rt, rs, sa, rd);
28599 break;
28600 case OPC_BSHFL:
28601 op2 = MASK_BSHFL(ctx->opcode);
28602 switch (op2) {
28603 case OPC_ALIGN:
28604 case OPC_ALIGN_1:
28605 case OPC_ALIGN_2:
28606 case OPC_ALIGN_3:
28607 case OPC_BITSWAP:
28608 check_insn(ctx, ISA_MIPS32R6);
28609 decode_opc_special3_r6(env, ctx);
28610 break;
28611 default:
28612 check_insn(ctx, ISA_MIPS32R2);
28613 gen_bshfl(ctx, op2, rt, rd);
28614 break;
28616 break;
28617 #if defined(TARGET_MIPS64)
28618 case OPC_DEXTM:
28619 case OPC_DEXTU:
28620 case OPC_DEXT:
28621 case OPC_DINSM:
28622 case OPC_DINSU:
28623 case OPC_DINS:
28624 check_insn(ctx, ISA_MIPS32R2);
28625 check_mips_64(ctx);
28626 gen_bitops(ctx, op1, rt, rs, sa, rd);
28627 break;
28628 case OPC_DBSHFL:
28629 op2 = MASK_DBSHFL(ctx->opcode);
28630 switch (op2) {
28631 case OPC_DALIGN:
28632 case OPC_DALIGN_1:
28633 case OPC_DALIGN_2:
28634 case OPC_DALIGN_3:
28635 case OPC_DALIGN_4:
28636 case OPC_DALIGN_5:
28637 case OPC_DALIGN_6:
28638 case OPC_DALIGN_7:
28639 case OPC_DBITSWAP:
28640 check_insn(ctx, ISA_MIPS32R6);
28641 decode_opc_special3_r6(env, ctx);
28642 break;
28643 default:
28644 check_insn(ctx, ISA_MIPS32R2);
28645 check_mips_64(ctx);
28646 op2 = MASK_DBSHFL(ctx->opcode);
28647 gen_bshfl(ctx, op2, rt, rd);
28648 break;
28650 break;
28651 #endif
28652 case OPC_RDHWR:
28653 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
28654 break;
28655 case OPC_FORK:
28656 check_mt(ctx);
28658 TCGv t0 = tcg_temp_new();
28659 TCGv t1 = tcg_temp_new();
28661 gen_load_gpr(t0, rt);
28662 gen_load_gpr(t1, rs);
28663 gen_helper_fork(t0, t1);
28664 tcg_temp_free(t0);
28665 tcg_temp_free(t1);
28667 break;
28668 case OPC_YIELD:
28669 check_mt(ctx);
28671 TCGv t0 = tcg_temp_new();
28673 gen_load_gpr(t0, rs);
28674 gen_helper_yield(t0, cpu_env, t0);
28675 gen_store_gpr(t0, rd);
28676 tcg_temp_free(t0);
28678 break;
28679 default:
28680 if (ctx->insn_flags & ISA_MIPS32R6) {
28681 decode_opc_special3_r6(env, ctx);
28682 } else {
28683 decode_opc_special3_legacy(env, ctx);
28688 /* MIPS SIMD Architecture (MSA) */
28689 static inline int check_msa_access(DisasContext *ctx)
28691 if (unlikely((ctx->hflags & MIPS_HFLAG_FPU) &&
28692 !(ctx->hflags & MIPS_HFLAG_F64))) {
28693 generate_exception_end(ctx, EXCP_RI);
28694 return 0;
28697 if (unlikely(!(ctx->hflags & MIPS_HFLAG_MSA))) {
28698 if (ctx->insn_flags & ASE_MSA) {
28699 generate_exception_end(ctx, EXCP_MSADIS);
28700 return 0;
28701 } else {
28702 generate_exception_end(ctx, EXCP_RI);
28703 return 0;
28706 return 1;
28709 static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
28711 /* generates tcg ops to check if any element is 0 */
28712 /* Note this function only works with MSA_WRLEN = 128 */
28713 uint64_t eval_zero_or_big = 0;
28714 uint64_t eval_big = 0;
28715 TCGv_i64 t0 = tcg_temp_new_i64();
28716 TCGv_i64 t1 = tcg_temp_new_i64();
28717 switch (df) {
28718 case DF_BYTE:
28719 eval_zero_or_big = 0x0101010101010101ULL;
28720 eval_big = 0x8080808080808080ULL;
28721 break;
28722 case DF_HALF:
28723 eval_zero_or_big = 0x0001000100010001ULL;
28724 eval_big = 0x8000800080008000ULL;
28725 break;
28726 case DF_WORD:
28727 eval_zero_or_big = 0x0000000100000001ULL;
28728 eval_big = 0x8000000080000000ULL;
28729 break;
28730 case DF_DOUBLE:
28731 eval_zero_or_big = 0x0000000000000001ULL;
28732 eval_big = 0x8000000000000000ULL;
28733 break;
28735 tcg_gen_subi_i64(t0, msa_wr_d[wt << 1], eval_zero_or_big);
28736 tcg_gen_andc_i64(t0, t0, msa_wr_d[wt << 1]);
28737 tcg_gen_andi_i64(t0, t0, eval_big);
28738 tcg_gen_subi_i64(t1, msa_wr_d[(wt << 1) + 1], eval_zero_or_big);
28739 tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt << 1) + 1]);
28740 tcg_gen_andi_i64(t1, t1, eval_big);
28741 tcg_gen_or_i64(t0, t0, t1);
28742 /* if all bits are zero then all elements are not zero */
28743 /* if some bit is non-zero then some element is zero */
28744 tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
28745 tcg_gen_trunc_i64_tl(tresult, t0);
28746 tcg_temp_free_i64(t0);
28747 tcg_temp_free_i64(t1);
28750 static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t op1)
28752 uint8_t df = (ctx->opcode >> 21) & 0x3;
28753 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
28754 int64_t s16 = (int16_t)ctx->opcode;
28756 check_msa_access(ctx);
28758 if (ctx->hflags & MIPS_HFLAG_BMASK) {
28759 generate_exception_end(ctx, EXCP_RI);
28760 return;
28762 switch (op1) {
28763 case OPC_BZ_V:
28764 case OPC_BNZ_V:
28766 TCGv_i64 t0 = tcg_temp_new_i64();
28767 tcg_gen_or_i64(t0, msa_wr_d[wt << 1], msa_wr_d[(wt << 1) + 1]);
28768 tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
28769 TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
28770 tcg_gen_trunc_i64_tl(bcond, t0);
28771 tcg_temp_free_i64(t0);
28773 break;
28774 case OPC_BZ_B:
28775 case OPC_BZ_H:
28776 case OPC_BZ_W:
28777 case OPC_BZ_D:
28778 gen_check_zero_element(bcond, df, wt);
28779 break;
28780 case OPC_BNZ_B:
28781 case OPC_BNZ_H:
28782 case OPC_BNZ_W:
28783 case OPC_BNZ_D:
28784 gen_check_zero_element(bcond, df, wt);
28785 tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
28786 break;
28789 ctx->btarget = ctx->base.pc_next + (s16 << 2) + 4;
28791 ctx->hflags |= MIPS_HFLAG_BC;
28792 ctx->hflags |= MIPS_HFLAG_BDS32;
28795 static void gen_msa_i8(CPUMIPSState *env, DisasContext *ctx)
28797 #define MASK_MSA_I8(op) (MASK_MSA_MINOR(op) | (op & (0x03 << 24)))
28798 uint8_t i8 = (ctx->opcode >> 16) & 0xff;
28799 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28800 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28802 TCGv_i32 twd = tcg_const_i32(wd);
28803 TCGv_i32 tws = tcg_const_i32(ws);
28804 TCGv_i32 ti8 = tcg_const_i32(i8);
28806 switch (MASK_MSA_I8(ctx->opcode)) {
28807 case OPC_ANDI_B:
28808 gen_helper_msa_andi_b(cpu_env, twd, tws, ti8);
28809 break;
28810 case OPC_ORI_B:
28811 gen_helper_msa_ori_b(cpu_env, twd, tws, ti8);
28812 break;
28813 case OPC_NORI_B:
28814 gen_helper_msa_nori_b(cpu_env, twd, tws, ti8);
28815 break;
28816 case OPC_XORI_B:
28817 gen_helper_msa_xori_b(cpu_env, twd, tws, ti8);
28818 break;
28819 case OPC_BMNZI_B:
28820 gen_helper_msa_bmnzi_b(cpu_env, twd, tws, ti8);
28821 break;
28822 case OPC_BMZI_B:
28823 gen_helper_msa_bmzi_b(cpu_env, twd, tws, ti8);
28824 break;
28825 case OPC_BSELI_B:
28826 gen_helper_msa_bseli_b(cpu_env, twd, tws, ti8);
28827 break;
28828 case OPC_SHF_B:
28829 case OPC_SHF_H:
28830 case OPC_SHF_W:
28832 uint8_t df = (ctx->opcode >> 24) & 0x3;
28833 if (df == DF_DOUBLE) {
28834 generate_exception_end(ctx, EXCP_RI);
28835 } else {
28836 TCGv_i32 tdf = tcg_const_i32(df);
28837 gen_helper_msa_shf_df(cpu_env, tdf, twd, tws, ti8);
28838 tcg_temp_free_i32(tdf);
28841 break;
28842 default:
28843 MIPS_INVAL("MSA instruction");
28844 generate_exception_end(ctx, EXCP_RI);
28845 break;
28848 tcg_temp_free_i32(twd);
28849 tcg_temp_free_i32(tws);
28850 tcg_temp_free_i32(ti8);
28853 static void gen_msa_i5(CPUMIPSState *env, DisasContext *ctx)
28855 #define MASK_MSA_I5(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28856 uint8_t df = (ctx->opcode >> 21) & 0x3;
28857 int8_t s5 = (int8_t) sextract32(ctx->opcode, 16, 5);
28858 uint8_t u5 = (ctx->opcode >> 16) & 0x1f;
28859 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28860 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28862 TCGv_i32 tdf = tcg_const_i32(df);
28863 TCGv_i32 twd = tcg_const_i32(wd);
28864 TCGv_i32 tws = tcg_const_i32(ws);
28865 TCGv_i32 timm = tcg_temp_new_i32();
28866 tcg_gen_movi_i32(timm, u5);
28868 switch (MASK_MSA_I5(ctx->opcode)) {
28869 case OPC_ADDVI_df:
28870 gen_helper_msa_addvi_df(cpu_env, tdf, twd, tws, timm);
28871 break;
28872 case OPC_SUBVI_df:
28873 gen_helper_msa_subvi_df(cpu_env, tdf, twd, tws, timm);
28874 break;
28875 case OPC_MAXI_S_df:
28876 tcg_gen_movi_i32(timm, s5);
28877 gen_helper_msa_maxi_s_df(cpu_env, tdf, twd, tws, timm);
28878 break;
28879 case OPC_MAXI_U_df:
28880 gen_helper_msa_maxi_u_df(cpu_env, tdf, twd, tws, timm);
28881 break;
28882 case OPC_MINI_S_df:
28883 tcg_gen_movi_i32(timm, s5);
28884 gen_helper_msa_mini_s_df(cpu_env, tdf, twd, tws, timm);
28885 break;
28886 case OPC_MINI_U_df:
28887 gen_helper_msa_mini_u_df(cpu_env, tdf, twd, tws, timm);
28888 break;
28889 case OPC_CEQI_df:
28890 tcg_gen_movi_i32(timm, s5);
28891 gen_helper_msa_ceqi_df(cpu_env, tdf, twd, tws, timm);
28892 break;
28893 case OPC_CLTI_S_df:
28894 tcg_gen_movi_i32(timm, s5);
28895 gen_helper_msa_clti_s_df(cpu_env, tdf, twd, tws, timm);
28896 break;
28897 case OPC_CLTI_U_df:
28898 gen_helper_msa_clti_u_df(cpu_env, tdf, twd, tws, timm);
28899 break;
28900 case OPC_CLEI_S_df:
28901 tcg_gen_movi_i32(timm, s5);
28902 gen_helper_msa_clei_s_df(cpu_env, tdf, twd, tws, timm);
28903 break;
28904 case OPC_CLEI_U_df:
28905 gen_helper_msa_clei_u_df(cpu_env, tdf, twd, tws, timm);
28906 break;
28907 case OPC_LDI_df:
28909 int32_t s10 = sextract32(ctx->opcode, 11, 10);
28910 tcg_gen_movi_i32(timm, s10);
28911 gen_helper_msa_ldi_df(cpu_env, tdf, twd, timm);
28913 break;
28914 default:
28915 MIPS_INVAL("MSA instruction");
28916 generate_exception_end(ctx, EXCP_RI);
28917 break;
28920 tcg_temp_free_i32(tdf);
28921 tcg_temp_free_i32(twd);
28922 tcg_temp_free_i32(tws);
28923 tcg_temp_free_i32(timm);
28926 static void gen_msa_bit(CPUMIPSState *env, DisasContext *ctx)
28928 #define MASK_MSA_BIT(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
28929 uint8_t dfm = (ctx->opcode >> 16) & 0x7f;
28930 uint32_t df = 0, m = 0;
28931 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
28932 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
28934 TCGv_i32 tdf;
28935 TCGv_i32 tm;
28936 TCGv_i32 twd;
28937 TCGv_i32 tws;
28939 if ((dfm & 0x40) == 0x00) {
28940 m = dfm & 0x3f;
28941 df = DF_DOUBLE;
28942 } else if ((dfm & 0x60) == 0x40) {
28943 m = dfm & 0x1f;
28944 df = DF_WORD;
28945 } else if ((dfm & 0x70) == 0x60) {
28946 m = dfm & 0x0f;
28947 df = DF_HALF;
28948 } else if ((dfm & 0x78) == 0x70) {
28949 m = dfm & 0x7;
28950 df = DF_BYTE;
28951 } else {
28952 generate_exception_end(ctx, EXCP_RI);
28953 return;
28956 tdf = tcg_const_i32(df);
28957 tm = tcg_const_i32(m);
28958 twd = tcg_const_i32(wd);
28959 tws = tcg_const_i32(ws);
28961 switch (MASK_MSA_BIT(ctx->opcode)) {
28962 case OPC_SLLI_df:
28963 gen_helper_msa_slli_df(cpu_env, tdf, twd, tws, tm);
28964 break;
28965 case OPC_SRAI_df:
28966 gen_helper_msa_srai_df(cpu_env, tdf, twd, tws, tm);
28967 break;
28968 case OPC_SRLI_df:
28969 gen_helper_msa_srli_df(cpu_env, tdf, twd, tws, tm);
28970 break;
28971 case OPC_BCLRI_df:
28972 gen_helper_msa_bclri_df(cpu_env, tdf, twd, tws, tm);
28973 break;
28974 case OPC_BSETI_df:
28975 gen_helper_msa_bseti_df(cpu_env, tdf, twd, tws, tm);
28976 break;
28977 case OPC_BNEGI_df:
28978 gen_helper_msa_bnegi_df(cpu_env, tdf, twd, tws, tm);
28979 break;
28980 case OPC_BINSLI_df:
28981 gen_helper_msa_binsli_df(cpu_env, tdf, twd, tws, tm);
28982 break;
28983 case OPC_BINSRI_df:
28984 gen_helper_msa_binsri_df(cpu_env, tdf, twd, tws, tm);
28985 break;
28986 case OPC_SAT_S_df:
28987 gen_helper_msa_sat_s_df(cpu_env, tdf, twd, tws, tm);
28988 break;
28989 case OPC_SAT_U_df:
28990 gen_helper_msa_sat_u_df(cpu_env, tdf, twd, tws, tm);
28991 break;
28992 case OPC_SRARI_df:
28993 gen_helper_msa_srari_df(cpu_env, tdf, twd, tws, tm);
28994 break;
28995 case OPC_SRLRI_df:
28996 gen_helper_msa_srlri_df(cpu_env, tdf, twd, tws, tm);
28997 break;
28998 default:
28999 MIPS_INVAL("MSA instruction");
29000 generate_exception_end(ctx, EXCP_RI);
29001 break;
29004 tcg_temp_free_i32(tdf);
29005 tcg_temp_free_i32(tm);
29006 tcg_temp_free_i32(twd);
29007 tcg_temp_free_i32(tws);
29010 static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
29012 #define MASK_MSA_3R(op) (MASK_MSA_MINOR(op) | (op & (0x7 << 23)))
29013 uint8_t df = (ctx->opcode >> 21) & 0x3;
29014 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
29015 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
29016 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
29018 TCGv_i32 tdf = tcg_const_i32(df);
29019 TCGv_i32 twd = tcg_const_i32(wd);
29020 TCGv_i32 tws = tcg_const_i32(ws);
29021 TCGv_i32 twt = tcg_const_i32(wt);
29023 switch (MASK_MSA_3R(ctx->opcode)) {
29024 case OPC_BINSL_df:
29025 switch (df) {
29026 case DF_BYTE:
29027 gen_helper_msa_binsl_b(cpu_env, twd, tws, twt);
29028 break;
29029 case DF_HALF:
29030 gen_helper_msa_binsl_h(cpu_env, twd, tws, twt);
29031 break;
29032 case DF_WORD:
29033 gen_helper_msa_binsl_w(cpu_env, twd, tws, twt);
29034 break;
29035 case DF_DOUBLE:
29036 gen_helper_msa_binsl_d(cpu_env, twd, tws, twt);
29037 break;
29039 break;
29040 case OPC_BINSR_df:
29041 switch (df) {
29042 case DF_BYTE:
29043 gen_helper_msa_binsr_b(cpu_env, twd, tws, twt);
29044 break;
29045 case DF_HALF:
29046 gen_helper_msa_binsr_h(cpu_env, twd, tws, twt);
29047 break;
29048 case DF_WORD:
29049 gen_helper_msa_binsr_w(cpu_env, twd, tws, twt);
29050 break;
29051 case DF_DOUBLE:
29052 gen_helper_msa_binsr_d(cpu_env, twd, tws, twt);
29053 break;
29055 break;
29056 case OPC_BCLR_df:
29057 switch (df) {
29058 case DF_BYTE:
29059 gen_helper_msa_bclr_b(cpu_env, twd, tws, twt);
29060 break;
29061 case DF_HALF:
29062 gen_helper_msa_bclr_h(cpu_env, twd, tws, twt);
29063 break;
29064 case DF_WORD:
29065 gen_helper_msa_bclr_w(cpu_env, twd, tws, twt);
29066 break;
29067 case DF_DOUBLE:
29068 gen_helper_msa_bclr_d(cpu_env, twd, tws, twt);
29069 break;
29071 break;
29072 case OPC_BNEG_df:
29073 switch (df) {
29074 case DF_BYTE:
29075 gen_helper_msa_bneg_b(cpu_env, twd, tws, twt);
29076 break;
29077 case DF_HALF:
29078 gen_helper_msa_bneg_h(cpu_env, twd, tws, twt);
29079 break;
29080 case DF_WORD:
29081 gen_helper_msa_bneg_w(cpu_env, twd, tws, twt);
29082 break;
29083 case DF_DOUBLE:
29084 gen_helper_msa_bneg_d(cpu_env, twd, tws, twt);
29085 break;
29087 break;
29088 case OPC_BSET_df:
29089 switch (df) {
29090 case DF_BYTE:
29091 gen_helper_msa_bset_b(cpu_env, twd, tws, twt);
29092 break;
29093 case DF_HALF:
29094 gen_helper_msa_bset_h(cpu_env, twd, tws, twt);
29095 break;
29096 case DF_WORD:
29097 gen_helper_msa_bset_w(cpu_env, twd, tws, twt);
29098 break;
29099 case DF_DOUBLE:
29100 gen_helper_msa_bset_d(cpu_env, twd, tws, twt);
29101 break;
29103 break;
29104 case OPC_ADD_A_df:
29105 switch (df) {
29106 case DF_BYTE:
29107 gen_helper_msa_add_a_b(cpu_env, twd, tws, twt);
29108 break;
29109 case DF_HALF:
29110 gen_helper_msa_add_a_h(cpu_env, twd, tws, twt);
29111 break;
29112 case DF_WORD:
29113 gen_helper_msa_add_a_w(cpu_env, twd, tws, twt);
29114 break;
29115 case DF_DOUBLE:
29116 gen_helper_msa_add_a_d(cpu_env, twd, tws, twt);
29117 break;
29119 break;
29120 case OPC_ADDS_A_df:
29121 switch (df) {
29122 case DF_BYTE:
29123 gen_helper_msa_adds_a_b(cpu_env, twd, tws, twt);
29124 break;
29125 case DF_HALF:
29126 gen_helper_msa_adds_a_h(cpu_env, twd, tws, twt);
29127 break;
29128 case DF_WORD:
29129 gen_helper_msa_adds_a_w(cpu_env, twd, tws, twt);
29130 break;
29131 case DF_DOUBLE:
29132 gen_helper_msa_adds_a_d(cpu_env, twd, tws, twt);
29133 break;
29135 break;
29136 case OPC_ADDS_S_df:
29137 switch (df) {
29138 case DF_BYTE:
29139 gen_helper_msa_adds_s_b(cpu_env, twd, tws, twt);
29140 break;
29141 case DF_HALF:
29142 gen_helper_msa_adds_s_h(cpu_env, twd, tws, twt);
29143 break;
29144 case DF_WORD:
29145 gen_helper_msa_adds_s_w(cpu_env, twd, tws, twt);
29146 break;
29147 case DF_DOUBLE:
29148 gen_helper_msa_adds_s_d(cpu_env, twd, tws, twt);
29149 break;
29151 break;
29152 case OPC_ADDS_U_df:
29153 switch (df) {
29154 case DF_BYTE:
29155 gen_helper_msa_adds_u_b(cpu_env, twd, tws, twt);
29156 break;
29157 case DF_HALF:
29158 gen_helper_msa_adds_u_h(cpu_env, twd, tws, twt);
29159 break;
29160 case DF_WORD:
29161 gen_helper_msa_adds_u_w(cpu_env, twd, tws, twt);
29162 break;
29163 case DF_DOUBLE:
29164 gen_helper_msa_adds_u_d(cpu_env, twd, tws, twt);
29165 break;
29167 break;
29168 case OPC_ADDV_df:
29169 switch (df) {
29170 case DF_BYTE:
29171 gen_helper_msa_addv_b(cpu_env, twd, tws, twt);
29172 break;
29173 case DF_HALF:
29174 gen_helper_msa_addv_h(cpu_env, twd, tws, twt);
29175 break;
29176 case DF_WORD:
29177 gen_helper_msa_addv_w(cpu_env, twd, tws, twt);
29178 break;
29179 case DF_DOUBLE:
29180 gen_helper_msa_addv_d(cpu_env, twd, tws, twt);
29181 break;
29183 break;
29184 case OPC_AVE_S_df:
29185 switch (df) {
29186 case DF_BYTE:
29187 gen_helper_msa_ave_s_b(cpu_env, twd, tws, twt);
29188 break;
29189 case DF_HALF:
29190 gen_helper_msa_ave_s_h(cpu_env, twd, tws, twt);
29191 break;
29192 case DF_WORD:
29193 gen_helper_msa_ave_s_w(cpu_env, twd, tws, twt);
29194 break;
29195 case DF_DOUBLE:
29196 gen_helper_msa_ave_s_d(cpu_env, twd, tws, twt);
29197 break;
29199 break;
29200 case OPC_AVE_U_df:
29201 switch (df) {
29202 case DF_BYTE:
29203 gen_helper_msa_ave_u_b(cpu_env, twd, tws, twt);
29204 break;
29205 case DF_HALF:
29206 gen_helper_msa_ave_u_h(cpu_env, twd, tws, twt);
29207 break;
29208 case DF_WORD:
29209 gen_helper_msa_ave_u_w(cpu_env, twd, tws, twt);
29210 break;
29211 case DF_DOUBLE:
29212 gen_helper_msa_ave_u_d(cpu_env, twd, tws, twt);
29213 break;
29215 break;
29216 case OPC_AVER_S_df:
29217 switch (df) {
29218 case DF_BYTE:
29219 gen_helper_msa_aver_s_b(cpu_env, twd, tws, twt);
29220 break;
29221 case DF_HALF:
29222 gen_helper_msa_aver_s_h(cpu_env, twd, tws, twt);
29223 break;
29224 case DF_WORD:
29225 gen_helper_msa_aver_s_w(cpu_env, twd, tws, twt);
29226 break;
29227 case DF_DOUBLE:
29228 gen_helper_msa_aver_s_d(cpu_env, twd, tws, twt);
29229 break;
29231 break;
29232 case OPC_AVER_U_df:
29233 switch (df) {
29234 case DF_BYTE:
29235 gen_helper_msa_aver_u_b(cpu_env, twd, tws, twt);
29236 break;
29237 case DF_HALF:
29238 gen_helper_msa_aver_u_h(cpu_env, twd, tws, twt);
29239 break;
29240 case DF_WORD:
29241 gen_helper_msa_aver_u_w(cpu_env, twd, tws, twt);
29242 break;
29243 case DF_DOUBLE:
29244 gen_helper_msa_aver_u_d(cpu_env, twd, tws, twt);
29245 break;
29247 break;
29248 case OPC_CEQ_df:
29249 switch (df) {
29250 case DF_BYTE:
29251 gen_helper_msa_ceq_b(cpu_env, twd, tws, twt);
29252 break;
29253 case DF_HALF:
29254 gen_helper_msa_ceq_h(cpu_env, twd, tws, twt);
29255 break;
29256 case DF_WORD:
29257 gen_helper_msa_ceq_w(cpu_env, twd, tws, twt);
29258 break;
29259 case DF_DOUBLE:
29260 gen_helper_msa_ceq_d(cpu_env, twd, tws, twt);
29261 break;
29263 break;
29264 case OPC_CLE_S_df:
29265 switch (df) {
29266 case DF_BYTE:
29267 gen_helper_msa_cle_s_b(cpu_env, twd, tws, twt);
29268 break;
29269 case DF_HALF:
29270 gen_helper_msa_cle_s_h(cpu_env, twd, tws, twt);
29271 break;
29272 case DF_WORD:
29273 gen_helper_msa_cle_s_w(cpu_env, twd, tws, twt);
29274 break;
29275 case DF_DOUBLE:
29276 gen_helper_msa_cle_s_d(cpu_env, twd, tws, twt);
29277 break;
29279 break;
29280 case OPC_CLE_U_df:
29281 switch (df) {
29282 case DF_BYTE:
29283 gen_helper_msa_cle_u_b(cpu_env, twd, tws, twt);
29284 break;
29285 case DF_HALF:
29286 gen_helper_msa_cle_u_h(cpu_env, twd, tws, twt);
29287 break;
29288 case DF_WORD:
29289 gen_helper_msa_cle_u_w(cpu_env, twd, tws, twt);
29290 break;
29291 case DF_DOUBLE:
29292 gen_helper_msa_cle_u_d(cpu_env, twd, tws, twt);
29293 break;
29295 break;
29296 case OPC_CLT_S_df:
29297 switch (df) {
29298 case DF_BYTE:
29299 gen_helper_msa_clt_s_b(cpu_env, twd, tws, twt);
29300 break;
29301 case DF_HALF:
29302 gen_helper_msa_clt_s_h(cpu_env, twd, tws, twt);
29303 break;
29304 case DF_WORD:
29305 gen_helper_msa_clt_s_w(cpu_env, twd, tws, twt);
29306 break;
29307 case DF_DOUBLE:
29308 gen_helper_msa_clt_s_d(cpu_env, twd, tws, twt);
29309 break;
29311 break;
29312 case OPC_CLT_U_df:
29313 switch (df) {
29314 case DF_BYTE:
29315 gen_helper_msa_clt_u_b(cpu_env, twd, tws, twt);
29316 break;
29317 case DF_HALF:
29318 gen_helper_msa_clt_u_h(cpu_env, twd, tws, twt);
29319 break;
29320 case DF_WORD:
29321 gen_helper_msa_clt_u_w(cpu_env, twd, tws, twt);
29322 break;
29323 case DF_DOUBLE:
29324 gen_helper_msa_clt_u_d(cpu_env, twd, tws, twt);
29325 break;
29327 break;
29328 case OPC_DIV_S_df:
29329 switch (df) {
29330 case DF_BYTE:
29331 gen_helper_msa_div_s_b(cpu_env, twd, tws, twt);
29332 break;
29333 case DF_HALF:
29334 gen_helper_msa_div_s_h(cpu_env, twd, tws, twt);
29335 break;
29336 case DF_WORD:
29337 gen_helper_msa_div_s_w(cpu_env, twd, tws, twt);
29338 break;
29339 case DF_DOUBLE:
29340 gen_helper_msa_div_s_d(cpu_env, twd, tws, twt);
29341 break;
29343 break;
29344 case OPC_DIV_U_df:
29345 switch (df) {
29346 case DF_BYTE:
29347 gen_helper_msa_div_u_b(cpu_env, twd, tws, twt);
29348 break;
29349 case DF_HALF:
29350 gen_helper_msa_div_u_h(cpu_env, twd, tws, twt);
29351 break;
29352 case DF_WORD:
29353 gen_helper_msa_div_u_w(cpu_env, twd, tws, twt);
29354 break;
29355 case DF_DOUBLE:
29356 gen_helper_msa_div_u_d(cpu_env, twd, tws, twt);
29357 break;
29359 break;
29360 case OPC_MAX_A_df:
29361 switch (df) {
29362 case DF_BYTE:
29363 gen_helper_msa_max_a_b(cpu_env, twd, tws, twt);
29364 break;
29365 case DF_HALF:
29366 gen_helper_msa_max_a_h(cpu_env, twd, tws, twt);
29367 break;
29368 case DF_WORD:
29369 gen_helper_msa_max_a_w(cpu_env, twd, tws, twt);
29370 break;
29371 case DF_DOUBLE:
29372 gen_helper_msa_max_a_d(cpu_env, twd, tws, twt);
29373 break;
29375 break;
29376 case OPC_MAX_S_df:
29377 switch (df) {
29378 case DF_BYTE:
29379 gen_helper_msa_max_s_b(cpu_env, twd, tws, twt);
29380 break;
29381 case DF_HALF:
29382 gen_helper_msa_max_s_h(cpu_env, twd, tws, twt);
29383 break;
29384 case DF_WORD:
29385 gen_helper_msa_max_s_w(cpu_env, twd, tws, twt);
29386 break;
29387 case DF_DOUBLE:
29388 gen_helper_msa_max_s_d(cpu_env, twd, tws, twt);
29389 break;
29391 break;
29392 case OPC_MAX_U_df:
29393 switch (df) {
29394 case DF_BYTE:
29395 gen_helper_msa_max_u_b(cpu_env, twd, tws, twt);
29396 break;
29397 case DF_HALF:
29398 gen_helper_msa_max_u_h(cpu_env, twd, tws, twt);
29399 break;
29400 case DF_WORD:
29401 gen_helper_msa_max_u_w(cpu_env, twd, tws, twt);
29402 break;
29403 case DF_DOUBLE:
29404 gen_helper_msa_max_u_d(cpu_env, twd, tws, twt);
29405 break;
29407 break;
29408 case OPC_MIN_A_df:
29409 switch (df) {
29410 case DF_BYTE:
29411 gen_helper_msa_min_a_b(cpu_env, twd, tws, twt);
29412 break;
29413 case DF_HALF:
29414 gen_helper_msa_min_a_h(cpu_env, twd, tws, twt);
29415 break;
29416 case DF_WORD:
29417 gen_helper_msa_min_a_w(cpu_env, twd, tws, twt);
29418 break;
29419 case DF_DOUBLE:
29420 gen_helper_msa_min_a_d(cpu_env, twd, tws, twt);
29421 break;
29423 break;
29424 case OPC_MIN_S_df:
29425 switch (df) {
29426 case DF_BYTE:
29427 gen_helper_msa_min_s_b(cpu_env, twd, tws, twt);
29428 break;
29429 case DF_HALF:
29430 gen_helper_msa_min_s_h(cpu_env, twd, tws, twt);
29431 break;
29432 case DF_WORD:
29433 gen_helper_msa_min_s_w(cpu_env, twd, tws, twt);
29434 break;
29435 case DF_DOUBLE:
29436 gen_helper_msa_min_s_d(cpu_env, twd, tws, twt);
29437 break;
29439 break;
29440 case OPC_MIN_U_df:
29441 switch (df) {
29442 case DF_BYTE:
29443 gen_helper_msa_min_u_b(cpu_env, twd, tws, twt);
29444 break;
29445 case DF_HALF:
29446 gen_helper_msa_min_u_h(cpu_env, twd, tws, twt);
29447 break;
29448 case DF_WORD:
29449 gen_helper_msa_min_u_w(cpu_env, twd, tws, twt);
29450 break;
29451 case DF_DOUBLE:
29452 gen_helper_msa_min_u_d(cpu_env, twd, tws, twt);
29453 break;
29455 break;
29456 case OPC_MOD_S_df:
29457 switch (df) {
29458 case DF_BYTE:
29459 gen_helper_msa_mod_s_b(cpu_env, twd, tws, twt);
29460 break;
29461 case DF_HALF:
29462 gen_helper_msa_mod_s_h(cpu_env, twd, tws, twt);
29463 break;
29464 case DF_WORD:
29465 gen_helper_msa_mod_s_w(cpu_env, twd, tws, twt);
29466 break;
29467 case DF_DOUBLE:
29468 gen_helper_msa_mod_s_d(cpu_env, twd, tws, twt);
29469 break;
29471 break;
29472 case OPC_MOD_U_df:
29473 switch (df) {
29474 case DF_BYTE:
29475 gen_helper_msa_mod_u_b(cpu_env, twd, tws, twt);
29476 break;
29477 case DF_HALF:
29478 gen_helper_msa_mod_u_h(cpu_env, twd, tws, twt);
29479 break;
29480 case DF_WORD:
29481 gen_helper_msa_mod_u_w(cpu_env, twd, tws, twt);
29482 break;
29483 case DF_DOUBLE:
29484 gen_helper_msa_mod_u_d(cpu_env, twd, tws, twt);
29485 break;
29487 break;
29488 case OPC_MADDV_df:
29489 switch (df) {
29490 case DF_BYTE:
29491 gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
29492 break;
29493 case DF_HALF:
29494 gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
29495 break;
29496 case DF_WORD:
29497 gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
29498 break;
29499 case DF_DOUBLE:
29500 gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
29501 break;
29503 break;
29504 case OPC_MSUBV_df:
29505 switch (df) {
29506 case DF_BYTE:
29507 gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
29508 break;
29509 case DF_HALF:
29510 gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
29511 break;
29512 case DF_WORD:
29513 gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
29514 break;
29515 case DF_DOUBLE:
29516 gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
29517 break;
29519 break;
29520 case OPC_ASUB_S_df:
29521 switch (df) {
29522 case DF_BYTE:
29523 gen_helper_msa_asub_s_b(cpu_env, twd, tws, twt);
29524 break;
29525 case DF_HALF:
29526 gen_helper_msa_asub_s_h(cpu_env, twd, tws, twt);
29527 break;
29528 case DF_WORD:
29529 gen_helper_msa_asub_s_w(cpu_env, twd, tws, twt);
29530 break;
29531 case DF_DOUBLE:
29532 gen_helper_msa_asub_s_d(cpu_env, twd, tws, twt);
29533 break;
29535 break;
29536 case OPC_ASUB_U_df:
29537 switch (df) {
29538 case DF_BYTE:
29539 gen_helper_msa_asub_u_b(cpu_env, twd, tws, twt);
29540 break;
29541 case DF_HALF:
29542 gen_helper_msa_asub_u_h(cpu_env, twd, tws, twt);
29543 break;
29544 case DF_WORD:
29545 gen_helper_msa_asub_u_w(cpu_env, twd, tws, twt);
29546 break;
29547 case DF_DOUBLE:
29548 gen_helper_msa_asub_u_d(cpu_env, twd, tws, twt);
29549 break;
29551 break;
29552 case OPC_ILVEV_df:
29553 switch (df) {
29554 case DF_BYTE:
29555 gen_helper_msa_ilvev_b(cpu_env, twd, tws, twt);
29556 break;
29557 case DF_HALF:
29558 gen_helper_msa_ilvev_h(cpu_env, twd, tws, twt);
29559 break;
29560 case DF_WORD:
29561 gen_helper_msa_ilvev_w(cpu_env, twd, tws, twt);
29562 break;
29563 case DF_DOUBLE:
29564 gen_helper_msa_ilvev_d(cpu_env, twd, tws, twt);
29565 break;
29567 break;
29568 case OPC_ILVOD_df:
29569 switch (df) {
29570 case DF_BYTE:
29571 gen_helper_msa_ilvod_b(cpu_env, twd, tws, twt);
29572 break;
29573 case DF_HALF:
29574 gen_helper_msa_ilvod_h(cpu_env, twd, tws, twt);
29575 break;
29576 case DF_WORD:
29577 gen_helper_msa_ilvod_w(cpu_env, twd, tws, twt);
29578 break;
29579 case DF_DOUBLE:
29580 gen_helper_msa_ilvod_d(cpu_env, twd, tws, twt);
29581 break;
29583 break;
29584 case OPC_ILVL_df:
29585 switch (df) {
29586 case DF_BYTE:
29587 gen_helper_msa_ilvl_b(cpu_env, twd, tws, twt);
29588 break;
29589 case DF_HALF:
29590 gen_helper_msa_ilvl_h(cpu_env, twd, tws, twt);
29591 break;
29592 case DF_WORD:
29593 gen_helper_msa_ilvl_w(cpu_env, twd, tws, twt);
29594 break;
29595 case DF_DOUBLE:
29596 gen_helper_msa_ilvl_d(cpu_env, twd, tws, twt);
29597 break;
29599 break;
29600 case OPC_ILVR_df:
29601 switch (df) {
29602 case DF_BYTE:
29603 gen_helper_msa_ilvr_b(cpu_env, twd, tws, twt);
29604 break;
29605 case DF_HALF:
29606 gen_helper_msa_ilvr_h(cpu_env, twd, tws, twt);
29607 break;
29608 case DF_WORD:
29609 gen_helper_msa_ilvr_w(cpu_env, twd, tws, twt);
29610 break;
29611 case DF_DOUBLE:
29612 gen_helper_msa_ilvr_d(cpu_env, twd, tws, twt);
29613 break;
29615 break;
29616 case OPC_PCKEV_df:
29617 switch (df) {
29618 case DF_BYTE:
29619 gen_helper_msa_pckev_b(cpu_env, twd, tws, twt);
29620 break;
29621 case DF_HALF:
29622 gen_helper_msa_pckev_h(cpu_env, twd, tws, twt);
29623 break;
29624 case DF_WORD:
29625 gen_helper_msa_pckev_w(cpu_env, twd, tws, twt);
29626 break;
29627 case DF_DOUBLE:
29628 gen_helper_msa_pckev_d(cpu_env, twd, tws, twt);
29629 break;
29631 break;
29632 case OPC_PCKOD_df:
29633 switch (df) {
29634 case DF_BYTE:
29635 gen_helper_msa_pckod_b(cpu_env, twd, tws, twt);
29636 break;
29637 case DF_HALF:
29638 gen_helper_msa_pckod_h(cpu_env, twd, tws, twt);
29639 break;
29640 case DF_WORD:
29641 gen_helper_msa_pckod_w(cpu_env, twd, tws, twt);
29642 break;
29643 case DF_DOUBLE:
29644 gen_helper_msa_pckod_d(cpu_env, twd, tws, twt);
29645 break;
29647 break;
29648 case OPC_SLL_df:
29649 switch (df) {
29650 case DF_BYTE:
29651 gen_helper_msa_sll_b(cpu_env, twd, tws, twt);
29652 break;
29653 case DF_HALF:
29654 gen_helper_msa_sll_h(cpu_env, twd, tws, twt);
29655 break;
29656 case DF_WORD:
29657 gen_helper_msa_sll_w(cpu_env, twd, tws, twt);
29658 break;
29659 case DF_DOUBLE:
29660 gen_helper_msa_sll_d(cpu_env, twd, tws, twt);
29661 break;
29663 break;
29664 case OPC_SRA_df:
29665 switch (df) {
29666 case DF_BYTE:
29667 gen_helper_msa_sra_b(cpu_env, twd, tws, twt);
29668 break;
29669 case DF_HALF:
29670 gen_helper_msa_sra_h(cpu_env, twd, tws, twt);
29671 break;
29672 case DF_WORD:
29673 gen_helper_msa_sra_w(cpu_env, twd, tws, twt);
29674 break;
29675 case DF_DOUBLE:
29676 gen_helper_msa_sra_d(cpu_env, twd, tws, twt);
29677 break;
29679 break;
29680 case OPC_SRAR_df:
29681 switch (df) {
29682 case DF_BYTE:
29683 gen_helper_msa_srar_b(cpu_env, twd, tws, twt);
29684 break;
29685 case DF_HALF:
29686 gen_helper_msa_srar_h(cpu_env, twd, tws, twt);
29687 break;
29688 case DF_WORD:
29689 gen_helper_msa_srar_w(cpu_env, twd, tws, twt);
29690 break;
29691 case DF_DOUBLE:
29692 gen_helper_msa_srar_d(cpu_env, twd, tws, twt);
29693 break;
29695 break;
29696 case OPC_SRL_df:
29697 switch (df) {
29698 case DF_BYTE:
29699 gen_helper_msa_srl_b(cpu_env, twd, tws, twt);
29700 break;
29701 case DF_HALF:
29702 gen_helper_msa_srl_h(cpu_env, twd, tws, twt);
29703 break;
29704 case DF_WORD:
29705 gen_helper_msa_srl_w(cpu_env, twd, tws, twt);
29706 break;
29707 case DF_DOUBLE:
29708 gen_helper_msa_srl_d(cpu_env, twd, tws, twt);
29709 break;
29711 break;
29712 case OPC_SRLR_df:
29713 switch (df) {
29714 case DF_BYTE:
29715 gen_helper_msa_srlr_b(cpu_env, twd, tws, twt);
29716 break;
29717 case DF_HALF:
29718 gen_helper_msa_srlr_h(cpu_env, twd, tws, twt);
29719 break;
29720 case DF_WORD:
29721 gen_helper_msa_srlr_w(cpu_env, twd, tws, twt);
29722 break;
29723 case DF_DOUBLE:
29724 gen_helper_msa_srlr_d(cpu_env, twd, tws, twt);
29725 break;
29727 break;
29728 case OPC_SUBS_S_df:
29729 switch (df) {
29730 case DF_BYTE:
29731 gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
29732 break;
29733 case DF_HALF:
29734 gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
29735 break;
29736 case DF_WORD:
29737 gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
29738 break;
29739 case DF_DOUBLE:
29740 gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
29741 break;
29743 break;
29744 case OPC_MULV_df:
29745 switch (df) {
29746 case DF_BYTE:
29747 gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
29748 break;
29749 case DF_HALF:
29750 gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
29751 break;
29752 case DF_WORD:
29753 gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
29754 break;
29755 case DF_DOUBLE:
29756 gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
29757 break;
29759 break;
29760 case OPC_SLD_df:
29761 gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
29762 break;
29763 case OPC_VSHF_df:
29764 gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
29765 break;
29766 case OPC_SUBV_df:
29767 switch (df) {
29768 case DF_BYTE:
29769 gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
29770 break;
29771 case DF_HALF:
29772 gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
29773 break;
29774 case DF_WORD:
29775 gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
29776 break;
29777 case DF_DOUBLE:
29778 gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
29779 break;
29781 break;
29782 case OPC_SUBS_U_df:
29783 switch (df) {
29784 case DF_BYTE:
29785 gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
29786 break;
29787 case DF_HALF:
29788 gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
29789 break;
29790 case DF_WORD:
29791 gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
29792 break;
29793 case DF_DOUBLE:
29794 gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
29795 break;
29797 break;
29798 case OPC_SPLAT_df:
29799 gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
29800 break;
29801 case OPC_SUBSUS_U_df:
29802 switch (df) {
29803 case DF_BYTE:
29804 gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
29805 break;
29806 case DF_HALF:
29807 gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
29808 break;
29809 case DF_WORD:
29810 gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
29811 break;
29812 case DF_DOUBLE:
29813 gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
29814 break;
29816 break;
29817 case OPC_SUBSUU_S_df:
29818 switch (df) {
29819 case DF_BYTE:
29820 gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
29821 break;
29822 case DF_HALF:
29823 gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
29824 break;
29825 case DF_WORD:
29826 gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
29827 break;
29828 case DF_DOUBLE:
29829 gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
29830 break;
29832 break;
29834 case OPC_DOTP_S_df:
29835 case OPC_DOTP_U_df:
29836 case OPC_DPADD_S_df:
29837 case OPC_DPADD_U_df:
29838 case OPC_DPSUB_S_df:
29839 case OPC_HADD_S_df:
29840 case OPC_DPSUB_U_df:
29841 case OPC_HADD_U_df:
29842 case OPC_HSUB_S_df:
29843 case OPC_HSUB_U_df:
29844 if (df == DF_BYTE) {
29845 generate_exception_end(ctx, EXCP_RI);
29846 break;
29848 switch (MASK_MSA_3R(ctx->opcode)) {
29849 case OPC_HADD_S_df:
29850 switch (df) {
29851 case DF_HALF:
29852 gen_helper_msa_hadd_s_h(cpu_env, twd, tws, twt);
29853 break;
29854 case DF_WORD:
29855 gen_helper_msa_hadd_s_w(cpu_env, twd, tws, twt);
29856 break;
29857 case DF_DOUBLE:
29858 gen_helper_msa_hadd_s_d(cpu_env, twd, tws, twt);
29859 break;
29861 break;
29862 case OPC_HADD_U_df:
29863 switch (df) {
29864 case DF_HALF:
29865 gen_helper_msa_hadd_u_h(cpu_env, twd, tws, twt);
29866 break;
29867 case DF_WORD:
29868 gen_helper_msa_hadd_u_w(cpu_env, twd, tws, twt);
29869 break;
29870 case DF_DOUBLE:
29871 gen_helper_msa_hadd_u_d(cpu_env, twd, tws, twt);
29872 break;
29874 break;
29875 case OPC_HSUB_S_df:
29876 switch (df) {
29877 case DF_HALF:
29878 gen_helper_msa_hsub_s_h(cpu_env, twd, tws, twt);
29879 break;
29880 case DF_WORD:
29881 gen_helper_msa_hsub_s_w(cpu_env, twd, tws, twt);
29882 break;
29883 case DF_DOUBLE:
29884 gen_helper_msa_hsub_s_d(cpu_env, twd, tws, twt);
29885 break;
29887 break;
29888 case OPC_HSUB_U_df:
29889 switch (df) {
29890 case DF_HALF:
29891 gen_helper_msa_hsub_u_h(cpu_env, twd, tws, twt);
29892 break;
29893 case DF_WORD:
29894 gen_helper_msa_hsub_u_w(cpu_env, twd, tws, twt);
29895 break;
29896 case DF_DOUBLE:
29897 gen_helper_msa_hsub_u_d(cpu_env, twd, tws, twt);
29898 break;
29900 break;
29901 case OPC_DOTP_S_df:
29902 switch (df) {
29903 case DF_HALF:
29904 gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
29905 break;
29906 case DF_WORD:
29907 gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
29908 break;
29909 case DF_DOUBLE:
29910 gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
29911 break;
29913 break;
29914 case OPC_DOTP_U_df:
29915 switch (df) {
29916 case DF_HALF:
29917 gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
29918 break;
29919 case DF_WORD:
29920 gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
29921 break;
29922 case DF_DOUBLE:
29923 gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
29924 break;
29926 break;
29927 case OPC_DPADD_S_df:
29928 switch (df) {
29929 case DF_HALF:
29930 gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
29931 break;
29932 case DF_WORD:
29933 gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
29934 break;
29935 case DF_DOUBLE:
29936 gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
29937 break;
29939 break;
29940 case OPC_DPADD_U_df:
29941 switch (df) {
29942 case DF_HALF:
29943 gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
29944 break;
29945 case DF_WORD:
29946 gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
29947 break;
29948 case DF_DOUBLE:
29949 gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
29950 break;
29952 break;
29953 case OPC_DPSUB_S_df:
29954 switch (df) {
29955 case DF_HALF:
29956 gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
29957 break;
29958 case DF_WORD:
29959 gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
29960 break;
29961 case DF_DOUBLE:
29962 gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
29963 break;
29965 break;
29966 case OPC_DPSUB_U_df:
29967 switch (df) {
29968 case DF_HALF:
29969 gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
29970 break;
29971 case DF_WORD:
29972 gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
29973 break;
29974 case DF_DOUBLE:
29975 gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
29976 break;
29978 break;
29980 break;
29981 default:
29982 MIPS_INVAL("MSA instruction");
29983 generate_exception_end(ctx, EXCP_RI);
29984 break;
29986 tcg_temp_free_i32(twd);
29987 tcg_temp_free_i32(tws);
29988 tcg_temp_free_i32(twt);
29989 tcg_temp_free_i32(tdf);
29992 static void gen_msa_elm_3e(CPUMIPSState *env, DisasContext *ctx)
29994 #define MASK_MSA_ELM_DF3E(op) (MASK_MSA_MINOR(op) | (op & (0x3FF << 16)))
29995 uint8_t source = (ctx->opcode >> 11) & 0x1f;
29996 uint8_t dest = (ctx->opcode >> 6) & 0x1f;
29997 TCGv telm = tcg_temp_new();
29998 TCGv_i32 tsr = tcg_const_i32(source);
29999 TCGv_i32 tdt = tcg_const_i32(dest);
30001 switch (MASK_MSA_ELM_DF3E(ctx->opcode)) {
30002 case OPC_CTCMSA:
30003 gen_load_gpr(telm, source);
30004 gen_helper_msa_ctcmsa(cpu_env, telm, tdt);
30005 break;
30006 case OPC_CFCMSA:
30007 gen_helper_msa_cfcmsa(telm, cpu_env, tsr);
30008 gen_store_gpr(telm, dest);
30009 break;
30010 case OPC_MOVE_V:
30011 gen_helper_msa_move_v(cpu_env, tdt, tsr);
30012 break;
30013 default:
30014 MIPS_INVAL("MSA instruction");
30015 generate_exception_end(ctx, EXCP_RI);
30016 break;
30019 tcg_temp_free(telm);
30020 tcg_temp_free_i32(tdt);
30021 tcg_temp_free_i32(tsr);
30024 static void gen_msa_elm_df(CPUMIPSState *env, DisasContext *ctx, uint32_t df,
30025 uint32_t n)
30027 #define MASK_MSA_ELM(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30028 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30029 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30031 TCGv_i32 tws = tcg_const_i32(ws);
30032 TCGv_i32 twd = tcg_const_i32(wd);
30033 TCGv_i32 tn = tcg_const_i32(n);
30034 TCGv_i32 tdf = tcg_const_i32(df);
30036 switch (MASK_MSA_ELM(ctx->opcode)) {
30037 case OPC_SLDI_df:
30038 gen_helper_msa_sldi_df(cpu_env, tdf, twd, tws, tn);
30039 break;
30040 case OPC_SPLATI_df:
30041 gen_helper_msa_splati_df(cpu_env, tdf, twd, tws, tn);
30042 break;
30043 case OPC_INSVE_df:
30044 gen_helper_msa_insve_df(cpu_env, tdf, twd, tws, tn);
30045 break;
30046 case OPC_COPY_S_df:
30047 case OPC_COPY_U_df:
30048 case OPC_INSERT_df:
30049 #if !defined(TARGET_MIPS64)
30050 /* Double format valid only for MIPS64 */
30051 if (df == DF_DOUBLE) {
30052 generate_exception_end(ctx, EXCP_RI);
30053 break;
30055 if ((MASK_MSA_ELM(ctx->opcode) == OPC_COPY_U_df) &&
30056 (df == DF_WORD)) {
30057 generate_exception_end(ctx, EXCP_RI);
30058 break;
30060 #endif
30061 switch (MASK_MSA_ELM(ctx->opcode)) {
30062 case OPC_COPY_S_df:
30063 if (likely(wd != 0)) {
30064 switch (df) {
30065 case DF_BYTE:
30066 gen_helper_msa_copy_s_b(cpu_env, twd, tws, tn);
30067 break;
30068 case DF_HALF:
30069 gen_helper_msa_copy_s_h(cpu_env, twd, tws, tn);
30070 break;
30071 case DF_WORD:
30072 gen_helper_msa_copy_s_w(cpu_env, twd, tws, tn);
30073 break;
30074 #if defined(TARGET_MIPS64)
30075 case DF_DOUBLE:
30076 gen_helper_msa_copy_s_d(cpu_env, twd, tws, tn);
30077 break;
30078 #endif
30079 default:
30080 assert(0);
30083 break;
30084 case OPC_COPY_U_df:
30085 if (likely(wd != 0)) {
30086 switch (df) {
30087 case DF_BYTE:
30088 gen_helper_msa_copy_u_b(cpu_env, twd, tws, tn);
30089 break;
30090 case DF_HALF:
30091 gen_helper_msa_copy_u_h(cpu_env, twd, tws, tn);
30092 break;
30093 #if defined(TARGET_MIPS64)
30094 case DF_WORD:
30095 gen_helper_msa_copy_u_w(cpu_env, twd, tws, tn);
30096 break;
30097 #endif
30098 default:
30099 assert(0);
30102 break;
30103 case OPC_INSERT_df:
30104 switch (df) {
30105 case DF_BYTE:
30106 gen_helper_msa_insert_b(cpu_env, twd, tws, tn);
30107 break;
30108 case DF_HALF:
30109 gen_helper_msa_insert_h(cpu_env, twd, tws, tn);
30110 break;
30111 case DF_WORD:
30112 gen_helper_msa_insert_w(cpu_env, twd, tws, tn);
30113 break;
30114 #if defined(TARGET_MIPS64)
30115 case DF_DOUBLE:
30116 gen_helper_msa_insert_d(cpu_env, twd, tws, tn);
30117 break;
30118 #endif
30119 default:
30120 assert(0);
30122 break;
30124 break;
30125 default:
30126 MIPS_INVAL("MSA instruction");
30127 generate_exception_end(ctx, EXCP_RI);
30129 tcg_temp_free_i32(twd);
30130 tcg_temp_free_i32(tws);
30131 tcg_temp_free_i32(tn);
30132 tcg_temp_free_i32(tdf);
30135 static void gen_msa_elm(CPUMIPSState *env, DisasContext *ctx)
30137 uint8_t dfn = (ctx->opcode >> 16) & 0x3f;
30138 uint32_t df = 0, n = 0;
30140 if ((dfn & 0x30) == 0x00) {
30141 n = dfn & 0x0f;
30142 df = DF_BYTE;
30143 } else if ((dfn & 0x38) == 0x20) {
30144 n = dfn & 0x07;
30145 df = DF_HALF;
30146 } else if ((dfn & 0x3c) == 0x30) {
30147 n = dfn & 0x03;
30148 df = DF_WORD;
30149 } else if ((dfn & 0x3e) == 0x38) {
30150 n = dfn & 0x01;
30151 df = DF_DOUBLE;
30152 } else if (dfn == 0x3E) {
30153 /* CTCMSA, CFCMSA, MOVE.V */
30154 gen_msa_elm_3e(env, ctx);
30155 return;
30156 } else {
30157 generate_exception_end(ctx, EXCP_RI);
30158 return;
30161 gen_msa_elm_df(env, ctx, df, n);
30164 static void gen_msa_3rf(CPUMIPSState *env, DisasContext *ctx)
30166 #define MASK_MSA_3RF(op) (MASK_MSA_MINOR(op) | (op & (0xf << 22)))
30167 uint8_t df = (ctx->opcode >> 21) & 0x1;
30168 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30169 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30170 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30172 TCGv_i32 twd = tcg_const_i32(wd);
30173 TCGv_i32 tws = tcg_const_i32(ws);
30174 TCGv_i32 twt = tcg_const_i32(wt);
30175 TCGv_i32 tdf = tcg_temp_new_i32();
30177 /* adjust df value for floating-point instruction */
30178 tcg_gen_movi_i32(tdf, df + 2);
30180 switch (MASK_MSA_3RF(ctx->opcode)) {
30181 case OPC_FCAF_df:
30182 gen_helper_msa_fcaf_df(cpu_env, tdf, twd, tws, twt);
30183 break;
30184 case OPC_FADD_df:
30185 gen_helper_msa_fadd_df(cpu_env, tdf, twd, tws, twt);
30186 break;
30187 case OPC_FCUN_df:
30188 gen_helper_msa_fcun_df(cpu_env, tdf, twd, tws, twt);
30189 break;
30190 case OPC_FSUB_df:
30191 gen_helper_msa_fsub_df(cpu_env, tdf, twd, tws, twt);
30192 break;
30193 case OPC_FCOR_df:
30194 gen_helper_msa_fcor_df(cpu_env, tdf, twd, tws, twt);
30195 break;
30196 case OPC_FCEQ_df:
30197 gen_helper_msa_fceq_df(cpu_env, tdf, twd, tws, twt);
30198 break;
30199 case OPC_FMUL_df:
30200 gen_helper_msa_fmul_df(cpu_env, tdf, twd, tws, twt);
30201 break;
30202 case OPC_FCUNE_df:
30203 gen_helper_msa_fcune_df(cpu_env, tdf, twd, tws, twt);
30204 break;
30205 case OPC_FCUEQ_df:
30206 gen_helper_msa_fcueq_df(cpu_env, tdf, twd, tws, twt);
30207 break;
30208 case OPC_FDIV_df:
30209 gen_helper_msa_fdiv_df(cpu_env, tdf, twd, tws, twt);
30210 break;
30211 case OPC_FCNE_df:
30212 gen_helper_msa_fcne_df(cpu_env, tdf, twd, tws, twt);
30213 break;
30214 case OPC_FCLT_df:
30215 gen_helper_msa_fclt_df(cpu_env, tdf, twd, tws, twt);
30216 break;
30217 case OPC_FMADD_df:
30218 gen_helper_msa_fmadd_df(cpu_env, tdf, twd, tws, twt);
30219 break;
30220 case OPC_MUL_Q_df:
30221 tcg_gen_movi_i32(tdf, df + 1);
30222 gen_helper_msa_mul_q_df(cpu_env, tdf, twd, tws, twt);
30223 break;
30224 case OPC_FCULT_df:
30225 gen_helper_msa_fcult_df(cpu_env, tdf, twd, tws, twt);
30226 break;
30227 case OPC_FMSUB_df:
30228 gen_helper_msa_fmsub_df(cpu_env, tdf, twd, tws, twt);
30229 break;
30230 case OPC_MADD_Q_df:
30231 tcg_gen_movi_i32(tdf, df + 1);
30232 gen_helper_msa_madd_q_df(cpu_env, tdf, twd, tws, twt);
30233 break;
30234 case OPC_FCLE_df:
30235 gen_helper_msa_fcle_df(cpu_env, tdf, twd, tws, twt);
30236 break;
30237 case OPC_MSUB_Q_df:
30238 tcg_gen_movi_i32(tdf, df + 1);
30239 gen_helper_msa_msub_q_df(cpu_env, tdf, twd, tws, twt);
30240 break;
30241 case OPC_FCULE_df:
30242 gen_helper_msa_fcule_df(cpu_env, tdf, twd, tws, twt);
30243 break;
30244 case OPC_FEXP2_df:
30245 gen_helper_msa_fexp2_df(cpu_env, tdf, twd, tws, twt);
30246 break;
30247 case OPC_FSAF_df:
30248 gen_helper_msa_fsaf_df(cpu_env, tdf, twd, tws, twt);
30249 break;
30250 case OPC_FEXDO_df:
30251 gen_helper_msa_fexdo_df(cpu_env, tdf, twd, tws, twt);
30252 break;
30253 case OPC_FSUN_df:
30254 gen_helper_msa_fsun_df(cpu_env, tdf, twd, tws, twt);
30255 break;
30256 case OPC_FSOR_df:
30257 gen_helper_msa_fsor_df(cpu_env, tdf, twd, tws, twt);
30258 break;
30259 case OPC_FSEQ_df:
30260 gen_helper_msa_fseq_df(cpu_env, tdf, twd, tws, twt);
30261 break;
30262 case OPC_FTQ_df:
30263 gen_helper_msa_ftq_df(cpu_env, tdf, twd, tws, twt);
30264 break;
30265 case OPC_FSUNE_df:
30266 gen_helper_msa_fsune_df(cpu_env, tdf, twd, tws, twt);
30267 break;
30268 case OPC_FSUEQ_df:
30269 gen_helper_msa_fsueq_df(cpu_env, tdf, twd, tws, twt);
30270 break;
30271 case OPC_FSNE_df:
30272 gen_helper_msa_fsne_df(cpu_env, tdf, twd, tws, twt);
30273 break;
30274 case OPC_FSLT_df:
30275 gen_helper_msa_fslt_df(cpu_env, tdf, twd, tws, twt);
30276 break;
30277 case OPC_FMIN_df:
30278 gen_helper_msa_fmin_df(cpu_env, tdf, twd, tws, twt);
30279 break;
30280 case OPC_MULR_Q_df:
30281 tcg_gen_movi_i32(tdf, df + 1);
30282 gen_helper_msa_mulr_q_df(cpu_env, tdf, twd, tws, twt);
30283 break;
30284 case OPC_FSULT_df:
30285 gen_helper_msa_fsult_df(cpu_env, tdf, twd, tws, twt);
30286 break;
30287 case OPC_FMIN_A_df:
30288 gen_helper_msa_fmin_a_df(cpu_env, tdf, twd, tws, twt);
30289 break;
30290 case OPC_MADDR_Q_df:
30291 tcg_gen_movi_i32(tdf, df + 1);
30292 gen_helper_msa_maddr_q_df(cpu_env, tdf, twd, tws, twt);
30293 break;
30294 case OPC_FSLE_df:
30295 gen_helper_msa_fsle_df(cpu_env, tdf, twd, tws, twt);
30296 break;
30297 case OPC_FMAX_df:
30298 gen_helper_msa_fmax_df(cpu_env, tdf, twd, tws, twt);
30299 break;
30300 case OPC_MSUBR_Q_df:
30301 tcg_gen_movi_i32(tdf, df + 1);
30302 gen_helper_msa_msubr_q_df(cpu_env, tdf, twd, tws, twt);
30303 break;
30304 case OPC_FSULE_df:
30305 gen_helper_msa_fsule_df(cpu_env, tdf, twd, tws, twt);
30306 break;
30307 case OPC_FMAX_A_df:
30308 gen_helper_msa_fmax_a_df(cpu_env, tdf, twd, tws, twt);
30309 break;
30310 default:
30311 MIPS_INVAL("MSA instruction");
30312 generate_exception_end(ctx, EXCP_RI);
30313 break;
30316 tcg_temp_free_i32(twd);
30317 tcg_temp_free_i32(tws);
30318 tcg_temp_free_i32(twt);
30319 tcg_temp_free_i32(tdf);
30322 static void gen_msa_2r(CPUMIPSState *env, DisasContext *ctx)
30324 #define MASK_MSA_2R(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30325 (op & (0x7 << 18)))
30326 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30327 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30328 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30329 uint8_t df = (ctx->opcode >> 16) & 0x3;
30330 TCGv_i32 twd = tcg_const_i32(wd);
30331 TCGv_i32 tws = tcg_const_i32(ws);
30332 TCGv_i32 twt = tcg_const_i32(wt);
30333 TCGv_i32 tdf = tcg_const_i32(df);
30335 switch (MASK_MSA_2R(ctx->opcode)) {
30336 case OPC_FILL_df:
30337 #if !defined(TARGET_MIPS64)
30338 /* Double format valid only for MIPS64 */
30339 if (df == DF_DOUBLE) {
30340 generate_exception_end(ctx, EXCP_RI);
30341 break;
30343 #endif
30344 gen_helper_msa_fill_df(cpu_env, tdf, twd, tws); /* trs */
30345 break;
30346 case OPC_NLOC_df:
30347 switch (df) {
30348 case DF_BYTE:
30349 gen_helper_msa_nloc_b(cpu_env, twd, tws);
30350 break;
30351 case DF_HALF:
30352 gen_helper_msa_nloc_h(cpu_env, twd, tws);
30353 break;
30354 case DF_WORD:
30355 gen_helper_msa_nloc_w(cpu_env, twd, tws);
30356 break;
30357 case DF_DOUBLE:
30358 gen_helper_msa_nloc_d(cpu_env, twd, tws);
30359 break;
30361 break;
30362 case OPC_NLZC_df:
30363 switch (df) {
30364 case DF_BYTE:
30365 gen_helper_msa_nlzc_b(cpu_env, twd, tws);
30366 break;
30367 case DF_HALF:
30368 gen_helper_msa_nlzc_h(cpu_env, twd, tws);
30369 break;
30370 case DF_WORD:
30371 gen_helper_msa_nlzc_w(cpu_env, twd, tws);
30372 break;
30373 case DF_DOUBLE:
30374 gen_helper_msa_nlzc_d(cpu_env, twd, tws);
30375 break;
30377 break;
30378 case OPC_PCNT_df:
30379 switch (df) {
30380 case DF_BYTE:
30381 gen_helper_msa_pcnt_b(cpu_env, twd, tws);
30382 break;
30383 case DF_HALF:
30384 gen_helper_msa_pcnt_h(cpu_env, twd, tws);
30385 break;
30386 case DF_WORD:
30387 gen_helper_msa_pcnt_w(cpu_env, twd, tws);
30388 break;
30389 case DF_DOUBLE:
30390 gen_helper_msa_pcnt_d(cpu_env, twd, tws);
30391 break;
30393 break;
30394 default:
30395 MIPS_INVAL("MSA instruction");
30396 generate_exception_end(ctx, EXCP_RI);
30397 break;
30400 tcg_temp_free_i32(twd);
30401 tcg_temp_free_i32(tws);
30402 tcg_temp_free_i32(twt);
30403 tcg_temp_free_i32(tdf);
30406 static void gen_msa_2rf(CPUMIPSState *env, DisasContext *ctx)
30408 #define MASK_MSA_2RF(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)) | \
30409 (op & (0xf << 17)))
30410 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30411 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30412 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30413 uint8_t df = (ctx->opcode >> 16) & 0x1;
30414 TCGv_i32 twd = tcg_const_i32(wd);
30415 TCGv_i32 tws = tcg_const_i32(ws);
30416 TCGv_i32 twt = tcg_const_i32(wt);
30417 /* adjust df value for floating-point instruction */
30418 TCGv_i32 tdf = tcg_const_i32(df + 2);
30420 switch (MASK_MSA_2RF(ctx->opcode)) {
30421 case OPC_FCLASS_df:
30422 gen_helper_msa_fclass_df(cpu_env, tdf, twd, tws);
30423 break;
30424 case OPC_FTRUNC_S_df:
30425 gen_helper_msa_ftrunc_s_df(cpu_env, tdf, twd, tws);
30426 break;
30427 case OPC_FTRUNC_U_df:
30428 gen_helper_msa_ftrunc_u_df(cpu_env, tdf, twd, tws);
30429 break;
30430 case OPC_FSQRT_df:
30431 gen_helper_msa_fsqrt_df(cpu_env, tdf, twd, tws);
30432 break;
30433 case OPC_FRSQRT_df:
30434 gen_helper_msa_frsqrt_df(cpu_env, tdf, twd, tws);
30435 break;
30436 case OPC_FRCP_df:
30437 gen_helper_msa_frcp_df(cpu_env, tdf, twd, tws);
30438 break;
30439 case OPC_FRINT_df:
30440 gen_helper_msa_frint_df(cpu_env, tdf, twd, tws);
30441 break;
30442 case OPC_FLOG2_df:
30443 gen_helper_msa_flog2_df(cpu_env, tdf, twd, tws);
30444 break;
30445 case OPC_FEXUPL_df:
30446 gen_helper_msa_fexupl_df(cpu_env, tdf, twd, tws);
30447 break;
30448 case OPC_FEXUPR_df:
30449 gen_helper_msa_fexupr_df(cpu_env, tdf, twd, tws);
30450 break;
30451 case OPC_FFQL_df:
30452 gen_helper_msa_ffql_df(cpu_env, tdf, twd, tws);
30453 break;
30454 case OPC_FFQR_df:
30455 gen_helper_msa_ffqr_df(cpu_env, tdf, twd, tws);
30456 break;
30457 case OPC_FTINT_S_df:
30458 gen_helper_msa_ftint_s_df(cpu_env, tdf, twd, tws);
30459 break;
30460 case OPC_FTINT_U_df:
30461 gen_helper_msa_ftint_u_df(cpu_env, tdf, twd, tws);
30462 break;
30463 case OPC_FFINT_S_df:
30464 gen_helper_msa_ffint_s_df(cpu_env, tdf, twd, tws);
30465 break;
30466 case OPC_FFINT_U_df:
30467 gen_helper_msa_ffint_u_df(cpu_env, tdf, twd, tws);
30468 break;
30471 tcg_temp_free_i32(twd);
30472 tcg_temp_free_i32(tws);
30473 tcg_temp_free_i32(twt);
30474 tcg_temp_free_i32(tdf);
30477 static void gen_msa_vec_v(CPUMIPSState *env, DisasContext *ctx)
30479 #define MASK_MSA_VEC(op) (MASK_MSA_MINOR(op) | (op & (0x1f << 21)))
30480 uint8_t wt = (ctx->opcode >> 16) & 0x1f;
30481 uint8_t ws = (ctx->opcode >> 11) & 0x1f;
30482 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30483 TCGv_i32 twd = tcg_const_i32(wd);
30484 TCGv_i32 tws = tcg_const_i32(ws);
30485 TCGv_i32 twt = tcg_const_i32(wt);
30487 switch (MASK_MSA_VEC(ctx->opcode)) {
30488 case OPC_AND_V:
30489 gen_helper_msa_and_v(cpu_env, twd, tws, twt);
30490 break;
30491 case OPC_OR_V:
30492 gen_helper_msa_or_v(cpu_env, twd, tws, twt);
30493 break;
30494 case OPC_NOR_V:
30495 gen_helper_msa_nor_v(cpu_env, twd, tws, twt);
30496 break;
30497 case OPC_XOR_V:
30498 gen_helper_msa_xor_v(cpu_env, twd, tws, twt);
30499 break;
30500 case OPC_BMNZ_V:
30501 gen_helper_msa_bmnz_v(cpu_env, twd, tws, twt);
30502 break;
30503 case OPC_BMZ_V:
30504 gen_helper_msa_bmz_v(cpu_env, twd, tws, twt);
30505 break;
30506 case OPC_BSEL_V:
30507 gen_helper_msa_bsel_v(cpu_env, twd, tws, twt);
30508 break;
30509 default:
30510 MIPS_INVAL("MSA instruction");
30511 generate_exception_end(ctx, EXCP_RI);
30512 break;
30515 tcg_temp_free_i32(twd);
30516 tcg_temp_free_i32(tws);
30517 tcg_temp_free_i32(twt);
30520 static void gen_msa_vec(CPUMIPSState *env, DisasContext *ctx)
30522 switch (MASK_MSA_VEC(ctx->opcode)) {
30523 case OPC_AND_V:
30524 case OPC_OR_V:
30525 case OPC_NOR_V:
30526 case OPC_XOR_V:
30527 case OPC_BMNZ_V:
30528 case OPC_BMZ_V:
30529 case OPC_BSEL_V:
30530 gen_msa_vec_v(env, ctx);
30531 break;
30532 case OPC_MSA_2R:
30533 gen_msa_2r(env, ctx);
30534 break;
30535 case OPC_MSA_2RF:
30536 gen_msa_2rf(env, ctx);
30537 break;
30538 default:
30539 MIPS_INVAL("MSA instruction");
30540 generate_exception_end(ctx, EXCP_RI);
30541 break;
30545 static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
30547 uint32_t opcode = ctx->opcode;
30548 check_insn(ctx, ASE_MSA);
30549 check_msa_access(ctx);
30551 switch (MASK_MSA_MINOR(opcode)) {
30552 case OPC_MSA_I8_00:
30553 case OPC_MSA_I8_01:
30554 case OPC_MSA_I8_02:
30555 gen_msa_i8(env, ctx);
30556 break;
30557 case OPC_MSA_I5_06:
30558 case OPC_MSA_I5_07:
30559 gen_msa_i5(env, ctx);
30560 break;
30561 case OPC_MSA_BIT_09:
30562 case OPC_MSA_BIT_0A:
30563 gen_msa_bit(env, ctx);
30564 break;
30565 case OPC_MSA_3R_0D:
30566 case OPC_MSA_3R_0E:
30567 case OPC_MSA_3R_0F:
30568 case OPC_MSA_3R_10:
30569 case OPC_MSA_3R_11:
30570 case OPC_MSA_3R_12:
30571 case OPC_MSA_3R_13:
30572 case OPC_MSA_3R_14:
30573 case OPC_MSA_3R_15:
30574 gen_msa_3r(env, ctx);
30575 break;
30576 case OPC_MSA_ELM:
30577 gen_msa_elm(env, ctx);
30578 break;
30579 case OPC_MSA_3RF_1A:
30580 case OPC_MSA_3RF_1B:
30581 case OPC_MSA_3RF_1C:
30582 gen_msa_3rf(env, ctx);
30583 break;
30584 case OPC_MSA_VEC:
30585 gen_msa_vec(env, ctx);
30586 break;
30587 case OPC_LD_B:
30588 case OPC_LD_H:
30589 case OPC_LD_W:
30590 case OPC_LD_D:
30591 case OPC_ST_B:
30592 case OPC_ST_H:
30593 case OPC_ST_W:
30594 case OPC_ST_D:
30596 int32_t s10 = sextract32(ctx->opcode, 16, 10);
30597 uint8_t rs = (ctx->opcode >> 11) & 0x1f;
30598 uint8_t wd = (ctx->opcode >> 6) & 0x1f;
30599 uint8_t df = (ctx->opcode >> 0) & 0x3;
30601 TCGv_i32 twd = tcg_const_i32(wd);
30602 TCGv taddr = tcg_temp_new();
30603 gen_base_offset_addr(ctx, taddr, rs, s10 << df);
30605 switch (MASK_MSA_MINOR(opcode)) {
30606 case OPC_LD_B:
30607 gen_helper_msa_ld_b(cpu_env, twd, taddr);
30608 break;
30609 case OPC_LD_H:
30610 gen_helper_msa_ld_h(cpu_env, twd, taddr);
30611 break;
30612 case OPC_LD_W:
30613 gen_helper_msa_ld_w(cpu_env, twd, taddr);
30614 break;
30615 case OPC_LD_D:
30616 gen_helper_msa_ld_d(cpu_env, twd, taddr);
30617 break;
30618 case OPC_ST_B:
30619 gen_helper_msa_st_b(cpu_env, twd, taddr);
30620 break;
30621 case OPC_ST_H:
30622 gen_helper_msa_st_h(cpu_env, twd, taddr);
30623 break;
30624 case OPC_ST_W:
30625 gen_helper_msa_st_w(cpu_env, twd, taddr);
30626 break;
30627 case OPC_ST_D:
30628 gen_helper_msa_st_d(cpu_env, twd, taddr);
30629 break;
30632 tcg_temp_free_i32(twd);
30633 tcg_temp_free(taddr);
30635 break;
30636 default:
30637 MIPS_INVAL("MSA instruction");
30638 generate_exception_end(ctx, EXCP_RI);
30639 break;
30644 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
30646 int32_t offset;
30647 int rs, rt, rd, sa;
30648 uint32_t op, op1;
30649 int16_t imm;
30651 /* make sure instructions are on a word boundary */
30652 if (ctx->base.pc_next & 0x3) {
30653 env->CP0_BadVAddr = ctx->base.pc_next;
30654 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
30655 return;
30658 /* Handle blikely not taken case */
30659 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
30660 TCGLabel *l1 = gen_new_label();
30662 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
30663 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
30664 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
30665 gen_set_label(l1);
30668 op = MASK_OP_MAJOR(ctx->opcode);
30669 rs = (ctx->opcode >> 21) & 0x1f;
30670 rt = (ctx->opcode >> 16) & 0x1f;
30671 rd = (ctx->opcode >> 11) & 0x1f;
30672 sa = (ctx->opcode >> 6) & 0x1f;
30673 imm = (int16_t)ctx->opcode;
30674 switch (op) {
30675 case OPC_SPECIAL:
30676 decode_opc_special(env, ctx);
30677 break;
30678 case OPC_SPECIAL2:
30679 #if defined(TARGET_MIPS64)
30680 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
30681 decode_mmi(env, ctx);
30682 #else
30683 if (ctx->insn_flags & ASE_MXU) {
30684 decode_opc_mxu(env, ctx);
30685 #endif
30686 } else {
30687 decode_opc_special2_legacy(env, ctx);
30689 break;
30690 case OPC_SPECIAL3:
30691 #if defined(TARGET_MIPS64)
30692 if (ctx->insn_flags & INSN_R5900) {
30693 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
30694 } else {
30695 decode_opc_special3(env, ctx);
30697 #else
30698 decode_opc_special3(env, ctx);
30699 #endif
30700 break;
30701 case OPC_REGIMM:
30702 op1 = MASK_REGIMM(ctx->opcode);
30703 switch (op1) {
30704 case OPC_BLTZL: /* REGIMM branches */
30705 case OPC_BGEZL:
30706 case OPC_BLTZALL:
30707 case OPC_BGEZALL:
30708 check_insn(ctx, ISA_MIPS2);
30709 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30710 /* Fallthrough */
30711 case OPC_BLTZ:
30712 case OPC_BGEZ:
30713 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30714 break;
30715 case OPC_BLTZAL:
30716 case OPC_BGEZAL:
30717 if (ctx->insn_flags & ISA_MIPS32R6) {
30718 if (rs == 0) {
30719 /* OPC_NAL, OPC_BAL */
30720 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
30721 } else {
30722 generate_exception_end(ctx, EXCP_RI);
30724 } else {
30725 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
30727 break;
30728 case OPC_TGEI: /* REGIMM traps */
30729 case OPC_TGEIU:
30730 case OPC_TLTI:
30731 case OPC_TLTIU:
30732 case OPC_TEQI:
30734 case OPC_TNEI:
30735 check_insn(ctx, ISA_MIPS2);
30736 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30737 gen_trap(ctx, op1, rs, -1, imm);
30738 break;
30739 case OPC_SIGRIE:
30740 check_insn(ctx, ISA_MIPS32R6);
30741 generate_exception_end(ctx, EXCP_RI);
30742 break;
30743 case OPC_SYNCI:
30744 check_insn(ctx, ISA_MIPS32R2);
30746 * Break the TB to be able to sync copied instructions
30747 * immediately.
30749 ctx->base.is_jmp = DISAS_STOP;
30750 break;
30751 case OPC_BPOSGE32: /* MIPS DSP branch */
30752 #if defined(TARGET_MIPS64)
30753 case OPC_BPOSGE64:
30754 #endif
30755 check_dsp(ctx);
30756 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
30757 break;
30758 #if defined(TARGET_MIPS64)
30759 case OPC_DAHI:
30760 check_insn(ctx, ISA_MIPS32R6);
30761 check_mips_64(ctx);
30762 if (rs != 0) {
30763 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
30765 break;
30766 case OPC_DATI:
30767 check_insn(ctx, ISA_MIPS32R6);
30768 check_mips_64(ctx);
30769 if (rs != 0) {
30770 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
30772 break;
30773 #endif
30774 default: /* Invalid */
30775 MIPS_INVAL("regimm");
30776 generate_exception_end(ctx, EXCP_RI);
30777 break;
30779 break;
30780 case OPC_CP0:
30781 check_cp0_enabled(ctx);
30782 op1 = MASK_CP0(ctx->opcode);
30783 switch (op1) {
30784 case OPC_MFC0:
30785 case OPC_MTC0:
30786 case OPC_MFTR:
30787 case OPC_MTTR:
30788 case OPC_MFHC0:
30789 case OPC_MTHC0:
30790 #if defined(TARGET_MIPS64)
30791 case OPC_DMFC0:
30792 case OPC_DMTC0:
30793 #endif
30794 #ifndef CONFIG_USER_ONLY
30795 gen_cp0(env, ctx, op1, rt, rd);
30796 #endif /* !CONFIG_USER_ONLY */
30797 break;
30798 case OPC_C0:
30799 case OPC_C0_1:
30800 case OPC_C0_2:
30801 case OPC_C0_3:
30802 case OPC_C0_4:
30803 case OPC_C0_5:
30804 case OPC_C0_6:
30805 case OPC_C0_7:
30806 case OPC_C0_8:
30807 case OPC_C0_9:
30808 case OPC_C0_A:
30809 case OPC_C0_B:
30810 case OPC_C0_C:
30811 case OPC_C0_D:
30812 case OPC_C0_E:
30813 case OPC_C0_F:
30814 #ifndef CONFIG_USER_ONLY
30815 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
30816 #endif /* !CONFIG_USER_ONLY */
30817 break;
30818 case OPC_MFMC0:
30819 #ifndef CONFIG_USER_ONLY
30821 uint32_t op2;
30822 TCGv t0 = tcg_temp_new();
30824 op2 = MASK_MFMC0(ctx->opcode);
30825 switch (op2) {
30826 case OPC_DMT:
30827 check_cp0_mt(ctx);
30828 gen_helper_dmt(t0);
30829 gen_store_gpr(t0, rt);
30830 break;
30831 case OPC_EMT:
30832 check_cp0_mt(ctx);
30833 gen_helper_emt(t0);
30834 gen_store_gpr(t0, rt);
30835 break;
30836 case OPC_DVPE:
30837 check_cp0_mt(ctx);
30838 gen_helper_dvpe(t0, cpu_env);
30839 gen_store_gpr(t0, rt);
30840 break;
30841 case OPC_EVPE:
30842 check_cp0_mt(ctx);
30843 gen_helper_evpe(t0, cpu_env);
30844 gen_store_gpr(t0, rt);
30845 break;
30846 case OPC_DVP:
30847 check_insn(ctx, ISA_MIPS32R6);
30848 if (ctx->vp) {
30849 gen_helper_dvp(t0, cpu_env);
30850 gen_store_gpr(t0, rt);
30852 break;
30853 case OPC_EVP:
30854 check_insn(ctx, ISA_MIPS32R6);
30855 if (ctx->vp) {
30856 gen_helper_evp(t0, cpu_env);
30857 gen_store_gpr(t0, rt);
30859 break;
30860 case OPC_DI:
30861 check_insn(ctx, ISA_MIPS32R2);
30862 save_cpu_state(ctx, 1);
30863 gen_helper_di(t0, cpu_env);
30864 gen_store_gpr(t0, rt);
30866 * Stop translation as we may have switched
30867 * the execution mode.
30869 ctx->base.is_jmp = DISAS_STOP;
30870 break;
30871 case OPC_EI:
30872 check_insn(ctx, ISA_MIPS32R2);
30873 save_cpu_state(ctx, 1);
30874 gen_helper_ei(t0, cpu_env);
30875 gen_store_gpr(t0, rt);
30877 * DISAS_STOP isn't sufficient, we need to ensure we break
30878 * out of translated code to check for pending interrupts.
30880 gen_save_pc(ctx->base.pc_next + 4);
30881 ctx->base.is_jmp = DISAS_EXIT;
30882 break;
30883 default: /* Invalid */
30884 MIPS_INVAL("mfmc0");
30885 generate_exception_end(ctx, EXCP_RI);
30886 break;
30888 tcg_temp_free(t0);
30890 #endif /* !CONFIG_USER_ONLY */
30891 break;
30892 case OPC_RDPGPR:
30893 check_insn(ctx, ISA_MIPS32R2);
30894 gen_load_srsgpr(rt, rd);
30895 break;
30896 case OPC_WRPGPR:
30897 check_insn(ctx, ISA_MIPS32R2);
30898 gen_store_srsgpr(rt, rd);
30899 break;
30900 default:
30901 MIPS_INVAL("cp0");
30902 generate_exception_end(ctx, EXCP_RI);
30903 break;
30905 break;
30906 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
30907 if (ctx->insn_flags & ISA_MIPS32R6) {
30908 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
30909 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30910 } else {
30911 /* OPC_ADDI */
30912 /* Arithmetic with immediate opcode */
30913 gen_arith_imm(ctx, op, rt, rs, imm);
30915 break;
30916 case OPC_ADDIU:
30917 gen_arith_imm(ctx, op, rt, rs, imm);
30918 break;
30919 case OPC_SLTI: /* Set on less than with immediate opcode */
30920 case OPC_SLTIU:
30921 gen_slt_imm(ctx, op, rt, rs, imm);
30922 break;
30923 case OPC_ANDI: /* Arithmetic with immediate opcode */
30924 case OPC_LUI: /* OPC_AUI */
30925 case OPC_ORI:
30926 case OPC_XORI:
30927 gen_logic_imm(ctx, op, rt, rs, imm);
30928 break;
30929 case OPC_J: /* Jump */
30930 case OPC_JAL:
30931 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
30932 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
30933 break;
30934 /* Branch */
30935 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
30936 if (ctx->insn_flags & ISA_MIPS32R6) {
30937 if (rt == 0) {
30938 generate_exception_end(ctx, EXCP_RI);
30939 break;
30941 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
30942 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30943 } else {
30944 /* OPC_BLEZL */
30945 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30947 break;
30948 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
30949 if (ctx->insn_flags & ISA_MIPS32R6) {
30950 if (rt == 0) {
30951 generate_exception_end(ctx, EXCP_RI);
30952 break;
30954 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
30955 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30956 } else {
30957 /* OPC_BGTZL */
30958 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30960 break;
30961 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
30962 if (rt == 0) {
30963 /* OPC_BLEZ */
30964 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30965 } else {
30966 check_insn(ctx, ISA_MIPS32R6);
30967 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
30968 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30970 break;
30971 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
30972 if (rt == 0) {
30973 /* OPC_BGTZ */
30974 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30975 } else {
30976 check_insn(ctx, ISA_MIPS32R6);
30977 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
30978 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
30980 break;
30981 case OPC_BEQL:
30982 case OPC_BNEL:
30983 check_insn(ctx, ISA_MIPS2);
30984 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30985 /* Fallthrough */
30986 case OPC_BEQ:
30987 case OPC_BNE:
30988 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
30989 break;
30990 case OPC_LL: /* Load and stores */
30991 check_insn(ctx, ISA_MIPS2);
30992 if (ctx->insn_flags & INSN_R5900) {
30993 check_insn_opc_user_only(ctx, INSN_R5900);
30995 /* Fallthrough */
30996 case OPC_LWL:
30997 case OPC_LWR:
30998 check_insn_opc_removed(ctx, ISA_MIPS32R6);
30999 /* Fallthrough */
31000 case OPC_LB:
31001 case OPC_LH:
31002 case OPC_LW:
31003 case OPC_LWPC:
31004 case OPC_LBU:
31005 case OPC_LHU:
31006 gen_ld(ctx, op, rt, rs, imm);
31007 break;
31008 case OPC_SWL:
31009 case OPC_SWR:
31010 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31011 /* fall through */
31012 case OPC_SB:
31013 case OPC_SH:
31014 case OPC_SW:
31015 gen_st(ctx, op, rt, rs, imm);
31016 break;
31017 case OPC_SC:
31018 check_insn(ctx, ISA_MIPS2);
31019 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31020 if (ctx->insn_flags & INSN_R5900) {
31021 check_insn_opc_user_only(ctx, INSN_R5900);
31023 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
31024 break;
31025 case OPC_CACHE:
31026 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31027 check_cp0_enabled(ctx);
31028 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
31029 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
31030 gen_cache_operation(ctx, rt, rs, imm);
31032 /* Treat as NOP. */
31033 break;
31034 case OPC_PREF:
31035 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31036 if (ctx->insn_flags & INSN_R5900) {
31037 /* Treat as NOP. */
31038 } else {
31039 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
31040 /* Treat as NOP. */
31042 break;
31044 /* Floating point (COP1). */
31045 case OPC_LWC1:
31046 case OPC_LDC1:
31047 case OPC_SWC1:
31048 case OPC_SDC1:
31049 gen_cop1_ldst(ctx, op, rt, rs, imm);
31050 break;
31052 case OPC_CP1:
31053 op1 = MASK_CP1(ctx->opcode);
31055 switch (op1) {
31056 case OPC_MFHC1:
31057 case OPC_MTHC1:
31058 check_cp1_enabled(ctx);
31059 check_insn(ctx, ISA_MIPS32R2);
31060 /* fall through */
31061 case OPC_MFC1:
31062 case OPC_CFC1:
31063 case OPC_MTC1:
31064 case OPC_CTC1:
31065 check_cp1_enabled(ctx);
31066 gen_cp1(ctx, op1, rt, rd);
31067 break;
31068 #if defined(TARGET_MIPS64)
31069 case OPC_DMFC1:
31070 case OPC_DMTC1:
31071 check_cp1_enabled(ctx);
31072 check_insn(ctx, ISA_MIPS3);
31073 check_mips_64(ctx);
31074 gen_cp1(ctx, op1, rt, rd);
31075 break;
31076 #endif
31077 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
31078 check_cp1_enabled(ctx);
31079 if (ctx->insn_flags & ISA_MIPS32R6) {
31080 /* OPC_BC1EQZ */
31081 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
31082 rt, imm << 2, 4);
31083 } else {
31084 /* OPC_BC1ANY2 */
31085 check_cop1x(ctx);
31086 check_insn(ctx, ASE_MIPS3D);
31087 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
31088 (rt >> 2) & 0x7, imm << 2);
31090 break;
31091 case OPC_BC1NEZ:
31092 check_cp1_enabled(ctx);
31093 check_insn(ctx, ISA_MIPS32R6);
31094 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
31095 rt, imm << 2, 4);
31096 break;
31097 case OPC_BC1ANY4:
31098 check_cp1_enabled(ctx);
31099 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31100 check_cop1x(ctx);
31101 check_insn(ctx, ASE_MIPS3D);
31102 /* fall through */
31103 case OPC_BC1:
31104 check_cp1_enabled(ctx);
31105 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31106 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
31107 (rt >> 2) & 0x7, imm << 2);
31108 break;
31109 case OPC_PS_FMT:
31110 check_ps(ctx);
31111 /* fall through */
31112 case OPC_S_FMT:
31113 case OPC_D_FMT:
31114 check_cp1_enabled(ctx);
31115 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31116 (imm >> 8) & 0x7);
31117 break;
31118 case OPC_W_FMT:
31119 case OPC_L_FMT:
31121 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
31122 check_cp1_enabled(ctx);
31123 if (ctx->insn_flags & ISA_MIPS32R6) {
31124 switch (r6_op) {
31125 case R6_OPC_CMP_AF_S:
31126 case R6_OPC_CMP_UN_S:
31127 case R6_OPC_CMP_EQ_S:
31128 case R6_OPC_CMP_UEQ_S:
31129 case R6_OPC_CMP_LT_S:
31130 case R6_OPC_CMP_ULT_S:
31131 case R6_OPC_CMP_LE_S:
31132 case R6_OPC_CMP_ULE_S:
31133 case R6_OPC_CMP_SAF_S:
31134 case R6_OPC_CMP_SUN_S:
31135 case R6_OPC_CMP_SEQ_S:
31136 case R6_OPC_CMP_SEUQ_S:
31137 case R6_OPC_CMP_SLT_S:
31138 case R6_OPC_CMP_SULT_S:
31139 case R6_OPC_CMP_SLE_S:
31140 case R6_OPC_CMP_SULE_S:
31141 case R6_OPC_CMP_OR_S:
31142 case R6_OPC_CMP_UNE_S:
31143 case R6_OPC_CMP_NE_S:
31144 case R6_OPC_CMP_SOR_S:
31145 case R6_OPC_CMP_SUNE_S:
31146 case R6_OPC_CMP_SNE_S:
31147 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31148 break;
31149 case R6_OPC_CMP_AF_D:
31150 case R6_OPC_CMP_UN_D:
31151 case R6_OPC_CMP_EQ_D:
31152 case R6_OPC_CMP_UEQ_D:
31153 case R6_OPC_CMP_LT_D:
31154 case R6_OPC_CMP_ULT_D:
31155 case R6_OPC_CMP_LE_D:
31156 case R6_OPC_CMP_ULE_D:
31157 case R6_OPC_CMP_SAF_D:
31158 case R6_OPC_CMP_SUN_D:
31159 case R6_OPC_CMP_SEQ_D:
31160 case R6_OPC_CMP_SEUQ_D:
31161 case R6_OPC_CMP_SLT_D:
31162 case R6_OPC_CMP_SULT_D:
31163 case R6_OPC_CMP_SLE_D:
31164 case R6_OPC_CMP_SULE_D:
31165 case R6_OPC_CMP_OR_D:
31166 case R6_OPC_CMP_UNE_D:
31167 case R6_OPC_CMP_NE_D:
31168 case R6_OPC_CMP_SOR_D:
31169 case R6_OPC_CMP_SUNE_D:
31170 case R6_OPC_CMP_SNE_D:
31171 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
31172 break;
31173 default:
31174 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
31175 rt, rd, sa, (imm >> 8) & 0x7);
31177 break;
31179 } else {
31180 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
31181 (imm >> 8) & 0x7);
31183 break;
31185 case OPC_BZ_V:
31186 case OPC_BNZ_V:
31187 case OPC_BZ_B:
31188 case OPC_BZ_H:
31189 case OPC_BZ_W:
31190 case OPC_BZ_D:
31191 case OPC_BNZ_B:
31192 case OPC_BNZ_H:
31193 case OPC_BNZ_W:
31194 case OPC_BNZ_D:
31195 check_insn(ctx, ASE_MSA);
31196 gen_msa_branch(env, ctx, op1);
31197 break;
31198 default:
31199 MIPS_INVAL("cp1");
31200 generate_exception_end(ctx, EXCP_RI);
31201 break;
31203 break;
31205 /* Compact branches [R6] and COP2 [non-R6] */
31206 case OPC_BC: /* OPC_LWC2 */
31207 case OPC_BALC: /* OPC_SWC2 */
31208 if (ctx->insn_flags & ISA_MIPS32R6) {
31209 /* OPC_BC, OPC_BALC */
31210 gen_compute_compact_branch(ctx, op, 0, 0,
31211 sextract32(ctx->opcode << 2, 0, 28));
31212 } else if (ctx->insn_flags & ASE_LEXT) {
31213 gen_loongson_lswc2(ctx, rt, rs, rd);
31214 } else {
31215 /* OPC_LWC2, OPC_SWC2 */
31216 /* COP2: Not implemented. */
31217 generate_exception_err(ctx, EXCP_CpU, 2);
31219 break;
31220 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
31221 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
31222 if (ctx->insn_flags & ISA_MIPS32R6) {
31223 if (rs != 0) {
31224 /* OPC_BEQZC, OPC_BNEZC */
31225 gen_compute_compact_branch(ctx, op, rs, 0,
31226 sextract32(ctx->opcode << 2, 0, 23));
31227 } else {
31228 /* OPC_JIC, OPC_JIALC */
31229 gen_compute_compact_branch(ctx, op, 0, rt, imm);
31231 } else if (ctx->insn_flags & ASE_LEXT) {
31232 gen_loongson_lsdc2(ctx, rt, rs, rd);
31233 } else {
31234 /* OPC_LWC2, OPC_SWC2 */
31235 /* COP2: Not implemented. */
31236 generate_exception_err(ctx, EXCP_CpU, 2);
31238 break;
31239 case OPC_CP2:
31240 check_insn(ctx, ASE_LMMI);
31241 /* Note that these instructions use different fields. */
31242 gen_loongson_multimedia(ctx, sa, rd, rt);
31243 break;
31245 case OPC_CP3:
31246 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31247 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
31248 check_cp1_enabled(ctx);
31249 op1 = MASK_CP3(ctx->opcode);
31250 switch (op1) {
31251 case OPC_LUXC1:
31252 case OPC_SUXC1:
31253 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
31254 /* Fallthrough */
31255 case OPC_LWXC1:
31256 case OPC_LDXC1:
31257 case OPC_SWXC1:
31258 case OPC_SDXC1:
31259 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
31260 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
31261 break;
31262 case OPC_PREFX:
31263 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
31264 /* Treat as NOP. */
31265 break;
31266 case OPC_ALNV_PS:
31267 check_insn(ctx, ISA_MIPS5 | ISA_MIPS32R2);
31268 /* Fallthrough */
31269 case OPC_MADD_S:
31270 case OPC_MADD_D:
31271 case OPC_MADD_PS:
31272 case OPC_MSUB_S:
31273 case OPC_MSUB_D:
31274 case OPC_MSUB_PS:
31275 case OPC_NMADD_S:
31276 case OPC_NMADD_D:
31277 case OPC_NMADD_PS:
31278 case OPC_NMSUB_S:
31279 case OPC_NMSUB_D:
31280 case OPC_NMSUB_PS:
31281 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32R2);
31282 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
31283 break;
31284 default:
31285 MIPS_INVAL("cp3");
31286 generate_exception_end(ctx, EXCP_RI);
31287 break;
31289 } else {
31290 generate_exception_err(ctx, EXCP_CpU, 1);
31292 break;
31294 #if defined(TARGET_MIPS64)
31295 /* MIPS64 opcodes */
31296 case OPC_LLD:
31297 if (ctx->insn_flags & INSN_R5900) {
31298 check_insn_opc_user_only(ctx, INSN_R5900);
31300 /* fall through */
31301 case OPC_LDL:
31302 case OPC_LDR:
31303 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31304 /* fall through */
31305 case OPC_LWU:
31306 case OPC_LD:
31307 check_insn(ctx, ISA_MIPS3);
31308 check_mips_64(ctx);
31309 gen_ld(ctx, op, rt, rs, imm);
31310 break;
31311 case OPC_SDL:
31312 case OPC_SDR:
31313 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31314 /* fall through */
31315 case OPC_SD:
31316 check_insn(ctx, ISA_MIPS3);
31317 check_mips_64(ctx);
31318 gen_st(ctx, op, rt, rs, imm);
31319 break;
31320 case OPC_SCD:
31321 check_insn_opc_removed(ctx, ISA_MIPS32R6);
31322 check_insn(ctx, ISA_MIPS3);
31323 if (ctx->insn_flags & INSN_R5900) {
31324 check_insn_opc_user_only(ctx, INSN_R5900);
31326 check_mips_64(ctx);
31327 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
31328 break;
31329 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
31330 if (ctx->insn_flags & ISA_MIPS32R6) {
31331 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
31332 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31333 } else {
31334 /* OPC_DADDI */
31335 check_insn(ctx, ISA_MIPS3);
31336 check_mips_64(ctx);
31337 gen_arith_imm(ctx, op, rt, rs, imm);
31339 break;
31340 case OPC_DADDIU:
31341 check_insn(ctx, ISA_MIPS3);
31342 check_mips_64(ctx);
31343 gen_arith_imm(ctx, op, rt, rs, imm);
31344 break;
31345 #else
31346 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
31347 if (ctx->insn_flags & ISA_MIPS32R6) {
31348 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
31349 } else {
31350 MIPS_INVAL("major opcode");
31351 generate_exception_end(ctx, EXCP_RI);
31353 break;
31354 #endif
31355 case OPC_DAUI: /* OPC_JALX */
31356 if (ctx->insn_flags & ISA_MIPS32R6) {
31357 #if defined(TARGET_MIPS64)
31358 /* OPC_DAUI */
31359 check_mips_64(ctx);
31360 if (rs == 0) {
31361 generate_exception(ctx, EXCP_RI);
31362 } else if (rt != 0) {
31363 TCGv t0 = tcg_temp_new();
31364 gen_load_gpr(t0, rs);
31365 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
31366 tcg_temp_free(t0);
31368 #else
31369 generate_exception_end(ctx, EXCP_RI);
31370 MIPS_INVAL("major opcode");
31371 #endif
31372 } else {
31373 /* OPC_JALX */
31374 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
31375 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
31376 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
31378 break;
31379 case OPC_MSA: /* OPC_MDMX */
31380 if (ctx->insn_flags & INSN_R5900) {
31381 #if defined(TARGET_MIPS64)
31382 gen_mmi_lq(env, ctx); /* MMI_OPC_LQ */
31383 #endif
31384 } else {
31385 /* MDMX: Not implemented. */
31386 gen_msa(env, ctx);
31388 break;
31389 case OPC_PCREL:
31390 check_insn(ctx, ISA_MIPS32R6);
31391 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
31392 break;
31393 default: /* Invalid */
31394 MIPS_INVAL("major opcode");
31395 generate_exception_end(ctx, EXCP_RI);
31396 break;
31400 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
31402 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31403 CPUMIPSState *env = cs->env_ptr;
31405 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
31406 ctx->saved_pc = -1;
31407 ctx->insn_flags = env->insn_flags;
31408 ctx->CP0_Config1 = env->CP0_Config1;
31409 ctx->CP0_Config2 = env->CP0_Config2;
31410 ctx->CP0_Config3 = env->CP0_Config3;
31411 ctx->CP0_Config5 = env->CP0_Config5;
31412 ctx->btarget = 0;
31413 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
31414 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
31415 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
31416 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
31417 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
31418 ctx->PAMask = env->PAMask;
31419 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
31420 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
31421 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
31422 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
31423 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
31424 /* Restore delay slot state from the tb context. */
31425 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
31426 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
31427 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
31428 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
31429 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
31430 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
31431 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
31432 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
31433 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
31434 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
31435 restore_cpu_state(env, ctx);
31436 #ifdef CONFIG_USER_ONLY
31437 ctx->mem_idx = MIPS_HFLAG_UM;
31438 #else
31439 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
31440 #endif
31441 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS32R6 |
31442 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
31444 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
31445 ctx->hflags);
31448 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
31452 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
31454 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31456 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
31457 ctx->btarget);
31460 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
31461 const CPUBreakpoint *bp)
31463 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31465 save_cpu_state(ctx, 1);
31466 ctx->base.is_jmp = DISAS_NORETURN;
31467 gen_helper_raise_exception_debug(cpu_env);
31469 * The address covered by the breakpoint must be included in
31470 * [tb->pc, tb->pc + tb->size) in order to for it to be
31471 * properly cleared -- thus we increment the PC here so that
31472 * the logic setting tb->size below does the right thing.
31474 ctx->base.pc_next += 4;
31475 return true;
31478 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
31480 CPUMIPSState *env = cs->env_ptr;
31481 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31482 int insn_bytes;
31483 int is_slot;
31485 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
31486 if (ctx->insn_flags & ISA_NANOMIPS32) {
31487 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31488 insn_bytes = decode_nanomips_opc(env, ctx);
31489 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
31490 ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
31491 insn_bytes = 4;
31492 decode_opc(env, ctx);
31493 } else if (ctx->insn_flags & ASE_MICROMIPS) {
31494 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31495 insn_bytes = decode_micromips_opc(env, ctx);
31496 } else if (ctx->insn_flags & ASE_MIPS16) {
31497 ctx->opcode = cpu_lduw_code(env, ctx->base.pc_next);
31498 insn_bytes = decode_mips16_opc(env, ctx);
31499 } else {
31500 generate_exception_end(ctx, EXCP_RI);
31501 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
31502 return;
31505 if (ctx->hflags & MIPS_HFLAG_BMASK) {
31506 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
31507 MIPS_HFLAG_FBNSLOT))) {
31509 * Force to generate branch as there is neither delay nor
31510 * forbidden slot.
31512 is_slot = 1;
31514 if ((ctx->hflags & MIPS_HFLAG_M16) &&
31515 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
31517 * Force to generate branch as microMIPS R6 doesn't restrict
31518 * branches in the forbidden slot.
31520 is_slot = 1;
31523 if (is_slot) {
31524 gen_branch(ctx, insn_bytes);
31526 ctx->base.pc_next += insn_bytes;
31528 if (ctx->base.is_jmp != DISAS_NEXT) {
31529 return;
31532 * Execute a branch and its delay slot as a single instruction.
31533 * This is what GDB expects and is consistent with what the
31534 * hardware does (e.g. if a delay slot instruction faults, the
31535 * reported PC is the PC of the branch).
31537 if (ctx->base.singlestep_enabled &&
31538 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
31539 ctx->base.is_jmp = DISAS_TOO_MANY;
31541 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
31542 ctx->base.is_jmp = DISAS_TOO_MANY;
31546 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
31548 DisasContext *ctx = container_of(dcbase, DisasContext, base);
31550 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
31551 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
31552 gen_helper_raise_exception_debug(cpu_env);
31553 } else {
31554 switch (ctx->base.is_jmp) {
31555 case DISAS_STOP:
31556 gen_save_pc(ctx->base.pc_next);
31557 tcg_gen_lookup_and_goto_ptr();
31558 break;
31559 case DISAS_NEXT:
31560 case DISAS_TOO_MANY:
31561 save_cpu_state(ctx, 0);
31562 gen_goto_tb(ctx, 0, ctx->base.pc_next);
31563 break;
31564 case DISAS_EXIT:
31565 tcg_gen_exit_tb(NULL, 0);
31566 break;
31567 case DISAS_NORETURN:
31568 break;
31569 default:
31570 g_assert_not_reached();
31575 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
31577 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
31578 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
31581 static const TranslatorOps mips_tr_ops = {
31582 .init_disas_context = mips_tr_init_disas_context,
31583 .tb_start = mips_tr_tb_start,
31584 .insn_start = mips_tr_insn_start,
31585 .breakpoint_check = mips_tr_breakpoint_check,
31586 .translate_insn = mips_tr_translate_insn,
31587 .tb_stop = mips_tr_tb_stop,
31588 .disas_log = mips_tr_disas_log,
31591 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31593 DisasContext ctx;
31595 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
31598 static void fpu_dump_state(CPUMIPSState *env, FILE * f, int flags)
31600 int i;
31601 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
31603 #define printfpr(fp) \
31604 do { \
31605 if (is_fpu64) \
31606 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31607 " fd:%13g fs:%13g psu: %13g\n", \
31608 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
31609 (double)(fp)->fd, \
31610 (double)(fp)->fs[FP_ENDIAN_IDX], \
31611 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
31612 else { \
31613 fpr_t tmp; \
31614 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
31615 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
31616 qemu_fprintf(f, "w:%08x d:%016" PRIx64 \
31617 " fd:%13g fs:%13g psu:%13g\n", \
31618 tmp.w[FP_ENDIAN_IDX], tmp.d, \
31619 (double)tmp.fd, \
31620 (double)tmp.fs[FP_ENDIAN_IDX], \
31621 (double)tmp.fs[!FP_ENDIAN_IDX]); \
31623 } while (0)
31626 qemu_fprintf(f,
31627 "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
31628 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
31629 get_float_exception_flags(&env->active_fpu.fp_status));
31630 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
31631 qemu_fprintf(f, "%3s: ", fregnames[i]);
31632 printfpr(&env->active_fpu.fpr[i]);
31635 #undef printfpr
31638 void mips_cpu_dump_state(CPUState *cs, FILE *f, int flags)
31640 MIPSCPU *cpu = MIPS_CPU(cs);
31641 CPUMIPSState *env = &cpu->env;
31642 int i;
31644 qemu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
31645 " LO=0x" TARGET_FMT_lx " ds %04x "
31646 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
31647 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
31648 env->hflags, env->btarget, env->bcond);
31649 for (i = 0; i < 32; i++) {
31650 if ((i & 3) == 0) {
31651 qemu_fprintf(f, "GPR%02d:", i);
31653 qemu_fprintf(f, " %s " TARGET_FMT_lx,
31654 regnames[i], env->active_tc.gpr[i]);
31655 if ((i & 3) == 3) {
31656 qemu_fprintf(f, "\n");
31660 qemu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x"
31661 TARGET_FMT_lx "\n",
31662 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
31663 qemu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x%016"
31664 PRIx64 "\n",
31665 env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
31666 qemu_fprintf(f, " Config2 0x%08x Config3 0x%08x\n",
31667 env->CP0_Config2, env->CP0_Config3);
31668 qemu_fprintf(f, " Config4 0x%08x Config5 0x%08x\n",
31669 env->CP0_Config4, env->CP0_Config5);
31670 if ((flags & CPU_DUMP_FPU) && (env->hflags & MIPS_HFLAG_FPU)) {
31671 fpu_dump_state(env, f, flags);
31675 void mips_tcg_init(void)
31677 int i;
31679 cpu_gpr[0] = NULL;
31680 for (i = 1; i < 32; i++)
31681 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
31682 offsetof(CPUMIPSState,
31683 active_tc.gpr[i]),
31684 regnames[i]);
31686 for (i = 0; i < 32; i++) {
31687 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
31688 msa_wr_d[i * 2] =
31689 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2]);
31691 * The scalar floating-point unit (FPU) registers are mapped on
31692 * the MSA vector registers.
31694 fpu_f64[i] = msa_wr_d[i * 2];
31695 off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[1]);
31696 msa_wr_d[i * 2 + 1] =
31697 tcg_global_mem_new_i64(cpu_env, off, msaregnames[i * 2 + 1]);
31700 cpu_PC = tcg_global_mem_new(cpu_env,
31701 offsetof(CPUMIPSState, active_tc.PC), "PC");
31702 for (i = 0; i < MIPS_DSP_ACC; i++) {
31703 cpu_HI[i] = tcg_global_mem_new(cpu_env,
31704 offsetof(CPUMIPSState, active_tc.HI[i]),
31705 regnames_HI[i]);
31706 cpu_LO[i] = tcg_global_mem_new(cpu_env,
31707 offsetof(CPUMIPSState, active_tc.LO[i]),
31708 regnames_LO[i]);
31710 cpu_dspctrl = tcg_global_mem_new(cpu_env,
31711 offsetof(CPUMIPSState,
31712 active_tc.DSPControl),
31713 "DSPControl");
31714 bcond = tcg_global_mem_new(cpu_env,
31715 offsetof(CPUMIPSState, bcond), "bcond");
31716 btarget = tcg_global_mem_new(cpu_env,
31717 offsetof(CPUMIPSState, btarget), "btarget");
31718 hflags = tcg_global_mem_new_i32(cpu_env,
31719 offsetof(CPUMIPSState, hflags), "hflags");
31721 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
31722 offsetof(CPUMIPSState, active_fpu.fcr0),
31723 "fcr0");
31724 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
31725 offsetof(CPUMIPSState, active_fpu.fcr31),
31726 "fcr31");
31727 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
31728 "lladdr");
31729 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
31730 "llval");
31732 #if defined(TARGET_MIPS64)
31733 cpu_mmr[0] = NULL;
31734 for (i = 1; i < 32; i++) {
31735 cpu_mmr[i] = tcg_global_mem_new_i64(cpu_env,
31736 offsetof(CPUMIPSState,
31737 active_tc.mmr[i]),
31738 regnames[i]);
31740 #endif
31742 #if !defined(TARGET_MIPS64)
31743 for (i = 0; i < NUMBER_OF_MXU_REGISTERS - 1; i++) {
31744 mxu_gpr[i] = tcg_global_mem_new(cpu_env,
31745 offsetof(CPUMIPSState,
31746 active_tc.mxu_gpr[i]),
31747 mxuregnames[i]);
31750 mxu_CR = tcg_global_mem_new(cpu_env,
31751 offsetof(CPUMIPSState, active_tc.mxu_cr),
31752 mxuregnames[NUMBER_OF_MXU_REGISTERS - 1]);
31753 #endif
31756 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
31757 target_ulong *data)
31759 env->active_tc.PC = data[0];
31760 env->hflags &= ~MIPS_HFLAG_BMASK;
31761 env->hflags |= data[1];
31762 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
31763 case MIPS_HFLAG_BR:
31764 break;
31765 case MIPS_HFLAG_BC:
31766 case MIPS_HFLAG_BL:
31767 case MIPS_HFLAG_B:
31768 env->btarget = data[2];
31769 break;